MailKit使用LetsEncrypt SSL证书获取SslHandshakeException

时间:2020-05-19 14:51:34

标签: centos postfix-mta mailkit dovecot

我有一个服务器(Centos 7)设置要用作邮件服务器。使用postfix / dovecot / opendkim / opendmarc .. 它可以正常工作,例如,用户可以使用gmail连接电子邮件。能够发送和接收邮件。

此外,当我使用MailKit并从家用PC测试我的.NET Core应用程序时,MailKit可以正常连接,并且电子邮件已发送。

但是,当我将应用程序部署到服务器时,MailKit无法连接。

如果我查看日志,会看到以下内容

postfix/submission/smtpd[4486]: match_hostname: unknown ~? 127.0.0.1/32
postfix/submission/smtpd[4486]: match_hostaddr: MY_SERVER_IP ~? 127.0.0.1/32
postfix/submission/smtpd[4486]: match_hostname: unknown ~? MY_SERVER_IP/32
postfix/submission/smtpd[4486]: match_hostaddr: MY_SERVER_IP  ~? MY_SERVER_IP/32
postfix/submission/smtpd[4486]: lost connection after STARTTLS from unknown[MY_SERVER_IP]

但是,如果我在日志中看起来更高一些,

Anonymous TLS connection established from unknown[MY_SERVER_IP]: TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)

我的MailKit(可以在服务器外部正常运行):

using (SmtpClient emailClient = new SmtpClient())
{
    await emailClient.ConnectAsync(emailConfiguration.SmtpServer, emailConfiguration.SmtpPort, SecureSocketOptions.StartTls);
    emailClient.AuthenticationMechanisms.Remove("XOAUTH2");  

    await emailClient.AuthenticateAsync(emailConfiguration.SmtpUsername, emailConfiguration.SmtpPassword);
    await emailClient.SendAsync(message);

    await emailClient.DisconnectAsync(true);
}

编辑: MailKit的异常(证书是正确的,不是自签名的):

MailKit.Security.SslHandshakeException: An error occurred while attempting to establish an SSL or TLS connection.
May 19 16:07:37 domain.com NETCoreApp[4452]: The server's SSL certificate could not be validated for the following reasons:
May 19 16:07:37 domain.com NETCoreApp[4452]: • The server certificate has the following errors:
May 19 16:07:37 domain.com NETCoreApp[4452]: • unable to get certificate CRL
May 19 16:07:37 domain.com NETCoreApp[4452]: • The root certificate has the following errors:
May 19 16:07:37 domain.com NETCoreApp[4452]: • unable to get certificate CRL
May 19 16:07:37 domain.com NETCoreApp[4452]: • unable to get local issuer certificate
May 19 16:07:37 domain.com NETCoreApp[4452]: ---> System.Security.Authentication.AuthenticationException: The remote certificate is invalid according to the validation procedure.

3 个答案:

答案 0 :(得分:0)

unable to get certificate CRL错误听起来像SslStream无法获取CRL,可能是由于某些原因CRL服务器无法访问。

您可以尝试在ConnectAsync之前添加emailClient.CheckCertificateRevocation = false;来检查是否是问题所在。

另一个错误unable to get local issuer certificate,可能是因为运行MailKit的服务器的X509Store中没有根CA证书,而家用PC却有。

更新:

问题在于LetsEncrypt SSL证书不包含CRL位置,这意味着证书吊销检查将失败。

要绕过此操作,您需要在连接之前设置client.CheckCertificateRevocation = false;

答案 1 :(得分:0)

我找到了一个可行的答案,但这不是我的首选方法,因为我希望能够使用MailKit不仅仅是我自己的服务器(使其可以在应用程序内部进行配置)

我之所以提出解决方案,是因为我认为这与一些内部流量出现问题有关。

通过使用 System.Net.Mail 中的旧 SmtpClient ,我可以使用 DefaultCredentials

using (SmtpClient client = new SmtpClient("127.0.0.1"))
{
    client.UseDefaultCredentials = true;

    MailAddress from = new MailAddress(emailMessage.FromAddress.Address, emailMessage.FromAddress.Name);

    foreach (IEmailAddress emailAddress in emailMessage.ToAddresses)
    {
        MailAddress to = new MailAddress(emailAddress.Address, emailAddress.Name);

        MailMessage email = new MailMessage(from, to)
        {
            Subject = emailMessage.Subject,
            Body = emailMessage.Content
        };

        await client.SendMailAsync(email);
    }
}

答案 2 :(得分:0)

我在 ubuntu 20.04 和 .NET core 3.1 上有同样的问题

经过 3 个小时的反复试验,我终于找到了解决方案
我刚刚忽略了 Certificate Validation CallBack

using var client = new SmtpClient(new ProtocolLogger("smtp.log"));
client.CheckCertificateRevocation = false;
client.ServerCertificateValidationCallback = (sender, certificate, chain, errors) => true;
client.Connect("your.smtp.host", 587, SecureSocketOptions.StartTls);

我希望这会有所帮助:)