SpringBoot+Thymeleaf发送模板邮件
如何在Spring Boot 应用中发送邮件以及使用简单强大的Thymeleaf模板引擎来制作邮件内容。
一、授权码
常用的电子协议有POP3,SMTP,IMAP,协议的具体区别就不进行详细介绍了。这里选择smtp协议进行演示。
登录邮箱,在设置中找到协议地址,点击开启。授权码只会显示一次,需要保存好。
下面是126邮箱对应的三种协议主机地址:
smtp.126.com
pop.126.com
imap.126.com
二、导入pom依赖
<!-- 发送邮件 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
<!-- thymeleaf -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
三、邮件服务器属性配置
通常情况下,如果所需要的依赖在 class path 中都是可用的话,这时候Spring会自动帮你注册一个默认实现的邮件发送服务 (default mail sender service)。 spring.mail.host 属性已经被自动定义了, 所有我们所需要做的事情就是把这个属性添加到我们应用的 application.properties 配置文件中。
为了防止springboot项目打包成jar文件之后,读取不到文件,我们把图片和附件都放在服务器指定路径上,直接读取该文件。
注意:password不是邮箱登录密码,而是第一步中获取的授权码。
#mail
spring.mail.host=smtp.126.com
spring.mail.username=xxx@126.com
spring.mail.password=********
spring.mail.properties.mail.smtp.auth=false
spring.mail.properties.mail.smtp.starttls.enable=false
spring.mail.properties.mail.smtp.starttls.required=false
#html template path (resources/templates/email/template.html)
templatePath=email/template
#mail image path
imagePath=D:\\image\\logo.jpg
#imagePath=/neworiental/web/cpbm/image/logo.jpg
一、默认端口号:25
25端口为SMTP(Simple Mail Transfer Protocol,简单邮件传输协议)服务所开放的,是用于发送邮件。
二、使用465端口发送邮件
465端口是为SMTPS(SMTP-over-SSL)协议服务开放的,这是SMTP协议基于SSL安全协议之上的一种变种它继承了SSL安全协议的非对称加密的高度安全可靠性,可防止邮件泄露。SMTPS和SMTP协议一样,也是用来发送邮件(最重要的一点是阿里云服务器上不能使用25端口发送)
有坑:Could not connect to SMTP host: smtp.qq.com, port: 465, response: -1
需要配置 SSL 如下:
spring:
mail:
host: smtp.126.com #发送邮件服务器
username: xxx@126.com #网易邮箱
password: ********** #客户端授权码
protocol: smtp #发送邮件协议
properties.mail.smtp.auth: true
properties.mail.smtp.port: 465
properties.mail.smtp.starttls.enable: true
properties.mail.smtp.starttls.required: true
properties.mail.smtp.ssl.enable: true #开启SSL
default-encoding: utf-8
from: xx@126.com
properties.mail.debug: true #开启邮件debug (有打印日志 -- 特详细太多)
三、邮件发送的工具类
参考:https://blog.youkuaiyun.com/xujunkai66/article/details/88545796
/**
* 发送邮件工具类
* @author
*/
@Component
public class SendEmailUtils {
private final static Logger logger = LoggerFactory.getLogger(SendEmailUtils.class);
@Autowired
private JavaMailSender javaMailSender;
@Autowired
private TemplateEngine templateEngine;
/**
* html模板邮件
* @param from 发件人
* @param to 收件人
* @param subject 邮件主题
* @param emailParam 给模板的参数
* @param template html模板路径(相对路径) Thymeleaf的默认配置期望所有HTML文件都放在 **resources/templates ** 目录下,以.html扩展名结尾。
* @param imagePath 图片/文件路径(绝对路径)
* @throws MessagingException
*/
public void thymeleafEmail(String from,String[] to, String subject,EmailParam emailParam,String template,String imgPath) throws MessagingException {
MimeMessage mimeMessage =javaMailSender.createMimeMessage();
MimeMessageHelper mimeMessageHelper = new MimeMessageHelper(mimeMessage, true);
mimeMessageHelper.setFrom(from);
mimeMessageHelper.setTo(to);
mimeMessageHelper.setSubject(subject);
// 利用 Thymeleaf 模板构建 html 文本
Context ctx = new Context();
// 给模板的参数的上下文
ctx.setVariable("emailParam", emailParam);
// 执行模板引擎,执行模板引擎需要传入模板名、上下文对象
// Thymeleaf的默认配置期望所有HTML文件都放在 **resources/templates ** 目录下,以.html扩展名结尾。
// String emailText = templateEngine.process("email/templates", ctx);
String emailText = templateEngine.process(template, ctx);
mimeMessageHelper.setText(emailText, true);
// FileSystemResource logoImage= new FileSystemResource("D:\\image\\logo.jpg");
//绝对路径
FileSystemResource logoImage = new FileSystemResource(imgPath);
//相对路径,项目的resources路径下
//ClassPathResource logoImage = new ClassPathResource("static/image/logonew.png");
// 添加附件,第一个参数表示添加到 Email 中附件的名称,第二个参数是图片资源
//一般图片调用这个方法
mimeMessageHelper.addInline("logoImage", logoImage);
//一般文件附件调用这个方法
// mimeMessageHelper.addAttachment("logoImage", resource);
javaMailSender.send(mimeMessage);
}
}
四、邮件参数实体类EmailParam.java
/**
* 邮件参数实体类
* @author
*/
public class EmailParam {
private String itemName;//产品名称
private String stuName;//学生姓名
private String updateContent;//变更操作
private String updatePerson;//操作人员
private String updateDate;//操作时间
private String remarks;//备注
//省略get、set方法
}
五、Controller调用邮件工具类发送邮件
@RestController
@RequestMapping("/test")
public class ItemController {
private final Logger log = LoggerFactory.getLogger(ItemController.class);
@Value("${spring.mail.username}")
private String from;
@Value("${templatePath}")
private String templatePath;
@Value("${imagePath}")
private String imagePath;
@Autowired
private SendEmailUtils sendEmailUtils;
/**
* email
* @param itemIds
* @param response
*/
@PostMapping(value ="/email", produces = "text/plain;charset=UTF-8")
public void testEmaili(String itemIds,HttpServletResponse response/*,
HttpServletRequest request, HttpSession session,
@RequestHeader("Authorization") String authToken, Principal puser*/) {
try {
EmailParam emailParam = new EmailParam();
emailParam.setStuName("张阿牛");
emailParam.setItemName("亚太银行账目统计");
emailParam.setUpdateContent("付款到账");
emailParam.setUpdatePerson("盖茨");
emailParam.setRemarks("成功到账");
//此处to数组输入多个值,即可实现批量发送
String [] to={
"**********@163.cn"};
sendEmailUtils.thymeleafEmail(from, to, "这是一封测试邮件主题", emailParam, templatePath, imagePath);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
六、通过事件监听器监听注册事件并发送邮件
通过监听器自动发送邮件
UserRegisterEvent 事件
import com.base.client.model.entity.BaseUser;
import lombok.Getter;
import org.springframework.context.ApplicationEvent;
/**
* 用户注册事件
*
* @author arjun
* @date 2020/12/15
*/
@Getter
public class UserRegisterEvent extends ApplicationEvent {
/**
* 发送内容
*/
private BaseUser user;
public UserRegisterEvent(Object source, BaseUser user) {
super(source);
this.user = user;
}
}
RegisterSentMailListener 监听器
import com.base.client.model.entity.BaseUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.event.EventListener;
import org.springframework.core.io.ClassPathResource;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Component;
import org.thymeleaf.context.Context;
import org.thymeleaf.spring5.SpringTemplateEngine;
import javax.mail.MessagingException;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import java.io.UnsupportedEncodingException;
/**
* @author arjun
* @date 2020/12/15
*/
@Component
public class RegisterSentMailListener {
@Value("${spring.mail.username}")
private String sender
@Autowired
private JavaMailSender mailSender;
@Autowired
private SpringTemplateEngine templateEngine;
@EventListener
public void sentMail(UserRegisterEvent event) throws MessagingException, UnsupportedEncodingException {
BaseUser user = event.getUser();
MimeMessage message = mailSender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(message, true);
// 发件人设置昵称
helper.setFrom(new InternetAddress(sender, "系统管理员", "UTF-8"));
// 收件人
helper.setTo(user.getEmail());
// 邮件标题
helper.setSubject("【邮件通知】:初始口令");
// 利用Thymeleaf 模板构建HTML文本
Context context = new Context();
// 给模板的参数的上下文
context.setVariable("user", user);
// 执行模板引擎,执行模板引擎需要传入模板名、上下文对象
// Thymeleaf的默认配置期望所有HTML文件都放在 **resources/templates ** 目录下,以.html扩展名结尾。
String emailText = templateEngine.process("email", context);
helper.setText(emailText, true);
// 相对路径,项目的resources路径下
ClassPathResource logoImage = new ClassPathResource("templates/images/logo.png");
// 一般图片调用这个方法,第一个参数表示添加到 Email 中附件的名称,第二个参数是图片资源
helper.addInline("logoImage", logoImage);
mailSender.send(message);
}
}
七、Html模板文件template.html
Thymeleaf的默认配置期望所有HTML文件都放在 **resources/templates ** 目录下,以.html扩展名结尾。
在项目中的路径:**resources/templates/email/template.html
例如:
<div>
<p>nick: <span th:text="${emailParam.itemName}">产品</span></p>
<p>phone: <span th:text="${emailParam.stuName}" >张三</span></p>
<p>email: <span th:text="${emailParam.updateDate}" >2020</span></p>
<p>address: <span th:text="${emailParam.remarks}" >北京</span></p>
</div>
样式详见https://blog.youkuaiyun.com/qq_39669058/article/details/90485532
利用拉易网制作邮箱模板:拉易网
附HTML模板(仅供参考)
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html lang="en" xmlns:th="http://www.thymeleaf.org" xmlns:layout="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<title>邮件通知</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
</head>
<body style="margin-top:0px;margin-bottom:0px;margin-left:0px;margin-right:0px; padding-top:0px;padding-bottom:0px;padding-left:0px;padding-right:0px;">
<table width="100%">
<tr>
<td style="width: 100%;">
<center>
<table class="content-wrap" style="margin: 0px auto; width: 600px;">
<tr>
<td style="