You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET 6升级后Amazon Linux EC2发送邮件遇SSL_ERROR_SSL问题

.NET 6.0在Amazon Linux上发送邮件SSL握手失败问题

问题场景

  • 代码在Windows开发环境(.NET 6.0)运行正常,部署到Amazon Linux EC2实例后出现SSL握手失败错误
  • 相同代码在.NET 3.1的Amazon Linux环境可正常运行,升级到6.0后出现问题
  • 错误日志如下:
Attempting to send email...
The email was not sent.
Error message: Authentication failed, see inner exception.
System.Security.Authentication.AuthenticationException: Authentication failed, see inner exception.
 ---> Interop+OpenSsl+SslException: SSL Handshake failed with OpenSSL error - SSL_ERROR_SSL.
 ---> Interop+Crypto+OpenSslCryptographicException: error:14094438:SSL routines:ssl3_read_bytes:tlsv1 alert internal error
   --- End of inner exception stack trace ---
   at Interop.OpenSsl.DoSslHandshake(SafeSslHandle context, ReadOnlySpan`1 input, Byte[]& sendBuf, Int32& sendCount)
   at System.Net.Security.SslStreamPal.HandshakeInternal(SafeFreeCredentials credential, SafeDeleteSslContext& context, ReadOnlySpan`1 inputBuffer, Byte[]& outputBuffer, SslAuthenticationOptions sslAuthenticationOptions)
   --- End of inner exception stack trace ---
   at System.Net.Security.SslStream.ForceAuthenticationAsync[TIOAdapter](TIOAdapter adapter, Boolean receiveFirst, Byte[] reAuthenticationData, Boolean isApm)
   at System.Net.Security.SslStream.AuthenticateAsClient(SslClientAuthenticationOptions sslClientAuthenticationOptions)
   at System.Net.Security.SslStream.AuthenticateAsClient(String targetHost, X509CertificateCollection clientCertificates, SslProtocols enabledSslProtocols, Boolean checkCertificateRevocation)
   at System.Net.TlsStream.AuthenticateAsClient()
   at System.Net.Mail.SmtpConnection.GetConnection(String host, Int32 port)
   at System.Net.Mail.SmtpTransport.GetConnection(String host, Int32 port)
   at System.Net.Mail.SmtpClient.GetConnection()
   at System.Net.Mail.SmtpClient.Send(MailMessage message)
   at EmailTester.EmailSender.SendEmail()

涉事代码

public class EmailSender
{
    private readonly SmtpOption _smtpOption;
    public EmailSender(IConfiguration configuration)
    {
        _smtpOption = configuration.GetSection("Smtp").Get<SmtpOption>();
    }

    public void SendEmail()
    {

        string defaultBody =
            "<h1>Amazon SES Test</h1>" +
            "<p>This email was sent through the " +
            "<a href='https://aws.amazon.com/ses'>Amazon SES</a> SMTP interface " +
            "using the .NET System.Net.Mail library.</p>";

        // Create and build a new MailMessage object
        MailMessage message = new()
        {
            IsBodyHtml = true,
            From = new MailAddress(_smtpOption.From, _smtpOption.FromName),
            Subject = _smtpOption.Subject,
            Body = _smtpOption.Body ?? defaultBody
        };

        message.To.Add(new MailAddress(_smtpOption.To));

        using (var client = new SmtpClient(_smtpOption.Host, _smtpOption.Port))
        {
            // Pass SMTP credentials
            client.Credentials =
                new NetworkCredential(_smtpOption.Username, _smtpOption.Password);

            // Enable SSL encryption
            client.EnableSsl = _smtpOption.EnableSsl;

            // Try to send the message. Show status in console.
            try
            {
                Console.WriteLine("Attempting to send email...");
                client.Send(message);
                Console.WriteLine("Email sent!");
            }
            catch (Exception ex)
            {
                Console.WriteLine("The email was not sent.");
                Console.WriteLine("Error message: " + ex.Message);
                Console.WriteLine(ex);
            }
        }
    }
}

public class SmtpOption
{
    public string From { get; set; }
    public string FromName { get; set; }
    public string To { get; set; }
    public string Host { get; set; }
    public int Port { get; set; }
    public string Username { get; set; }
    public string Password { get; set; }
    public string Subject { get; set; }
    public string Body { get; set; }
    public bool EnableSsl { get; set; }
}

解决方案:调整Amazon Linux系统级加密策略

Amazon Linux基于RHEL,使用crypto-policies管理系统级加密规则,无需直接修改openssl.cnf,操作步骤如下:

  1. 查看当前加密策略
    执行以下命令查看当前系统生效的加密策略:

    update-crypto-policies --show
    
  2. 切换到兼容型加密策略
    .NET 5+默认收紧了TLS密码套件,而Amazon SES SMTP可能依赖部分旧套件,可切换到LEGACY策略(包含更多兼容旧服务的套件):

    sudo update-crypto-policies --set LEGACY
    
  3. 使策略生效
    策略变更后需要重启系统或应用服务,确保新策略生效:

    sudo reboot
    

备选方案:代码层面调整(无需系统变更)

如果不想修改系统级策略,也可以在代码中指定兼容的TLS版本和套件:

// 在创建SmtpClient前添加以下配置
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 | SecurityProtocolType.Tls13;
// 强制使用旧版Socket处理(部分场景下可解决握手问题)
AppContext.SetSwitch("System.Net.UseSocketsHttpHandler", false);

内容的提问来源于stack exchange,提问作者Sunil Shahi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 02:57:52