前言
講解了日志相關的知識點后。今天來點相對簡單的,一般上,我們在開發一些注冊功能、發送驗證碼或者訂單服務時,都會通過短信或者郵件的方式通知消費者,注冊或者訂單的相關信息。而且基本上郵件的內容都是模版,一些差異化的可根據實際情況來進行替換。比如12306購票成功后,會發送一封購票信息郵件;在京東下單成功后,也會收到一封包含訂單的郵件。所以,今天就來講講如何利用
Spring
提供的JavaMailSender
接口,實現郵件發送功能。
一點知識
講解前,我們先來簡單了解下相關郵件知識。
JavaMail介紹
JavaMail
是由Sun
定義的一套收發電子郵件的API
,不同的廠商可以提供自己的實現類。但它並沒有包含在JDK中,而是作為JavaEE
的一部分。而JavaMailSender
底層也是基於JavaMail
jar包的,官網介紹時就說了依賴關系:
郵件通信協議
- SMTP:簡單郵件傳輸協議,用於發送電子郵件的傳輸協議;
- POP3:用於接收電子郵件的標准協議;
- IMAP:互聯網消息協議,是POP3的替代協議。
這三種協議都有對應SSL加密傳輸的協議,分別是SMTPS
,POP3S
和IMAPS
。除JavaMail
服務提供程序之外,JavaMail
還需要JAF(JavaBeans Activation Framework)
來處理不是純文本的郵件內容,這包括MIME(多用途互聯網郵件擴展)、URL頁面和文件附件等內容。
JavaMail關鍵對象
- Properties:屬性對象。針對不同的的郵件協議,JavaMail規定了服務提供者必須支持一系列屬性。
- Session會話對象
這個不要混淆了,和web
中的session
不一樣的,簡單來說,它就是配置的集合。
Session的主要作用包括兩個方面:
- 接收各種配置屬性信息:通過Properties對象設置的屬性信息;
- 初始化JavaMail環境:根據JavaMail的配置文件,初始化JavaMail環境,以便通過Session對象創建其他重要類的實例。
-
Transport和Store:傳輸和存儲
郵件操作只有發送或接收兩種處理方式,JavaMail
將這兩種不同操作描述為傳輸(javax.mail.Transport)
和存儲(javax.mail.Store)
,傳輸對應郵件的發送,而存儲對應郵件的接收。 -
Message:消息對象
一旦獲得Session
對象,就可以繼續創建要發送的消息。Message
是個抽象類,常用的實現類為:javax.mail.internet.MimeMessage
(下文中使用它來實現附件發送)。 -
Address:地址
創建了Session
和Message
,並將內容填入消息后,就可以用Address
確定信件地址了。Address
也是個抽象類。對應常用實現類:javax.mail.internet.InternetAddress
。
其他相關信息,可點擊查看:https://blog.csdn.net/a2241076850/article/details/52856863講解的比較清楚。這里就不闡述了(本人也是不甚了解,只是寫這篇文章時,有搜索了些相關資料)
Spring
封裝后,使用起來基本上都不需要去關心這些對象值了,簡單了解下即可。當然了,有興趣,可以搜索下相關資料。也可以去官網查看:https://java.net/projects/javamail/pages/Home
SpringBoot集成
SpringBoot
中,集成郵件發送功能,是很簡單的。只需引入spring-boot-starter-mail
即可,以下就簡單的介紹下如何發送不同格式的郵件,已滿足不同的業務需求。
前提條件
0.加入pom
依賴
<!-- 加入mail pom -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
1.配置文件加入相關配置信息,如發送方郵箱信息等。
# 郵件相關
# SMTP服務器地址
spring.mail.host=smtp.qq.com
# SMTP服務器端口號
# spring.mail.port=25
# 發送方帳號
spring.mail.username=郵箱
# 發送方密碼(授權碼)
spring.mail.password=郵箱密碼
#javaMailProperties 配置
# 開啟用戶身份驗證
spring.mail.properties.mail.smtp.auth=true
# STARTTLS:一種通信協議,具體可以搜索下
#spring.mail.properties.mail.smtp.starttls.enable=true
#spring.mail.properties.mail.smtp.starttls.required=true
這里需要注意:使用QQ郵箱
發送時,需要開通POP3/SMTP
服務,郵箱密碼是填寫授權碼
的,而不是郵箱密碼,這個需要注意下。具體網站說明:在設置
-->賬戶
-->POP3/IMAP/SMTP/Exchange/CardDAV/CalDAV服務
有說明,大家可自行獲取授權碼。
關於JavaMailSender
使用文檔,可以查看官網指南:https://docs.spring.io/spring/docs/4.3.18.RELEASE/spring-framework-reference/htmlsingle/#mail。
3.引入JavaMailSender
接口對象,已經自動注入了,只需引入即可。
@Autowired
private JavaMailSender mailSender;
具體可查看spring-boot-autoconfigure
jar包下的org.springframework.boot.autoconfigure.mail
類,里面已經引入了JavaMailSenderImpl
實現類了。
純文本格式
純文本格式,比較簡單,使用
SimpleMailMessage
即可。
/**
* 純文本格式
* @return
*/
@GetMapping("/simple")
public String simpleSend() {
SimpleMailMessage message = new SimpleMailMessage();
message.setFrom("499452441@qq.com");
message.setTo("499452441@qq.com");
message.setSubject("主題:來自oKong郵件");
message.setText("公眾號:一枚趔趄的猿(lqdevOps),作者:oKong");
mailSender.send(message);
return "發送成功!";
}
啟動后,發送,一切正常情況下,可以看見郵件發送成功了。
附件格式
上文有提到,創建附件時,可使用
MimeMessage
消息對象。使用也很簡單,如下:
@GetMapping("/attach")
public String attachSend() throws MessagingException {
MimeMessage mimeMessage = mailSender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true);
helper.setFrom("499452441@qq.com");
helper.setTo("499452441@qq.com");
helper.setSubject("主題:來自oKong郵件(帶附件)");
helper.setText("(含附件)公眾號:一枚趔趄的猿(lqdevOps),作者:oKong");
//添加附件
File qrCode = new File("wxgzh8cm.jpg");
//建議文件帶上后綴,可支持在線預覽
helper.addAttachment("公眾號二維碼.jpg", qrCode);
mailSender.send(mimeMessage);
return "附件郵件發送成功!";
}
說明:主要就是利用addAttachment
方法進行附件添加,可添加多個。附件名稱建議帶上后綴。
運行后,即可看見郵件已發送成功:
HTML內容格式
以上的格式,基本都是純文本格式。我們知道,在發送郵件時,一般上可以使用
html
格式進行發送,可嵌入靜態資源,如圖片等等。而JavaMailSender
中使用也很簡單,主要就是利用MimeMessageHelper
類的setText(String text, boolean html)
方法。
/**
* html格式
* @return
* @throws MessagingException
*/
@GetMapping("/html")
public String htmlSend() throws MessagingException {
MimeMessage mimeMessage = mailSender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true);
helper.setFrom("499452441@qq.com");
helper.setTo("499452441@qq.com");
helper.setSubject("主題:來自oKong郵件(帶附件)");
helper.setText("<html><body><div>(含附件)公眾號:一枚趔趄的猿(lqdevOps),作者:oKong</div><div><img src='cid:winxinQr'></div></body></html>",true);
//抄送人
// helper.setCc("");
//密送人
// helper.setBcc("");
//添加附件
File qrCode = new File("wxgzh8cm.jpg");
//建議文件帶上后綴,可支持在線預覽
helper.addAttachment("公眾號二維碼.jpg", qrCode);
helper.addInline("winxinQr", qrCode);
mailSender.send(mimeMessage);
return "附件郵件發送成功!";
}
注意:這里的cid(Content-ID)
是固定寫法,冒號后面的值即為需要替換資源的contentId
值,就是對應addInline
的資源id。
而且注意官網的一句話:Be sure to first add the text and after that the resources. If you are doing it the other way around, it won’t work! 順序不能顛倒了,需要先設置text
,之后添加資源信息!
啟動后,一切正常即可看見郵件內容如下:
模版郵件
業務開發時,一般上發送的郵件格式都是固定的,而是替換部分參數即可,如用戶信息、訂單信息等。所以,我們可以利用之前講解過的
模版引擎
進行管理各類模版郵件,同時在發送時替換對應的參數值。以下以freemarker
模版引擎為例子。
關於模版引擎的使用,可點擊查看文章:第十六章:web應用開發
0.引入pom依賴
<!-- 加入模版引擎 freemarker -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>
1.加入配置信息,指定模版目錄、后綴名等:
# 緩存配置 開發階段應該配置為false 因為經常會改
spring.freemarker.cache=false
# 模版后綴名 默認為ftl
spring.freemarker.suffix=.ftl
# 文件編碼
spring.freemarker.charset=UTF-8
# 模版加載的目錄
spring.freemarker.template-loader-path=classpath:/templates/
2.編寫模版文件(放在resources\templates
目錄下),主要就是替換userName
變量:
mail.ftl
<html>
<body>
<div>
尊敬的${userName}:
</div>
<div >
您好!
</div>
<div >
多謝關注公眾號:一枚趔趄的猿(ledevOps),分享程序猿日常,不定期發布關於SpringBoot、SpringCloud、Java及其他相關教程,記錄工作中碰到的問題。歡迎關注~
</div>
<div >
一起學習,共同進步!
</div>
<div >
<img src="cid:winxinQr">
</div>
</body>
</html>
3.編寫具體實現類:
//自動注入
@Autowired
freemarker.template.Configuration freemarkerConfig;
@GetMapping("/template")
public String template(String userName) throws Exception {
MimeMessage mimeMessage = mailSender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true);
helper.setFrom("499452441@qq.com");
helper.setTo("499452441@qq.com");
helper.setSubject("主題:" + userName + ",你有一封來自oKong郵件(From模版)");
//設置替換的參數對象
Map<String, Object> model = new HashMap<String, Object>();
model.put("userName", StringUtils.isEmpty(userName) ? "oKong" : userName);
String templateString = FreeMarkerTemplateUtils.processTemplateIntoString(freemarkerConfig.getTemplate("mail.ftl"), model);
helper.setText(templateString,true);
//抄送人
// helper.setCc("");
//密送人
// helper.setBcc("");
//添加附件
File qrCode = new File("wxgzh8cm.jpg");
//建議文件帶上后綴,可支持在線預覽
helper.addAttachment("公眾號二維碼.jpg", qrCode);
helper.addInline("winxinQr", qrCode);
mailSender.send(mimeMessage);
return "模版文件發送成功!";
}
這里說明下:
使用FreeMarker
模版時,可直接使用Spring
提供的工具類FreeMarkerTemplateUtils
的processTemplateIntoString
方法進行模版文件的替換。而freemarker.template.Template
類,熟悉FreeMarker
的同學應該知道,可以直接從配置類freemarker.template.Configuration
中獲取,此類直接注入即可,SpringBoot
在啟動時,已經注入這個bean
了。具體的自動配置可查看:org.springframework.boot.autoconfigure.freemarker
類。
關於一些Freemarker
的語法這里就不說明了,大家可到官網查看下:https://freemarker.apache.org/docs/index.html或者,中文參考(可能版本不是最新):http://freemarker.foofun.cn/toc.html
啟動后,一切正常情況下可以看見如下:郵件內容已被替換了:
參考資料
- https://docs.spring.io/spring/docs/4.3.18.RELEASE/spring-framework-reference/htmlsingle/#mail
- https://docs.spring.io/spring-boot/docs/1.5.15.RELEASE/reference/htmlsingle/#boot-features-email
- https://blog.csdn.net/a2241076850/article/details/52856863
總結
本注解主要簡單的講解了如何利用
JavaMailSender
發送各類格式的郵件。這里只是演示了以JavaMailSender
發送郵件時,使用是很簡單的,只需要調用相應的api方法即可。想了解底層如何實現的同學,建議搜索下相關JavaMail
的知識,加深印象。
最后
目前互聯網上很多大佬都有
SpringBoot
系列教程,如有雷同,請多多包涵了。原創不易,碼字不易,還希望大家多多支持。若文中有所錯誤之處,還望提出,謝謝。
老生常談
- 個人QQ:
499452441
- 微信公眾號:
lqdevOps
個人博客:http://blog.lqdev.cn
完整示例:https://github.com/xie19900123/spring-boot-learning/tree/master/chapter-26
原文地址:http://blog.lqdev.cn/2018/08/29/springboot/chapter-twenty-six