暑假在家做一个类似知乎的问答型网站(代码可见: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);
下面把完整代码发布出来:
1. LoginExceptionHandler.java
1 | package com.nowcoder.async.handler; |
2. LoginController.java1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114package 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", "****@qq.com")
.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.java1
2
3
4
5
6
7
8
9
10
11
12
13
14package 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
1 | package com.nowcoder.util; |
5. login_exception.html 发送消息模板(可自定义)
1 | 你好$username,你的登陆有问题! |
一切都好了,运行。
登录。
发送邮件过来了。
总结来说:这个错误就是jdk1.8中的一个jce的包,安全性机制导致访问https会报错。