0

I'm trying to send a mail message using System.Net.Mail.SmtpClient with SSL enabled. While changing no external factors (i.e. hit F5, then hit F5 Again - or even in a loop) it works some times, but most of the times it fails.

Example code:

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

In my catch block I just get a timeout, but if I set up a trace for System.Net and System.Net.Sockets I can see a number of different exceptions:

  • 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

All of which happen post EHLO, STARTTLS and authentication. The client and the server are chatting along in their cryptographic ways when the exceptions are thrown.

System.Net.Mail.SmtpClient.Send() is the the only frame all call stacks have in common.

Of course I've tried changing the code in a number of ways, such as setting client.UseDefaultCredentials, using client.SendAsync() and whatnot. But I suspect it's something entirely different knocking the connection over at different times - a configuration error on one of the machines involved perhaps?

So I've checked the Event Logs for signs of something messing with the connection, but I haven't found anything.

Any suggestions as to what I should be looking for here?

user1666620
  • 4,800
  • 18
  • 27
Torben Frandsen
  • 89
  • 1
  • 10
  • Do you really expect to find an SMTP server located at smtp.example.com??? – JamieMeyer Feb 10 '16 at 15:22
  • @JamieMeyer do you want the OP to provide all the details of his SMTP server for public perusal? – user1666620 Feb 10 '16 at 15:26
  • I don't think the problem is with the code you posted but with something else in your application. Can you show the code that calls your `SendMail()` method? Have you set breakpoints to see where exactly the exception occurs and where it is caught? Also, can somebody explain the downvote? – user1666620 Feb 10 '16 at 15:39
  • Of course I've redacted server names etc. I don't always want to send my mails to to@example.com either :) – Torben Frandsen Feb 10 '16 at 15:47
  • There is no more code to show except a call to this method. This code has been isolated in a small console app in order to exclude sources of error. – Torben Frandsen Feb 10 '16 at 15:49
  • Check these and see if they help: http://stackoverflow.com/questions/5791453/failure-sending-mail-unable-to-write-data-to-the-transport-connection http://stackoverflow.com/questions/17497154/smtpexception-unable-to-read-data-from-the-transport-connection-net-io-connec https://social.msdn.microsoft.com/Forums/en-US/212feb8f-cf96-4561-9953-40a21d21ea47/exception-an-established-connection-was-aborted-by-the-software-in-your-host-machine?forum=netfxnetcom – user1666620 Feb 10 '16 at 16:01

3 Answers3

2

Sometimes a timeout is just a timeout ...

Digging further into this issue I used Wireshark to see what was going on at the network level.

When the failures happened, the client machine invariably sent a TCP [RST, ACK] packet around 10 seconds after EHLO. A timespan conspicuously close to my timeout value. When I doubled the timeout value the mails came through without failure every single time.

Of course if we were to spend more than 10 seconds sending each mail, we'd soon be queuing up mails for hours in our production system, so I needed to find out why it took so long.

One detail caught my attention:Wireshark trace

The client was spending upwards of four seconds between two packets. And it was generally spending hundreds of milliseconds between packets whereas the server would respond within tens.

The next step was to build the code without debug symbols and measure again without a debugger attached. The time spent per e-mail sent immediately went sub-second. Now it's no news to me that code runs slower with a debugger attached, but seeing it run that much slower was a surprise.

So the lessons for me to learn were: Try not to overanalyze, and when timing is involved kill the debugger once in a while.

Torben Frandsen
  • 89
  • 1
  • 10
1

This should be a comment (I don't have reputation to make comments), but it could be a firewall issue, given you're getting an "Unable to read data from the transport connection: An established connection was aborted by the software in your host machine" error (basically, firewall or anti-virus cancelled your attempt to send a mail).

The error "Unable to read data from the transport connection: A blocking operation was interrupted by a call to WSACancelBlockingCall" happens when a stream is closed - see this question - and the other errors you've listed seem like they're related to trying to access a stream when it's closed, too.

All these error point to a common cause, a connection cancelled somewhere between you and the server and most likely on your machine/ network, and you get different errors depending at what point the effect propagates through to your application.

Another thing is, if you use

Credentials = new NetworkCredential(fromAddress.Address, fromPassword)

then you have to enable ssl afterwards, not before, otherwise it's cleared.

Community
  • 1
  • 1
secret squirrel
  • 802
  • 9
  • 13
-1

I suppose you have missed to set Credentials property of your host. However the another reason for exceptions may be wrong host name and port.Try something like :

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

It is tested with gmail host which is smtp.gmail.com and it works correctly

yanis
  • 303
  • 3
  • 15
  • This is a bad answer as it does not explain what is wrong with the OP's code, why the OP is getting an error or why this code is better than the code the OP has posted. In fact it looks like you haven't read the OP's question at all. – user1666620 Feb 10 '16 at 15:27
  • Your edit is still insufficient as the SMTP connection details can also be defined in the .config file of the application. Also, the error messages the OP provided do not point to a client authentication error. As the OP explains, sometimes the emails get sent correctly, sometimes there are exceptions. – user1666620 Feb 10 '16 at 15:30
  • I edited the post in order to explain what i suppose of the information given. – yanis Feb 10 '16 at 15:33
  • How do incorrect credentials explain the error "Unable to read data from the transport connection: A blocking operation was interrupted by a call to WSACancelBlockingCall"? – user1666620 Feb 10 '16 at 15:34
  • As you can see there is one more assumption for the problems. Of course if I find out more about the problem i will edit the post – yanis Feb 10 '16 at 15:37