邮件在工作中中经常被用到,场景非常的广泛,比如:注册账户,接收验证码,或者是公司发的公告,又或者是异常消息推送等等。本文中的Spring Boot 的版本是2.6.0
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0modelVersion>
<parent>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-parentartifactId>
<version>2.6.0version>
<relativePath/>
parent>
<groupId>com.aliangroupId>
<artifactId>springEmailartifactId>
<version>0.0.1-SNAPSHOTversion>
<name>SpringEmailname>
<description>SpringEmaildescription>
<properties>
<java.version>1.8java.version>
properties>
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-mailartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-freemarkerartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-testartifactId>
dependency>
<dependency>
<groupId>com.alibabagroupId>
<artifactId>fastjsonartifactId>
<version>1.2.68version>
dependency>
<dependency>
<groupId>org.projectlombokgroupId>
<artifactId>lombokartifactId>
<version>1.16.14version>
dependency>
<dependency>
<groupId>junitgroupId>
<artifactId>junitartifactId>
<version>4.13.2version>
<scope>testscope>
dependency>
dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-maven-pluginartifactId>
plugin>
plugins>
build>
project>
Email.java
@Data
public class Email {
/**
* 邮件发送方
*/
private String sender;
/**
* 邮件接收方
*/
private List<String> receiverList = new ArrayList<>();
/**
* 邮件抄送方
*/
private List<String> ccList = new ArrayList<>();
/**
* 邮件主题
*/
private String subject;
/**
* 邮件内容
*/
private String content;
/**
* 嵌入式资源(key:contentId,value:filePath)
*/
private Map<String, String> inlineMap=new HashMap<>();
/**
* 附件列表(value:filePath)
*/
private List<String> attachmentList = new ArrayList<>();
public String[] getReceiverArray() {
return this.receiverList.toArray(new String[0]);
}
public String[] getCcArray() {
return this.ccList.toArray(new String[0]);
}
public String toJsonString() {
return JSON.toJSONString(this);
}
}
邮件对象主要包含:
EmailService.java
@Slf4j
@Service
public class EmailService {
@Autowired
private JavaMailSenderImpl mailSender;
@Autowired
private FreeMarkerConfigurer configurer;
public boolean sendSimpleEmail(Email email) {
log.info("发送简单邮件信息:{}", email.toJsonString());
// 实例化SimpleMailMessage
SimpleMailMessage simpleMailMessage = new SimpleMailMessage();
try {
// 设置邮件发件人
simpleMailMessage.setFrom(email.getSender());
// 设置邮件接收人(可以多人)
simpleMailMessage.setTo(email.getReceiverArray());
// 设置邮件抄送
String[] ccArray = email.getCcArray();
if (ccArray.length > 0) {
simpleMailMessage.setCc(ccArray); // 普通抄送[邮件接收人可以看到抄送给谁了]
// simpleMailMessage.setBcc(); // 盲抄送[邮件接收人可以看不到抄送给谁了]
}
// 设置邮件主题
simpleMailMessage.setSubject(email.getSubject());
// 设置邮件内容
simpleMailMessage.setText(email.getContent());
// 发送简单邮件
mailSender.send(simpleMailMessage);
return true;
} catch (Exception e) {
log.error(null, e);
}
return false;
}
public boolean sendComplexEmail(Email email, String templateName, Map<String, Object> data) {
log.info("发送复杂邮件信息:{}", email.toJsonString());
MimeMessage mimeMessage = mailSender.createMimeMessage();
try {
MimeMessageHelper messageHelper = new MimeMessageHelper(mimeMessage,true,"UTF-8");
// 设置邮件发件人
messageHelper.setFrom(email.getSender());
// 设置邮件接收人(可以多人)
messageHelper.setTo(email.getReceiverArray());
// 设置邮件抄送
String[] ccArray = email.getCcArray();
if (ccArray.length > 0) {
messageHelper.setCc(ccArray); // 普通抄送[邮件接收人可以看到抄送给谁了]
// messageHelper.setBcc(ccArray); // 盲抄送[邮件接收人可以看不到抄送给谁了]
}
// 设置邮件主题
messageHelper.setSubject(email.getSubject());
// 通过模板后去内容
String content = getContent(templateName, data);
// 设置邮件内容,第二个参数为true表示将发送内容设置为"text/html"
messageHelper.setText(content, true);
// 批量处理嵌入式资源
Map<String, String> inlineMap = email.getInlineMap();
for (Map.Entry<String, String> entry : inlineMap.entrySet()) {
String contentId = entry.getKey();
String filePath = entry.getValue();
// 设置嵌入式资源
messageHelper.addInline(contentId, new File(filePath));
}
// 批量处理附件
List<String> attachmentList = email.getAttachmentList();
for (int i = 0; i < attachmentList.size(); i++) {
String filePath = attachmentList.get(i);
String fileName = i + "-" + filePath.substring(filePath.lastIndexOf(File.separator));
// 设置附件
messageHelper.addAttachment(fileName, new File(filePath));
}
// 发送简单邮件
mailSender.send(mimeMessage);
return true;
} catch (Exception e) {
log.error(null, e);
}
return false;
}
public String getContent(String templateName, Map<String, Object> data) throws TemplateException, IOException {
// 获取模板
Template template = configurer.getConfiguration().getTemplate(templateName, "UTF-8");
// 填充数据并把模板转为字符串
return FreeMarkerTemplateUtils.processTemplateIntoString(template, data);
}
}
其中:
如果你的代码里有多个附件或者多嵌入式资源,就需要如下:
MimeMessageHelper messageHelper = new MimeMessageHelper(mimeMessage,true,"UTF-8");
第二个参数说明你有多个资源文件(嵌入式资源或者附件)
通过MimeMessageHelper的addInline方法可以添加嵌入式资源,比如在邮件里显示图片。
// 设置嵌入式资源
messageHelper.addInline(contentId, new File(filePath));
需要注意的是
通过MimeMessageHelper的addAttachment方法可以添加附件。
// 设置附件
messageHelper.addAttachment(fileName, new File(filePath));
需要注意的是:这里的文件名fileName尽量不要相同,如果有相同的,最好加以区分
complex-email.ftl
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>${title}title>
head>
<body>
<p>
<img width="100" height="50" src='cid:CSDN1234'/>
<img width="100" height="100"src='cid:Alian1223'/>
br>
<span>欢迎使用CSDN博客系统span>
p>
<table>
<tr>
<td>平台地址:td>
<td><a href="${website}">${website}a>td>
tr>
<tr>
<td>登录账号:td>
<td>${account}td>
tr>
<tr>
<td>登录密码:td>
<td>${password}td>
tr>
table>
<p>
温馨提示:密码有效期为90天,密码必须包含大小写字母数字及特殊符号且长度不小于8位,请妥善保管好密码,祝您工作顺利!
p>
body>
html>
需要注意的是:我这里的模板文件complex-email.ftl放到resources目录下了
FreeMarker是一款 模板引擎: 即一种基于模板和要改变的数据, 并用来生成输出文本(HTML网页,电子邮件,配置文件,源代码等)的通用工具。因为我们发送邮件可能会有很多种,频繁改动代码不方便,所以我们采用模板,增加一个模板,然后把参数传入即可。
@Autowired
private FreeMarkerConfigurer configurer;
public String getContent(String templateName, Map<String, Object> data) throws TemplateException, IOException {
// 获取模板
Template template = configurer.getConfiguration().getTemplate(templateName, "UTF-8");
// 填充数据并把模板转为字符串
return FreeMarkerTemplateUtils.processTemplateIntoString(template, data);
}
我们通过FreeMarkerConfigurer来获取到我们的模板,然后通过Spring提供的方法FreeMarkerTemplateUtils.processTemplateIntoString(template, data)完成数据的封装。
当我们使用MimeMessage发送html邮件时,设置邮件内容时,第二个参数为true表示将发送内容设置为"text/html",不然就会把内容当成文本发送了。
// 设置邮件内容,第二个参数为true表示将发送内容设置为"text/html"
messageHelper.setText(content, true);
application.properties
#服务端口
server.port=8080
#上下文路径
server.servlet.context-path=/email
#163邮箱
#配置邮件发送的服务器
spring.mail.host=smtp.163.com
#邮件的发送者
spring.mail.username=你的163邮箱
#邮箱申请的授权码
spring.mail.password=你的授权码
#邮件的编码格式
spring.mail.default-encoding=UTF-8
#邮件服务器连接超时
spring.mail.properties.mail.smtp.connectiontimeout=10000
#邮件接收超时
spring.mail.properties.mail.smtp.timeout=20000
#邮件发送超时
spring.mail.properties.mail.smtp.writetimeout=10000
我上面是使用163邮箱发送,如果你想用QQ邮箱或者企业微信邮箱则类似如下配置:
QQ邮箱
##qq邮箱配置(开启POP3,设置客户端授权码)
##配置邮件发送的服务器
#spring.mail.host=smtp.qq.com
##邮件的发送者
#spring.mail.username=你的QQ号@qq.com
##邮箱申请的授权码
#spring.mail.password=你的授权码
企业微信邮箱
##企业微信邮箱
##配置邮件发送的服务器
#spring.mail.host=smtp.exmail.qq.com
##邮件的发送者
#spring.mail.username=你的企业微信邮箱
##邮箱申请的授权码
#spring.mail.password=你的授权码
spring.mail.port=465
spring.mail.properties.mail.smtp.ssl.enable=true
@Slf4j
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest
public class SimpleEmailTest {
@Autowired
private EmailService emailService;
@Test
public void sendSimpleEmail() {
List<String> receiverList = new ArrayList<>();
receiverList.add("[email protected]");
Email email = new Email();
email.setSender("[email protected]");
email.setReceiverList(receiverList);
email.setSubject("发送简单邮件测试(纯文本)");
email.setContent("文章你都没有看完,好意思说有5年Java功力???");
boolean b = emailService.sendSimpleEmail(email);
log.info("发送结果:{}", b);
}
}
@Slf4j
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest
public class ComplexEmailTest {
@Autowired
private EmailService emailService;
@Test
public void sendComplexEmail() {
List<String> receiverList = new ArrayList<>();
receiverList.add("[email protected]");
// 邮件对象
Email email = new Email();
email.setSender("[email protected]");
email.setReceiverList(receiverList);
email.setSubject("发送复杂邮件测试(带附件)");
// 嵌入式资源
Map<String, String> inlineMap = email.getInlineMap();
inlineMap.put("CSDN1234", "C:\\myFile\\CSDN\\csdn.png");
inlineMap.put("Alian1223", "C:\\myFile\\CSDN\\alian.png");
email.setInlineMap(inlineMap);
// 附件
List<String> attachmentList = email.getAttachmentList();
attachmentList.add("C:\\myFile\\CSDN\\csdn.png");
attachmentList.add("C:\\myFile\\CSDN\\alian.png");
email.setAttachmentList(attachmentList);
// 设置模板数据
Map<String, Object> data = new HashMap<>();
data.put("title", "注册成功");
data.put("website", "https://blog.csdn.net/Alian_1223");
data.put("account", "alian");
data.put("password", "Alian1234");
boolean b = emailService.sendComplexEmail(email, "complex-email.ftl", data);
log.info("发送结果:{}", b);
}
}