Spring mail 报错“got bad greeting from host “smtp.exmail.qq.com“, port: 465, response: [EOF]“ 问题排查

背景

java代码编写的 spring boot 项目,需要发送重置密码邮件,因此,集成了 Spring maill ,本地window 开发测试一切顺利,能正常发出去。一通过docker 容器部署jar包,运行就报错
Error1: got bad greeting from host "smtp.exmail.qq.com", port: 465, response: [EOF] ==》 翻译意思:就是 “smtp.exmail.qq.com” 连接不上。
Error2: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target ==》 翻译意思: 就是"smtp.exmail.qq.com"SSL认证不通过。

排查过程

  1. 首先,本地能正常发送邮件,服务器外部也能正常启动发送邮件,排除了代码问题和mail配置问题。但部署到容器内部就启动失败报错 ,基本锁定是容器的问题,要么是环境,要么是参数。
  2. 其次,网络、防火墙方面也是没问题,能ping smtp.exmail.qq.com ,也能telnet smtp.exmail.qq.com 465 ,排除网络问题。
  3. 然后,由于容器也有正常运行过一段时间,所以我下意识的就忽略了运行参数,焦点在容器jdk版本。由于docker容器的jdk版本使用的别人编译好的 ibmjdk ,版本跟本地的不一致,不可控,为了验证是否是jdk 的问题,特意 把本地的jdk1.8_341拷贝到服务器,并用容器编译了一个 jdk1.8容器,然后容器运行jar,启动报错,失败…
  1. 最终,仔细查看 java -jar 的启动参数,定位问题所在。。。

最终原因

经过漫长的排查,最终发现是因为服务器的容器启动java命令参数上,我加了-Djavax.net.ssl.keyStore=xxx.keystore 指定了自己自定义的密码库(这是之前用 jvisuialvm监控jar服务运行情况的时候,开启了SSL证书认证,并且指定使用了自签的证书的路径,导致JDK默认的密码库路径%JAVA_HOME%/lib/security/cacerts被覆盖,最终导致无法正常识别 smtp.exmail.qq.com (当然无法识别,我指定的自签的证书允许通过的只有服务器ip),因为浪费了一个下午,太恶心特此记录一下。

解决办法

Docker启动命令: jvisualvm 开启了TSL认证的,密码库覆盖了JDK默认的密码库,导致Error2: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath的问题

# Docker启动命令: jvisualvm 开启了TSL认证的
docker run
-p 8080:8080 -p 1232:1232 -p 1233:1233 -p 465:465
-v /mydata/xxl-job:/data/applogs/xxl-job
--env JAVA_OPTS=-Xmx512M -Xms256m -Dfile.encoding=UTF-8 -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=1232  -Dcom.sun.management.jmxremote.rmi.port=1233 -Djava.rmi.server.hostname=IP  -Dcom.sun.management.jmxremote.authenticate=false  -Dcom.sun.management.jmxremote.ssl=true  -Dcom.sun.management.jmxremote.registry.ssl=true  -Dcom.sun.management.jmxremote.ssl.need.client.auth=true  -Djavax.net.ssl.keyStore=/data/applogs/xxl-job/visualvm/server/visualvm-server.keystore  -Djavax.net.ssl.keyStorePassword=study@1024  -Djavax.net.ssl.trustStore=/data/applogs/xxl-job/visualvm/server/visualvm-server.truststore -Djavax.net.ssl.trustStorePassword=study@1024
--name xxl-job-admin xxl-job-admin:2.4.0 --restart=always -d xxl-job-admin

解决办法1:

如果既想要使用 jvisualvm 开启了TSL认证使用自定自签的TSL证书,同时又想兼顾SMTP邮件服务的SSL认证。可以利用 keeptool工具,给 JDK默认的%JAVA_HOME%/lib/security/cacerts 导入 jvisualvm 自签的密码库。我试过这个方法比较麻烦,不是容器的话在宿主机外的话倒是还好一些,但是容器内部的话,需要频繁删除容器重新部署,要求docker 就嵌套拼接好 keeptool import 证书导入命令 ,比较麻烦不利于维护。 所以放弃。

解决办法2,选择不使用 jvisualvm ,或者 使用 jvisualvm 但关闭了TSL自签证书认证的方式 。

注意 :jvisualvm 关闭ssl认证的方式不安全,建议只在测试环境这个弄。

# Docker启动命令: jvisualvm 关闭了SSL认证
docker run
-p 8080:8080 -p 1232:1232 -p 1233:1233 -p 465:465
-v /mydata/xxl-job:/data/applogs/xxl-job
--env JAVA_OPTS=-Xmx512M -Xms256m -Dfile.encoding=UTF-8  -Djava.rmi.server.hostname=IP -Dcom.sun.management.jmxremote.port=1232  -Dcom.sun.management.jmxremote.rmi.port=1233   -Dcom.sun.management.jmxremote.authenticate=false  -Dcom.sun.management.jmxremote.ssl=false 
--name xxl-job-admin
xxl-job-admin:2.4.0 --restart=always -d xxl-job-admin

参考资料

【JAVA导入可信任证书】(https://www.freesion.com/article/3510738952/#1_keytool__4)

【由于“PKIX 路径构建失败”错误,无法连接到 SSL 服务】(https://confluence.atlassian.com/kb/unable-to-connect-to-ssl-services-due-to-pkix-path-building-failed-779355358.html)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值