SpringBoot按照模板定时发送邮件,JavaMail发送,支持FreeMark模板渲染

最近写一个监控爬虫采集量,定时发送邮件的功能,基于springboot实现,定时任务用quartz,邮件用JaveMail,邮件模板用FreeMark

添加依赖

 
            org.springframework.boot
            spring-boot-starter-mail
        
        
            org.springframework.boot
            spring-boot-starter-freemarker
        

邮件授权码申请

邮件协议有两个
smtp:邮件发送协议
pop3:邮件接收协议
我们现在要实现的邮件发送,需要用到smtp协议
在这里我们借助第三的邮件系统的smtp服务器来。比如QQ 163等

  • 以QQ邮箱为例:
    打开邮箱设置-》账户


    SpringBoot按照模板定时发送邮件,JavaMail发送,支持FreeMark模板渲染_第1张图片
    image.png

    生成授权码

  • 注:(PS:QQ修改密码后,授权码需要重新生成)

配置文件

#email
spring.mail.host=smtp.qq.com
spring.mail.username=your qq邮箱
spring.mail.password=生成授权码
spring.mail.properties.mail.smtp.auth=true
spring.mail.properties.mail.smtp.starttls.enable=true
spring.mail.properties.mail.smtp.starttls.required=true
#默认收件人
mail.receiveEmail=默认收件人邮箱

#编码格式
spring.freemarker.charset=UTF-8
#req访问request
spring.freemarker.allow-request-override=false
#缓存配置
spring.freemarker.cache=false
spring.freemarker.expose-request-attributes=false
spring.freemarker.expose-session-attributes=false
spring.freemarker.content-type=text/html
spring.freemarker.template-loader-path=classpath:/static/template/
spring.freemarker.expose-spring-macro-helpers=false
spring.freemarker.check-template-location=true
spring.freemarker.enabled=true

邮件类 Mail.java

package com.nbspider.domain;

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

/**
 * @author: shaol
 * @date: 2018年12月6日22:16:38
 */
public class Mail implements Serializable {
    private static final long serialVersionUID = 1L;
    //接收方邮件
    private String email;

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

    // 自定义参数
    private Map 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 getParams() {
        return params;
    }

    public void setParams(Map params) {
        this.params = params;
    }
}

邮件发送service

package com.nbspider.service;

import com.nbspider.domain.Mail;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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: shaol
 * @date: 2018年12月6日22:17:16
 */
@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 = "采集监控管理员";

    /**
     * 默认的收件人邮箱
     */
    @Value("${mail.receiveEmail")
    private String receiveEmail;

    /**
     * 根据模板名 获取邮件内容
     *
     * @param templateName
     * @param params
     * @return
     */
    private String getMailTextByTemplateName(String templateName, Map 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 + "<" + USERNAME + ">");
            MimeMessage mimeMessage = javaMailSender.createMimeMessage();
            MimeMessageHelper mimeMessageHelper = new MimeMessageHelper(mimeMessage, true);
            //添加默认收件人
            String email = mail.getEmail();
            if (StringUtils.isBlank(email)) {
                email = this.receiveEmail;
            }
            mimeMessageHelper.setTo(email);
            mimeMessageHelper.setFrom(from);
            mimeMessageHelper.setSubject(mail.getSubject());
            HashMap 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;
        }
    }

}

编辑采集日志模板 data_monitor_report.ftl

注意配置文件在 resources\static\template下

  • data_monitor_report.ftl



    大数据采集系统采集监控
    
    
    
    



${date}采集任务入库量统计

<#list keyPairs as keyPair>
采集任务 采集量
${keyPair.name} ${keyPair.value}
  • freemark list遍历参考https://blog.csdn.net/pauony/article/details/80164688

如果有其他邮件,编写不同的模板即可
因为用到了模板名称渲染,所以我们根据规范,编写一个模板枚举

package com.nbspider.domain;

/**
 * @author: shaol
 * @date: 2018年12月6日22:18:52
 */
public enum MailTemplateNameEnum{

    DataMonitorReport("data_monitor_report.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;
    }

}

编写测试类

package com.nbspider.spider;

import com.nbspider.domain.Mail;
import com.nbspider.domain.MailTemplateNameEnum;
import com.nbspider.service.MailSendService;
import com.nbspider.util.ConfigProperty;
import com.nbspider.site.domain.KeyPair;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import java.util.*;

/**
 * @author: shaol
 * @date:2018年12月6日22:19:52
 */
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest
public class MailSendServiceTest {

    @Autowired
    private MailSendService mailSendService;

    @Test
    public void sendWithHTMLTemplate() {

        List allCountLsit = new ArrayList<>();
        KeyPair keyPair1 = new KeyPair("test", 1);
        KeyPair keyPair2 = new KeyPair("test", 1);
        KeyPair keyPair3 = new KeyPair("test", 1);
        allCountLsit.add(keyPair1);
        allCountLsit.add(keyPair1);
        allCountLsit.add(keyPair2);
        allCountLsit.add(keyPair3);
        // 参数
        Map params = new HashMap<>();
        params.put("keyPairs", allCountLsit);
        params.put("date", "2018年12月6日 12:00 ~ 2018年12月6日 19:00 ");

        Mail mail = new Mail();
        //传null会给配置文件里默认邮箱发邮件
        mail.setEmail(null);
        mail.setParams(params);
        mail.setTemplate(MailTemplateNameEnum.DataMonitorReport.getCode());
        mail.setSubject("采集监控报告");
        mailSendService.sendWithHTMLTemplate(mail);
    }
}

添加定时任务

-主类添加注解@EnableScheduling

  • 创建定时任务类
@Slf4j
@Component
public class ScheduledService {
    @Scheduled(cron = "0/5 * * * * *")
    public void scheduled(){
        log.info("=====>>>>>使用cron  {}",System.currentTimeMillis());
    }
    @Scheduled(fixedRate = 5000)
    public void scheduled1() {
        log.info("=====>>>>>使用fixedRate{}", System.currentTimeMillis());
    }
    @Scheduled(fixedDelay = 5000)
    public void scheduled2() {
        log.info("=====>>>>>fixedDelay{}",System.currentTimeMillis());
    }
}

注意:可以看到三个定时任务都已经执行,并且使同一个线程中串行执行,如果只有一个定时任务,这样做肯定没问题,当定时任务增多,如果一个任务卡死,会导致其他任务也无法执行,多线程任务执行可以参考https://blog.csdn.net/wqh8522/article/details/79224290

邮件效果如下:

SpringBoot按照模板定时发送邮件,JavaMail发送,支持FreeMark模板渲染_第2张图片
image.png

你可能感兴趣的:(SpringBoot按照模板定时发送邮件,JavaMail发送,支持FreeMark模板渲染)