暑假在家做一个类似知乎的问答型网站(代码可见: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。

eb155a3b6f0b1b2c107f04ec5a0d3826.png

百度出来的结果

点进去是这样的:(如下图)

cc70f0012dcd57c5e3b6883b1edf5f77.png

开源中国

093a7f78bb68073621e7805493728727.png

正确解决方式

结果就是:这个问题是jdk导致的,jdk1.8里面有一个jce的包,安全性机制导致的访问https会报错,官网上有替代的jar包,如果替换掉就可以了。问题的解决方法还可以就是在整个项目中把你的jdk换成是1.7去,同样也可以解决这个我问题。这两个jar包的下载地址:http://www.oracle.com/technetwork/java/javase/downloads/jce-7-download-432124.html

2c636a1e1b8faba9ecdad423fa343b41.png

包下载

然后下载之后,把这个压缩文件解压,得到两个jar包去覆盖jdk安装目录下的jre\lib\security\下相同的jar包就能解决java8的邮件发送问题。接着用QQ邮箱我亲测有用,但是要注意一点就是:开启SMTP服务后要记得将你的16位授权码作为你的qq邮箱登录密码。

MailSender.java中mailSender.setPassword("16位授权码");

mailSender.setHost("smtp.qq.com");

mailSender.setPort(465);

578bbd020ae0b3f7e2a10d7e7d1948fe.png

开启服务注意的地方

a07cebdb93a4f91ab875b0575d99190d.png

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 map = new HashMap();

map.put("username", model.getExt("username"));

mailSender.sendWithHTMLTemplate(model.getExt("email"), "登陆IP异常", "mails/login_exception.html", map);

}

@Override

public List 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 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 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.java

package com.nowcoder.async;

import java.util.List;

/**

* Created by 10412 on 2016/8/10.

*/

public interface EventHandler

{

void doHandle(EventModel model);

List 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. // ***@qq.com 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 model)

{

try {

String nick = MimeUtility.encodeText("***");

InternetAddress from = new InternetAddress(nick + "");

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("***@qq.com");

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,你的登陆有问题!

一切都好了,运行。登录。发送邮件过来了。

3237ea80722ad114e9c253343774e8d6.png

邮件发过来了

总结来说:这个错误就是jdk1.8中的一个jce的包,安全性机制导致访问https会报错。

Logo

一站式 AI 云服务平台

更多推荐