SpringBoot+Freemarker+Quartz 实现定时邮件推送

近期项目中有定时邮件推送的需求,经过一番实践,最终实现,因此将开发步骤记录下来:

涉及的技术:

SpringBoot:v1.5.13.RELEASE

Freemarker:2.0

Springcloud:Dalston.SR3

Quartz 

1.引入依赖,分别为SpringBoot对mail和freemarker模板的集成

<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-mail</artifactId>
</dependency>
<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>

2.配置发送邮箱,bootstrap.yml中配置如下

# 发送邮件配置
  freemarker:
    f
  mail:
    host: 127.0.0.0
    port: xxx
    username: xxx
    password: xxx
    properties:
      mail:
        smtp:
          auth: true
          starttls:
            enable: true
            required: true
          ssl:
            checkserveridentity: false
            trust: 127.0.0.0

3.新建定时任务类JobBusiness ,实现BusinessAgent 

public class JobBusiness implements BusinessAgent {
	
	@Override
	public void execute(String configId, Map jobMap, List jobList) {
	  JobService jobService = ApplicationObjectUtils.getBean(JobService.class);
	  jobService .sendMail();
	}
}

4.新建发送邮件接口JobService

public interface JobService {

    void sendMail();
}

5.新建发送邮件JobServiceImpl

@Service
public class JobServiceImpl extends MybatisManagerImpl implements JobService{

    private static final Logger logger = LoggerFactory.getLogger(JobService.class);

    @Autowired
    private FreeMarkerConfigurer freeMarkerConfigurer;

    @Autowired
    private JavaMailSender javaMailSender;

    private static final String FROM = "bank@xxxx.com";
    private String toarray [] = {"bank1@xxx.com"};
    private String bcc [] = {"bank2@xxx.com"};

    @Override
    public void sendMail() {
        List<Map> list = this.myBatisDao.getSqlSession().selectList("geiMailQuery");
        if(list.size() == 0){
            log.info(""+getToday()+",没有待推送的邮件,本次任务结束!");
            return;
        }
        String title = "订阅:xxx("+getToday()+")";
        //initConfig();//获取redis的收件人、抄送人邮箱
        sendEmail(list,title,toarray, bcc, "Mail.ftl");
    }


    public R sendEmail(List<Map> list, String subject, String[] to, String[] cc, String templateName){
        Long startTime = System.currentTimeMillis();
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("list", list);
        try {
            if (StringUtils.isEmpty(subject)) {
                log.error("发送邮件失败,主题不能为空!");
                return R.success("发送邮件失败,主题不能为空!");
            }
            if (to.length == 0) {
                log.error("发送邮件失败,收件人不能为空!");
                return R.success("发送邮件失败,收件人不能为空!");
            }
            //调用发送模块
            MimeMessage mimeMessage = javaMailSender.createMimeMessage();
            MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true);
            //设置发件信息人
            helper.setFrom(FROM);
            //设置标题
            helper.setSubject(subject);
            helper.setTo(to);
            //抄送
            if (cc.length > 0) {
                helper.setCc(cc);
            }
            //密送
            //helper.setBcc(bccList);
            //获取模板
            Configuration configuration = freeMarkerConfigurer.getConfiguration();
            Template template = configuration.getTemplate(templateName, "UTF-8");
            String text = FreeMarkerTemplateUtils.processTemplateIntoString(template, map);
            helper.setText(text, true);
            //发送
            javaMailSender.send(mimeMessage);
            //附件,后续支持
            //Resource resource = new ClassPathResource("xxx.jpg");
            //helper.addInline("contentId", resource);
            Long endTime = System.currentTimeMillis();
            log.info("邮件发送成功 耗时:" + (endTime - startTime) / 1000 + "s");
            return R.success("邮件发送成功");
        } catch (Exception e) {
            log.error("发送邮件失败:" + e.getMessage());
            return R.success("邮件发送成功");
        }
    }


    private String getToday(){
        Date date = new Date();
        return new SimpleDateFormat("yyyy-MM-dd").format(date);
    }

注:R为封装的一个返回类,具体的返回类型可以自己定义 

6.以163邮箱为发送服务器(测试能发)

public R send163Email(List<Map> list, String subject, String[] to, String[] cc, String templateName){
        Long startTime = System.currentTimeMillis();
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("list", list);
        Properties props = new Properties();
        props.put("mail.smtp.host", "smtp.163.com");
        props.put("mail.smtp.auth", "true");
        props.put("username", "xxx");
        props.put("password", "xxx");//此处为smtp的密码,非邮箱密码
        MimeMessage mimeMessage = null;
        try {
            if (StringUtils.isEmpty(subject)) {
                log.error("发送邮件失败,主题不能为空!");
                return R.success("发送邮件失败,主题不能为空!");
            }
            if (to.length == 0) {
                log.error("发送邮件失败,收件人不能为空!");
                return R.success("发送邮件失败,收件人不能为空!");
            }
            InternetAddress fromAddress = new InternetAddress("xxx@163.com");
            // toemails(字符串,多个收件人用,隔开)
            Session mailSession = Session.getDefaultInstance(props, new Authenticator() {
                protected PasswordAuthentication getPasswordAuthentication() {
                    return new PasswordAuthentication("xxx@163.com", "xxx");//此处为smtp的密码,非邮箱密码
                }
            });
            mimeMessage = new MimeMessage(mailSession);
            MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true);
            //设置发件信息人
            helper.setFrom(FROM);
            //设置标题
            helper.setSubject(subject);
            helper.setTo(to);
            //抄送
            if (cc.length > 0) {
                helper.setCc(cc);
            }
            //密送
            //helper.setBcc(bccList);
            //获取模板
            Configuration configuration = freeMarkerConfigurer.getConfiguration();
            Template template = configuration.getTemplate(templateName, "UTF-8");
            String text = FreeMarkerTemplateUtils.processTemplateIntoString(template, map);
            helper.setText(text, true);
            mimeMessage.saveChanges();
            Transport.send(mimeMessage);
            Long endTime = System.currentTimeMillis();
            log.info("邮件发送成功 耗时:" + (endTime - startTime) / 1000 + "s");
        } catch (Exception e) {
            log.error("Error while sending mail." + e.getMessage(), e);
        }

7.新建Mail.ftl邮件模板,位置:resources/templates

<!DOCTYPE html>
<html lang="zh">
<head>
    <META http-equiv=Content-Type content='text/html; charset=UTF-8'>
    <title>Title</title>
    <style type="text/css">

        table.gridtable {
            font-family: verdana,arial,sans-serif;
            text-align:center;
            font-size:11px;
            color:#333333;
            border-width: 1px;
            border-color: #666666;
            border-collapse: collapse;
            word-break: keep-all;
        }
        table.gridtable th {
            border-width: 1px;
            padding: 8px;
            border-style: solid;
            border-color: #666666;
            background-color: #B7DEE8;
        }
        table.gridtable td {
            border-width: 1px;
            padding: 8px;
            border-style: solid;
            border-color: #666666;
            background-color: #ffffff;
        }


        h3 {
            font-size: 1.8em;
            margin: 2px 0;
            line-height: 1.8em;
        }
    </style>
</head>
<body>
<p style="font-family:&quot;font-size:13px;background-color:#FFFFFF;">
    各位同事大家好!
<div>
    系统内以下数据异常,请核实处理!
</div>
</p>
<table class="gridtable">
    <tr>
        <th>序号</th>
        <th>xx</th>
        <th>xx</th>
        <th>xx</th>
        <th>xx</th>
        <th>xx</th>
        <th>xx</th>
    </tr>
    <#list list as data>
        <tr>
            <th>
                ${data.xx}
            </th>
            <td>
                ${data.xx}
            </td>
            <td>
                ${data.xx}
            </td>
            <td>
                <strong style="color:red">${data.xx}</strong>
            </td>
            <td>
                <strong style="color:red">${data.xx?if_exists}</strong>
            </td>
            <td>
                ${data.xx?if_exists}
            </td>
            <td>
                ${data.xx?if_exists}
            </td>
        </tr>
    </#list>
</table>
<p style="margin: 0px 0cm; widows: 1; font-size: 14px; line-height: 15.75pt; font-family: 宋体; text-align: justify; background-color: rgb(255, 255, 255);"><b><br /></b></p>
<p style="margin: 0px 0cm; widows: 1; font-size: 14px; line-height: 15.75pt; font-family: 宋体; text-align: justify; background-color: rgb(255, 255, 255);"><b><br /></b></p>
<p style="margin: 0px 0cm; widows: 1; font-size: 14px; line-height: 15.75pt; font-family: 宋体; text-align: justify; background-color: rgb(255, 255, 255);"><b><br /></b></p>
<span style="font-family:&quot;font-size:13px;background-color:#FFFFFF;">xxx有限公司</span><br />
<span style="font-family:&quot;font-size:13px;background-color:#FFFFFF;">xxx</span><br />
<p>
    <span style="font-family:&quot;font-size:13px;background-color:#FFFFFF;">邮箱:xx@xxx.com&nbsp;</span>
</p>
<p>
    <span style="font-family:&quot;font-size:13px;background-color:#FFFFFF;">地址:xxx</span>
</p>
<hr color="red" size="“5”" style="font-size: 14px; line-height: 21px; font-family: Verdana;" />
<p style="margin: 0px 0cm; widows: 1; line-height: 15.75pt; font-size: 12pt; font-family: 宋体; background-color: rgb(255, 255, 255);"><span lang="EN-US" style="font-size: 10.5pt; font-family: Calibri, sans-serif; color: rgb(31, 73, 125);"><font size="1" style="color: rgb(0, 0, 0); widows: 2; font-family: Verdana;">系统定时发送,如果收件有误,请将此邮件删除,谢谢</font></span></p>
<br/>
<br/>
</body>
</html>

注意: 如果data.xxx可能为null,则后面加:?if_exists,否则ftl页面将报错

8.收到的邮件如下图

Spring Boot是一个用于构建独立的、基于生产级别的Spring应用程序的框架。而Freemarker是一种模板引擎,用于生成动态内容,特别适合Web应用程序的开发。在Spring Boot中使用Freemarker可以通过引入相应的依赖和配置来实现。 首先,在Spring Boot工程中引入Freemarker依赖。可以通过在pom.xml文件中添加以下依赖来实现: ``` <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-freemarker</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> ``` 这样,在工程中就可以使用Freemarker来处理模板了。如果想要修改模板文件的位置等配置,可以在application.properties文件中进行配置。比如可以通过以下配置来指定模板文件的位置: ``` spring.freemarker.allow-request-override=false spring.freemarker.allow-session-override=false spring.freemarker.cache=false spring.freemarker.charset=UTF-8 spring.freemarker.check-template-location=true spring.freemarker.content-type=text/html spring.freemarker.expose-request-attributes=false spring.freemarker.expose-session-attributes=false spring.freemarker.suffix=.ftl spring.freemarker.template-loader-path=classpath:/templates/ ``` 这样,Spring Boot就会根据这些配置来加载并解析模板文件,生成相应的动态内容。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [Spring Boot 整合 Freemarker](https://blog.csdn.net/yaxuan88521/article/details/117173289)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* [Springboot整合FreeMarker](https://blog.csdn.net/m0_67402096/article/details/126114796)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值