拓冰建站拓冰建站
首页 / 资讯中心 / 正文

彻底解决 Hutool 邮件发送 SSLHandshakeException:六种方案全记录

环境Ubuntu 24.04 LTS | OpenJDK 1.8.0_492 | Hutool 5.3.x | 阿里企业邮箱smtp.mxhichina.com:587一、踩坑现场某天使用Hutool的MailUtil.send()发送邮件时控制台无情地抛出了cn.hutool.extra.mail.MailException: MessagingException: Could not connect to SMTP host: smtp.mxhichina.com, port: 587 Caused by: javax.net.ssl.SSLHandshakeException: No appropriate protocol (protocol is disabled or cipher suites are inappropriate)邮件服务器是阿里企业邮箱端口 587开启 STARTTLS。按说配置无误为何握手失败二、问题根源JDK 1.8.0_492 的java.security文件中jdk.tls.disabledAlgorithms默认禁用了TLSv1和TLSv1.1仅保留 TLSv1.2 及以上。而部分邮件服务商尤其是老实例可能只支持 TLSv1.0 或 TLSv1.1双方无法协商出共同协议于是抛出SSLHandshakeException。三、解决方案概览我尝试了多种手段最终采用方法二修改 java.security成功。但为了给读者更多选择这里整理了六种方案按推荐度排序方案核心操作适用场景风险① 代码指定 TLS 协议通过MailAccount设置mail.smtp.ssl.protocols大部分场景最推荐低② 修改java.security移除jdk.tls.disabledAlgorithms中的 TLSv1/TLSv1.1JVM 全局生效本文采用中影响所有 Java 应用③ 检查 STARTTLS 配置确保端口 587 开启 STARTTLS关闭 SSL 直连配置遗漏导致的连接失败无④ 改用 SSL 直连端口 465切换端口并启用sslEnable服务商支持 465 端口无⑤ 跳过证书验证设置MailSSLSocketFactory信任所有主机仅限开发测试极高生产禁用⑥ 升级依赖版本升级hutool-all和javax.mail旧版本无配置属性或Bug时低下面逐一详解。四、方案详解✅ 方案一代码中指定 TLS 协议版本首选此方法侵入性最小无需修改 JVM控制粒度细。在MailAccount中直接指定允许的协议列表MailAccountaccountnewMailAccount();account.setHost(smtp.mxhichina.com);account.setPort(587);account.setAuth(true);account.setUser(youremail.com);account.setPass(your-password);// 核心启用 STARTTLSaccount.setStarttlsEnable(true);account.setSslEnable(false);// 指定可用的 TLS 版本按优先级顺序account.setCustomProperty(mail.smtp.ssl.protocols,TLSv1.2 TLSv1.1 TLSv1);// 如果 Hutool 版本较旧可能不支持 setCustomProperty可改用系统属性// System.setProperty(mail.smtp.ssl.protocols, TLSv1.2 TLSv1.1 TLSv1);注意setCustomProperty在 Hutool 5.7.19 中可用。若版本过低可升级依赖或直接通过System.setProperty临时设置作用域为整个 JVM。✅ 方案二修改java.security本文采用的方法如果代码级配置无效比如邮件库内部强制使用了 JVM 全局设置可直接修改 JDK 的安全策略。步骤找到java.security文件该文件位于 JDK 安装目录下的jre/lib/security/java.security。假设你的JAVA_HOME环境变量已正确设置例如/usr/lib/jvm/java-8-openjdk-amd64则完整路径为$JAVA_HOME/jre/lib/security/java.security若JAVA_HOME未设置可通过which java和readlink -f获取实际路径再向上定位到 JDK 根目录。备份原文件务必执行sudocp$JAVA_HOME/jre/lib/security/java.security$JAVA_HOME/jre/lib/security/java.security.bak编辑文件找到jdk.tls.disabledAlgorithms...一行删除其中的TLSv1和TLSv1.1保留其他禁用算法- jdk.tls.disabledAlgorithmsSSLv3, TLSv1, TLSv1.1, RC4, DES, MD5withRSA, ... jdk.tls.disabledAlgorithmsSSLv3, RC4, DES, MD5withRSA, ...保存退出重启所有使用该 JDK 的 Java 应用无需重启操作系统。效果所有基于该 JDK 的 Java 程序均可使用 TLSv1/TLSv1.1邮件发送恢复正常。⚠️安全提示TLSv1 和 TLSv1.1 已被 IETF 标记为废弃存在已知漏洞。仅在内网或临时应急时采用后续应推动服务端升级。✅ 方案三检查 STARTTLS 配置端口 587 的标准用法是STARTTLS先明文连接再升级为 TLS。若错误配置为 SSL 直连会失败。正确配置account.setPort(587);account.setStarttlsEnable(true);// 开启 STARTTLSaccount.setSslEnable(false);// 关闭 SSL 直连若服务商要求必须使用 STARTTLS且未正确设置即使协议版本匹配也可能连接不上。✅ 方案四改用 SSL 直连端口 465部分邮件服务商如阿里云、腾讯企业邮同时支持465 端口SMTPS。此时可直接使用 SSL 加密无需 STARTTLS。account.setPort(465);account.setSslEnable(true);// 启用 SSL 直连account.setStarttlsEnable(false);// 关闭 STARTTLS// 同样可指定协议版本可选account.setCustomProperty(mail.smtp.ssl.protocols,TLSv1.2 TLSv1.1 TLSv1);注意需要服务商开放 465 端口且支持 SSL。⚠️ 方案五跳过 SSL 证书验证仅限测试此方法用于绕过证书链校验解决证书过期或自签名问题但会完全丧失安全性生产环境绝对禁止。MailSSLSocketFactorysfnewMailSSLSocketFactory();sf.setTrustAllHosts(true);// 信任所有主机account.setCustomProperty(mail.smtp.ssl.socketFactory,sf);// 或者account.setCustomProperty(mail.smtp.ssl.trust,*);若其他方案无效且只在开发环境可临时使用以验证是否为证书问题。✅ 方案六升级依赖版本如果 Hutool 或 JavaMail 版本过旧可能缺少某些配置属性或存在 SSL 相关 Bug。升级至较新版本通常能解决问题。!-- pom.xml --dependencygroupIdcn.hutool/groupIdartifactIdhutool-all/artifactIdversion5.8.28/version!-- 最新稳定版 --/dependencydependencygroupIdcom.sun.mail/groupIdartifactIdjavax.mail/artifactIdversion1.6.2/version!-- 或 jakarta.mail 3.x --/dependency升级后可尝试方案一中的setCustomProperty通常即可生效。五、验证与测试修改后建议先用以下命令确认服务端支持的 TLS 版本openssl s_client-connectsmtp.mxhichina.com:587-starttlssmtp-tls1_2openssl s_client-connectsmtp.mxhichina.com:587-starttlssmtp-tls1_1openssl s_client-connectsmtp.mxhichina.com:587-starttlssmtp-tls1哪个版本能成功握手就在配置中优先列出该版本。六、最终选择与效果我先行尝试了方案一但不知为何可能 Hutool 底层未完全覆盖仍然报错。于是采用方案二修改java.security问题立刻解决。后来为了安全又联系邮件服务商确认是否支持 TLSv1.2在确认支持后将配置改回仅 TLSv1.2并移除java.security的修改最终稳定运行。个人建议若你的服务商支持 TLSv1.2尽量保持 JDK 默认禁用低版本仅通过代码方案一指定协议列表。若服务商确实老旧再考虑修改全局配置但务必评估风险。七、总结SSLHandshakeException: No appropriate protocol的本质是 TLS 版本协商失败。本文提供的六种方案覆盖了从代码到 JVM、从轻到重的解决路径。希望这篇实战记录能帮助你快速摆脱邮件发送的困扰。如果你有其他更好的方法欢迎在评论区补充交流发布日期2026-08-27
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门