【SpringBoot2.0系列12】SpringBoot之JavaMail傳送,支援FreeMark模板渲染

weixin_33912445發表於2018-12-05

目錄

【SpringBoot2.0文章彙總目錄,java多執行緒教程文章彙總 長期更新系列

請多多支援

前言 我們在日常生活經常會用到郵箱,比如登入驗證碼,找回密碼驗證碼/連結等, 今天我就實現一個類似功能,郵件驗證碼登入,注重點郵件的傳送,模板的選擇。

依賴

      <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-freemarker</artifactId>
       </dependency>
       <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-mail</artifactId>
       </dependency>
  • freemark是使用者模板渲染支援
  • mail 是用於郵件傳送支援

編碼實現

大家都知道郵件協議有兩個
smtp:郵件傳送協議
pop3:郵件接收協議
我們現在要實現的郵件傳送,那麼重點就要放在smtp上。
在這裡我們藉助第三的郵件系統的smtp伺服器來。比如QQ 126等。

開啟qq郵箱


5338436-09866635217a24dc.png
image.png

獲取生成的授權碼

然後開啟application.yml
配置smtp相關資訊

spring:
  mail:
    host: smtp.qq.com  # qq  smtp伺服器地址
    username: 你的郵箱
    password: 剛剛的許可權碼
    properties:
      mail:
        smtp:
          auth: true
          starttls:
            enable: true
            required: true

然後我們還需要配置一下freemark的配置,我在之前的【SpringBoot2.0系列03】SpringBoot之使用freemark檢視模板介紹過 我就不在講了。

    freemarker:
    charset: UTF-8
    allow-request-override: false
    cache: false
    expose-request-attributes: false
    expose-session-attributes: false
    content-type: text/html
    template-loader-path: classpath:/static/template/  #模板目錄
    expose-spring-macro-helpers: false
    check-template-location: true
    enabled: true

郵件實體類Mail.java

package com.yukong.mail.entity;

import java.io.Serializable;
import java.util.Map;

/**
 * @author: yukong
 * @date: 2018/12/5 17:25
 */
public class Mail implements Serializable {
    private static final long serialVersionUID = 1L;
    //接收方郵件
    private String email;

    //主題
    private String subject;
    //模板
    private String template;

    // 自定義引數
    private Map<String, Object> params;

    public static long getSerialVersionUID() {
        return serialVersionUID;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getSubject() {
        return subject;
    }

    public void setSubject(String subject) {
        this.subject = subject;
    }

    public String getTemplate() {
        return template;
    }

    public void setTemplate(String template) {
        this.template = template;
    }

    public Map<String, Object> getParams() {
        return params;
    }

    public void setParams(Map<String, Object> params) {
        this.params = params;
    }
}

郵件傳送實現類 MailSendService.java

package com.yukong.mail;

import com.yukong.mail.entity.Mail;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Service;
import org.springframework.ui.freemarker.FreeMarkerTemplateUtils;
import org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer;

import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeUtility;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

/**
 * @author: yukong
 * @date: 2018/12/5 16:56
 */
@Service
public class MailSendService {
    private Logger logger = LoggerFactory.getLogger(getClass());

    @Autowired
    private JavaMailSender javaMailSender;

    @Autowired
    private FreeMarkerConfigurer freeMarkerConfigurer;

    @Value("${spring.mail.username}")
    private  String USERNAME = "yukong";




    /**
     * 根據模板名 獲取郵件內容
     * @param templateName
     * @param params
     * @return
     */
    private String getMailTextByTemplateName(String templateName, Map<String,Object> params) throws IOException, TemplateException {
        String mailText = "";
        //通過指定模板名獲取FreeMarker模板例項
        Template template = freeMarkerConfigurer.getConfiguration().getTemplate(templateName);
        //FreeMarker通過Map傳遞動態資料
        //注意動態資料的key和模板標籤中指定的屬性相匹配
        //解析模板並替換動態資料,最終code將替換模板檔案中的${code}標籤。
        mailText = FreeMarkerTemplateUtils.processTemplateIntoString(template, params);
        return mailText;
    }

    public boolean sendWithHTMLTemplate(Mail mail) {
        try {
            //發件人的暱稱
            String nick = MimeUtility.encodeText(USERNAME);
            //發件人是誰
            InternetAddress from = new InternetAddress(nick + "<541130126@qq.com>");
            MimeMessage mimeMessage = javaMailSender.createMimeMessage();
            MimeMessageHelper mimeMessageHelper = new MimeMessageHelper(mimeMessage,true);
            mimeMessageHelper.setTo(mail.getEmail());
            mimeMessageHelper.setFrom(from);
            mimeMessageHelper.setSubject(mail.getSubject());
            HashMap<String, Object> params = new HashMap<>();
            // 使用模板生成html郵件內容
            String result =getMailTextByTemplateName(mail.getTemplate(), mail.getParams());
            mimeMessageHelper.setText(result, true);
            javaMailSender.send(mimeMessage);
            return true;
        } catch (Exception e) {
            logger.error("傳送郵件失敗" + e.getMessage());
            return false;
        }
    }


}

編寫模板login_code.ftl
注意它的目錄是resource/static/tempalte/login_code.ftl

你好,你本次的登入驗證碼為${code}若非本人操作,請忽略本郵件。

如果有其他郵件,編寫不同的模板即可
因為用到了模板名稱渲染,所以我們根據規範,編寫一個模板列舉

package com.yukong.mail;

/**
 * @author: yukong
 * @date: 2018/12/5 17:23
 */
public enum MailTemplateNameEnum {

    LOGIN_CODE("login_code.ftl", "登入驗證碼模板");

    String code;

    String desc;

   private MailTemplateNameEnum(String code, String desc) {
        this.code = code;
        this.desc = desc;
    }

    public String getCode() {
        return code;
    }

    public String getDesc() {
        return desc;
    }

}

接下里就是編寫測試類測試, ctrl+shift+T

 @Test
    public void sendWithHTMLTemplate() {
        Map<String, Object> params = new HashMap<>();
        // 引數
        Integer code = (int)(Math.random()*9+1)*100000;
        params.put("code", code);
        Mail mail  = new Mail();
        mail.setEmail("yukonga@vip.qq.com");
        mail.setParams(params);
        mail.setTemplate(MailTemplateNameEnum.LOGIN_CODE.getCode());
        mail.setSubject("登入驗證碼");
        mailSendService.sendWithHTMLTemplate(mail);
    }

效果如下


5338436-9bc2915619b8451b.png
image.png

但是實際情況中 我們登入的驗證郵件不應該這麼用,如果郵件傳送失敗,會導致整個流程阻塞,這時候需要我們的訊息佇列來解耦,【SpringBoot2.0系列09】SpringBoot之rabbitmq使用

最後原始碼地址如下:https://github.com/YuKongEr/SpringBoot-Study/tree/master/chapter11

歡迎大家關注一下我的個人公眾號。一起交流一起學習,有問必答。
交流qq群: 558509374


5338436-ddb4dd1530787751.png
公眾號

相關文章