zoukankan      html  css  js  c++  java
  • (转)解决jdk1.8中发送邮件失败(handshake_failure)问题

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

    2016.08.12 22:44* 字数 1573 阅读 2818评论 6

    暑假在家做一个类似知乎的问答型网站(代码可见: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安装目录下的jrelibsecurity下相同的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会报错。

  • 相关阅读:
    Linux搭建iscsi服务,客户端(Linux&Win XP)挂载使用
    SecucreCRT安装与破解
    最全的HCIA-R&S实验笔记
    AtCoder Grand Contest 036
    Comet OJ CCPC-Wannafly & Comet OJ 夏季欢乐赛(2019)
    2019慈溪集训小记
    Codeforces Round #573 (Div. 1)
    Comet OJ
    Codeforces Round #576 (Div. 1)
    Codechef August Challenge 2019 Division 2
  • 原文地址:https://www.cnblogs.com/roy-blog/p/7346554.html
Copyright © 2011-2022 走看看