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相关连接问题,怀疑两者存在关联。
原因分析
- Jakarta Mail规范切换:Spring Boot 3.x全面迁移到Jakarta EE规范,邮件模块从原
javax.mail改为jakarta.mail,对应的com.sun.mail:jakarta.mail客户端对SSL身份验证的默认策略更严格。 - Java 17 SSL规则收紧:Java 17强化了SSL握手时的主机名与证书匹配检查,旧版本Spring Boot依赖的Java环境可能存在宽松的兼容逻辑,升级后触发严格验证。
- 自动配置参数覆盖: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
相关产品推荐
相关产品推荐

