J.J. Huang   2019-04-15   Spring Boot   瀏覽次數:次  

SpringBoot - 第二十七章 | JavaMailSender發送信件

📑 目錄
  1. 相關知識
    1. JavaMail介紹
    2. 信件通訊協議
    3. JavaMail關鍵對象
  2. 使用範例
    1. 加入pom的依賴
    2. 參數配置
    3. 單元測試 (純文本格式)
    4. 測試結果
  3. 進階範例
    1. 夾帶附件 (addAttachment)
    2. 測試結果
    3. 嵌入靜態資源 (addInline)
    4. 測試結果
    5. 模板信件 (template)
    6. 測試結果

在開發一些註冊功能、訂閱功能、訂票功能、驗證功能⋯⋯等等,都會透過發送簡訊或是信件的方式通知使用者,基本上內容就是包括了驗證資訊、訂單資訊之類的,而這些內容基本上都是透過模板的方式去做呈現,且可以根據實際上的需求去做調整。例如:我在某網站註冊後,會收到一封需要驗證信箱的信件,或是在網站上訂購了票卷,將會收到該票卷的一些相關資訊。

相信使用過Spring的眾多開發者都知道Spring提供了非常好用的JavaMailSender接口實現信件發送。在Spring Boot的Starter模板中也為此提供了自動化配置。下面通過範例看看如何在Spring Boot中使用JavaMailSender發送信件。

相關知識

JavaMail介紹

是由Sun定義的一套收發電子信件的API,詳細 JavaMail​‌‌‌​​‌‌​‌‌‌​​​​​‌‌‌​​‌​​‌‌​‌​​‌​‌‌​‌‌‌​​‌‌​​‌‌‌​‌‌​​​‌​​‌‌​‌‌‌‌​‌‌​‌‌‌‌​‌‌‌​‌​​​​‌​‌‌​‌​​‌‌​​‌​​​‌‌​​​​​​‌‌​​​‌​​‌‌‌​​‌​​‌‌​​​​​​‌‌​‌​​​​‌‌​​​‌​​‌‌​‌​‌​​‌​‌‌​‌​‌‌‌​​‌‌​‌‌‌​​​​​‌‌‌​​‌​​‌‌​‌​​‌​‌‌​‌‌‌​​‌‌​​‌‌‌​‌‌​​​‌​​‌‌​‌‌‌‌​‌‌​‌‌‌‌​‌‌‌​‌​​​​‌‌​​‌​​​‌‌​‌‌‌

信件通訊協議

常見的電子信件協定有以下幾種:SMTP(簡單信件傳輸協定)、POP3(郵局協定)、IMAP(Internet信件存取協定)、HTTP、S/MIME。這幾種協定都是由TCP/IP協定族定義的。

協議 說明
SMTP SMTP (Simple Mail Transfer Protocol)
主要負責底層的信件系統如何將信件從一台機器傳至另外一台機器。
POP POP (Post Office Protocol)
目前的版本為POP3,POP3是把信件從電子信箱中傳輸到本地電腦的協定。
IMAP IMAP (Internet Message Access Protocol)
目前的版本為IMAP4,是POP3的一種替代協定,提供了信件檢索和信件處理的新功能,這樣用戶可以完全不必下載信件正文就可以看到信件的標題摘要,從信件用戶端軟體就可以對伺服器上的信件和資料夾目錄等進行操作。IMAP協定增強了電子信件的靈活性,同時也減少了垃圾信件對本地系統的直接危害,同時相對節省了用戶察看電子信件的時間。除此之外,IMAP協定可以記憶用戶在離線狀態下對信件的操作(例如移動信件,刪除信件等)在下一次開啟網路連接的時候會自動執行。

這三種協議都有對應SSL加密傳輸的協議,分別是SMTPS,POP3S和IMAPS。

JavaMail關鍵對象

  • Properties:屬性對象。針對不同的的信件協議,JavaMail規定了服務提供者必須支持一系列屬性。
屬性名 類型 說明
mail.stmp.host String SMTP伺服器地址,如smtp.sina.com.cn
mail.stmp.port int SMTP伺服器端口號,默認為25
mail.stmp.auth boolean SMTP伺服器是否需要用戶認證,默認為false
mail.stmp.user String SMTP默認的登陸用戶名
mail.stmp.from String 默認的信件發送源地址
mail.stmp.socketFactory.class String socket工廠類類名,通過設置該屬性可以覆蓋提供者默認的實現,必須實現javax.net.SocketFactory接口
mail.stmp.socketFactory.port int 指定socket工廠類所用的端口號,如果沒有規定,則使用默認的端口號
mail.smtp.socketFactory.fallback boolean 設置為true時,當使用指定的socket類建立socket失敗後,將使用java.net.Socket建立socket,默認為true
mail.stmp.timeout int I/O連接超時時間,單位為毫秒,默認為永不超時
  • Session會話對象
    這個不要混淆了,和web中的session不一樣的,簡單來說,它就是配置的集合。 Session的主要作用包括兩個方面:

1.接收各種配置屬性訊息:通過Properties對象設置的屬性訊息
2.初始化JavaMail環境:根據JavaMail的配置文件,初始化JavaMail環境,以便通過Session對象建立其他重要類的實例​‌‌‌​​‌‌​‌‌‌​​​​​‌‌‌​​‌​​‌‌​‌​​‌​‌‌​‌‌‌​​‌‌​​‌‌‌​‌‌​​​‌​​‌‌​‌‌‌‌​‌‌​‌‌‌‌​‌‌‌​‌​​​​‌​‌‌​‌​​‌‌​​‌​​​‌‌​​​​​​‌‌​​​‌​​‌‌‌​​‌​​‌‌​​​​​​‌‌​‌​​​​‌‌​​​‌​​‌‌​‌​‌​​‌​‌‌​‌​‌‌‌​​‌‌​‌‌‌​​​​​‌‌‌​​‌​​‌‌​‌​​‌​‌‌​‌‌‌​​‌‌​​‌‌‌​‌‌​​​‌​​‌‌​‌‌‌‌​‌‌​‌‌‌‌​‌‌‌​‌​​​​‌‌​​‌​​​‌‌​‌‌‌

  • Transport和Store:傳輸和儲存信件操作只有發送或接收兩種處理方式,JavaMail將這兩種不同操作描述為傳輸(javax.mail.Transport)儲存(javax.mail.Store),傳輸對應信件的發送,而儲存對應信件的接收。

  • Message:消息對象 一旦獲得Session對象,就可以繼續建立要發送的消息。 Message是個抽像類,常用的實現類為:javax.mail.internet.MimeMessage(下文中使用它來實現附件發送)。

  • Address:地址 建立了SessionMessage,並將內容填入消息後,就可以用Address確定信件地址了。 Address也是個抽像類。對應常用實現類:javax.mail.internet.InternetAddress。​‌‌‌​​‌‌​‌‌‌​​​​​‌‌‌​​‌​​‌‌​‌​​‌​‌‌​‌‌‌​​‌‌​​‌‌‌​‌‌​​​‌​​‌‌​‌‌‌‌​‌‌​‌‌‌‌​‌‌‌​‌​​​​‌​‌‌​‌​​‌‌​​‌​​​‌‌​​​​​​‌‌​​​‌​​‌‌‌​​‌​​‌‌​​​​​​‌‌​‌​​​​‌‌​​​‌​​‌‌​‌​‌​​‌​‌‌​‌​‌‌‌​​‌‌​‌‌‌​​​​​‌‌‌​​‌​​‌‌​‌​​‌​‌‌​‌‌‌​​‌‌​​‌‌‌​‌‌​​​‌​​‌‌​‌‌‌‌​‌‌​‌‌‌‌​‌‌‌​‌​​​​‌‌​​‌​​​‌‌​‌‌‌

更詳細的講解 JavaMail JavaMail发送和接收邮件API(详解) ,可以看這邊。


使用範例

加入pom的依賴

1
2
3
4
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>

參數配置

在src/main/resources/application.properties中配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 信件相關
# SMTP伺服器地址
spring.mail.host=smtp.office365.com
# SMTP伺服器端口號
spring.mail.port=587
# 發送方帳號
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

這邊使用outlook.com來做範例,詳細的設定參數可以參閱 Outlook.com 的 POP、IMAP 和 SMTP 設定
注意:信箱密碼,根據不同的信箱可能是填寫所謂的授權碼,像是這邊hotmail,我是使用應用程式密碼來登入的。​‌‌‌​​‌‌​‌‌‌​​​​​‌‌‌​​‌​​‌‌​‌​​‌​‌‌​‌‌‌​​‌‌​​‌‌‌​‌‌​​​‌​​‌‌​‌‌‌‌​‌‌​‌‌‌‌​‌‌‌​‌​​​​‌​‌‌​‌​​‌‌​​‌​​​‌‌​​​​​​‌‌​​​‌​​‌‌‌​​‌​​‌‌​​​​​​‌‌​‌​​​​‌‌​​​‌​​‌‌​‌​‌​​‌​‌‌​‌​‌‌‌​​‌‌​‌‌‌​​​​​‌‌‌​​‌​​‌‌​‌​​‌​‌‌​‌‌‌​​‌‌​​‌‌‌​‌‌​​​‌​​‌‌​‌‌‌‌​‌‌​‌‌‌‌​‌‌‌​‌​​​​‌‌​​‌​​​‌‌​‌‌‌

單元測試 (純文本格式)

測試結果

SpringBoot - 第二十七章 - 圖 1 (01)

SpringBoot - 第二十七章 - 圖 1 (02) SpringBoot - 第二十七章 - 圖 1 (02)

進階範例

在上面範例中,我們通過使用SimpleMailMessage實現了簡單的信件發送,但是實際使用過程中,我們還可能會帶上附件、或是使用信件模板等。這個時候我們就需要使用MimeMessage來設置複雜一些的信件內容。

夾帶附件 (addAttachment)

測試結果

SpringBoot - 第二十七章 - 圖 2 (03)​‌‌‌​​‌‌​‌‌‌​​​​​‌‌‌​​‌​​‌‌​‌​​‌​‌‌​‌‌‌​​‌‌​​‌‌‌​‌‌​​​‌​​‌‌​‌‌‌‌​‌‌​‌‌‌‌​‌‌‌​‌​​​​‌​‌‌​‌​​‌‌​​‌​​​‌‌​​​​​​‌‌​​​‌​​‌‌‌​​‌​​‌‌​​​​​​‌‌​‌​​​​‌‌​​​‌​​‌‌​‌​‌​​‌​‌‌​‌​‌‌‌​​‌‌​‌‌‌​​​​​‌‌‌​​‌​​‌‌​‌​​‌​‌‌​‌‌‌​​‌‌​​‌‌‌​‌‌​​​‌​​‌‌​‌‌‌‌​‌‌​‌‌‌‌​‌‌‌​‌​​​​‌‌​​‌​​​‌‌​‌‌‌

SpringBoot - 第二十七章 - 圖 2 (04) SpringBoot - 第二十七章 - 圖 2 (04)

嵌入靜態資源 (addInline)

以上的格式,基本都是純文本格式。我們知道,在發送信件時,一般上可以使用html格式進行發送,可嵌入靜態資源,如圖片等等。而JavaMailSender中使用也很簡單,主要就是利用MimeMessageHelper類的setText(String text, boolean html)方法。

注意:這裡的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! 順序不能顛倒了,需要先設置文本,之後添加資源訊息!

測試結果

SpringBoot - 第二十七章 - 圖 3 (05)​‌‌‌​​‌‌​‌‌‌​​​​​‌‌‌​​‌​​‌‌​‌​​‌​‌‌​‌‌‌​​‌‌​​‌‌‌​‌‌​​​‌​​‌‌​‌‌‌‌​‌‌​‌‌‌‌​‌‌‌​‌​​​​‌​‌‌​‌​​‌‌​​‌​​​‌‌​​​​​​‌‌​​​‌​​‌‌‌​​‌​​‌‌​​​​​​‌‌​‌​​​​‌‌​​​‌​​‌‌​‌​‌​​‌​‌‌​‌​‌‌‌​​‌‌​‌‌‌​​​​​‌‌‌​​‌​​‌‌​‌​​‌​‌‌​‌‌‌​​‌‌​​‌‌‌​‌‌​​​‌​​‌‌​‌‌‌‌​‌‌​‌‌‌‌​‌‌‌​‌​​​​‌‌​​‌​​​‌‌​‌‌‌

SpringBoot - 第二十七章 - 圖 3 (06) SpringBoot - 第二十七章 - 圖 3 (06)

模板信件 (template)

通常我們使用信件發送服務的時候,都會有一些固定的場景,比如重置密碼、註冊確認等,給每個用戶發送的內容可能只有小部分是變化的。所以,很多時候我們會使用模板引擎來為各類信件設置成模板,這樣我們只需要在發送時去替換變化部分的參數即可。

在Spring Boot中使用模板引擎來實現模板化的信件發送也是非常容易的,下面我們以freemarker為例實現一下。

引入freemarker模組的依賴:​‌‌‌​​‌‌​‌‌‌​​​​​‌‌‌​​‌​​‌‌​‌​​‌​‌‌​‌‌‌​​‌‌​​‌‌‌​‌‌​​​‌​​‌‌​‌‌‌‌​‌‌​‌‌‌‌​‌‌‌​‌​​​​‌​‌‌​‌​​‌‌​​‌​​​‌‌​​​​​​‌‌​​​‌​​‌‌‌​​‌​​‌‌​​​​​​‌‌​‌​​​​‌‌​​​‌​​‌‌​‌​‌​​‌​‌‌​‌​‌‌‌​​‌‌​‌‌‌​​​​​‌‌‌​​‌​​‌‌​‌​​‌​‌‌​‌‌‌​​‌‌​​‌‌‌​‌‌​​​‌​​‌‌​‌‌‌‌​‌‌​‌‌‌‌​‌‌‌​‌​​​​‌‌​​‌​​​‌‌​‌‌‌

1
2
3
4
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>

application.properties加入相關配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 緩存配置 開發階段應該配置為false 因為經常會改
spring.freemarker.cache=false
# 模版後綴名 默認為ftl
spring.freemarker.suffix=.html
# 文件編碼
spring.freemarker.charset=UTF-8
# 模版加載的目錄
spring.freemarker.template-loader-path=classpath:/templates/
# 配置
# locale 該選項指定該模板所用的國家/語言選項
# number_format 指定格式化輸出數字的格式:currency、
# boolean_format 指定兩個布爾值的語法格式,默認值是true,false
# date_format,time_format,datetime_format 定格式化輸出日期的格式
# time_zone 設置格式化輸出日期時所使用的時區
# 數字 千分位標識
spring.freemarker.settings.number_format=,##0.00

在resources/templates/下,建立一個模板頁面template.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<html>
<body>
<div>
    尊敬的${userName}:
</div>
<div >
    &nbsp; &nbsp;你好!
</div>
<div >
    &nbsp; &nbsp;讓我們一起學習,共同進步!
</div>
<div >
    <img src="cid:qrCode">
</div>
</body>
</html>

測試結果

SpringBoot - 第二十七章 - 圖 4 (07)​‌‌‌​​‌‌​‌‌‌​​​​​‌‌‌​​‌​​‌‌​‌​​‌​‌‌​‌‌‌​​‌‌​​‌‌‌​‌‌​​​‌​​‌‌​‌‌‌‌​‌‌​‌‌‌‌​‌‌‌​‌​​​​‌​‌‌​‌​​‌‌​​‌​​​‌‌​​​​​​‌‌​​​‌​​‌‌‌​​‌​​‌‌​​​​​​‌‌​‌​​​​‌‌​​​‌​​‌‌​‌​‌​​‌​‌‌​‌​‌‌‌​​‌‌​‌‌‌​​​​​‌‌‌​​‌​​‌‌​‌​​‌​‌‌​‌‌‌​​‌‌​​‌‌‌​‌‌​​​‌​​‌‌​‌‌‌‌​‌‌​‌‌‌‌​‌‌‌​‌​​​​‌‌​​‌​​​‌‌​‌‌‌

SpringBoot - 第二十七章 - 圖 4 (08) SpringBoot - 第二十七章 - 圖 4 (08)

註:以上參考了
程序猿DD-翟永超Spring Boot中使用JavaMailSender发送邮件 文章。
oKongSpringBoot | 第二十六章:邮件发送文章。