Spring Boot整合郵件配置


概述

這個技術是做什么?學習該技術的原因,技術的難點在哪里。

這個技術能使項目具備發送郵件的功能,這個技術我是作為技術儲備來學習的,沒想到在學習后沒多久就能夠有用武之地。該項技術總體難度不大,硬要說難的地方就在於整合模板引擎發送模板郵件,因為還要同時了解一些模板引擎的知識,不過如果有JSP相關知識會容易應付得多。

整合郵件發送功能

Spring Boot 2.x集成了mail模塊

image-20200614220248741

在pom.xml中引入依賴

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

 

郵箱配置

一些必要的名詞解釋

  • 什么是POP3、SMTP和IMAP?
    他們是三種郵件協議。簡單來說,POP3和IMAP是用來從服務器上下載郵件的。SMTP適用於發送或中轉信件時找到下一個目的地。所以我們發送郵件應該使用SMTP協議。

  • 什么是郵箱客戶端授權碼?
    郵箱客戶端授權碼是為了避免郵箱密碼被盜后,盜號者通過客戶端登錄郵箱而設計的安防功能。

QQ郵箱配置

網頁登錄QQ郵箱→設置→開啟相應服務並生成授權碼

image-20200614211908944

spring boot配置:

spring:
  mail:
    host: smtp.qq.com #發送郵件服務器
    username: xx@qq.com #QQ郵箱
    password: xxxxxxxxxxx #客戶端授權碼
    protocol: smtp #發送郵件協議
    properties.mail.smtp.auth: true
    properties.mail.smtp.port: 465 #端口號465或587
    properties.mail.display.sendmail: aaa #可以任意
    properties.mail.display.sendname: bbb #可以任意
    properties.mail.smtp.starttls.enable: true
    properties.mail.smtp.starttls.required: true
    properties.mail.smtp.ssl.enable: true #開啟SSL
    default-encoding: utf-8

 

網易系(126/163/yeah)郵箱配置

網頁登錄網易郵箱→設置→POP3/SMTP/IMAP

image-20200614212409282

spring boot配置:

spring:
  mail:
    host: smtp.126.com #發送郵件服務器
    username: xx@126.com #網易郵箱
    password: xxxxxxxx #客戶端授權碼
    protocol: smtp #發送郵件協議
    properties.mail.smtp.auth: true
    properties.mail.smtp.port: 994 #465或者994
    properties.mail.display.sendmail: aaa #可以任意
    properties.mail.display.sendname: bbb #可以任意
    properties.mail.smtp.starttls.enable: true
    properties.mail.smtp.starttls.required: true
    properties.mail.smtp.ssl.enable: true #開啟SSL
    default-encoding: utf-8
    from: xx@126.com

 

  • 126郵箱SMTP服務器地址:smtp.126.com
  • 163郵箱SMTP服務器地址:smtp.163.com
  • yeah郵箱SMTP服務器地址:smtp.yeah.net

發送簡單的文本郵件

寫個郵件服務Service

@Service
public class MailService {
    // Spring官方提供的集成郵件服務的實現類,目前是Java后端發送郵件和集成郵件服務的主流工具。
    @Resource
    private JavaMailSender mailSender;

    // 從配置文件中注入發件人的姓名
    @Value("${spring.mail.username}")
    private String fromEmail;

    /**
     * 發送文本郵件
     *
     * @param to      收件人
     * @param subject 標題
     * @param content 正文
     * @throws MessagingException
     */
    public void sendSimpleMail(String to, String subject, String content) {
        SimpleMailMessage message = new SimpleMailMessage();
        message.setFrom(fromEmail); // 發件人
        message.setTo(to);    
        message.setSubject(subject);
        message.setText(content);
        mailSender.send(message);
    }
}

 

在業務中調用該服務的方法即可

mailService.sendSimpleMail("xxxxxx@xx.com","普通文本郵件","普通文本郵件內容");

發送html郵件

為了方便,在原來的Service里直接添加一個方法

/**
 * 發送html郵件
 */
public void sendHtmlMail(String to, String subject, String content) throws MessagingException {
    //注意這里使用的是MimeMessage
    MimeMessage message = mailSender.createMimeMessage();
    MimeMessageHelper helper = new MimeMessageHelper(message, true);
    helper.setFrom(from);
    helper.setTo(to);
    helper.setSubject(subject);
    //第二個參數:格式是否為html
    helper.setText(content, true);

    mailSender.send(message);
}

 

調用該方法,直接傳入html代碼的字符串作為正文參數:

mailService.sendHtmlMail("xxxxxx@xx.com","一封html測試郵件","
            "<div style=\"text-align: center;position: absolute;\" >\n"
            +"<h3>\"一封html測試郵件\"</h3>\n"
            + "<div>一封html測試郵件</div>\n"
            + "</div>");

 

像上面直接傳遞html字符串發送html郵件,在java類里寫html代碼總有點怪怪的,而且有很明顯的缺點,若是要用相同樣式發送不同的內容,代碼冗余度就會增加;而且若是需要發送一個復雜的html頁面,代碼看起來就一團亂麻,而且不方便調整郵件的樣式。

我們希望html和java分離開,在java里就只管java,頁面代碼乖乖到頁面文件里面,需要時直接調取該頁面文件,整合模板引擎就是一個不錯的解決方案。👇

發送基於模板的郵件(以模板引擎freemarker為例)

該方法本質上還是發送html郵件,只不過是有一個把模板轉換成html字符串的過程,thymeleaf也可以實現。這個方法還能使你的系統發出的郵件更加美觀。

image-20200614213422214

說明:這里不詳細介紹freemarker的內容,在這里只描述它的一個使用場景——生成電子郵件,想要進一步了解freemarker請行學習

添加依賴:

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

 

springboot配置

spring:
#freemarker默認存放路徑
freemarker:
template-loader-path: classpath:/templates/freemarker/
suffix: .ftl
cache: false
charset: UTF-8
settings:
classic_compatible: true

 

在存放模板的文件夾下寫一個html模板

image-20200614170329668

內容如下:

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8" />
    <title>freemarker簡單示例</title>
</head>
<body>
<h1>Hello Freemarker</h1>
    <div>My name is ${myname}</div>
</body>
</html>

 

仍然為了方便,在原來的Service里直接添加代碼

@Autowired
private FreeMarkerConfigurer freeMarkerConfigurer;

@Test
public void sendTemplateMail(String to, String subject, String template) throws IOException, TemplateException, MessagingException {
    // 獲得模板
    Template template = freeMarkerConfigurer.getConfiguration().getTemplate(template);
    // 使用Map作為數據模型,定義屬性和值
    Map<String,Object> model = new HashMap<>();
    model.put("myname","ZYF");
    // 傳入數據模型到模板,替代模板中的占位符,並將模板轉化為html字符串
    String templateHtml = FreeMarkerTemplateUtils.processTemplateIntoString(template,model);
    // 該方法本質上還是發送html郵件,調用之前發送html郵件的方法
    this.sendHtmlMail(to, subject, templateHtml);
}

 

要用的時候調用即可

mailService.sendTemplateMail("xxxxx@xx.com", "基於模板的html郵件", "fremarkertemp.html");

 

發送帶附件的郵件

話不多說上代碼:

/**
 * 發送帶附件的郵件
 */
public void sendAttachmentsMail(String to, String subject, String content, String filePath) throws MessagingException {
    MimeMessage message = mailSender.createMimeMessage();
    //要帶附件第二個參數設為true
    MimeMessageHelper helper = new MimeMessageHelper(message, true);
    helper.setFrom(fromEmail);
    helper.setTo(to);
    helper.setSubject(subject);
    helper.setText(content, true);

    FileSystemResource file = new FileSystemResource(new File(filePath));
    String fileName = filePath.substring(filePath.lastIndexOf(File.separator));
    helper.addAttachment(fileName, file);

    mailSender.send(message);
}

 

調用時傳入文件路徑:

String filePath = "D:\\projects\\springboot\\template.png";
mailService.sendAttachmentsMail("xxxx@xx.com", "帶附件的郵件", "郵件中有附件", filePath);

 

郵箱服務實戰

這是我某次實踐中郵箱服務的運用,目的是為了能夠定時發送郵件,由於發送郵件是耗時操作,為了不妨礙系統處理用戶請求,添加了@Async注解,定時任務將會在獨立的線程中被執行,下面放上鏈接:

ScheduleJob.java

MailServiceImpl.java

EmailTemplate.html

application.yml

我的踩坑記錄

郵件服務器連接失敗

org.springframework.mail.MailSendException: Mail server connection failed; 
...
nested exception is:
  java.net.UnknownHostException: smtp.163.com 
 ...

 

  1. 網絡問題

    控制台輸入ping smtp.163.com看看是否能ping通;

  2. 配置問題

    檢查一下application.yml的郵件服務器配置有沒有拼寫或格式錯誤(比如多按了一個空格);

    開啟SSL時使用587端口時是無法連接QQ郵件服務器的,請使用465端口

授權失敗

org.springframework.mail.MailAuthenticationException: Authentication failed;nested exception is
javax.mail.AuthenticationFailedException: 550 User has no permission
...

 

這個坑是我在教同學時遇到的

按照上文去打開郵箱的stmp服務即可解決

消息發送失敗

org.springframework.mail.MailSendException: Failed messages: 
 
com.sun.mail.smtp.SMTPSendFailedException: 554 DT:SPM 163 smtp11,D8CowACX7CmSHB5b3SrlCA--.26635S3 
 
1528700051,please see http://mail.163.com/help/help_spam_16.htm?ip=182.138.102.204&hostid=smtp11&time=1528700051
...

 

點進報錯信息提供的網址瞧瞧,是網易官方的退信代碼說明,也就是說我們發送的消息被退回來了:

image-20200614214050517

注意到報錯信息的退信代碼554,看看554是啥來頭:

image-20200614214201544

原來是被識別為垃圾郵件了,檢查一下郵件的主題及內容,使用合法信息,我當時是因為郵件內容包含test測試這些字眼所以被攔截了。

 

轉載自:https://www.cnblogs.com/sillyby/p/13131340.html

 


免責聲明!

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



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