Jenkins JavaMail 配置:JCE 及其他

Jenkins 上线一段时间,逐渐完善中。原想 nightly build 缓一缓开启,前两天发现trunk有编译不过的代码导致build fail,心想着要是不早点发现,代码排查也麻烦,如果新版本上线当天发现就更折腾,于是就开了nightly build。

既然开了nightly build,跟手动启动的build你会去关注结果不一样,自动启动的build不一定会记得,如果没有留意到build fail就没有意义了。所以顺便就配置结果邮件了。以下是踩坑记录。JCE部分建议大家留意一下,不知道的话,做security相关开发一不小心就在这上面浪费时间。

JCE

邮箱直接用QQ邮箱的SMTP服务,理由有二:

  1. 自己配置邮件服务器,折腾
  2. 折腾完之后,对于这种无名服务器发出来的邮件,还极高概率被扔进垃圾箱,得一个一个通知收件同事设置例外,还是折腾

这本没有什么难度,在Jenkins全局配置里,多数一看就知道怎么填:

  • SMTP服务器:smtp.qq.com
  • 使用SMTP认证:√
    • 用户名:youraccount@qq.com
    • 密码:这里比较特殊,不是填登录密码,而是在QQ邮箱设置 > 账户 里打开SMTP功能时,会生成一个密码,填这个
  • 使用SSL协议:√ (QQ邮箱要求打开)
  • SMTP端口:465

发送测试邮件,发现无法连上服务器。报以下错误:

1
javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure at com.sun.mail.smtp.SMTPTransport.openServer(SMTPTransport.java:1934)

第一反应,检查Jenkins服务器的网络环境,网络连接、端口检查了一通,没发现问题,只好拿着这个Exception放Google,然后果然就找到了原因:

http://www.cnblogs.com/interdrp/p/5766107.html

原文一笔带过,我补充解释一下:

JCE,Java Cryptography Extension,在早期JDK版本中,由于受美国的密码出口条例约束,Java中涉及加解密功能的API被限制出口,所以Java中安全组件被分成了两部分: 不含加密功能的JCA(Java Cryptography Architecture )和含加密功能的JCE(Java Cryptography Extension)。在JDK1.1-1.3版本期间,JCE属于扩展包,仅供美国和加拿大的用户下载,JDK1.4+版本后,随JDK核心包一起分发。

然而,即使是最新版JDK自带的JCE,仍然是受限的版本,引用unlimited JCE自带的README的内容:

Due to import control restrictions of some countries, the version of
the JCE policy files that are bundled in the Java Runtime Environment,
or JRE(TM), 8 environment allow “strong” but limited cryptography to be
used. This download bundle (the one including this README file)
provides “unlimited strength” policy files which contain no
restrictions on cryptographic strengths.

受某些国家的进口控制约束,随 JDK / JRE 发布的JCE版本的加密算法是受限制的,想摆脱这个限制,就要额外下载unlimited JCE,替换掉 $JRE_HOME/lib/security/下的 local_policy.jar 和 US_export_policy.jar 两个文件。

替换之后,要重启一下tomcat让它重新加载lib。

个人觉得这个问题特别坑!! 一般人只会怀疑自己的环境配置,或者代码,很少会怀疑到JDK本身上面去。建议大家记住这个坑,以后跟加密有关的错误,例如SSL相关的,可以排查一下是不是JCE的问题。或者干脆现在就去,把开发环境和生产环境的JCE换掉。

管理员邮箱

换了JCE之后重新测试,这次报以下错误:

1
2
3
4
com.sun.mail.smtp.SMTPSendFailedException: 501 mail from address must be same as authorization user
;
nested exception is:
com.sun.mail.smtp.SMTPSenderFailedException: 501 mail from address must be same as authorization user

这倒是个小问题:前面设置管理员邮箱时,我填了我自己的邮箱;但是为了区分哪些是自动发的,哪些是我个人发的邮件,SMTP邮箱填的是团队的邮箱。

Jenkins 会自动把管理员邮箱设为发信人,但是QQ邮箱不允许发信人和登录账号不一致,所以报错。

把管理员邮箱也换成同一个邮箱就好了。


知识共享 “署名-非商业性使用-相同方式共享” 4.0 (CC BY-NC-SA 4.0)”许可协议
本文为本人原创,采用知识共享 “署名-非商业性使用-相同方式共享” 4.0 (CC BY-NC-SA 4.0)”许可协议进行许可。
本作品可自由复制、传播及基于本作品进行演绎创作。如有以上需要,请留言告知,在文章开头明显位置加上署名(Jayce Chant)、原链接及许可协议信息,并明确指出修改(如有),不得用于商业用途。谢谢合作。
详情请点击查看协议具体内容。