c# - SslHandshakeException : An error occurred while attempting to establish an SSL or TLS connection

标签 c# ssl imap xunit mailkit

我正在尝试使用 imap 访问 gmail 电子邮件,并且代码在 ssl 握手时失败,而没有显示任何错误。如果有人能帮忙解决这个问题,我真的很感激。我使用 xunit、.NET Core 2.1 构建了它。我正在使用 MailKit Nuget

   public GMailHandler(string mailServer, int port, bool ssl, string login, string password)

          //mailServer = imap.gmail.com
          //port = 993
          //ssl = true

          {

                  if (ssl)

                         Client.Connect(mailServer, port);

                  else

                         Client.Connect(mailServer, port);

                  Client.Authenticate(login, password);

                  Client.Inbox.Open(FolderAccess.ReadOnly);

          }

最佳答案

这是来自 MailKit FAQ 的复制和粘贴:

问:为什么我会得到 "MailKit.Security.SslHandshakeException: An error occurred while attempting to establish an SSL or TLS connection."当我尝试连接?

当您收到带有该错误消息的异常时,通常意味着您遇到了
以下场景之一:

1. 邮件服务器在指定端口上不支持 SSL。

有 2 种不同的方法可以对邮件服务器使用 SSL/TLS 加密。

第一种方法是在连接到服务器后立即启用 SSL/TLS 加密
SMTP、POP3 或 IMAP 服务器。此方法需要“SSL 端口”,因为标准
为协议(protocol)定义的端口用于纯文本通信。

第二种方式是通过 STARTTLS可选的命令(又名 STLS 用于 POP3)
服务器支持。

下面是 MailKit 支持的协议(protocol)和标准纯文本端口的表格
(它们要么根本不支持任何 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.StartTlsSecureSocketOptions.StartTlsWhenAvailable .

如果要连接到 SSL 端口之一,则需要使用 SecureSocketOptions.SslOnConnect .

您也可以尝试使用 SecureSocketOptions.Auto哪个通过选择适当使用的选项来起作用
通过将指定端口与上表中的端口进行比较。

2. 您要连接的邮件服务器正在使用过期(或不可信)的 SSL 证书。

很多时候,邮件服务器会使用自签名证书,而不是使用
已由受信任的证书颁发机构签名。另一个潜在的陷阱是在本地
安装的防病毒软件会替换证书以扫描 Web 流量中的病毒。

当您的系统因为未签名而无法验证邮件服务器的证书时
通过已知且受信任的证书颁发机构,将发生上述错误。

您可以通过提供自定义 RemoteCertificateValidationCallback 来解决此问题。
并将其设置在客户端的 ServerCertificateValidationCallback
属性(property)。

在最简单的例子中,你可以做这样的事情(尽管我强烈建议在
生产用途):

using (var client = new SmtpClient ()) {
    client.ServerCertificateValidationCallback = (s,c,h,e) => true;

    client.Connect (hostName, port, SecureSocketOptions.Auto);

    // ...
}

您很可能想要比较证书的 Thumbprint
属性(property)到您在之前的日期验证过的已知值(value)。

您还可以使用此回调来提示用户(就像您可能已经看到网络浏览器所做的那样)
至于证书是否应该被信任。

3. 链中一个或多个证书的证书颁发机构 CRL 服务器暂时不可用。

大多数证书颁发机构可能非常擅长保持他们的 CRL 和/或 OCSP 服务器 24/7,但偶尔
由于您和服务器之间的其他网络问题,它们确实会关闭或无法访问。当这件事发生时,
无法检查链中一个或多个证书的吊销状态。

要忽略吊销检查,您可以设置
CheckCertificateRevocation
IMAP、POP3 或 SMTP 客户端的属性为 false连接之前:

using (var client = new SmtpClient ()) {
    client.CheckCertificateRevocation = false;

    client.Connect (hostName, port, SecureSocketOptions.Auto);

    // ...
}

4. 服务器不支持客户端配置使用的同一组 SSL/TLS 协议(protocol)。

MailKit 试图跟上最新的安全建议,因此不断删除旧的 SSL 和 TLS
从默认配置不再被认为是安全的协议(protocol)。这通常意味着 MailKit 的 SMTP,
POP3 和 IMAP 客户端将无法连接到仍在使用旧 SSL 和 TLS 协议(protocol)的服务器。目前,
默认不支持的 SSL 和 TLS 协议(protocol)有:SSL v2.0、SSL v3.0 和 TLS v1.0。

您可以覆盖 MailKit 的默认支持集
SSL and TLS protocols
通过设置 SslProtocols 的值
SMTP、POP3 或 IMAP 客户端上的属性。

例如:

using (var client = new SmtpClient ()) {
    // Allow SSLv3.0 and all versions of TLS
    client.SslProtocols = SslProtocols.Ssl3 | SslProtocols.Tls | SslProtocols.Tls11 | SslProtocols.Tls12 | SslProtocols.Tls13;

    client.Connect ("smtp.gmail.com", 465, true);

    // ...
}

关于c# - SslHandshakeException : An error occurred while attempting to establish an SSL or TLS connection,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59026301/

相关文章:

c# - 如何在命令行上将运行时参数传递给 dotnet test?

c# - 如何在标签中创建图形对象

c# - Selenium WebDriver - Chrome - C# - 无法以隐身模式启动 selenium 浏览器作为最大化浏览器

ssl - 如何将域与 EC2 和 SSL 链接

php - SNI 错误 Apache2 日志

php - 使用smtp发送邮件并将其反射(reflect)到电子邮件服务器的 "Sent"文件夹中

python - 是否有一个工具包可以为远程 IMAP 服务器提供基于 Web 的 API(xmlrpc、REST 等)?

c# - 从 XDocument 中获取后代

security - SSL - 如果有人拥有公共(public)证书,有人可以进行中间人攻击吗?

java - Imap 获取时出现异常