SmtpClient.Dispose抛出System.IO.IOException

时间:2017-09-25 08:35:29

标签: c# .net dispose smtpclient

我的代码发送这样的电子邮件:

    private void DispatchMail(MailMessage mailMessage)
    {
        using (var smtpClient = new SmtpClient())
        {
            smtpClient.Send(mailMessage);
        }
    }

使用HTML正文并且没有附件,MailMessage实例非常简单。

SmtpClient的配置在web.config中,如下所示:

<system.net>
    <mailSettings>
        <smtp from="yourmail@gmail.com">
            <network host="mailprovider.org" port="587" enableSsl="true" userName="username@host" password="secret" />
       </smtp>
    </mailSettings>
</system.net>

每当调用方法DispatchMail时,邮件实际上都会发送给收件人,但是在隐式调用的SmtpClient.Dispose方法中我得到了一个例外。

  

异常:无法从传输连接读取数据:远程主机强行关闭现有连接。

     

在System.Net.Sockets.NetworkStream.Read(Byte []缓冲区,Int32偏移量,Int32大小)       在System.Net.FixedSizeReader.ReadPacket(Byte []缓冲区,Int32偏移量,Int32计数)       在System.Net.Security._SslStream.StartFrameBody(Int32 readBytes,Byte [] buffer,Int32 offset,Int32 count,AsyncProtocolRequest asyncRequest)       在System.Net.Security._SslStream.StartFrameHeader(Byte []缓冲区,Int32偏移量,Int32计数,AsyncProtocolRequest asyncRequest)       在System.Net.Security._SslStream.StartReading(Byte []缓冲区,Int32偏移量,Int32计数,AsyncProtocolRequest asyncRequest)       在System.Net.Security._SslStream.ProcessRead(Byte []缓冲区,Int32偏移量,Int32计数,AsyncProtocolRequest asyncRequest)       在System.Net.TlsStream.Read(Byte []缓冲区,Int32偏移量,Int32大小)       在System.Net.PooledStream.Read(Byte []缓冲区,Int32偏移量,Int32大小)       在System.Net.Mail.SmtpPooledStream.Dispose(布尔处理)       在System.IO.Stream.Close()       在System.IO.Stream.Dispose()       在System.Net.ConnectionPool.Destroy(PooledStream pooledStream)       在System.Net.ConnectionPool.ForceCleanup()       在System.Net.ConnectionPoolManager.CleanupConnectionPool(ServicePoint servicePoint,String groupName)       在System.Net.Mail.SmtpClient.Dispose(布尔处理)       在System.Net.Mail.SmtpClient.Dispose()       在QueuedMailDispatcherService.DispatchMail(MailMessage mailMessage)

     

内部异常:远程主机强行关闭现有连接

     

在System.Net.Sockets.Socket.Receive(Byte []缓冲区,Int32偏移量,Int32大小,SocketFlags socketFlags)      在System.Net.Sockets.NetworkStream.Read(Byte []缓冲区,Int32偏移量,Int32大小)

这是.NET Framework 4.5.2中的错误还是我错误管理了SMTP客户端的生命周期?

有问题的SMTP服务器响应为“Microsoft ESMTP MAIL服务”。

更新

首先我解决了这个问题,因为它只发生在我的机器上,但后来发生在运行相同代码但具有发布配置的生产机器上。

由于此错误间歇性地发生,我决定修改该方法以使用两级异常处理策略,其中忽略调用Dispose时发生的任何异常。

当我能够捕获此错误并逐步执行框架源时,似乎偏移参数已损坏(它比缓冲区高几MB).System.SNet.Sockets.NetworkStream.Read和System之间的某处.Net.Sockets.Socket.Receive。然而,对源的进一步检查并不意味着偏移将被改变。事实上,System.Net.Security._SslStream.StartFrameHeader在调用堆栈中将偏移量设置为更高的5。这让我相信发生了下列事情之一:

  • 调试的机器级代码与我在Visual Studio中完成的源代码不匹配
  • 某种内存损坏(但是在调试和发布配置中,一次重启和两台不同的机器上都存在问题)
  • 我实际上是在调试两个不同的线程而没有意识到它
  • 有某种困难的罕见种族情况
  • 存在某种优化错误,可能与竞争条件相结合
  • SMTP服务器实施或网络传输在SMTP Quit期间不可靠,但它是一个众所周知的SMTP服务器软件,我不明白为什么这个问题会间歇性,也不能解释出界的偏移值。< / LI>

2 个答案:

答案 0 :(得分:-1)

尝试以下示例:

using System.Net.Mail;


private void DispatchMail(string to)
{
    var mail = new MailMessage
    {
        Subject = "subject",
        From = new MailAddress(@"sender email", @"sender name")
    };
    mail.To.Add(to);
    mail.Body = "your message body";

    var smtp = new SmtpClient(@"smtp mail server address");
    smtp.Port = 587;
    smtp.Credentials = new System.Net.NetworkCredential("username", "password");
    smtp.EnableSsl = true;
    smtp.Send(mail);

    mail.Dispose();
    smtp.Dispose();
}

答案 1 :(得分:-1)

你可以做这样的事情

           var fromAddress = new MailAddress("fromAddress", "My Name");
            var toAddress = new MailAddress("gtoAddress ", "Mr Test");
            const string fromPassword = "fromPassword";
            string subject = "hello";
            string body = "how are you doing?";

            var smtp = new SmtpClient
            {

                Host = "smtp.gmail.com",
                Port = 587,
                EnableSsl = true,
                DeliveryMethod = SmtpDeliveryMethod.Network,
                UseDefaultCredentials = false,
                Credentials = new NetworkCredential(fromAddress.Address, fromPassword),
                Timeout = 20000
            };

            using (var message = new MailMessage(fromAddress, toAddress)
            {
                Subject = subject,
                Body = body
            })
            {
                smtp.Send(message);

            }

并在您的Gmail帐户here

上启用安全性较低的应用