Ted
Ted

Reputation: 20184

SmtpClient very slow - about 2 seconds to send one very small email

I'm using SmtpClient to send a simple email.

The email consists of about 25 plaintext characters so it's small.

It however takes the SmtpClient about 2000 milliseconds to send one of them. I do not create the SmtpClient for each send - that is created on program start so the only thing that is done is this:

DateTime start = DateTime.Now;

MailMessage oMsg = new MailMessage();
// TODO: Replace with sender e-mail address.
oMsg.From = new MailAddress(settings._Username);
oMsg.To.Add(new MailAddress(emailEvent._ContactItemToUse.Data));
oMsg.Subject = emo._Subject;
oMsg.BodyEncoding = Encoding.UTF8;
oMsg.IsBodyHtml = emo._IsHtmlText;
oMsg.Body = emo._Text;
client.Send(oMsg);
TimeSpan timeWasted = DateTime.Now.Subtract(start); // between 1000-2000 ms

This is of course very bad, and I can't figure out why. Can I improve it?

Upvotes: 8

Views: 18379

Answers (7)

John Ranger
John Ranger

Reputation: 633

in 2021, I get about 580..620 Mails / Minute through, when using the net.mail.SmtpClient from within Powershell core.

If I let 2 instances of the script run on the same server (with different e-mail address lists of course) I get on the 1st one about 350..400 mails / min and on the 2nd one about 500..550 mails / min.

In my case, the mails are HTML-formatted mails with each 4 images in them and each of the mails has to be generated individually.

So net.mail.SmtpClient by itself is definitely not slow.

Of course, it heavily depends on the performance of your SMTP server - and the connection between your sending client and the SMTP server.

We have an enterprise-grade SMTP solution and GBit/s LAN between the Server which is generating the e-Mails and our SMTP server.

This is using smtp.send(), not smtp.sendAsync(). So every mail is generated sequentially and waits until the SMTP server has accepted it.

In my opinion, net.mail.SmtpClient really can be used for mass mailing and it is very easy to use.

Free tip made out of hard experience: Just make absolutely sure that you dispose the Net.Mail.MailMessage object after sending each mail - otherwise the "to" mailadresses do cumulate up and you are ending up sending a mail to the same recipient multiple times and the recipients see each other in the "to" field.

Upvotes: 1

Sonic Soul
Sonic Soul

Reputation: 24949

had the same exact issue. ~2 seconds per email.

for us this fixed it:

c:\windows\system32\set-receiveconnector "External - TLS Exempt" -MaxAcknowledgeDelay 0

Configure Receive Connector Properties

Upvotes: 0

Can Gencer
Can Gencer

Reputation: 8885

The SmtpClient class I believe does not reuse the same connection for each mail sent (edit: apparently this is now possible in .NET 4.0, see the differences in documentation for SmtpClient). Opening a new connection is expensive, and that is probably what takes time. There are commercial SMTP components that do and offer much higher performance. Depending on SMTP server and mail size, it is possible to achieve something like at least 50mails/second.

However this might not be an issue for you if you change the architecture slightly. What I do in my application is that SmtpClient delivers mails to a folder, by using smtpClient.DeliveryMethod = SmtpDeliveryMethod.SpecifiedPickupDirectory and setting the PickupDirectoryLocation to the wanted directory. What this does is, instead of sending the mail messages over the network, it will write them to the specified folder as standard mime messages (.eml format).

Here you can either use the IIS SMTP server or simply make another background thread/process to consume the .eml files created and deliver them to the recipients or to another SMTP server.

This approach I think is much superior, simply because:

  • The client code sending the mail never has to wait for the actual mail to be sent, which can take a fair while depending on connection speed, latency etc.
  • If the mail sent did not succeed, the client code is not affected. The mail can be sent some other time in the background.
  • The mail queue is persistent, if the application is stopped and started again, mails in the queue will not be lost.
  • Easier for testing purposes.

As a simpler approach, you can use SendAsync instead of Send, but it doesn't give all the immediate approaches the PickupDirectory approach will give.

Upvotes: 8

Teoman Soygul
Teoman Soygul

Reputation: 25742

Speed of SmtpClient class is mostly dependent on the SMTP server that you're connecting to & your internet connection speed. The best way to optimize your through-output using SmtpClient.SendAsync and creating up to 10 or more streamlined connections to the smtp server. After all, this is same strategy of all the modern web browsers do to speed up browsing.

Upvotes: 4

jishi
jishi

Reputation: 24634

Try telnetting and emulate the protocol to the smtp-server in question and see which command that actually delays your communication.

My guess is that the RCPT TO command makes some sort of validation that takes some time.

Upvotes: 0

ChrisLively
ChrisLively

Reputation: 88072

A few things come to mind.

First off, some sites will purposely slow down the connection in order to make it less profitable for spammers to send mail to their systems. This is called Tarpitting.

Interestingly, the mail server your site uses to broadcast out might even have this turned on. ( http://winzenz.blogspot.com/2005/12/enabling-smtp-tarpitting-in-windows.html )

Other things that might cause issues is if the receiving mail server has a short TTL for it's DNS settings and/or YOUR web server has some bad (e.g. dead or overloaded) DNS servers in it's IP setup.

Upvotes: 4

TomTom
TomTom

Reputation: 62157

Maybe it is not your problem. To send, a server has to receive,. Depending on your server that can take some time. Have you validated that part, too?

Upvotes: 0

Related Questions