前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【SpringBoot2.0系列12】SpringBoot之JavaMail发送,支持FreeMark模板渲染

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

作者头像
yukong
发布2018-12-24 10:19:16
9090
发布2018-12-24 10:19:16
举报
文章被收录于专栏:yukong的小专栏

前言 我们在日常生活经常会用到邮箱,比如登录验证码,找回密码验证码/链接等, 今天我就实现一个类似功能,邮件验证码登录,注重点邮件的发送,模板的选择。

依赖

代码语言:javascript
复制
      <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邮箱

image.png

获取生成的授权码

然后打开application.yml

配置smtp相关信息

代码语言:javascript
复制
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视图模板介绍过 我就不在讲了。

代码语言:javascript
复制
    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

代码语言:javascript
复制
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

代码语言:javascript
复制
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

代码语言:javascript
复制
你好,你本次的登录验证码为${code}若非本人操作,请忽略本邮件。

如果有其他邮件,编写不同的模板即可

因为用到了模板名称渲染,所以我们根据规范,编写一个模板枚举

代码语言:javascript
复制
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

代码语言:javascript
复制
 @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);
    }

效果如下

image.png

但是实际情况中 我们登录的验证邮件不应该这么用,如果邮件发送失败,会导致整个流程阻塞,这时候需要我们的消息队列来解耦,【SpringBoot2.0系列09】SpringBoot之rabbitmq使用

最后源码地址如下:https://github.com/YuKongEr/SpringBoot-Study/tree/master/chapter11

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2018.12.05 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 依赖
  • 编码实现
相关产品与服务
验证码
腾讯云新一代行为验证码(Captcha),基于十道安全栅栏, 为网页、App、小程序开发者打造立体、全面的人机验证。最大程度保护注册登录、活动秒杀、点赞发帖、数据保护等各大场景下业务安全的同时,提供更精细化的用户体验。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档