近期项目中有定时邮件推送的需求,经过一番实践,最终实现,因此将开发步骤记录下来:
涉及的技术:
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:"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:"font-size:13px;background-color:#FFFFFF;">xxx有限公司</span><br />
<span style="font-family:"font-size:13px;background-color:#FFFFFF;">xxx</span><br />
<p>
<span style="font-family:"font-size:13px;background-color:#FFFFFF;">邮箱:xx@xxx.com </span>
</p>
<p>
<span style="font-family:"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.收到的邮件如下图