Spring Boot集成Gmail SMTP发送邮件遇SSL握手协议错误求助
问题描述
本地Spring Boot应用基于smtp.gmail.com实现邮件发送时,出现SSL握手错误,日志如下:
2022-09-11 12:17:31,499 [DEBUG] from org.springframework.web.servlet.DispatcherServlet in http-nio-1995-exec-1 - Failed to complete request: org.springframework.mail.MailSendException: Mail server connection failed; nested exception is javax.mail.MessagingException: Can't send command to SMTP host; nested exception is: javax.net.ssl.SSLHandshakeException: No appropriate protocol (protocol is disabled or cipher suites are inappropriate). Failed messages: javax.mail.MessagingException: Can't send command to SMTP host; nested exception is: javax.net.ssl.SSLHandshakeException: No appropriate protocol (protocol is disabled or cipher suites are inappropriate); message exceptions (1) are: Failed message 1: javax.mail.MessagingException: Can't send command to SMTP host; nested exception is: javax.net.ssl.SSLHandshakeException: No appropriate protocol (protocol is disabled or cipher suites are inappropriate) 2022-09-11 12:17:31,500 [DEBUG] from org.springframework.security.web.context.SecurityContextPersistenceFilter in http-nio-1995-exec-1 - Cleared SecurityContextHolder to complete request 2022-09-11 12:17:31,501 [ERROR] from org.apache.catalina.core.ContainerBase.[Tomcat-1].[localhost].[/].[dispatcherServlet] in http-nio-1995-exec-1 - Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.mail.MailSendException: Mail server connection failed; nested exception is javax.mail.MessagingException: Can't send command to SMTP host; nested exception is: javax.net.ssl.SSLHandshakeException: No appropriate protocol (protocol is disabled or cipher suites are inappropriate). Failed messages: javax.mail.MessagingException: Can't send command to SMTP host; nested exception is: javax.net.ssl.SSLHandshakeException: No appropriate protocol (protocol is disabled or cipher suites are inappropriate); message exceptions (1) are: Failed message 1: javax.mail.MessagingException: Can't send command to SMTP host; nested exception is: javax.net.ssl.SSLHandshakeException: No appropriate protocol (protocol is disabled or cipher suites are inappropriate)] with root cause javax.net.ssl.SSLHandshakeException: No appropriate protocol (protocol is disabled or cipher suites are inappropriate) at java.base/sun.security.ssl.HandshakeContext.<init>(HandshakeContext.java:172)
当前邮件配置类:
@Configuration public class MailConfig { @Bean public JavaMailSender getJavaMailSender() { JavaMailSenderImpl mailSender = new JavaMailSenderImpl(); mailSender.setHost("smtp.gmail.com"); mailSender.setPort(587); mailSender.setUsername(MyConstants.MY_EMAIL); mailSender.setPassword(MyConstants.MY_PASSWORD); Properties props = mailSender.getJavaMailProperties(); props.put("mail.transport.protocol", "smtp"); props.put("mail.smtp.auth", "true"); props.put("mail.smtp.starttls.enable", "true"); props.put("mail.debug", "true"); return mailSender; } }
常量类:
public class MyConstants { public static final String MY_EMAIL = "myMail@gmail.com"; public static final String MY_PASSWORD = "passwordGeneretedFromGmail"; public static final String FRIEND_EMAIL = "senderToMail@gmail.com"; }
控制器类:
@Controller @RequestMapping("/api") public class SimpleEmailExampleController { @Autowired public JavaMailSender emailSender; @ResponseBody @RequestMapping("/sendSimpleEmail") public String sendSimpleEmail() { // Create a Simple MailMessage. SimpleMailMessage message = new SimpleMailMessage(); message.setTo(MyConstants.FRIEND_EMAIL); message.setSubject("Test Simple Email"); message.setText("Hello, Im testing Simple Email"); // Send Message! this.emailSender.send(message); return "Email Sent!"; } }
配置逻辑无明显问题,寻求解决该错误的配置调整方案。
解决方案
该错误源于JDK默认禁用了部分旧版TLS协议,而Gmail SMTP在STARTTLS模式下需要兼容的协议支持。可通过以下方式解决:
方法1:在邮件配置中指定SSL协议
修改MailConfig,添加指定TLSv1.2协议的配置项,确保握手时使用兼容协议:
@Configuration public class MailConfig { @Bean public JavaMailSender getJavaMailSender() { JavaMailSenderImpl mailSender = new JavaMailSenderImpl(); mailSender.setHost("smtp.gmail.com"); mailSender.setPort(587); mailSender.setUsername(MyConstants.MY_EMAIL); mailSender.setPassword(MyConstants.MY_PASSWORD); Properties props = mailSender.getJavaMailProperties(); props.put("mail.transport.protocol", "smtp"); props.put("mail.smtp.auth", "true"); props.put("mail.smtp.starttls.enable", "true"); props.put("mail.debug", "true"); // 添加以下两行配置,强制指定使用TLSv1.2协议 props.put("mail.smtp.ssl.protocols", "TLSv1.2"); props.put("mail.smtp.starttls.required", "true"); return mailSender; } }
方法2:修改JDK全局安全配置
找到JDK安装目录下的jre/lib/security/java.security文件,调整禁用协议列表:
- 定位
jdk.tls.disabledAlgorithms配置行,移除TLSv1.2(若存在),确保仅禁用不兼容的旧协议,示例:jdk.tls.disabledAlgorithms=SSLv3, TLSv1, TLSv1.1, RC4, DES, MD5withRSA
注意:此修改会影响所有使用该JDK的应用,适合全局需要调整协议的场景。
方法3:通过JVM启动参数指定协议
在应用启动时添加JVM参数,强制客户端使用TLSv1.2:
-Djdk.tls.client.protocols=TLSv1.2
或同时指定HTTPS协议:
-Dhttps.protocols=TLSv1.2 -Djdk.tls.client.protocols=TLSv1.2
额外检查项
- 确认Gmail账号已开启两步验证,且使用的是正确生成的应用专用密码,而非账号原密码。
- 检查本地网络是否能正常访问
smtp.gmail.com的587端口,避免防火墙、代理拦截连接。
内容的提问来源于stack exchange,提问作者Hicham ALAGAD
相关产品推荐
相关产品推荐

