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?
NET and . NET Core come with built-in support for sending emails through the System. Net.Mail namespace. While it might seem like the easy choice, you will need an SMTP server for this to work.
Simple Mail Transfer Protocol (SMTP) is a TCP/IP protocol used in sending and receiving e-mail. Most e-mail systems that send mail over the Internet use SMTP to send messages from one server to another. The messages can then be retrieved with an e-mail client using either POP or IMAP.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With