SpringBoot | 第二十六章:郵件發送


前言

講解了日志相關的知識點后。今天來點相對簡單的,一般上,我們在開發一些注冊功能、發送驗證碼或者訂單服務時,都會通過短信或者郵件的方式通知消費者,注冊或者訂單的相關信息。而且基本上郵件的內容都是模版,一些差異化的可根據實際情況來進行替換。比如12306購票成功后,會發送一封購票信息郵件;在京東下單成功后,也會收到一封包含訂單的郵件。所以,今天就來講講如何利用Spring提供的JavaMailSender接口,實現郵件發送功能。

一點知識

講解前,我們先來簡單了解下相關郵件知識。

JavaMail介紹
JavaMail是由Sun定義的一套收發電子郵件的API,不同的廠商可以提供自己的實現類。但它並沒有包含在JDK中,而是作為JavaEE的一部分。而JavaMailSender底層也是基於JavaMailjar包的,官網介紹時就說了依賴關系:
jar依賴

郵件通信協議

  • SMTP:簡單郵件傳輸協議,用於發送電子郵件的傳輸協議;
  • POP3:用於接收電子郵件的標准協議;
  • IMAP:互聯網消息協議,是POP3的替代協議。

這三種協議都有對應SSL加密傳輸的協議,分別是SMTPSPOP3SIMAPS。除JavaMail服務提供程序之外,JavaMail還需要JAF(JavaBeans Activation Framework)來處理不是純文本的郵件內容,這包括MIME(多用途互聯網郵件擴展)、URL頁面和文件附件等內容。

JavaMail關鍵對象

  • Properties:屬性對象。針對不同的的郵件協議,JavaMail規定了服務提供者必須支持一系列屬性。

javaMailProperties

  • 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

其他相關信息,可點擊查看: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服務有說明,大家可自行獲取授權碼。

QQ郵箱


關於JavaMailSender使用文檔,可以查看官網指南:https://docs.spring.io/spring/docs/4.3.18.RELEASE/spring-framework-reference/htmlsingle/#mail

官網文檔

3.引入JavaMailSender接口對象,已經自動注入了,只需引入即可。

    @Autowired
    private JavaMailSender mailSender;

具體可查看spring-boot-autoconfigurejar包下的org.springframework.boot.autoconfigure.mail類,里面已經引入了JavaMailSenderImpl實現類了。

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,之后添加資源信息!

官網提示

啟動后,一切正常即可看見郵件內容如下:

html格式

模版郵件

業務開發時,一般上發送的郵件格式都是固定的,而是替換部分參數即可,如用戶信息、訂單信息等。所以,我們可以利用之前講解過的模版引擎進行管理各類模版郵件,同時在發送時替換對應的參數值。以下以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 >
    &nbsp; &nbsp;您好!
</div>
<div >
    &nbsp; &nbsp;多謝關注公眾號:一枚趔趄的猿(ledevOps),分享程序猿日常,不定期發布關於SpringBoot、SpringCloud、Java及其他相關教程,記錄工作中碰到的問題。歡迎關注~
</div>
<div >
    &nbsp; &nbsp;一起學習,共同進步!
</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提供的工具類FreeMarkerTemplateUtilsprocessTemplateIntoString方法進行模版文件的替換。而freemarker.template.Template類,熟悉FreeMarker的同學應該知道,可以直接從配置類freemarker.template.Configuration中獲取,此類直接注入即可,SpringBoot在啟動時,已經注入這個bean了。具體的自動配置可查看:org.springframework.boot.autoconfigure.freemarker類。

freemarker自動配置

關於一些Freemarker的語法這里就不說明了,大家可到官網查看下:https://freemarker.apache.org/docs/index.html或者,中文參考(可能版本不是最新):http://freemarker.foofun.cn/toc.html

啟動后,一切正常情況下可以看見如下:郵件內容已被替換了:

模版郵件

參考資料

  1. https://docs.spring.io/spring/docs/4.3.18.RELEASE/spring-framework-reference/htmlsingle/#mail
  2. https://docs.spring.io/spring-boot/docs/1.5.15.RELEASE/reference/htmlsingle/#boot-features-email
  3. https://blog.csdn.net/a2241076850/article/details/52856863

總結

本注解主要簡單的講解了如何利用JavaMailSender發送各類格式的郵件。這里只是演示了以qq郵箱作為發送方,使用其他郵箱時,可能會進行相應的配置調整,具體看各郵件系統的要求了。一般上各郵箱系統都會有相應的說明的。使用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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM