8

I'm using NLog an target to send log to some emails using smtp.google.com:587 SMTP server. When I'm using standard System.Net.Mail.SmtpClient library it's working without any problems but when using MailKit it throw me error:

Error sending mail. Exception: >System.Net.Internals.SocketExceptionFactory+ExtendedSocketException (10061): .No connection could be made because the target machine actively refused it .>[::ffff:173.194.76.108]:587

I added one solution with two console projects. One using MailKit and other System.Net.Mail. All settings parameters looks are the same but it doesn't work in MailKit:

using System;
using System.Diagnostics;
using MailKit.Net.Smtp;
using MailKit;
using MailKit.Security;
using MimeKit;

namespace SendMailKit
{
    class Program
    {
        public static void Main(string[] args)
        {
            Console.WriteLine("Create message");
            var message = new MimeMessage();
            message.From.Add(new MailboxAddress("GTS", "tfs.gettaxsolutions@gmail.com"));
            message.To.Add(new MailboxAddress("Me", "info@gettaxsolutions.com"));
            message.Subject = "Test mail";
            message.Body = new TextPart("plain")
            {
                Text = @"Hello, This is the test"
            };

            Console.WriteLine("Create SMTP client");
            using (var client = new SmtpClient())
            {
                // For demo-purposes, accept all SSL certificates (in case the server supports STARTTLS)
                client.ServerCertificateValidationCallback = (s, c, h, e) => true;
                Console.WriteLine("Connect");
                **client.Connect("smtp.gmail.com", 587, true);**
                Console.WriteLine("Authenticate");
                client.Authenticate("tfs.gettaxsolutions", "*********");
                client.Connected += Client_Connected;
                client.Disconnected += Client_Disconnected;
                client.Authenticated += Client_Authenticated;
                client.MessageSent += Client_MessageSent;
                Console.WriteLine("Send Message");
                client.Send(message);
                Console.WriteLine("Disconnect");
                client.Disconnect(true);
            }

            Console.ReadLine();
        }

        private static void Client_MessageSent(object sender, MessageSentEventArgs e)
        {
            Console.WriteLine("MessageSent");
        }

        private static void Client_Authenticated(object sender, AuthenticatedEventArgs e)
        {
            Console.WriteLine("Authenticated");
        }

        private static void Client_Disconnected(object sender, DisconnectedEventArgs e)
        {
            Console.WriteLine("Disconnected");
        }

        private static void Client_Connected(object sender, ConnectedEventArgs e)
        {
            Console.WriteLine("Connected");
        }
    }
}

And this throw the same exception like this one in NLog. the exception is in client.Connect("smtp.gmail.com", 587, true); So the problem is in the MailKit connect. In other project which using System.Net.Mail everything is working fine and the mail is sent successful. I'm starting them on same machine, same environment just change the startup point of console application to test (so the connectivity is not a problem):

using System;
using System.Net;
using System.Net.Mail;
using System.Net.Mime;
using System.Threading;
using System.ComponentModel;
namespace SendSimpleMail
{
    public class Program
    {
        static bool mailSent = false;
        private static void SendCompletedCallback(object sender, AsyncCompletedEventArgs e)
        {
            // Get the unique identifier for this asynchronous operation.
            String token = (string)e.UserState;

            if (e.Cancelled)
            {
                Console.WriteLine("[{0}] Send canceled.", token);
            }
            if (e.Error != null)
            {
                Console.WriteLine("[{0}] {1}", token, e.Error.ToString());
            }
            else
            {
                Console.WriteLine("Message sent.");
            }
            mailSent = true;
        }
        public static void Main()
        {
            // Command-line argument must be the SMTP host.
            SmtpClient client = new SmtpClient("smtp.gmail.com", 587);
            client.EnableSsl = true;
            client.UseDefaultCredentials = false;
            client.Credentials = new NetworkCredential("tfs.gettaxsolutions", "***********");
            // Specify the email sender.
            // Create a mailing address that includes a UTF8 character
            // in the display name.
            MailAddress from = new MailAddress("tfs.gettaxsolutions@gmail.com", "GTS");
            // Set destinations for the email message.
            MailAddress to = new MailAddress("info@gettaxsolutions.com", "Me");
            // Specify the message content.
            MailMessage message = new MailMessage(from, to);
            message.Body = "This is a test email message sent by an application. ";
            // Include some non-ASCII characters in body and subject.
            string someArrows = new string(new char[] { '\u2190', '\u2191', '\u2192', '\u2193' });
            message.Body += Environment.NewLine + someArrows;
            message.BodyEncoding = System.Text.Encoding.UTF8;
            message.Subject = "test message 1" + someArrows;
            message.SubjectEncoding = System.Text.Encoding.UTF8;
            // Set the method that is called back when the send operation ends.
            client.SendCompleted += new
            SendCompletedEventHandler(SendCompletedCallback);
            // The userState can be any object that allows your callback 
            // method to identify this send operation.
            // For this example, the userToken is a string constant.
            string userState = "test message1";
            client.SendAsync(message, userState);
            Console.WriteLine("Sending message... press c to cancel mail. Press any other key to exit.");
            string answer = Console.ReadLine();
            // If the user canceled the send, and mail hasn't been sent yet,
            // then cancel the pending operation.
            if (answer.StartsWith("c") && mailSent == false)
            {
                client.SendAsyncCancel();
            }
            // Clean up.
            message.Dispose();
            Console.WriteLine("Goodbye.");
        }
    }
}

I can't find what is the issue with MailKit. The settings looks like identical. Do you have some idea what can be a problem? Is it bug or have some problem in my settings?

MailKit have to send email successful

ASP.NET Core 2.2, MailKit 2.1.3

GetTaxSolutions
  • 111
  • 1
  • 1
  • 6
  • Check out the accepted answer to a similar question here: https://stackoverflow.com/questions/9695224/no-connection-could-be-made-because-the-target-machine-actively-refused-it-127-0 – jstedfast Mar 28 '19 at 12:04

5 Answers5

3

I just partly-solved a very similar problem merely a few minutes ago; what I learned may help you.

In the case I have, there was reliably working code for MailKit to send from application with target of NET Core 2.1.

Recently I updated all the Nuget packages, thinking it was good practice to do this. Then I later discovered that my working SMTP send code had suddenly stopped working and it was reporting identical error to what you have experienced.

With this situation I checked all kinds of problems with smtp server, firewall, etc., until I remembered the Nuget update, began experimenting and eventually downgraded MailKit to 2.0.0. The send code began working again once MailKit had the version downgrade.

I have not pinpointed the exact location and mechanism of failure but have developed some confidence that (in the case I have been working on) the MailKit version used is directly involved. For today it's restored to working on the MailKit 2.0.0 downgrade and there is more research to be done to take it beyond that status.

  • Try setting the client.Timeout to -1 to see if perhaps the problem is a connection timeout? That's the main thing that changed between 2.0 and 2.1 (Connect became cancellable via timeout value). – jstedfast Mar 28 '19 at 15:03
  • Will check that out. The failure was consistent connecting against two entirely different smtp servers. (And success with both servers when heading back to 2.0.) There was no code change so maybe the default taken was not good. – An commercial developer Mar 28 '19 at 16:59
  • Hmm, just remembered I changed from doing Dns.GetHostAddresses() and then looping over each IP address returned to just having `Socket.Connect (string hostname, int port)`. Perhaps the problem is that Socket.Connect() when given a host name isn't using the right IP? – jstedfast Mar 28 '19 at 19:13
  • Are you on a WIndows system or a Unix-based system like Linux/MacOS? Seems there is/was(?) a bug in .NET's SOcket logic when connecting via a hostname instead of an IPAddress because Linux/MacOS can't reuse sockets. – jstedfast Mar 29 '19 at 10:32
  • Try going to https://www.myget.org/feed/mimekit/package/nuget/MailKit and installing the latest MailKit version (>= 2.1.3.15). I made some changes to the Connect logic that *may* solve this? – jstedfast Mar 29 '19 at 12:17
  • Able to worked by downgrade version to MailKit 2.0.0 – khoi Apr 03 '19 at 04:47
  • Please try the myget builds so that I know if that fixes things for you. If it does, I'll make a new release so that you can upgrade to the latest. If no one tests my fix, how will I know it works? – jstedfast Apr 03 '19 at 15:50
  • @jstedfast replying to your question it's Windows. I haven't tried code changes yet, unfortunately working other issues and just saw your March 29 msg here. – An commercial developer Apr 04 '19 at 03:34
  • @Ancommercialdeveloper I'm working with .NET Framework 4.6.2. Do you know if what you've suggested (using MailKit 2.0.0) is still true? I've just installed MailKit 3.0.0, but it is 2 years later. – Rod Dec 14 '21 at 22:52
1

I changed the code of connect to this one:

client.ServerCertificateValidationCallback = (s, c, h, e) => true; client.Connect("smtp.gmail.com", 587, SecureSocketOptions.StartTlsWhenAvailable);

So it's clean that will use Tls when available. Certificate validation is turned off. It's working perfect in MailKit 2.0.7 but same code in 2.1.3 continue to throw the error in issue's description. Don't know why. May be have some bug in the all last versions(2.1.x)?

GetTaxSolutions
  • 111
  • 1
  • 1
  • 6
  • As of MailKit 2.1.0, MailKit uses the SmtpClient.Timeout value to abort Connect after the timeout period has expired. By default, this timeout is `2 * 60 * 1000` - perhaps try setting it to a much larger value? Or try setting it to `-1`. – jstedfast Mar 28 '19 at 12:00
1

I've working in api on .NET 5.0 and I had the same problem.

The version Mailkit: 2.15.0

I tested several option and the next code working for me:

public async Task SendEmailAsync(MailStructure mailStructure)
    {
        var email = new MimeMessage();
        email.Sender = MailboxAddress.Parse(mailStructure.CorreoSMTP);
        email.To.Add(MailboxAddress.Parse(mailStructure.Para));
        email.Subject = "Notificación de pago Sireves";
        var builder = new BodyBuilder();
       
        email.Body = new TextPart(TextFormat.Html)
        {
            Text = "prueba de correo mailkit"
        };

        using var smtp = new SmtpClient();
        smtp.ServerCertificateValidationCallback = (s, c, h, e) => true;
        smtp.Connect("smtp.gmail.com", 587, SecureSocketOptions.StartTlsWhenAvailable);
        smtp.Authenticate(mailStructure.CorreoSMTP, mailStructure.PassSMTP);

        await smtp.SendAsync(email);
        smtp.Disconnect(true);
    }
manolo386
  • 69
  • 1
0

Part of the problem is that SMTP port 587 does not support SSL. You need to pass false as the useSsl argument.

Port 587 uses STARTTLS (which MailKit will automatically use if it can).

If you want more control, use the Connect[Async] methods that take a SecureSocketOptions enum value.

When using the Connect[Async] methods that take a boolean argument, true is the equivalent of SecureSocketOptions.SslOnCOnnect and false is the equivalent of SecureSOcketOptions.StartTlsWhenAvailable.

That said, however, the main part of the problem seems to be a bug in MailKit's newer Socket connection code. As of MailKit 2.1.x, MailKit began using Socket.BeginConnect (string host, int port, ...) instead of Socket.Connect (IPAddress address, int port) thereby allowing the underlying .NET implementation to resolve the host name into the appropriate IPAddress itself and to allow cancelability. Unfortunately, this seems to have broken things for some people (why?).

I have updated MailKit again to go back to resolving host names to a list of IP addresses (using Dns.GetHostAddresses[Async]) and looping over each IPAddress until it is able to successfully connect. This fix will be available in MailKit >= 2.1.4. Until then, you can install via the myget feed at https://www.myget.org/feed/mimekit/package/nuget/MailKit

jstedfast
  • 35,744
  • 5
  • 97
  • 110
  • Actually I tried to set it to false but the error is the same. Tried with different SecureSocketOptions without success – GetTaxSolutions Mar 28 '19 at 09:11
  • Can you write a simple program that uses a socket to connect to that host/port? Does it work? Maybe you have some sort of firewall in the way. The error suggests that the host rejected your connection. – jstedfast Mar 28 '19 at 09:28
  • Tried with timeout -1. The same error. In the description of issue I was described that have 2 projects and start them on same machine - one use direct socket to connect to that host/port the other use MailKit. The first is working without any problems but Mailkt v.2.1.x not. Lower version of MailKit also are worked without changes in code. So the connectivity is fine. – GetTaxSolutions Mar 29 '19 at 12:16
  • Try going to https://myget.org/feed/mimekit/package/nuget/MailKit and installing the latest MailKit version (>= 2.1.3.15). I made some changes to the Connect logic that may solve this? – jstedfast Mar 29 '19 at 12:17
  • 2
    Please try the myget builds so that I know if that fixes things for you. If it does, I'll make a new release so that you can upgrade to the latest. If no one tests my fix, how will I know it works? – jstedfast Apr 03 '19 at 15:51
0

There is a setting in the google email account that allows "less secure" apps to log in to and send smtp from the gmail account, if this isnt on the app or machine trying to send will get blocked by google.

joe blogs
  • 142
  • 4
  • 16