Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/340.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ssl/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 为什么SmtpClient在使用SSL时会出现几个不同的异常而失败?_C#_Ssl_Smtp_System.net.mail_System.net - Fatal编程技术网

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

C# 为什么SmtpClient在使用SSL时会出现几个不同的异常而失败?,c#,ssl,smtp,system.net.mail,system.net,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

我正在尝试使用启用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块中,我只得到一个超时,但是如果我为
System.Net
System.Net.Sockets
设置跟踪,我可以看到许多不同的异常:

  • 无法从传输连接读取数据:对WSACancelBlockingCall的调用中断了阻塞操作
  • 无法从传输连接读取数据:主机中的软件中止了已建立的连接
  • 无法访问已释放的对象
  • 此流不支持读取
  • 此流不支持写入
所有这些都发生在EHLO、STARTTLS和身份验证之后。当抛出异常时,客户端和服务器正在以加密方式聊天

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

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

因此,我检查了事件日志,查看是否有迹象表明连接有问题,但我没有发现任何东西


关于我应该在这里寻找什么,有什么建议吗?

我想您没有设置主机的
凭据。但是,出现异常的另一个原因可能是主机名和端口错误。请尝试以下操作:

    public void SendMail()
    {
        try
        {
            var fromAddress = new MailAddress("from@example.com", "Some text");
            var toAddress = new MailAddress("to@example.com");
            const string fromPassword = "from account password";

            var smtp = new SmtpClient
            {
                Host = "smtp.example.com",
                Port = "your host port", //for gmail is 587
                EnableSsl = true,
                DeliveryMethod = SmtpDeliveryMethod.Network,
                UseDefaultCredentials = false,
                Credentials = new NetworkCredential(fromAddress.Address, fromPassword)
            };
            using (var message = new MailMessage(fromAddress, toAddress)
            {
                Subject = "Test",
                Body = "Message " + DateTime.Now.ToString()
            })
            {
                smtp.Send(message);
            }
        }
        catch (Exception ex)
        {
            //do something
        }
   }

它是用gmail主机测试的,它是
smtp.gmail.com
,工作正常

我想你没有设置主机的
凭证
属性。但是,出现异常的另一个原因可能是主机名和端口错误。请尝试以下操作:

    public void SendMail()
    {
        try
        {
            var fromAddress = new MailAddress("from@example.com", "Some text");
            var toAddress = new MailAddress("to@example.com");
            const string fromPassword = "from account password";

            var smtp = new SmtpClient
            {
                Host = "smtp.example.com",
                Port = "your host port", //for gmail is 587
                EnableSsl = true,
                DeliveryMethod = SmtpDeliveryMethod.Network,
                UseDefaultCredentials = false,
                Credentials = new NetworkCredential(fromAddress.Address, fromPassword)
            };
            using (var message = new MailMessage(fromAddress, toAddress)
            {
                Subject = "Test",
                Body = "Message " + DateTime.Now.ToString()
            })
            {
                smtp.Send(message);
            }
        }
        catch (Exception ex)
        {
            //do something
        }
   }
这是用gmail主机测试的,它是
smtp.gmail.com
,工作正常

这应该是一个评论(我没有发表评论的名声),但如果你得到一个“无法从传输连接读取数据:已建立的连接被主机中的软件中止”错误(基本上,防火墙或防病毒软件取消了您发送邮件的尝试)

“无法从传输连接读取数据:对WSACancelBlockingCall的调用中断了阻塞操作”错误发生在流关闭时—请参阅—您列出的其他错误似乎也与在流关闭时尝试访问流有关

所有这些错误都指向一个共同的原因,即在您和服务器之间的某个地方以及最有可能在您的计算机/网络上取消的连接,并且您会收到不同的错误,这取决于影响传播到应用程序的点

另一件事是,如果你使用

Credentials=新网络凭据(fromAddress.Address,fromPassword)

然后您必须在之后而不是之前启用ssl,否则它将被清除。

这应该是一个注释(我没有发表评论的声誉),但这可能是一个防火墙问题,因为您会遇到“无法从传输连接读取数据:已建立的连接被主机中的软件中止”错误(基本上,防火墙或防病毒软件会取消您发送邮件的尝试)

“无法从传输连接读取数据:对WSACancelBlockingCall的调用中断了阻塞操作”错误发生在流关闭时—请参阅—您列出的其他错误似乎也与在流关闭时尝试访问流有关

所有这些错误都指向一个共同的原因,即在您和服务器之间的某个地方以及最有可能在您的计算机/网络上取消的连接,并且您会收到不同的错误,这取决于影响传播到应用程序的点

另一件事是,如果你使用

Credentials=新网络凭据(fromAddress.Address,fromPassword)


然后您必须在之后而不是之前启用ssl,否则它将被清除。

有时超时只是一个超时

我使用Wireshark进一步研究了这个问题,以了解网络层面的情况

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

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

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

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

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


因此,我要吸取的教训是:尽量不要过度分析,当涉及计时时,偶尔杀死调试器。

有时超时就是超时

我使用Wireshark进一步研究了这个问题,以了解网络层面的情况

当发生故障时,客户机总是发送一个