(轉)解決jdk1.8中發送郵件失敗(handshake_failure)問題

解決jdk1.8中發送郵件失敗(handshake_failure)問題

2016.08.12 22:44* 字數 1573 閱讀 2818評論 6

暑假在家作一個相似知乎的問答型網站(代碼可見:Github/wenda 喜歡的能夠給個star或者本身fork而後修改,目前功能還未很完善),其中有一個站內郵件通知系統(這裏簡單的講一個例子:若是用戶登陸的時候出現異常,那麼就會經過郵件發送通知用戶)。然而卻碰到一個問題。問題錯誤信息以下:html

發送郵件失敗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_failurejava

本身在將錯誤信息代碼google了一下,找了好久發現不少解決方案,包括stackoverflow上的一些解決方案,但仍是沒用。而後呢用百度試了下,結果在第一條是開源中國的一篇博客:javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failuregit


百度出來的結果

點進去是這樣的:(以下圖)github


開源中國

正確解決方式

結果就是:這個問題是jdk致使的,jdk1.8裏面有一個jce的包,安全性機制致使的訪問https會報錯,官網上有替代的jar包,若是替換掉就能夠了。問題的解決方法還能夠就是在整個項目中把你的jdk換成是1.7去,一樣也能夠解決這個我問題。這兩個jar包的下載地址:http://www.oracle.com/technetwork/java/javase/downloads/jce-7-download-432124.htmlweb


包下載

而後下載以後,把這個壓縮文件解壓,獲得兩個jar包去覆蓋jdk安裝目錄下的jre\lib\security\下相同的jar包就能解決java8的郵件發送問題。接着用QQ郵箱我親測有用,可是要注意一點就是:開啓SMTP服務後要記得將你的16位受權碼做爲你的qq郵箱登陸密碼。spring

MailSender.java中mailSender.setPassword("16位受權碼");
mailSender.setHost("smtp.qq.com");
mailSender.setPort(465);apache


開啓服務注意的地方

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.javacookie

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會報錯。

相關文章
相關標籤/搜索