SmtpClient 非常慢 - 发送一封非常小的电子邮件大约需要 2 秒
我正在使用 SmtpClient 发送简单的电子邮件。
该电子邮件由大约 25 个纯文本字符组成,因此很小。
然而,SmtpClient 需要大约 2000 毫秒才能发送其中一个。我不会为每个发送创建 SmtpClient - 这是在程序启动时创建的,所以唯一要做的就是:
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
这当然非常糟糕,我不明白为什么。我可以改进吗?
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?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
我相信 SmtpClient 类不会为发送的每封邮件重用相同的连接(编辑:显然这在 .NET 4.0 中现在是可能的,请参阅文档中的差异 SmtpClient)。打开新连接的成本很高,而且可能需要时间。有些商业 SMTP 组件可以提供更高的性能。根据 SMTP 服务器和邮件大小,可以达到至少 50 封邮件/秒。
但是,如果您稍微更改架构,这对您来说可能不是问题。我在应用程序中所做的是,SmtpClient 通过使用 smtpClient.DeliveryMethod = SmtpDeliveryMethod.SpecifiedPickupDirectory 并将 PickupDirectoryLocation 设置为所需目录,将邮件传送到文件夹。它的作用是,不是通过网络发送邮件消息,而是将它们作为标准 mime 消息(.eml 格式)写入指定的文件夹。
在这里,您可以使用 IIS SMTP 服务器,也可以简单地创建另一个后台线程/进程来使用创建的 .eml 文件并将它们传递给收件人或另一个 SMTP 服务器。
我认为这种方法要优越得多,因为:
作为一种更简单的方法,您可以使用 SendAsync 而不是 Send,但它不会提供 PickupDirectory 方法将提供的所有直接方法。
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:
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.
我想到了一些事情。
首先,一些网站会故意减慢连接速度,以降低垃圾邮件发送者向其系统发送邮件的利润。这称为柏油防水。
有趣的是,您的站点用于广播的邮件服务器甚至可能打开了此功能。 (http://winzenz.blogspot.com/2005/ 12/enabling-smtp-tarpitting-in-windows.html )
其他可能导致问题的事情是,如果接收邮件服务器的 DNS 设置的 TTL 很短和/或您的 Web 服务器有一些问题(例如死机)或过载)其 IP 设置中的 DNS 服务器。
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.
SmtpClient 类的速度主要取决于您要连接的 SMTP 服务器&您的互联网连接速度。使用
SmtpClient.SendAsync
优化直通输出并创建最多 10 个或更多到 smtp 服务器的简化连接的最佳方法。毕竟,这与所有现代网络浏览器为加快浏览速度而采取的策略相同。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.到 2021 年,当在 Powershell 核心内使用 net.mail.SmtpClient 时,我每分钟收到大约 580..620 封邮件。
如果我让脚本的 2 个实例在同一台服务器上运行(当然具有不同的电子邮件地址列表),第一个实例的速度约为 350..400 封邮件/分钟,第二个实例的速度约为 500..550 封邮件/分钟分钟。
就我而言,邮件是 HTML 格式的邮件,每封邮件中包含 4 个图像,并且每封邮件都必须单独生成。
因此 net.mail.SmtpClient 本身绝对不慢。
当然,这在很大程度上取决于 SMTP 服务器的性能以及发送客户端和 SMTP 服务器之间的连接。
我们在生成电子邮件的服务器和我们的 SMTP 服务器之间拥有企业级 SMTP 解决方案和 GBit/s LAN。
这是使用 smtp.send(),而不是 smtp.sendAsync()。因此,每封邮件都会按顺序生成并等待 SMTP 服务器接受它。
在我看来,net.mail.SmtpClient确实可以用来群发邮件,而且非常好用。
根据艰苦经验得出的免费提示:只需绝对确保在发送每封邮件后处理 Net.Mail.MailMessage 对象 - 否则“收件人”邮件地址会累积起来,最终会发送一个多次向同一收件人发送邮件,并且收件人可以在“收件人”字段中看到对方。
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.
也许这不是你的问题。要发送,服务器必须接收。根据您的服务器,这可能需要一些时间。您也验证了该部分吗?
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?
尝试远程登录并模拟相关 smtp 服务器的协议,看看哪个命令实际上延迟了您的通信。
我的猜测是 RCPT TO 命令进行某种需要一些时间的验证。
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.
有同样的问题。每封电子邮件约 2 秒。
对于我们来说,这修复了它:
配置接收连接器属性< /a>
had the same exact issue. ~2 seconds per email.
for us this fixed it:
Configure Receive Connector Properties