c# - 为什么在使用 SSL 时 SmtpClient 会失败并出现几个不同的异常?

标签 c# ssl smtp system.net.mail system.net

我正在尝试使用启用了 SSL 的 System.Net.Mail.SmtpClient 发送邮件消息。虽然没有改变任何外部因素(即点击 F5,然后再次点击 F5 - 或者甚至在一个循环中),它有时会起作用,但大多数时候它会失败。

示例代码:

public void SendMail()
        {
            using (var client = new SmtpClient())
            {
                MailMessage mailMessage = new MailMessage();
                client.EnableSsl = true;
                client.Host = "smtp.example.com";
                client.Timeout = 10000;
                client.DeliveryMethod = SmtpDeliveryMethod.Network;
                mailMessage.From = new MailAddress("from@example.com");
                mailMessage.To.Add(new MailAddress("to@example.com"));
                mailMessage.Subject = "Test";
                mailMessage.Body = "Message " + DateTime.Now.ToString();
                try
                {
                    client.Send(mailMessage);
                }
                catch (Exception ex)
                {
                    // This being a Pokemon block is besides the point
                }
            }
        }

在我的 catch block 中,我只是得到一个超时,但是如果我为 System.NetSystem.Net.Sockets 设置跟踪,我可以看到一些不同的异常(exception):

  • Unable to read data from the transport connection: A blocking operation was interrupted by a call to WSACancelBlockingCall
  • Unable to read data from the transport connection: An established connection was aborted by the software in your host machine
  • Cannot access a disposed object
  • Reading is not supported on this stream
  • Writing is not supported on this stream

所有这些都发生在 EHLO、STARTTLS 和身份验证之后。抛出异常时,客户端和服务器正在以加密方式聊天。

System.Net.Mail.SmtpClient.Send() 是所有调用堆栈唯一共有的框架。

当然,我尝试过以多种方式更改代码,例如设置 client.UseDefaultCredentials、使用 client.SendAsync() 等等。但我怀疑在不同时间断开连接是完全不同的事情——可能是其中一台机器上的配置错误?

因此,我检查了事件日志以查找连接出现问题的迹象,但我没有发现任何问题。

关于我应该在这里寻找什么的任何建议?

最佳答案

有时超时只是超时...

为了进一步研究这个问题,我使用 Wireshark 来查看网络级别发生了什么。

当故障发生时,客户端机器总是在 EHLO 后大约 10 秒发送一个 TCP [RST, ACK] 数据包。时间跨度明显接近我的超时值。当我将超时值加倍时,邮件每次都顺利通过。

当然,如果我们发送每封邮件的时间超过 10 秒,我们的生产系统很快就会让邮件排队数小时,所以我需要找出为什么要花这么长时间。

一个细节引起了我的注意:Wireshark trace

客户端在两个数据包之间花费了超过四秒的时间。它通常在数据包之间花费数百毫秒,而服务器会在几十毫秒内做出响应。

下一步是在没有调试符号的情况下构建代码,并在没有附加调试器的情况下再次测量。立即发送每封电子邮件所花费的时间是亚秒级的。现在,代码在附加调试器的情况下运行速度变慢对我来说已经不是什么新闻了,但看到它运行得慢得多却令人惊讶。

所以我要吸取的教训是:尽量不要过度分析,当涉及到时间时,偶尔停止调试器。

关于c# - 为什么在使用 SSL 时 SmtpClient 会失败并出现几个不同的异常?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35318768/

相关文章:

c# - asp.net 的 SqlDependency 问题

c# - 如何避免此异步/等待程序中可能的堆栈溢出?

ASP.NET 启用点符号 web.config

apache - 如何让所有子域域在没有通配符的情况下使用一个 SSL

ruby - 电子邮件主题未正确分配给 Ruby net/smtp

python - 发送电子邮件时 Postfix 挂起

linux - Spring Boot 发送邮件

javascript - 转换 AI 和 EPS 文件以在 HTML Canvas 中使用

c# - 数组到字典

java - Netty SSL/TLS/HTTPS 支持