简体   繁体   中英

SmtpClient.Dispose throws System.IO.IOException

My code sends e-mails like this:

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

The MailMessage instances are very simple with a HTML body and no attachments.

The configuration of the SmtpClient is in web.config like this:

<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>

Whenever the method DispatchMail is called, the mail is actually sent to the recipient, however I get an exception in the implicitly called SmtpClient.Dispose method.

Exception: Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host.

at System.Net.Sockets.NetworkStream.Read(Byte[] buffer, Int32 offset, Int32 size) at System.Net.FixedSizeReader.ReadPacket(Byte[] buffer, Int32 offset, Int32 count) at System.Net.Security._SslStream.StartFrameBody(Int32 readBytes, Byte[] buffer, Int32 offset, Int32 count, AsyncProtocolRequest asyncRequest) at System.Net.Security._SslStream.StartFrameHeader(Byte[] buffer, Int32 offset, Int32 count, AsyncProtocolRequest asyncRequest) at System.Net.Security._SslStream.StartReading(Byte[] buffer, Int32 offset, Int32 count, AsyncProtocolRequest asyncRequest) at System.Net.Security._SslStream.ProcessRead(Byte[] buffer, Int32 offset, Int32 count, AsyncProtocolRequest asyncRequest) at System.Net.TlsStream.Read(Byte[] buffer, Int32 offset, Int32 size) at System.Net.PooledStream.Read(Byte[] buffer, Int32 offset, Int32 size) at System.Net.Mail.SmtpPooledStream.Dispose(Boolean disposing) at System.IO.Stream.Close() at System.IO.Stream.Dispose() at System.Net.ConnectionPool.Destroy(PooledStream poo ledStream) at System.Net.ConnectionPool.ForceCleanup() at System.Net.ConnectionPoolManager.CleanupConnectionPool(ServicePoint servicePoint, String groupName) at System.Net.Mail.SmtpClient.Dispose(Boolean disposing) at System.Net.Mail.SmtpClient.Dispose() at QueuedMailDispatcherService.DispatchMail(MailMessage mailMessage)

Inner exception: An existing connection was forcibly closed by the remote host

at System.Net.Sockets.Socket.Receive(Byte[] buffer, Int32 offset, Int32 size, SocketFlags socketFlags) at System.Net.Sockets.NetworkStream.Read(Byte[] buffer, Int32 offset, Int32 size)

Is this a bug in the .NET Framework 4.5.2 or am I mismanaging the life-cycle of the SMTP client?

The SMTP server in question responds as "Microsoft ESMTP MAIL Service".

Update

First I dismissed this problem since it only happened on my machine, but then it happened on the production machine running same code but with release configuration.

Since this error happens intermittently I have decided to modify the method to use a two-level exception handling strategy where any exception occurring when Dispose is called is ignored.

When I was able to catch this error and step through the framework source it seemed like the offset parameter was corrupted (it was several MB higher than the buffer.Length) somewhere between System.Net.Sockets.NetworkStream.Read and System.Net.Sockets.Socket.Receive. However further inspection of the source does not imply that the offset would be changed. In fact System.Net.Security._SslStream.StartFrameHeader sets offset to 5 higher up in the call stack. This leads me to believe that one of the following things happened:

  • The debugged machine level code was not matching the source I stepped through in Visual Studio
  • Some kind of memory corruption (however the problem has persisted through one reboot and on two different machines both in debug and release configuration)
  • I was actually debugging two different threads without realizing it
  • There is some kind of difficult rare race condition going on
  • There is some kind of optimization going wrong, maybe in combination with the race condition
  • The SMTP server implementation or the network transmission is not reliable during SMTP Quit, however it is a well known SMTP server software and I cannot see why this problem would be intermittent also it does not explain the out of bound offset value.

Try the below sample:

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();
}

you can do something like this

           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);

            }

and enable less secure apps on your Gmail account here

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM