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

2024-05-02 08:58

本文主要是介绍解决jdk1.8中发送邮件失败(handshake_failure)问题,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

暑假在家做一个类似知乎的问答型网站(代码可见: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
{@AutowiredMailSender mailSender;@Overridepublic 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);}@Overridepublic 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);@AutowiredUserService userService;@AutowiredEventProducer 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;@Autowiredprivate 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;}}@Overridepublic 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)问题的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/953880

相关文章

线上Java OOM问题定位与解决方案超详细解析

《线上JavaOOM问题定位与解决方案超详细解析》OOM是JVM抛出的错误,表示内存分配失败,:本文主要介绍线上JavaOOM问题定位与解决方案的相关资料,文中通过代码介绍的非常详细,需要的朋... 目录一、OOM问题核心认知1.1 OOM定义与技术定位1.2 OOM常见类型及技术特征二、OOM问题定位工具

C++右移运算符的一个小坑及解决

《C++右移运算符的一个小坑及解决》文章指出右移运算符处理负数时左侧补1导致死循环,与除法行为不同,强调需注意补码机制以正确统计二进制1的个数... 目录我遇到了这么一个www.chinasem.cn函数由此可以看到也很好理解总结我遇到了这么一个函数template<typename T>unsigned

Vue3绑定props默认值问题

《Vue3绑定props默认值问题》使用Vue3的defineProps配合TypeScript的interface定义props类型,并通过withDefaults设置默认值,使组件能安全访问传入的... 目录前言步骤步骤1:使用 defineProps 定义 Props步骤2:设置默认值总结前言使用T

504 Gateway Timeout网关超时的根源及完美解决方法

《504GatewayTimeout网关超时的根源及完美解决方法》在日常开发和运维过程中,504GatewayTimeout错误是常见的网络问题之一,尤其是在使用反向代理(如Nginx)或... 目录引言为什么会出现 504 错误?1. 探索 504 Gateway Timeout 错误的根源 1.1 后端

Web服务器-Nginx-高并发问题

《Web服务器-Nginx-高并发问题》Nginx通过事件驱动、I/O多路复用和异步非阻塞技术高效处理高并发,结合动静分离和限流策略,提升性能与稳定性... 目录前言一、架构1. 原生多进程架构2. 事件驱动模型3. IO多路复用4. 异步非阻塞 I/O5. Nginx高并发配置实战二、动静分离1. 职责2

解决升级JDK报错:module java.base does not“opens java.lang.reflect“to unnamed module问题

《解决升级JDK报错:modulejava.basedoesnot“opensjava.lang.reflect“tounnamedmodule问题》SpringBoot启动错误源于Jav... 目录问题描述原因分析解决方案总结问题描述启动sprintboot时报以下错误原因分析编程异js常是由Ja

基于Python实现自动化邮件发送系统的完整指南

《基于Python实现自动化邮件发送系统的完整指南》在现代软件开发和自动化流程中,邮件通知是一个常见且实用的功能,无论是用于发送报告、告警信息还是用户提醒,通过Python实现自动化的邮件发送功能都能... 目录一、前言:二、项目概述三、配置文件 `.env` 解析四、代码结构解析1. 导入模块2. 加载环

深度剖析SpringBoot日志性能提升的原因与解决

《深度剖析SpringBoot日志性能提升的原因与解决》日志记录本该是辅助工具,却为何成了性能瓶颈,SpringBoot如何用代码彻底破解日志导致的高延迟问题,感兴趣的小伙伴可以跟随小编一起学习一下... 目录前言第一章:日志性能陷阱的底层原理1.1 日志级别的“双刃剑”效应1.2 同步日志的“吞吐量杀手”

使用Python的requests库来发送HTTP请求的操作指南

《使用Python的requests库来发送HTTP请求的操作指南》使用Python的requests库发送HTTP请求是非常简单和直观的,requests库提供了丰富的API,可以发送各种类型的HT... 目录前言1. 安装 requests 库2. 发送 GET 请求3. 发送 POST 请求4. 发送

MySQL 表空却 ibd 文件过大的问题及解决方法

《MySQL表空却ibd文件过大的问题及解决方法》本文给大家介绍MySQL表空却ibd文件过大的问题及解决方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考... 目录一、问题背景:表空却 “吃满” 磁盘的怪事二、问题复现:一步步编程还原异常场景1. 准备测试源表与数据