9

This should be pretty routine, right?

public static SmtpClient GetSmtpClient()
{
    var client = new SmtpClient
    {
        Host = _smtpServer,
        UseDefaultCredentials = false,
        Credentials = new NetworkCredential(_smtpUsername, _smtpPassword),
        Port = _smtpPort, // port 25
        EnableSsl = _smtpSsl // false
    };
    return client;
}
...
var m = new MailMessage 
{
    // contents of mail message
}
using (var server = GetSmtpClient())
{
    server.Send(m);
}

But server.Send() is throwing an SmtpException:

Failure sending mail. ---> System.IO.IOException: Unable to read data from the transport connection: net_io_connectionclosed

Something wrong with my credentials? IP block on the SMTP server? Maybe my ISP blocking outgoing requests to port 25? I downloaded and installed Thunderbird on the same machine as my debug environment, and set up identical SMTP credentials there, and it works perfectly.

So why does it work in Thunderbird, but not in my code?

UPDATE: Following up on @tzachs's suggestion, I downloaded Wireshark and found that the transaction progress is identical, up to a point.

Thunderbird:

TCP 62  25 → 50924 [SYN, ACK] Seq=0 Ack=1 Win=5840 Len=0 MSS=1360 SACK_PERM=1
SMTP    143 S: 220 smtp.somedomain.com ESMTP Sendmail 8.13.8/8.13.8; Sat, 5 Dec 2015 15:46:22 -0500
TCP 54  25 → 50924 [ACK] Seq=90 Ack=18 Win=5840 Len=0
SMTP    289 S: 250 smtp.somedomain.com Hello my-computer.myisp.com [x.x.60.61], pleased to meet you | 250 ENHANCEDSTATUSCODES | 250 PIPELINING | 250 8BITMIME | 250 SIZE | 250 DSN | 250 ETRN | 250 AUTH LOGIN PLAIN | 250 DELIVERBY | 250 HELP
SMTP    82  S: 235 2.0.0 OK Authenticated
etc.

SmtpClient:

TCP 62  25 → 50889 [SYN, ACK] Seq=0 Ack=1 Win=5840 Len=0 MSS=1360 SACK_PERM=1
SMTP    143 S: 220 smtp.somedomain.com ESMTP Sendmail 8.13.8/8.13.8; Sat, 5 Dec 2015 15:45:08 -0500
TCP 54  25 → 50889 [ACK] Seq=90 Ack=21 Win=5840 Len=0
SMTP    289 S: 250 smtp.somedomain.com Hello my-computer.myisp.com [x.x.60.61], pleased to meet you | 250 ENHANCEDSTATUSCODES | 250 PIPELINING | 250 8BITMIME | 250 SIZE | 250 DSN | 250 ETRN | 250 AUTH LOGIN PLAIN | 250 DELIVERBY | 250 HELP
TCP 54  25 → 50889 [FIN, ACK] Seq=325 Ack=62 Win=5840 Len=0
TCP 54  25 → 50889 [ACK] Seq=326 Ack=63 Win=5840 Len=0

Notice that after the "pleased to meet you" line in the SmtpClient trace, there's nothing about authentication. Not "accepted", not "failed" - nothing. Just terminates the connection.

Does that shed any light?

ANOTHER UPDATE: The Smtp server is running SendMail, FWIW. The error is specific to this particular Smtp host; when I point at different servers, the code works fine.

Shaul Behr
  • 36,951
  • 69
  • 249
  • 387
  • Some servers require you to log into the incoming server before the outgoing, did you also set up the POP server in Thunderbird? Are you sure the SMTP server is using non-ssl port 25? Many have moved to SSL on port 465 or 587. – Ron Beyer Dec 04 '15 at 13:17
  • Yes, definitely non SSL, port 25. As it happens I am logging into the incoming mail (POP) before sending mail, but that's using a different object. Anyway, how would I check mail first using a SmtpClient? It can only send outgoing mail. – Shaul Behr Dec 04 '15 at 13:21
  • 2
    I would try to capture the network communications with wireshark, it might give you a clue. – tzachs Dec 04 '15 at 14:22
  • @tzachs - question updated with wireshark output. Thanks for the idea! – Shaul Behr Dec 05 '15 at 21:12
  • Perhaps Wireshark is too low level to produce any insights to anyone other than protocol experts. Another troubleshooting option i have successfully used in the past is TELNET. There are many good recipes on how to do it. Example: https://technet.microsoft.com/en-us/library/aa995718%28v=exchg.65%29.aspx – jsanalytics Dec 06 '15 at 16:53
  • @jstreet Nice idea, Telnet connection works fine, managed to send a mail. Problem still appears to be only in my C# code, using the SmtpClient object. – Shaul Behr Dec 06 '15 at 18:00
  • @ShaulBehr: in your post you mention that the problem is _"...specific to this particular Smtp host..."_. So, i wouldn't be suspicious of the `SmtpClient`... Not sure how you did it but, if you can, i would RDP into the host you're having problem with and execute your Telnet troubleshooting sequence from there. In my particular case, the server at some point replied with "unable to relay". And that was enough info for the system admins to fix the problem. – jsanalytics Dec 06 '15 at 18:35
  • @jstreet Telnet works fine even from my local environment; it wouldn't help me to RDP in to the server? The only thing not working is SmtpClient from C#, and I have verified that the same behavior appears on multiple clients. – Shaul Behr Dec 06 '15 at 18:56
  • 3
    @ShaulBehr I have a feeling wireshark may be hiding some extra information in the expandable rows. Could you try fiddler, and configure it via: http://stackoverflow.com/questions/5116148/how-to-get-fiddler-to-filter-specific-localhost-ports to be localhost:25 - and post your full results ? Make sure to select the `Raw` tab for both the request and responses. It'll be quite verbose but should give us a better idea of what's going on. – Rob Dec 07 '15 at 05:02
  • @Rob Sorry, I might be a little dense here, but how do you get Fiddler to capture outgoing SMTP traffic? As far as I was aware, Fiddler only captures HTTP/S traffic? – Shaul Behr Dec 07 '15 at 14:32
  • @ShaulBehr Oh my bad, you're absolutely right. I could have sworn I've used fiddler for non-http traffic, but I suppose not. I recommended it because in my experience, wireshark typically shows the high-level communication unless you explicitly drill down into it. That being said, could you drill down into the last two SMTP messages sent by the thunderbird client? There should be, at least, an outgoing header or packet used for the authentication which is missing from your .NET application – Rob Dec 08 '15 at 01:52
  • @ShaulBehr Has you checked the Host Settings and tried the CallBack like described in my answer? – gReX Dec 08 '15 at 09:05

5 Answers5

2

I did have my share of issues working with different SMTP servers. On my experience, the default .net smtpclient API sometimes doesn't tell you what is really happening (to be fair it could be a side effect of simplifying things for us). What helped me in the past, specially on the troubleshooting phase is the use of a .Net SMTP API that allows me to debug it up to the rcpt commands and give me richer exception information.

For that i recommend you to download the source code of this project and debug their SMTP examples : MailSystem.Net There is a windows forms project named ActiveUp.Net.Samples, just build and execute it and you are good to go on minutes.

If you prefer to use it programmatically, its quite similar than the .net smtpclient (and it does have an overload to pass credentials):

        ActiveUp.Net.Mail.Message message = new ActiveUp.Net.Mail.Message();

        // We assign the sender email
        message.From.Email = this.fromEmailTextbox.Text;

        // We assign the recipient email
        message.To.Add(this.toEmailTextbox.Text);

        // We assign the subject
        message.Subject = this.subjectTextbox.Text;

        // We assign the body text
        message.BodyText.Text = this.bodyTextTextbox.Text;

        // We send the email using the specified SMTP server
        this.AddLogEntry("Sending message.");

        try
        {
            SmtpClient.Send(message, this.smtpServerAddressTextbox.Text);

            this.AddLogEntry("Message sent successfully.");
        }
        catch (SmtpException ex)
        {
            this.AddLogEntry(string.Format("Smtp Error: {0}", ex.Message));
        }
        catch (Exception ex)
        {
            this.AddLogEntry(string.Format("Failed: {0}", ex.Message));
        }

Hope it helps.

Jhonatan P
  • 516
  • 1
  • 4
  • 12
  • Amazing. ActiveUp mail works with this Smtp host, while the native C# SmtpClient doesn't. I don't know if I'll ever understand why, but it's good enough to get you the bounty. – Shaul Behr Dec 13 '15 at 12:13
0

[update] comparing this case with your posted Wireshark transactions, the connection is closed by the SMTP-Server. The question is: why? Maybe there is something wrong with your E-Mail. Check if you filled in From, To, Subject and Body.

Hope this helps.

[old] I had something similar, when trying send messages programmatically.

Check the settings of your mail-Host, if every Client Access is allowed.

See also so

"Under the "Access for less secure apps" section, you can enable access to your account from other devices/applications... like your C# application."

I also added a certificat-Call-Back, like ukhardy wrote. But this is only necessary, if you EnableSsl, and the callback should do some validation.

ServicePointManager.ServerCertificateValidationCallback = 
delegate(object s, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) 
{ return true; };
 smtp.Send(mail);

Check if disabling Firewall and Antivirus work.

Client-Timeout Default is:

client.Timeout = 10000;

Another user had the same exception caused by Program-Structure, see putting client Creation outside loop helped. May refactoring Client Generation outside the static Factory help.

Also check the DeliveryMethod:

client.DeliveryMethod = SmtpDeliveryMethod.Network;
Community
  • 1
  • 1
gReX
  • 1,060
  • 1
  • 20
  • 35
  • Spoke to the network admin of the mail host. It's running on a Linux server, and there is nothing there can can distinguish between different clients. And certificate call-back does nothing. – Shaul Behr Dec 08 '15 at 09:09
  • You just added a timeout? What's the default timeout? – Shaul Behr Dec 08 '15 at 14:36
  • @ShaulBehr: oh, 100000 (100 Seconds) is the default. So, this won't help. – gReX Dec 08 '15 at 14:40
  • @ShaulBehr: may setting client.DeliveryMethod does help? – gReX Dec 09 '15 at 07:52
  • The default is Network. What setting are you suggesting? – Shaul Behr Dec 09 '15 at 08:01
  • @ShaulBehr: Try set DeliveryMethod explicit. From MSDN "The default value for this property can also be set in a machine or application configuration file. Any changes made to the PickupDirectoryLocation property override the configuration file settings." – gReX Dec 09 '15 at 08:20
  • I set it explicitly, doesn't make any difference – Shaul Behr Dec 09 '15 at 09:10
0

I was facing same issue when I switch to amazon Email service. My previous Email server required port but amazon Email service run without it. Port and Enable SSL settings are required as per your email SMTP Server. Add Port and EnableSSL if required.

public static SmtpClient GetSmtpClient()
{
   var client= new SmtpClient();
   client.Host= _smtpServer;
   client.UseDefaultCredentials = false;
   if (smtpUseDefaultCredential)
   { 
      client.UseDefaultCredentials = true;
   }
   else
   {
      client.UseDefaultCredentials = false;
      client.Credentials = new NetworkCredential(smtpUser, smtpPassword);
   }

   if(isPortRequired)
    {
     client.Port= _smtpPort;
    }
    if(isEnableSslRequired)
    {
     client.EnableSsl= true;
    }

    return client;
}
Bhavik Patel
  • 1,466
  • 1
  • 12
  • 28
0

Is it possible that your ISP has implemented something like POP before SMTP? I see that you don't have any authentication traffic getting sent in the Thunderbird conversation, but I do remember having an ISP that used that mechanism a decade or so ago.

scwagner
  • 3,975
  • 21
  • 16
-1

Have you tried Mailgun. It will send the mail for you and will show the email was sent from the specified sender. It is a really simple setup.

You can also add email attachments.

Just add this to your webconfig

Web.config This will work with smtp4dev

<system.net>
  <mailSettings>
    <smtp>
      <network host="localhost" port="25" />
    </smtp>
  </mailSettings>
</system.net>

Web.Release.config

<system.net>
  <mailSettings>
    <smtp deliveryMethod="Network" from="noreply@email_you_chose.com" xdt:Transform="Replace">
      <network host="smtp.mailgun.org" userName="postmaster@the_address_you_chose.com" password="password the site gives you" />
    </smtp>
  </mailSettings>
</system.net>

Service.cs

private MailMessage MailMessageFactory(EmailDTO emailDto)
{
    var text = emailDto.Body;
    var html = emailDto.Body;

    var mailMessage = new MailMessage();
    foreach (var recipient in emailDto.To)
    {
        mailMessage.To.Add(new MailAddress(recipient));
    }
    mailMessage.From = new MailAddress(emailDto.From);
    mailMessage.Subject = emailDto.Subject;
    mailMessage.Body = emailDto.Body;
    mailMessage.AlternateViews.Add(AlternateView.CreateAlternateViewFromString(text, null, MediaTypeNames.Text.Plain));
    mailMessage.AlternateViews.Add(AlternateView.CreateAlternateViewFromString(html, null, MediaTypeNames.Text.Html));
    mailMessage.IsBodyHtml = true;

    return mailMessage;
}

EmailDto.cs

public class EmailDTO
{
    public string From { get; set; }

    public IList<string> To { get; set; }

    public string Subject { get; set; }

    public string Body { get; set; }
}
Tomaltach
  • 913
  • 1
  • 11
  • 30