郵件服務(wù)已經(jīng)是基礎(chǔ)性服務(wù)了 ,是網(wǎng)站的必備功能之一,當(dāng)注冊(cè)了某些網(wǎng)站的時(shí)候,郵箱里通常會(huì)收到一封注冊(cè)成功通知郵件或者點(diǎn)擊激活賬號(hào)的郵件,博客園也是如此。本文使用Spring Boot,通過QQ郵箱來模仿博客園發(fā)送一封通知郵件。
博客園發(fā)送的“歡迎您加入博客園”的主題郵件如圖所示。這種通知郵件,只有登錄用戶名在變化,其它郵件內(nèi)容均不變,很適合用郵件模板來處理。

模板可以實(shí)現(xiàn)顯示與數(shù)據(jù)分離,將模板文件和數(shù)據(jù)通過模板引擎生成最終的HTML代碼。
Thymeleaf是一個(gè)適用于Web和獨(dú)立環(huán)境的現(xiàn)代服務(wù)器端Java模板引擎,能夠處理HTML,XML,JavaScript,CSS甚至純文本。Thymeleaf由于使用了標(biāo)簽屬性做為語法,模版頁面直接用瀏覽器渲染,與其它模板引擎(比如Freemaker)相比,Thymeleaf最大的特點(diǎn)是能夠直接在瀏覽器中打開并正確顯示模板頁面,而不需要啟動(dòng)整個(gè)Web應(yīng)用。
Thymeleaf作為Spring官方推薦的模板引擎,Spring boot對(duì)Thymeleaf支持比較友好,配置簡單,這里使用Thymeleaf作為模板引擎。
下面正式開始實(shí)現(xiàn)仿博客園發(fā)送通知郵件。
1. pom.xml添加郵件和模板相關(guān)依賴
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
2. application.property配置郵箱和thymelea模板
我使用的是QQ郵箱,需要獲得QQ郵箱的授權(quán)碼。
關(guān)于QQ郵箱生成授權(quán)碼:進(jìn)入QQ郵箱 --> 郵箱設(shè)置 --> 賬戶 --> POP3/IMAP/SMTP/Exchange/CardDAV/CalDAV服務(wù) --> 生成授權(quán)碼 --> 手機(jī)發(fā)送驗(yàn)證短信 -->得到授權(quán)碼
spring.mail.host=smtp.qq.com
spring.mail.username=QQ郵箱
spring.mail.password=授權(quán)碼
spring.mail.properties.mail.smtp.auth=true
spring.mail.properties.mail.smtp.starttls.enable=true
spring.mail.properties.mail.smtp.starttls.required=true
#thymelea模板配置
spring.thymeleaf.prefix=classpath:/templates/
spring.thymeleaf.suffix=.html
spring.thymeleaf.mode=HTML
spring.thymeleaf.encoding=UTF-8
spring.thymeleaf.servlet.content-type:text/html
#熱部署文件,頁面不產(chǎn)生緩存,及時(shí)更新
spring.thymeleaf.cache=false
spring.resources.chain.strategy.content.enabled=true
spring.resources.chain.strategy.content.paths=/**
3. 編寫Service及其實(shí)現(xiàn)
Service中有兩個(gè)方法:
sendSimpleMail用于發(fā)送簡單的文本郵件,是一個(gè)比較基礎(chǔ)的案例。
sendHtmlMail用于發(fā)送HTML郵件,發(fā)送通知郵件用的就是這個(gè)方法。其實(shí)模板郵件也就是HTML郵件中的一個(gè)子類。
MailService:
public interface MailService {
public void sendSimpleMail(String to, String subject, String content);
public void sendHtmlMail(String to, String subject, String content);
}
MailServiceImpl:
@Component
public class MailServiceImpl implements MailService {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
@Autowired
private JavaMailSender mailSender;
@Value("${spring.mail.username}")
private String from;
@Override
public void sendSimpleMail(String to, String subject, String content) {
SimpleMailMessage message = new SimpleMailMessage();
message.setFrom(from);
message.setTo(to);//郵件接收者
message.setSubject(subject);//郵件主題
message.setText(content);//郵件內(nèi)容
try {
mailSender.send(message);
logger.info("發(fā)送簡單郵件成功!");
} catch (Exception e) {
logger.error("發(fā)送簡單郵件時(shí)發(fā)生異常!", e);
}
}
@Override
public void sendHtmlMail(String to, String subject, String content) {
MimeMessage message = mailSender.createMimeMessage();
try {
//true表示需要?jiǎng)?chuàng)建一個(gè)multipart message
MimeMessageHelper helper = new MimeMessageHelper(message, true);
helper.setFrom(from);
helper.setTo(to);
helper.setSubject(subject);
helper.setText(content, true);
mailSender.send(message);
logger.info("發(fā)送HTML郵件成功!");
} catch (MessagingException e) {
logger.error("發(fā)送HTML郵件時(shí)發(fā)生異常!", e);
}
}
}
4. 創(chuàng)建模板
在resorces/templates下創(chuàng)建emailTemplate.html模板,與模板配置中的spring.thymeleaf.prefix=classpath:/templates/對(duì)應(yīng),不然會(huì)找不到模板。
關(guān)于Thymeleaf的使用這里簡單介紹一下:
引入命名空間:<html xmlns:th="http://www.thymeleaf.org">。不同的約束文檔中,可能會(huì)出現(xiàn)不同含義的相同標(biāo)記名稱,引入名稱空間可以避免混淆和沖突。
訪問數(shù)據(jù):#{user.name}
訪問變量:${today}
輸出URL: 博客園
更多詳情的說明和規(guī)則請(qǐng)參見:Thymeleaf官方文檔
emailTemplate.html:
<!DOCTYPE html>
<html lang="zh" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8" />
<title>歡迎您加入博客園</title>
</head>
<body>
<p>您好,您在博客園的帳戶激活成功,您的登錄用戶名是:<span th:text="${username}"></span>。</p>
<p>--</p>
<div>博客園(
<a th:href="@{https://www.cnblogs.com }">www.cnblogs.com</a>
) - 開發(fā)者的網(wǎng)上家園</div>
<p>代碼改變世界!</p>
</body>
</html>
5. JUnit單元測(cè)試
使用Junit進(jìn)行單元測(cè)試,pom.xml中已經(jīng)默認(rèn)配置好了,需要編寫測(cè)試類和測(cè)試方法。測(cè)試類以xxxTest.java命名,測(cè)試方法上面加@Test注解就可以使用了。具體代碼如下:
@RunWith(SpringRunner.class)
@SpringBootTest
public class EmailTest {
@Autowired
private MailService mailService;
@Autowired
private TemplateEngine templateEngine;
@Test
public void testSendSimpleMail() throws Exception {
mailService.sendSimpleMail("xxx@qq.com", "測(cè)試發(fā)送簡單文本郵件", "測(cè)試發(fā)送簡單文本郵件");
}
@Test
public void testSendTemplateMail() {
Context context = new Context();
context.setVariable("username", "shangguanhao");
String emailContent = templateEngine.process("emailTemplate", context);
mailService.sendHtmlMail("xxx@qq.com", "歡迎您加入博客園", emailContent);
}
}
進(jìn)行Junit測(cè)試,就可以發(fā)送一個(gè)簡答的文本郵件和一個(gè)HTML的模板郵件,幾乎和博客園的一模一樣(如下圖所示):

完整代碼:GitHub地址