以下是从MailKit FAQ中复制并粘贴出来的内容:
问:当我尝试连接时,为什么会出现"MailKit.Security.SslHandshakeException: An error occurred while attempting to establish an SSL or TLS connection."
?
当您遇到具有该错误消息的异常时,通常意味着您遇到了以下情况之一:
1. 邮件服务器不支持在指定端口上使用SSL。
使用邮件服务器进行SSL/TLS加密有两种不同的方式。
第一种方式是在连接到SMTP、POP3或IMAP服务器时立即启用SSL/TLS加密。这种方法需要一个“SSL端口”,因为协议定义的标准端口是用于纯文本通信的。
第二种方式是通过一个可选的STARTTLS
命令(对于POP3而言是STLS
)来实现。邮件服务器可以选择性地支持它。
下面是MailKit支持的协议以及标准纯文本端口(这些端口不支持任何SSL/TLS加密,或者只支持通过STARTTLS
命令扩展)和需要在成功连接到远程主机后立即进行SSL/TLS加密的SSL端口的表格。
|Protocol|Standard Port|SSL Port|
|:------:|:-----------:|:------:|
| SMTP | 25 or 587 | 465 |
| POP3 | 110 | 995 |
| IMAP | 143 | 993 |
使用正确的SecureSocketOptions
连接到端口非常重要。
如果您要连接上面的标准端口之一,则需要使用SecureSocketOptions.None
、
SecureSocketOptions.StartTls
或SecureSocketOptions.StartTlsWhenAvailable
。
如果您要连接SSL端口之一,则需要使用SecureSocketOptions.SslOnConnect
。
您还可以尝试使用SecureSocketOptions.Auto
,它通过比较指定端口与上表中的端口来选择要使用的适当选项。
2. 您连接的邮件服务器使用过期(或不受信任)的SSL证书。
通常情况下,邮件服务器会使用自签名证书,而不是使用由可信证书颁发机构签名的证书。另一个潜在的问题是当本地安装的反病毒软件替换证书以扫描Web流量中的病毒时。
当您的系统无法验证邮件服务器的证书,因为它没有被已知和信任的证书颁发机构签名时,将会出现上述错误。
您可以通过提供自定义的RemoteCertificateValidationCallback并将其设置为客户端的ServerCertificateValidationCallback属性来解决此问题。
在最简单的示例中,您可以像这样做(虽然我强烈建议在生产中不要这样做):
using (var client = new SmtpClient ()) {
client.ServerCertificateValidationCallback = (s,c,h,e) => true;
client.Connect (hostName, port, SecureSocketOptions.Auto);
}
通常情况下,您可能希望将证书的Thumbprint属性与已在先前日期验证的已知值进行比较。
您还可以使用此回调提示用户(就像您可能看到Web浏览器执行的那样)是否应信任证书。
3. 证书颁发机构的CRL服务器暂时无法访问其中一张或多张证书。
大多数证书颁发机构都很擅长保持其CRL和/或OCSP服务器全天候可用,但偶尔由于网络问题等其他原因,它们也可能会出现故障或无法访问。当发生这种情况时,检查链中一个或多个证书的吊销状态变得不可能。
要忽略吊销检查,您可以在连接之前将IMAP、POP3或SMTP客户端的CheckCertificateRevocation属性设置为false
:
using (var client = new SmtpClient ()) {
client.CheckCertificateRevocation = false;
client.Connect (hostName, port, SecureSocketOptions.Auto);
}
4. 服务器不支持客户端配置的相同SSL/TLS协议集。
MailKit试图跟上最新的安全建议,因此正在持续从默认配置中删除已不再被视为安全的旧版SSL和TLS协议。这通常意味着MailKit的SMTP、POP3和IMAP客户端无法连接仍在使用旧版SSL和TLS协议的服务器。目前,默认情况下不支持的SSL和TLS协议有:SSL v2.0、SSL v3.0和TLS v1.0。
您可以通过设置SMTP、POP3或IMAP客户端的SslProtocols属性值来覆盖MailKit的默认支持的
SSL和TLS协议集合。
例如:
using (var client = new SmtpClient ()) {
client.SslProtocols = SslProtocols.Ssl3 | SslProtocols.Tls | SslProtocols.Tls11 | SslProtocols.Tls12 | SslProtocols.Tls13;
client.Connect ("smtp.gmail.com", 465, true);
}