tags:

views:

257

answers:

3

I have a .NET service that processes a queue on a background thread and from the items in the queue sends out a large number of small e-mail messages at a very high rate (say 100 messages per second if that is even possible). Currently, I use SmtpClient.Send() but I'm afraid that it may hamper performance.

Each call to Send() goes through a full cycle of opening the socket, performing the SMTP conversation (HELO, MAIL FROM, RCPT TO, DATA) and closing the socket. In pseudo code:

for each message {
  open socket
  send HELO
  send MAIL FROM
  send RCPT TO
  send DATA
  send QUIT
  close socket
}

(Edit: This statement about SmtpClient.Send() is in fact false as I have explained in my answer.)

I would think that the following pseudo code would be more optimal:

open socket
send HELO
for each message {
  send MAIL FROM
  send RCPT TO
  send DATA
}
send QUIT
close socket

Should I be concerned about the performance of SmtpClient.Send() when sending e-mail at a high rate? What are my options for optimizing the performance?

A: 

The process of sending an email using SMTP is specified (originally) in RFC 821. There have been numerous updates and additions since but the basic protocol is still the same. You need to start each transaction with a HELO command and then add the sender info, recipients, etc. If you are sending the same message to all the recipients then you can add multiple recipients in one message. However, if the text of the message is different for each recipient I think you are going to need to send individual messages to each one which means a separate transaction for each.

TLiebe
I have discovered the `SmtpClient.Send()` when called repeatedly will only open the socket once, issue one EHLO command and then submit multiple MAIL FROM, RCPT TO and DATA commands on the same connection.
Martin Liversage
+1  A: 

Create an email server that sends off emails asynchronously using a threadpool or something. That way you can "fire and forget" your emails at the server and let it worry about sending them all off. Set it up with a few threads or more and it should be able to whip through emails pretty fast.

Chris
That is exactly what we are doing, except that we seem to have some performance problems. My question is about the most performant way to "fire and forget" e-mails from a .NET service.
Martin Liversage
What performance issues? In my implementation I could send thousands of emails a minute. Is it throwing exceptions? These are incredibly slow in mail as you quite often have to wait for a socket to time out.
Chris
@Chris: On average we are currently sending 20 e-mails per second, but there are many factors in our environment that may affect this number. I'm investigating if we can improve on the mail sending aspect.
Martin Liversage
If i were you I would set up a small bit of monitoring code that detects emails that are slow to send, and logs information about them. This way you may be able to quickly figure out if certain parameters are slowing it down.
Chris
+1  A: 

The SmtpClient class is caching SMTP server connections behind the scenes. Calling SmtpClient.Send() repeatedly to submit multiple messages to the same SMTP server will effectively execute the pseudo code in the second example.

One way to improve performance may be to use multiple instances of SmtpClient running on multiple threads. Instead of having just one connection to the SMTP server the service will now have many concurrent connections. Incomming e-mail messages are taken from the queue and dispatched to a pool of worker threads that calls SmtpClient.Send() to send the message to the SMTP server.

I have done some rudimentary tests and found that this may improve performance by as much as 100%. However, the optimal number of concurrent connections and the actual performance improvement is probably very much dependendent on the SMTP server. One way to extend this idea is to connect to multiple SMTP servers.

Martin Liversage