MailKit -SmtpClient Connect方法冻结



我正在开发一个Xamarin Android应用程序,在某个时候(成功交易之后(该应用必须向客户发送信息电子邮件。创建模仿实例以及实际发送的整个过程都是通过任务完成的。该消息(在大多数情况下包含链接的图像(是完美创建的,但是一旦我称之为实际发送该呼叫的执行冻结的方法,整个任务仍处于活动状态,但在此时冻结。

这是我的SendMail方法,在MimeMessage参数旁边,它接收了MailAccount类,其中包含有关SMTP计算机,端口和发送者帐户的信息。一旦对MailKit的SmtpClient实例的Connect方法进行呼叫,我就会描述"冷冻"行为。我尝试了很多次 - 甚至没有一旦代码继续超过该行。

private static int SendMail(MailAccount account, MimeMessage message)
{
    using (var client = new SmtpClient())
    {
        try
        {
            client.Connect(account.Server, account.Port, false);
        }
        catch (SmtpCommandException)
        {
            return -1;
        }
        catch (SmtpProtocolException)
        {
            return -2;
        }
        client.AuthenticationMechanisms.Remove("XOAUTH2");
        if (client.Capabilities.HasFlag(SmtpCapabilities.Authentication))
        {
            try
            {
                client.Authenticate(account.User, Decrypt(account.Pass));
            }
            catch (AuthenticationException)
            {
                return -3;
            }
            catch (SmtpCommandException)
            {
                return -1;
            }
            catch (SmtpProtocolException)
            {
                return -2;
            }
        }
        int status = 1; //assume success
        try
        {
            client.Send(message);
        }
        catch (SmtpCommandException ex)
        {
            switch (ex.ErrorCode)
            {
                case SmtpErrorCode.MessageNotAccepted:
                    status = -6;
                    break;
                case SmtpErrorCode.SenderNotAccepted:
                    status = -5;
                    break;
                case SmtpErrorCode.RecipientNotAccepted:
                    status = -4;
                    break;
                default:
                    status = -7;
                    break;
            }
        }
        client.Disconnect(true);
        return status;
    }
}

通常,呼叫client.Connect时挂起,建议您尝试与之连接的主机或端口是不可用的。检查主机和端口是否正确。

如果它们正确正确,请确保您使用的是最新版本的MailKit作为一些较旧版本的Socket.BeginConnect (string, int ...),在启用IPv6的OS上,有时会尝试通过IPv6使用IPv4并挂起在某些情况下(例如使用像Avast这样的病毒扫描仪(。

MailKit的新版本(> = 2.1.4和Pre-2.0版本(对远程主机进行DNS查找,并手动指定实例化套接字时要使用的正确地址系列(IPv4 vs ipv6(,以避免这种情况问题。

悬挂也可能是由SSL/TLS证书撤销检查与无反应证书授权机构引起的。您可以使用以下代码段禁用证书撤销检查:

client.CheckCertificateRevocation = false;

只需确保在拨打Connect之前设置该属性

通过在Visual Studio中创建新的控制台应用程序并将其粘贴在以下代码中并检查其有效的方法可能值得测试对SMTP服务器的访问:

using System;
using System.Threading;
using System.Threading.Tasks;
using MailKit;
using MailKit.Net.Smtp;
namespace ConsoleApp {
    public class Program
    {
        static void Main (string[] args)
        {
            using (var client = new SmtpClient (new ProtocolLogger ("smtp.log"))) {
                using (var cts = new CancellationTokenSource (60000)) {
                    try {
                        client.Connect ("your-host.com", 25, false, cts.Token);
                        client.Disconnect (true);
                    } catch (Exception ex) {
                        Console.WriteLine ("Error connecting: {0}", ex.Message);
                        Console.WriteLine (ex.StackTrace);
                    }
                }
            }
        }
    }
}

知道您的Android应用程序是否在端口465(useSsl = true(上连接到smtp.gmail.com的问题也很有趣。

最新更新