【问题标题】:Unable to send mail to local SMTP server with TLS无法使用 TLS 将邮件发送到本地 SMTP 服务器
【发布时间】:2017-12-16 15:28:50
【问题描述】:

所以我们有一个本地交换服务器,用作内部服务器的 SMTP 服务器。我正在尝试修复它以使其适用于 TLS,但现在不能。

我有一个分配给 SMTP 和 IIS 角色的通配符证书。但是,当我尝试通过 PowerShell 使用 send-mailmessage 时,我得到了。

Send-MailMessage -SmtpServer mail.domain.com -UseSsl -port 465 -From fromaddress 
-To tomailaddress -Subject test -BodyAsHtml test -Encoding ([System.Text.Encoding]::UTF8)

根据验证程序,远程证书无效。

当我访问 IIS 站点(或使用相同证书的任何其他站点)时,使用的证书对我有效。

那我做错了什么?或者我该如何解决这个问题。

【问题讨论】:

    标签: ssl smtp exchange-server


    【解决方案1】:

    请注意,无法使用 IIS 管理 SMTP 的 SSL 证书。您需要在此处使用 powershell (Enable-ExchangeCertificate) [更多信息here]

    例子:

    启用-ExchangeCertificate -Thumbprint 434AC224C8459924B26521298CE8834C514856AB -服务 SMTP

    通常,您可以使用 Openssl 对此类 TLS 连接(通过端口 465)进行故障排除(有关操作方法,请参阅 here)。

    网址也有一些解决方案,这里就不一一复制了。一般来说,问题是:

    • SSL 证书在远程计算机上不完全受信任(或在密钥库中,这不适用于您的 powershell 测试,但可能适用于您的第 3 方软件)
    • 仍有自签名 SSL 证书与 SMTP 一起使用

    结论: 我认为您仍然在 SMTP 端口上使用自签名 ssl 证书,应该使用上面的命令进行更改。

    【讨论】:

    • 我记得在更新证书时通过powershell将该证书添加到服务中。但我可以看到我们有更多的证书分配给 SMTP 服务。我尝试将它们粘贴到这里,但 stackoverflow 说我习惯了很多字符。从 SMTP 服务中删除其他证书是否安全? FriendlyName:TenantEncryptionCert FriendlyName:wildcard.domain.com FriendlyName:Microsoft Exchange FriendlyName:Exchange 委派联合 FriendlyName:Microsoft Exchange Server Auth Certificate
    • 为了安全起见,您可以使用 MMC 和 SSL 管理单元导出您想要删除的 ssl 证书(使用公钥!!!)。然后你可以导入它们。然而,通常只有一个 SSL 证书分配给一个端口。一个端口不能有多个 ssl 证书。但是可能存在具有不同端口的不同连接器,因此分配了不同的 SSL 证书(因为它们都是不同的 SMTP 连接器)。您可以将输出传递到 Pastbin 并在此处添加链接。从输出中删除任何敏感信息,例如主机名。
    • 更新您的评论:您不应该删除 MS 默认证书“Microsoft Exchange Server Auth Certificate”、“Exchange Delegation Federation”等。如上所述,仅将 SMTP 端口上的错误 ssl 证书替换为正确的证书。您还应该使用 openSSL 检查使用了哪个 ssl 证书,然后确定使用了错误的证书,您需要更换它。
    【解决方案2】:

    我有同样的问题。首先,我使用下面的代码来保存 SMTP 服务器使用的证书的副本(因为我无权访问服务器本身/即使您有权访问,这也显示了正在呈现的服务器,因此可能会标记它是否不同达到您的预期)。我通过 LinqPad5 作为 c# 程序运行它。

    void Main()
    {
        System.Net.ServicePointManager.ServerCertificateValidationCallback = new System.Net.Security.RemoteCertificateValidationCallback(OutputCertificateCallback);
        using (System.Net.Mail.SmtpClient S = new System.Net.Mail.SmtpClient("smtprelay.subdomain.example.com"))
        {
            S.EnableSsl = true;
            using (System.Net.Mail.MailMessage M = new System.Net.Mail.MailMessage("john.bevan@example.com", "john.bevan@example.com", "Test", "Test"))
            {
                try
                {
                    S.Send(M);
                    Console.WriteLine("Sent");
                }
                catch (Exception e)
                {
                    Console.WriteLine("Error {0}", e);
                }
            }
        }
    }
    
    private bool OutputCertificateCallback(object sender, System.Security.Cryptography.X509Certificates.X509Certificate certificate, System.Security.Cryptography.X509Certificates.X509Chain chain, System.Net.Security.SslPolicyErrors sslPolicyErrors)
    {
        Console.WriteLine(certificate);
        System.IO.File.WriteAllBytes(@"C:\Temp\cert.cer", certificate.Export(System.Security.Cryptography.X509Certificates.X509ContentType.Cert));
        var c2 = new System.Security.Cryptography.X509Certificates.X509Certificate2(certificate);
        return c2.Verify();
    }
    

    然后我可以通过查看保存的文件来检查证书:C:\Temp\cert.cer

    检查到期日期以确保证书有效。 如果不是,那就是问题所在。获取新证书。

    检查我的客户受信任的 CA 中的根证书:

    • 启动、运行、MMC
    • 文件 > 添加/删除管理单元 > 证书 > 添加 > 我的用户帐户 > 完成 > 确定
    • 证书 - 当前用户 > 受信任的根证书颁发机构 > 证书
    • 在此列表中搜索根 CA(即与您的证书同名的 CA)

    如果不是,您可能需要安装根 CA、中间 CA 或证书本身(您可以使用刚刚使用上述脚本保存的文件来完成)。

    检查端口是否在防火墙上打开。您可以通过以下 PowerShell 进行测试:

    try {
        $tcp = New-Object -TypeName 'system.net.sockets.tcpclient' -ArgumentList 'smtprelay.subdomain.example.com', 465 
        if ($tcp.Connected) {':)'} else {':('}
    } catch {
        ':('
        $_.Exception.Message
    }
    

    就我而言,以上所有都不足以发现问题。最终我意识到该服务使用了通配符证书(例如*.example.com),但邮件服务器位于子域(例如smtprelay.subdomain.example.com)上,因此不在此证书范围内。在子域上使用通配符(例如*.subdomain.example.com)会起作用;虽然我们只是要求为服务提供一个明确命名的证书(对于smtprelay.subdomain.example.com),包括服务的各个节点的 FQDN 作为主题备用名称,以防我们需要针对特定​​节点进行调试。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-03-28
      • 2013-01-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多