SpringBoot 集成郵件服務(wù)(七)

? ?互聯(lián)網(wǎng)發(fā)展到現(xiàn)在,相必大家都知道發(fā)送郵件應(yīng)該是網(wǎng)站的必備功能之一:用戶(hù)注冊(cè)發(fā)送郵箱驗(yàn)證、忘記密碼、監(jiān)控提醒以及發(fā)送營(yíng)銷(xiāo)信息等。
? ?Spring Email抽象的核心是MailSender接口,MailSender的實(shí)現(xiàn)能夠把Email發(fā)送給郵件服務(wù)器,由郵件服務(wù)器實(shí)現(xiàn)郵件發(fā)送的功能。
? ?早期發(fā)送郵件是通過(guò)Java自帶的JavaMail類(lèi)來(lái)發(fā)送郵件的,需要自己封裝消息體;
? ?后來(lái)Spring推出了JavaMailSender類(lèi)大大簡(jiǎn)化了發(fā)送郵件的過(guò)程,JavaMailSender繼承自MailSender,提供了更強(qiáng)大的郵件發(fā)送功能,可支持不同類(lèi)型的郵件發(fā)送。再到現(xiàn)在的Spring Boot又對(duì)其進(jìn)行封裝從而出現(xiàn)了spring-boot-starter-mail,進(jìn)一步優(yōu)化和完善郵件發(fā)送功能。


一、郵箱授權(quán)

在集成郵件服務(wù)前,需要獲取郵箱的授權(quán)碼。

? ?1、163郵箱步驟
? ?163郵箱- > 設(shè)置 - > 郵箱安全設(shè)置 - >客戶(hù)端授權(quán)密碼 - > 開(kāi)啟客戶(hù)端授權(quán)碼 - > 填寫(xiě)授權(quán)碼。


? ?2、QQ郵箱步驟
QQ郵箱 - > 設(shè)置 - > 賬戶(hù)- >POP3/SMTP服務(wù):開(kāi)啟服務(wù)后會(huì)獲得QQ的授權(quán)碼。


二、搭建準(zhǔn)備

? ?1、pom.xml文件

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-mail</artifactId>
</dependency>

? ?2、配置文件

 spring.mail.host=smtp.163.com
 # 郵箱地址
 spring.mail.username=****@qq.com
 # 郵箱授權(quán)碼
 spring.mail.password=****
 spring.mail.properties.mail.smtp.auth=true
 spring.mail.properties.mail.smtp.starttls.enable=true
 spring.mail.properties.mail.smtp.starttls.required=true
 spring.mail.default-encoding=UTF-8

? ?3、創(chuàng)建郵件發(fā)送Bean

 public class MailBean implements Serializable {
        private static final long serialVersionUID = -2116367492649751914L;
        private String recipient;//郵件接收人
        private String subject; //郵件主題
        private String content; //郵件內(nèi)容
       // 省略setget方法
}

三、文本郵件發(fā)送

??Spring已經(jīng)幫我們內(nèi)置了JavaMailSender,直接在項(xiàng)目中引用即可。有了JavaMailSender,那么郵件發(fā)送就是一件再簡(jiǎn)單不過(guò)的事情了。我們只需要將JavaMailSender的Bean注入到我們自己的實(shí)現(xiàn)類(lèi)中,然后使用JavaMail API來(lái)發(fā)送Email。

@Component
public class MailUtil {
@Value("${spring.mail.username}")
private String MAIL_SENDER; //郵件發(fā)送者

@Autowired
private JavaMailSender javaMailSender;

private Logger logger = LoggerFactory.getLogger(MailUtil.class);

/**
 * 發(fā)送文本郵件
 *
 * @param mailBean
 */
public  void sendSimpleMail(MailBean mailBean) {
    try {
        SimpleMailMessage mailMessage= new SimpleMailMessage();
        mailMessage.setFrom(MAIL_SENDER);
        mailMessage.setTo(mailBean.getRecipient());
        mailMessage.setSubject(mailBean.getSubject());
        mailMessage.setText(mailBean.getContent());
        //mailMessage.copyTo(copyTo);

        javaMailSender.send(mailMessage);
    } catch (Exception e) {
        logger.error("郵件發(fā)送失敗", e.getMessage());
    }
}
}

其中:
from:即為郵件發(fā)送者,一般設(shè)置在配置文件中
to:郵件接收者,此參數(shù)可以為數(shù)組,同時(shí)發(fā)送多人
subject:郵件主題
content:郵件的主體
copyTo:抄送人

  • 文本郵件測(cè)試類(lèi)
@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringbootMailApplicationTests {

@Autowired
private MailUtil mailUtil;

@Autowired
private TemplateEngine templateEngine;

//接收人
private static final String RECIPINET = "****@163.com";

/**
 * 發(fā)送文本郵件
 */
@Test
public void sendSimpleMail() {
    MailBean mailBean = new MailBean();
    mailBean.setRecipient(RECIPINET);
    mailBean.setSubject("SpringBootMail之這是一封文本的郵件");
    mailBean.setContent("SpringBootMail發(fā)送一個(gè)簡(jiǎn)單格式的郵件,時(shí)間為:" + DateUtils.format(new Date()));

    mailUtil.sendSimpleMail(mailBean);
}

}
  • 稍微等待幾秒,就可以在郵箱中找到此郵件內(nèi)容了。至此一個(gè)簡(jiǎn)單的文本郵件發(fā)送就完成了。

四、HTML格式郵件發(fā)送

? ? 與文本格式郵件代碼對(duì)比,富文本HTML郵件發(fā)送使用MimeMessageHelper類(lèi),把setText()方法的消息文本設(shè)置為html,并將第二個(gè)參數(shù)設(shè)置為true,表示這是html的富文本。MimeMessageHelper支持發(fā)送復(fù)雜郵件模板,支持文本、附件、HTML、圖片等。

 public void sendHTMLMail(MailBean mailBean) {
         MimeMessage mimeMailMessage = null;
   try {
        mimeMailMessage = javaMailSender.createMimeMessage();
        //true 表示需要?jiǎng)?chuàng)建一個(gè)multipart message
        MimeMessageHelper mimeMessageHelper = new MimeMessageHelper(mimeMailMessage, true);
        mimeMessageHelper.setFrom(MAIL_SENDER);
        mimeMessageHelper.setTo(mailBean.getRecipient());
        mimeMessageHelper.setSubject(mailBean.getSubject());
        //郵件抄送
        //mimeMessageHelper.addCc("抄送人");
        mimeMessageHelper.setText(mailBean.getContent(), true);
        javaMailSender.send(mimeMailMessage);
        } catch (Exception e) {
           logger.error("郵件發(fā)送失敗", e.getMessage());
      }
 }
  • HTML格式郵件測(cè)試類(lèi)
 @Test
 public void sendHTMLMail() {
       MailBean mailBean = new MailBean();
       mailBean.setRecipient(RECIPINET);
       mailBean.setSubject("SpringBootMailHTML之這是一封HTML格式的郵件");
       StringBuilder sb = new StringBuilder();
       sb.append("<h2>SpirngBoot測(cè)試郵件HTML</h2>")
         .append("<p style='text-align:left'>這是一封HTML郵件...</p>")
         .append("<p> 時(shí)間為:"+ DateUtils.format(new Date()) +"</p>");
       mailBean.setContent(sb.toString());
       mailUtil.sendHTMLMail(mailBean);
}
  • 郵件內(nèi)容寫(xiě)了一段話(huà),下面為接收到的效果:

由此我們發(fā)現(xiàn)發(fā)送HTML郵件,就是需要拼接一段HTML的String字符串交給MimeMessageHelper來(lái)處理,最后由郵件客戶(hù)端負(fù)責(zé)渲染顯示內(nèi)容。


五、附件格式郵件發(fā)送

? ? 發(fā)送附件需要用到FileSystemResource類(lèi)對(duì)文件進(jìn)行封裝,再添加到MimeMessageHelper中??梢酝ㄟ^(guò)多個(gè)addAttachment方法發(fā)送多個(gè)附件,File.separator是用來(lái)分隔同一個(gè)路徑字符串中的目錄。

public void sendAttachmentMail(MailBean mailBean) {
       MimeMessage mimeMailMessage = null;
       try {
            mimeMailMessage = javaMailSender.createMimeMessage();
            //true 表示需要?jiǎng)?chuàng)建一個(gè)multipart message
            MimeMessageHelper mimeMessageHelper = new MimeMessageHelper(mimeMailMessage, true);
            mimeMessageHelper.setFrom(MAIL_SENDER);
            mimeMessageHelper.setTo(mailBean.getRecipient());
            mimeMessageHelper.setSubject(mailBean.getSubject());
            mimeMessageHelper.setText(mailBean.getContent());
            //文件路徑 目前寫(xiě)死在代碼中,之后可以當(dāng)參數(shù)傳過(guò)來(lái),或者在MailBean中添加屬性absolutePath
           String absolutePath = "D:\\Program Files\\test.jpg";
           FileSystemResource file = new FileSystemResource(new File(absolutePath));
           //FileSystemResource file = new FileSystemResource(new File("src/main/resources/static/image/email.png"));
           String fileName = absolutePath.substring(absolutePath.lastIndexOf(File.separator));
           //添加附件,第一個(gè)參數(shù)表示添加到 Email 中附件的名稱(chēng),第二個(gè)參數(shù)是圖片資源
           mimeMessageHelper.addAttachment(fileName, file);
          //多個(gè)附件
          //mimeMessageHelper.addAttachment(fileName1, file1);

           javaMailSender.send(mimeMailMessage);
           } catch (Exception e) {
               logger.error("郵件發(fā)送失敗", e.getMessage());
           }   
}
  • 測(cè)試郵件發(fā)送
@Test
public void sendAttachmentMail(){
   MailBean mailBean = new MailBean();
   mailBean.setRecipient(RECIPINET);
   mailBean.setSubject("SpringBootMail之這是一封有附件格式的郵件");
   mailBean.setContent("SpringBootMail發(fā)送一封有附件格式的郵件,時(shí)間為:"+ DateUtils.format(new Date()));

   mailUtil.sendAttachmentMail(mailBean);
}
  • 效果圖如下:

六、靜態(tài)資源格式郵件發(fā)送

? ? 郵件格式的靜態(tài)資源,需要用到MimeMessageHelper中的addInline方法。需要注意的是:添加內(nèi)聯(lián)資源,一個(gè)id對(duì)應(yīng)一個(gè)資源,最終通過(guò)id來(lái)找到該資源。
? ? 即<img src='cid:"+ rscId + "' >和addInline(rscId,res)中的rscId要一致。
同時(shí)要添加多個(gè)圖片,可以使用多條<img src='cid:"+ rscId + "' >和addInline(rscId,res)來(lái)實(shí)現(xiàn)。

public void sendInlineMail(MailBean mailBean) {
       MimeMessage mimeMailMessage = null;
    try {
         mimeMailMessage = javaMailSender.createMimeMessage();
         MimeMessageHelper mimeMessageHelper = new MimeMessageHelper(mimeMailMessage, true);
         mimeMessageHelper.setFrom(MAIL_SENDER);
         mimeMessageHelper.setTo(mailBean.getRecipient());
         mimeMessageHelper.setSubject(mailBean.getSubject());
         mimeMessageHelper.setText(mailBean.getContent(), true);
         //文件路徑
         String absolutePath = "D:\\Program Files\\email.png";
         FileSystemResource file = new FileSystemResource(new File(absolutePath));
        //FileSystemResource file = new FileSystemResource(new File("src/main/resources/static/image/email.png"))
        //添加多個(gè)圖片可以使用多條 <img src='cid:" + rscId + "' > 和 
        mimeMessageHelper.addInline(rscId, res) 來(lái)實(shí)現(xiàn)
        mimeMessageHelper.addInline("picture", file);

       javaMailSender.send(mimeMailMessage);
     } catch (Exception e) {
         logger.error("郵件發(fā)送失敗", e.getMessage());
     }
}
  • 靜態(tài)資源格式郵件發(fā)送
@Test
public void sendInlineMail() {
     MailBean mailBean = new MailBean();
     //id,目前寫(xiě)死了,可根據(jù)需要封裝
      String rscId = "picture";
     String content="<html><body>這是有圖片的郵件:<img src=\'cid:" + rscId + "\' ></body></html>";
      mailBean.setRecipient(RECIPINET);
      mailBean.setSubject("SpringBootMail之這是一封有靜態(tài)資源格式的郵件");
      mailBean.setContent(content);
      mailUtil.sendInlineMail(mailBean);
}
  • 返回結(jié)果如下:

七、Thymeleaf模板郵件發(fā)送

? ? 上述介紹HTML格式的郵件不太優(yōu)雅,修改起來(lái)也很不便,并且HTML硬編碼在程序中。另外模板也適用于局部變化的內(nèi)容,例如某云的郵件提示


更改郵件內(nèi)容時(shí)只需更改用戶(hù)名和鏈接地址即可。

  • 添加依賴(lài)
<dependency>
     <groupId>org.springframework.boot</groupId>
     <artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
  • 創(chuàng)建email.html
 <!DOCTYPE html>
 <html lang="en" xmlns:th="http://www.thymeleaf.org">
 <head>
    <meta charset="UTF-8">
    <title>Title</title>
 </head>
<body>
<h3 th:text="|尊敬的${username} :|"></h3><br />
        <img src="http://gtms02.alicdn.com/tps/i2/T1YoblFq4cXXa94Hfd-32-32.png" /> 您有代金券即將到期,逾期失效,請(qǐng)盡早使用。<a th:href = "${url}" >點(diǎn)此查看</a>
        <br />
  </body>
</html>
  • 解析模板并發(fā)送
    注意:Context類(lèi)是在org.thymeleaf.context.Context包下的。process第一個(gè)參數(shù)名稱(chēng)要和templates下的模板頁(yè)面視圖名稱(chēng)一致,要不然會(huì)報(bào)錯(cuò)。
@Test
public void sendTemplate2Mail() {
     //注意:Context 類(lèi)是在org.thymeleaf.context.Context包下的。
     Context context = new Context();
     //html中填充動(dòng)態(tài)屬性值
     context.setVariable("username", "碼農(nóng)用戶(hù)");
     context.setVariable("url", "https://www.aliyun.com/?utm_content=se_1000301881");
     //注意:process第一個(gè)參數(shù)名稱(chēng)要和templates下的模板名稱(chēng)一致。要不然會(huì)報(bào)錯(cuò)
     //org.thymeleaf.exceptions.TemplateInputException: Error resolving template [email]
     String emailContent = templateEngine.process("email", context);

     MailBean mailBean = new MailBean();
     mailBean.setRecipient(RECIPINET);
     mailBean.setSubject("主題:這是模板郵件");
     mailBean.setContent(emailContent);
     mailUtil.sendHTMLMail(mailBean);
}
  • 返回結(jié)果如下:

八、常見(jiàn)問(wèn)題

九、總結(jié)

? ?使用 Spring Boot 集成發(fā)送郵件的功能非常簡(jiǎn)單,只需要簡(jiǎn)單編碼就可以實(shí)現(xiàn)發(fā)送普通文本郵件、帶附件郵件、HTML 格式郵件、帶圖片郵件等。
? ?如果需要做成一個(gè)郵件系統(tǒng)還需要考慮很多因素,比如:郵箱發(fā)送失敗重試機(jī)制、防止郵件被識(shí)別為垃圾郵件,固定時(shí)間內(nèi)發(fā)送郵件的限制等。
? ?在微服務(wù)架構(gòu)中,常常將一些基礎(chǔ)功能下沉下來(lái),作為獨(dú)立的服務(wù)來(lái)使用,郵件系統(tǒng)作為平臺(tái)的基礎(chǔ)功能,特別適合做為獨(dú)立的微服務(wù)來(lái)支持整個(gè)系統(tǒng)。


注意啦! 往期SpringBoot在這里

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀(guān)點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容