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

Spring Boot 2.7.x升级至3.1.x后邮件发送失败问题求助

Spring Boot 3.1.1(Java 17)邮件发送TLS连接身份验证失败问题

将服务从Spring Boot 2.7.x迁移至3.1.1(基于Java 17、spring-boot-starter-parent v3.1.1)后,出现此前未发生的邮件发送错误,回退旧版本可正常发送,已排除SMTP服务器证书本身的问题。具体报错如下:

2023-08-18 11:31:05.560 ERROR 78703 --- [ntContainer#0-1] c.d.s.portal.service.EmailService        : An error has occurred while sending the mail 

org.springframework.mail.MailSendException: Mail server connection failed. Failed messages: jakarta.mail.MessagingException: Could not convert socket to TLS;
  nested exception is:
    java.io.IOException: Can't verify identity of server: my-smtp-server
Caused by: jakarta.mail.MessagingException: Could not convert socket to TLS
    at com.sun.mail.smtp.SMTPTransport.startTLS(SMTPTransport.java:2189)
    at com.sun.mail.smtp.SMTPTransport.protocolConnect(SMTPTransport.java:766)
    at jakarta.mail.Service.connect(Service.java:342)
    at org.springframework.mail.javamail.JavaMailSenderImpl.connectTransport(JavaMailSenderImpl.java:518)
    at org.springframework.mail.javamail.JavaMailSenderImpl.doSend(JavaMailSenderImpl.java:437)
    ... 46 common frames omitted
Caused by: java.io.IOException: Can't verify identity of server: my-smtp-server
    at com.sun.mail.util.SocketFetcher.checkServerIdentity(SocketFetcher.java:699)
    at com.sun.mail.util.SocketFetcher.configureSSLSocket(SocketFetcher.java:636)
    at com.sun.mail.util.SocketFetcher.startTLS(SocketFetcher.java:555)
    at com.sun.mail.smtp.SMTPTransport.startTLS(SMTPTransport.java:2184)
    ... 50 common frames omitted

已尝试替换org.springframework.mail.javamail.JavaMailSender为org.springframework.mail.MailSender,问题依旧;且另一服务升级Spring Boot 3.x后也出现SSL相关连接问题,怀疑两者存在关联。

原因分析

  1. Jakarta Mail规范切换:Spring Boot 3.x全面迁移到Jakarta EE规范,邮件模块从原javax.mail改为jakarta.mail,对应的com.sun.mail:jakarta.mail客户端对SSL身份验证的默认策略更严格。
  2. Java 17 SSL规则收紧:Java 17强化了SSL握手时的主机名与证书匹配检查,旧版本Spring Boot依赖的Java环境可能存在宽松的兼容逻辑,升级后触发严格验证。
  3. 自动配置参数覆盖:Spring Boot 3.x的邮件自动配置逻辑调整,可能覆盖了原有自定义的SSL相关参数,导致身份验证逻辑未按预期执行。

解决办法

1. 修正主机名与证书的匹配关系

确认SMTP服务器证书的Subject Alternative Name (SAN)或Common Name (CN)字段,是否包含配置中使用的my-smtp-server主机名。若不匹配,要么修改配置使用证书中已存在的主机名,要么更新服务器证书添加该主机名。

2. 调整Jakarta Mail SSL验证参数

在Spring Boot配置文件中添加以下参数,灵活调整验证策略:

application.properties:

# 强制启用TLS连接
spring.mail.properties.mail.smtp.starttls.enable=true
# 指定信任的SMTP主机名(生产环境推荐)
spring.mail.properties.mail.smtp.ssl.trust=my-smtp-server
# 临时关闭服务器身份验证(仅用于测试,生产不建议)
# spring.mail.properties.mail.smtp.ssl.checkserveridentity=false

application.yml:

spring:
  mail:
    properties:
      mail:
        smtp:
          starttls:
            enable: true
          ssl:
            trust: my-smtp-server
            # checkserveridentity: false

3. 导入证书到JVM信任库

如果SMTP使用自签名证书或不在默认信任链中的证书,将证书导入JVM的系统信任库:

# 替换证书路径和自定义别名
keytool -import -alias my-smtp-cert -file /path/to/your-smtp-cert.crt -keystore $JAVA_HOME/lib/security/cacerts

默认信任库密码为changeit,导入完成后重启应用即可。

4. 手动配置JavaMailSender

若自动配置不符合需求,手动创建JavaMailSender Bean确保参数生效:

@Bean
public JavaMailSender javaMailSender() {
    JavaMailSenderImpl mailSender = new JavaMailSenderImpl();
    mailSender.setHost("my-smtp-server");
    mailSender.setPort(587);
    mailSender.setUsername("your-email-username");
    mailSender.setPassword("your-email-password");

    Properties props = mailSender.getJavaMailProperties();
    props.put("mail.smtp.starttls.enable", "true");
    props.put("mail.smtp.ssl.trust", "my-smtp-server");
    // 测试场景下可临时关闭身份验证
    // props.put("mail.smtp.ssl.checkserveridentity", "false");

    return mailSender;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 07:11:00