(轉)解決jdk1.8中發送郵件失敗(handshake_failure)問題
解決jdk1.8中發送郵件失敗(handshake_failure)問題
作者 zhisheng_tian 2016.08.12 22:44* 字數 1573 閱讀 2818評論 6喜歡 9暑假在家做一個類似知乎的問答型網站(代碼可見:Github/wenda 喜歡的可以給個star或者自己fork然後修改,目前功能還未很完善),其中有一個站內郵件通知系統(這裏簡單的講一個例子:如果用戶登錄的時候出現異常,那麽就會通過郵件發送通知用戶)。然而卻碰到一個問題。問題錯誤信息如下:
發送郵件失敗Mail server connection failed; nested exception is javax.mail.MessagingException: Could not connect to SMTP host: smtp.qq.com, port: 465;
nested exception is: javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure. Failed messages: javax.mail. MessagingException: Could not connect to SMTP host: smtp.qq.com, port: 465;
nested exception is: javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
自己在將錯誤信息代碼google了一下,找了很久發現很多解決方案,包括stackoverflow上的一些解決方案,但還是沒用。然後呢用百度試了下,結果在第一條是開源中國的一篇博客:javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure。
百度出來的結果
點進去是這樣的:(如下圖)
開源中國
正確解決方式
結果就是:這個問題是jdk導致的,jdk1.8裏面有一個jce的包,安全性機制導致的訪問https會報錯,官網上有替代的jar包,如果替換掉就可以了。問題的解決方法還可以就是在整個項目中把你的jdk換成是1.7去,同樣也可以解決這個我問題。這兩個jar包的下載地址:http://www.oracle.com/technetwork/java/javase/downloads/jce-7-download-432124.html
包下載
然後下載之後,把這個壓縮文件解壓,得到兩個jar包去覆蓋jdk安裝目錄下的jre\lib\security\下相同的jar包就能解決java8的郵件發送問題。接著用QQ郵箱我親測有用,但是要註意一點就是:開啟SMTP服務後要記得將你的16位授權碼作為你的qq郵箱登錄密碼。
MailSender.java中mailSender.setPassword("16位授權碼");
mailSender.setHost("smtp.qq.com");
mailSender.setPort(465);
開啟服務註意的地方
16位授權碼
下面把完整代碼發布出來:
1. LoginExceptionHandler.java
package com.nowcoder.async.handler;
import com.nowcoder.async.EventHandler;
import com.nowcoder.async.EventModel;
import com.nowcoder.async.EventType;
import com.nowcoder.util.MailSender;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Created by 10412 on 2016/8/10.
*/
@Component
public class LoginExceptionHandler implements EventHandler
{
@Autowired
MailSender mailSender;
@Override
public void doHandle(EventModel model) {
// xxxx判斷發現這個用戶登陸異常
Map<String, Object> map = new HashMap<String, Object>();
map.put("username", model.getExt("username"));
mailSender.sendWithHTMLTemplate(model.getExt("email"), "登陸IP異常", "mails/login_exception.html", map);
}
@Override
public List<EventType> getSupportEventTypes() {
return Arrays.asList(EventType.LOGIN);
}
}
2. LoginController.java
package com.nowcoder.controller;
import com.nowcoder.async.EventModel;
import com.nowcoder.async.EventProducer;
import com.nowcoder.async.EventType;
import com.nowcoder.service.UserService;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.CookieValue;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletResponse;
import java.util.Map;
/**
* Created by 10412 on 2016/7/2.
*/
@Controller
public class LoginController {
private static final Logger logger = LoggerFactory.getLogger(LoginController.class);
@Autowired
UserService userService;
@Autowired
EventProducer eventProducer;
@RequestMapping(path = {"/reg/"}, method = {RequestMethod.POST})
public String reg(Model model, @RequestParam("username") String username,
@RequestParam("password") String password,
@RequestParam("next") String next,
@RequestParam(value="rememberme", defaultValue = "false") boolean rememberme,
HttpServletResponse response) {
try {
Map<String, Object> map = userService.register(username, password);
if (map.containsKey("ticket")) {
Cookie cookie = new Cookie("ticket", map.get("ticket").toString());
cookie.setPath("/");
if (rememberme) {
cookie.setMaxAge(3600*24*5);
}
response.addCookie(cookie);
if (StringUtils.isNotBlank(next)) {
return "redirect:" + next;
}
return "redirect:/";
} else {
model.addAttribute("msg", map.get("msg"));
return "login";
}
} catch (Exception e) {
logger.error("註冊異常" + e.getMessage());
model.addAttribute("msg", "服務器錯誤");
return "login";
}
}
@RequestMapping(path = {"/reglogin"}, method = {RequestMethod.GET})
public String regloginPage(Model model, @RequestParam(value = "next", required = false) String next) {
model.addAttribute("next", next);
return "login";
}
@RequestMapping(path = {"/login/"}, method = {RequestMethod.POST})
public String login(Model model, @RequestParam("username") String username,
@RequestParam("password") String password,
@RequestParam(value="next", required = false) String next,
@RequestParam(value="rememberme", defaultValue = "false") boolean rememberme,
HttpServletResponse response) {
try {
Map<String, Object> map = userService.login(username, password);
if (map.containsKey("ticket")) {
Cookie cookie = new Cookie("ticket", map.get("ticket").toString());
cookie.setPath("/");
if (rememberme) {
cookie.setMaxAge(3600*24*5);
}
response.addCookie(cookie);
eventProducer.fireEvent(new EventModel(EventType.LOGIN)
.setExt("username", username).setExt("email", "[email protected]")
.setActorId((int)map.get("userId")));
if (StringUtils.isNotBlank(next)) {
return "redirect:" + next;
}
return "redirect:/";
} else {
model.addAttribute("msg", map.get("msg"));
return "login";
}
} catch (Exception e) {
logger.error("登陸異常" + e.getMessage());
return "login";
}
}
@RequestMapping(path = {"/logout"}, method = {RequestMethod.GET, RequestMethod.POST})
public String logout(@CookieValue("ticket") String ticket) {
userService.logout(ticket);
return "redirect:/";
}
}
3. EventHandler.java
package com.nowcoder.async;
import java.util.List;
/**
* Created by 10412 on 2016/8/10.
*/
public interface EventHandler
{
void doHandle(EventModel model);
List<EventType> getSupportEventTypes();
}
4. MailSender.java
package com.nowcoder.util;
import org.apache.velocity.app.VelocityEngine;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mail.javamail.JavaMailSenderImpl;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Service;
import org.springframework.ui.velocity.VelocityEngineUtils;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeUtility;
import java.util.Map;
import java.util.Properties;
/**
* Created by 10412 on 2016/8/10. // [email protected] wnppafhsbrcgbfbh(16位授權碼)
*/
@Service
public class MailSender implements InitializingBean {
private static final Logger logger = LoggerFactory.getLogger(MailSender.class);
private JavaMailSenderImpl mailSender;
@Autowired
private VelocityEngine velocityEngine;
public boolean sendWithHTMLTemplate(String to, String subject, String template, Map<String, Object> model)
{
try {
String nick = MimeUtility.encodeText("***");
InternetAddress from = new InternetAddress(nick + "<[email protected]>");
MimeMessage mimeMessage = mailSender.createMimeMessage();
MimeMessageHelper mimeMessageHelper = new MimeMessageHelper(mimeMessage);
String result = VelocityEngineUtils
.mergeTemplateIntoString(velocityEngine, template, "UTF-8", model);
mimeMessageHelper.setTo(to);
mimeMessageHelper.setFrom(from);
mimeMessageHelper.setSubject(subject);
mimeMessageHelper.setText(result, true);
mailSender.send(mimeMessage);
return true;
} catch (Exception e) {
logger.error("發送郵件失敗" + e.getMessage());
return false;
}
}
@Override
public void afterPropertiesSet() throws Exception {
mailSender = new JavaMailSenderImpl();
mailSender.setUsername("[email protected]");
mailSender.setPassword("wnppafhsbrcgbfbh"); //qq郵箱開啟smtp服務後使用16位授權碼在第三方登錄
// mailSender.setHost("smtp.exmail.qq.com");
mailSender.setHost("smtp.qq.com");
mailSender.setPort(465);
// mailSender.setHost("smtp.163.com"); //163郵箱
// mailSender.setPort(25);
mailSender.setProtocol("smtps");
mailSender.setDefaultEncoding("utf8");
Properties javaMailProperties = new Properties();
javaMailProperties.put("mail.smtp.ssl.enable", true);
//javaMailProperties.put("mail.smtp.auth", true);
//javaMailProperties.put("mail.smtp.starttls.enable", true);
mailSender.setJavaMailProperties(javaMailProperties);
}
}
5. login_exception.html 發送消息模板(可自定義)
你好$username,你的登陸有問題!
一切都好了,運行。登錄。發送郵件過來了。
郵件發過來了
總結來說:這個錯誤就是jdk1.8中的一個jce的包,安全性機制導致訪問https會報錯。
(轉)解決jdk1.8中發送郵件失敗(handshake_failure)問題