java smtp tls加密_java Mail發郵件 smtp被TLS加密認證不了的解決方案

開始測試前,要確保發郵件的服務器的smtp服務可用。

8dff5939b3ec700d0efa6e3fbb8882f2.jpe

不然會拋出異常:

Sending the email to the following server failed : m.xxx.com:25

Caused by: javax.mail.AuthenticationFailedException: 334 NTLM supported

然后介紹下我的開發環境(context):目前用的開發框架是playframework,它幫忙封裝了apache的mail工具類,代碼如下:

public static void sendMail(SendMailDto sendMailDto){

if(sendMailDto!=null){

HtmlEmail email = new HtmlEmail();

email.setCharset("UTF-8");// 編碼格式

try {

email.addTo(sendMailDto.accepterEmail);// 接收者

email.setFrom(sendMailDto.sender, sendMailDto.name);// 發送者,姓名

email.setSubject(sendMailDto.title);// 郵件標題

email.setMsg(sendMailDto.content);// 發送內容

Mail.send(email);

Logger.info("接收郵件: "+sendMailDto.accepterEmail+" 發送成功!");

Logger.info("發送郵件服務器: "+sendMailDto.sender);

Logger.info("發送郵件名: "+sendMailDto.name);

}catch (Exception e) {

Logger.info("郵件: "+sendMailDto.accepterEmail+" 發送失敗!");

e.printStackTrace();

}

}

}

在配置文件中要申明:

mail.smtp.host=xxxx

mail.smtp.user=xxxx

mail.smtp.pass=xxxx

本質上還是用的apache的setMailSession()方法。

當一切都配置好了,開始執行,還是報上面的異常,后來發現還需要在配置文件加上 mail.smtp.protocol=smtps,分析下源碼:

public static Session getSession() {

if (session == null) {

Properties props = new Properties();

// Put a bogus value even if we are on dev mode, otherwise JavaMail will complain

props.put("mail.smtp.host", Play.configuration.getProperty("mail.smtp.host", "localhost"));

String channelEncryption;

if (Play.configuration.containsKey("mail.smtp.protocol") && Play.configuration.getProperty("mail.smtp.protocol", "smtp").equals("smtps")) {

// Backward compatibility before stable5

channelEncryption = "starttls";

} else {

channelEncryption = Play.configuration.getProperty("mail.smtp.channel", "clear");

}

if (channelEncryption.equals("clear")) {

props.put("mail.smtp.port", "25");

} else if (channelEncryption.equals("ssl")) {

// port 465 + setup yes ssl socket factory (won't verify that the server certificate is signed with a root ca.)

props.put("mail.smtp.port", "465");

props.put("mail.smtp.socketFactory.port", "465");

props.put("mail.smtp.socketFactory.class", "play.utils.YesSSLSocketFactory");

props.put("mail.smtp.socketFactory.fallback", "false");

} else if (channelEncryption.equals("starttls")) {

// port 25 + enable starttls + ssl socket factory

props.put("mail.smtp.port", "25");

props.put("mail.smtp.starttls.enable", "true");

// can't install our socket factory. will work only with server that has a signed certificate

// story to be continued in javamail 1.4.2 : https://glassfish.dev.java.net/issues/show_bug.cgi?id=5189

}

if (Play.configuration.containsKey("mail.smtp.localhost")) {

props.put("mail.smtp.localhost", Play.configuration.get("mail.smtp.localhost")); //override defaults

}

if (Play.configuration.containsKey("mail.smtp.socketFactory.class")) {

props.put("mail.smtp.socketFactory.class", Play.configuration.get("mail.smtp.socketFactory.class"));

}

if (Play.configuration.containsKey("mail.smtp.port")) {

props.put("mail.smtp.port", Play.configuration.get("mail.smtp.port"));

}

String user = Play.configuration.getProperty("mail.smtp.user");

String password = Play.configuration.getProperty("mail.smtp.pass");

if (password == null) {

// Fallback to old convention

password = Play.configuration.getProperty("mail.smtp.password");

}

String authenticator = Play.configuration.getProperty("mail.smtp.authenticator");

session = null;

if (authenticator != null) {

props.put("mail.smtp.auth", "true");

try {

session = Session.getInstance(props, (Authenticator) Play.classloader.loadClass(authenticator).newInstance());

} catch (Exception e) {

Logger.error(e, "Cannot instanciate custom SMTP authenticator (%s)", authenticator);

}

}

if (session == null) {

if (user != null && password != null) {

props.put("mail.smtp.auth", "true");

session = Session.getInstance(props, new SMTPAuthenticator(user, password));

} else {

props.remove("mail.smtp.auth");

session = Session.getInstance(props);

}

}

if (Boolean.parseBoolean(Play.configuration.getProperty("mail.debug", "false"))) {

session.setDebug(true);

}

}

return session;

}

為了向后兼容,需要在session中設置:

props.put("mail.smtp.port", "25");

props.put("mail.smtp.starttls.enable", "true");

配置好了以后再來嘗試下,發現還是有異常拋出:

javax.mail.MessagingException: Could not convert socket to TLS

sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

不能把socket解析為TLS(通過上面的截圖,可以看到我的郵件服務器是TLS加密了的)

不能對訪問的目標提供有效證書。

到這里有兩種解決方案:

2.把當前smtp host設為可信任 props.put("mail.smtp.ssl.trust", "smtp服務器地址")

到此 所有問題都解決了。

總結下:

產生第一個異常的原因有以下3個:

1. 郵件服務器的smtp沒有開啟。

2. 用戶名密碼錯誤。

3. mail工具類版本較低,不能有效生成socket factory

解決方案:登錄郵箱,在設置里面開啟smtp服務,驗證程序中登錄郵箱的用戶名密碼填寫正確,用高版本的mail.jar 或者在session中設置props.put("mail.smtp.port", "25");   props.put("mail.smtp.starttls.enable", "true");

產生第二異常的原因:

smtp設置了加密,或者嘗試訪問不受信任地址

解決方案:用工具類生成安全證書,放在\jdk1.6.0_31\jre\lib\security下面

關於apache的mail還有很多不明白的地方,上面只是記錄解決問題的過程,和大家共同學習。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值