在.NET Core 2.2中使用MailKit SMTP客户端通过Gmail SMTP发送邮件对我不起作用

时间:2019-03-27 16:34:53

标签: .net asp.net-core .net-core smtp mailkit

我正在使用NLog作为目标,以使用smtp.google.com:587 SMTP服务器将日志发送到某些电子邮件。当我使用标准的System.Net.Mail.SmtpClient库时,它运行正常,没有任何问题,但是当使用MailKit时,它使我出错:

  

发送邮件时出错。异常:> System.Net.Internals.SocketExceptionFactory + ExtendedSocketException(10061):无法建立连接,因为目标计算机主动拒绝了它。> [:: ffff:173.194.76.108]:587

我添加了带有两个控制台项目的解决方案。一种使用MailKit,另一种使用System.Net.Mail。所有设置参数的外观都相同,但在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");
        }
    }
}

这会引发与NLog中的异常相同的异常。例外发生在client.Connect(“ smtp.gmail.com”,587,true);因此问题出在MailKit连接中。在另一个使用System.Net.Mail的项目中,一切正常,并且邮件发送成功。我要在同一台计算机上,同一环境中启动它们,只需更改控制台应用程序的启动点以进行测试(因此连接性不是问题):

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.");
        }
    }
}

我找不到MailKit的问题。设置看起来一样。您知道什么可能是问题吗?是bug还是我的设置有问题?

MailKit必须成功发送电子邮件

ASP.NET Core 2.2,MailKit 2.1.3

3 个答案:

答案 0 :(得分:1)

几分钟前,我只是部分解决一个非常相似的问题;我学到的东西可能对您有帮助。

在我有这种情况的情况下,MailKit有可靠的工作代码可以从目标为NET Core 2.1的应用程序发送。

最近,我更新了所有的Nu​​get软件包,认为这样做是个好习惯。然后,我后来发现我正在工作的SMTP发送代码突然停止工作,并且正在报告与您遇到的错误相同的错误。

在这种情况下,我检查了smtp服务器,防火墙等各种问题,直到我想起了Nuget更新,开始尝试并最终将MailKit降级为2.0.0。 MailKit的版本降级后,发送代码再次开始工作。

我没有查明故障的确切位置和机制,但是已经有了一定的信心,即(在我正在研究的情况下)所使用的MailKit版本直接涉及其中。今天,它已恢复到可以对MailKit 2.0.0进行降级的工作,并且需要做更多的研究才能使它超出此状态。

答案 1 :(得分:0)

部分问题是SMTP端口587不支持SSL。您需要传递false作为useSsl参数。

端口587使用STARTTLS(MailKit将自动使用它)。

如果需要更多控制,请使用采用SecureSocketOptions枚举值的Connect [Async]方法。

使用带有布尔参数的Connect [Async]方法时,true等效于SecureSocketOptions.SslOnCOnnectfalse等效于SecureSOcketOptions.StartTlsWhenAvailable

但是,问题的主要部分似乎是MailKit较新的Socket连接代码中的错误。从MailKit 2.1.x开始,MailKit开始使用Socket.BeginConnect (string host, int port, ...)而不是Socket.Connect (IPAddress address, int port),从而允许基础.NET实现将主机名解析为适当的IPAddress本身并允许取消。不幸的是,这似乎对某些人来说是坏事(为什么?)。

我再次更新了MailKit,以返回将主机名解析为IP地址列表(使用Dns.GetHostAddresses[Async])并遍历每个IPAddress直到能够成功连接。此修补程序将在MailKit> = 2.1.4中提供。在此之前,您可以通过https://www.myget.org/feed/mimekit/package/nuget/MailKit

上的myget提要进行安装。

答案 2 :(得分:0)

我更改了连接到该代码的代码:

  

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

因此很干净,将在可用时使用Tls。证书验证已关闭。它在MailKit 2.0.7中运行完美,但在2.1.3中相同的代码继续引发问题说明中的错误。不知道为什么。可能是所有最新版本(2.1.x)都有错误吗?