解决jdk1.8中发送邮件失败(handshake_failure)问题

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", "***@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<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. // ***@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<String, Object> model)
{
try {
String nick = MimeUtility.encodeText("***");
InternetAddress from = new InternetAddress(nick + "<***@qq.com>");
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,你的登陆有问题!

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

邮件发过来了

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

(转)解决jdk1.8中发送邮件失败(handshake_failure)问题的更多相关文章

  1. JDK1.8导致发送邮件失败

    问题:本地JDK1.6测试可以发送邮件,但是linux上jdk1.8发送邮件失败.报错: Sending the email to the following server failed : smtp ...

  2. 解决vs code中golang插件依赖安装失败问题

    解决vs code中golang插件依赖安装失败问题 Installing github.com/nsf/gocode SUCCEEDED Installing github.com/uudashr/ ...

  3. 解决 VS Code 中 golang.org 被墙导致的 Go 插件安装失败问题

    微软官方开发的 Go for Visual Studio Code 插件为 Go 语言 提供了丰富的支持.在 VS Code 中首次打开 Go 工作区后,VS Code 会自动检测当前开发环境为 Go ...

  4. Spring Cloud中,如何解决Feign/Ribbon第一次请求失败的问题?

    Spring Cloud中,如何解决Feign/Ribbon第一次请求失败的问题? Spring Cloud中,Feign和Ribbon在整合了Hystrix后,可能会出现首次调用失败的问题,要如何解 ...

  5. python通过SMTP发送邮件失败,报错505/535

    python通过SMTP发送邮件失败:错误1:smtplib.SMTPAuthenticationError: (550, b'User has no permission')    我们使用pyth ...

  6. JavaMail应用--通过javamail API实现在代码中发送邮件功能

    JavaMail应用   在日常开发中,可能会引用到发邮件功能,例如在持续集成中,自动化测试运行完毕,自动将测试结果以报表的形式发送邮件给相关人.那么在Java中如何实现发邮件呢? 在java EE ...

  7. Linux SendMail发送邮件失败诊断案例(三)

    一Linux服务器突然发送不出邮件,检查了很多地方都没有发现异常,检查/var/log/maillog发现如下具体信息: Apr 12 00:36:04 mylinux sendmail[4685]: ...

  8. Android 编译Settings、Mms等模块,并Push到手机中安装失败

    问题描述:在编译完Settings等相关模块后,并push到手机中安装失败(在手机中无法找到该应用),但是使用adb shell命令进入到手机中在System/app或者System/priv-app ...

  9. 如何解决testng执行用例失败自动重跑问题

    注: 以下内容引自 http://blog.csdn.net/MenofGod/article/details/72846649 看过几个相关问题的帖子,内容类似,不过这篇解决问题的步骤和代码比较清晰 ...

随机推荐

  1. python视频教程全集

    由于Python语言的简洁.易读以及可扩展性,在国外用Python做科学计算的研究机构日益增多,一些知名大学已经用它来教授程序设计课程.如果你想找python视频教程全集,来这就对了!这是链接: py ...

  2. python 小白(无编程基础,无计算机基础)的开发之路 辅助知识1 with...as

    这个语法是用来代替传统的try...finally语法的. with EXPRESSION [ as VARIABLE] WITH-BLOCK 基本思想是with所求值的对象必须有一个__enter_ ...

  3. C#中抽象类和接口的区别2

    1.接口是为了满足外部调用而定义的一个功能约定, 因此反映的是事物的外部特性        抽象类是从一系列相关对象中抽象出来的概念, 因此反映的是事物的内部共性:       2. 下面分别从声明, ...

  4. C#多功能DataGridView打印类(WinForm)

    ;                printPreviewDialog.ShowDialog();            }            catch            {         ...

  5. 手动安装Eclipse的PyDev插件,重启无效

    想好好学习Python,又不想只用Emeditor开发,于是想到了Eclipse.之前配置过PyDev,很久没用,就放下了.这次重新配置,遇到了不少问题总结如下: 第一,使用网址自动更新.从网上搜了很 ...

  6. 【转】Entity Framework 5.0系列之约定配置

    Code First之所以能够让开发人员以一种更加高效.灵活的方式进行数据操作有一个重要的原因在于它的约定配置.现在软件开发越来复杂,大家也都试图将软件设计的越来越灵活,很多内容我们都希望是可配置的, ...

  7. C#值参数和引用参数

    一.值参数 未用ref或out修饰符声明的参数为值参数. 使用值参数,通过将实参的值复制到形参的方式,把数据传递到方法.方法被调用时,系统做如下操作. 在栈中为形参分配空间. 复制实参到形参. 值参数 ...

  8. 【JAVA零基础入门系列】Day15 对象的比较

    最近一直有事,博客也停笔了一段时间,十分抱歉. 这一篇主要讲讲对象的比较,什么是对象的比较,我们知道两个数值类型只需要用"=="符号即可进行相等判断,但如果是两个Goods对象呢? ...

  9. python开发 getpass获取操作系统登陆名

    需用使用python getpass模块 import getpass def get_system_user_name(): return getpass.getuser() def main(): ...

  10. Winwos Server 2012发布ASP.NET MVC5 项目

    一.本文实验环境: Windows Server 2012 R2 Visual Studio 2015 项目为:ASP.NET MVC 5.0,使用的是SQL SERVER 2008 R2数据库 二. ...