MailKit 使用 LetsEncrypt SSL 证书获取 SslHandshakeException
MailKit gets an SslHandshakeException with LetsEncrypt SSL certificates
我有一个服务器 (Centos 7) 设置用作邮件服务器。使用 postfix/dovecot/opendkim/opendmarc..
它可以正常工作,例如,用户可以使用 gmail 连接他们的电子邮件。能够收发邮件。
另外,当我使用 MailKit 并从我的家用电脑测试我的 .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.
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;
。
我找到了一个可行的答案,但不是我的首选方法,因为我希望能够将 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);
}
}
我在 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);
希望对您有所帮助:)
我有一个服务器 (Centos 7) 设置用作邮件服务器。使用 postfix/dovecot/opendkim/opendmarc.. 它可以正常工作,例如,用户可以使用 gmail 连接他们的电子邮件。能够收发邮件。
另外,当我使用 MailKit 并从我的家用电脑测试我的 .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.
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;
。
我找到了一个可行的答案,但不是我的首选方法,因为我希望能够将 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);
}
}
我在 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);
希望对您有所帮助:)