Spring Boot實現傳送QQ郵件
簡述
在日常工作開發中,專案中會使用到傳送郵件功能,通過郵件實時通知,實現告警或預警功能,首先介紹以下與傳送接受郵件相關的一些協議:
- 傳送郵件:SMPT、MIME,是一種基於"推"的協議,通過SMPT協議將郵件傳送至郵件伺服器,MIME協議是對SMPT協議的一種補充,如傳送圖片附件等
- 接收郵件:POP、IMAP,是一種基於"拉"的協議,收件人通過POP協議從郵件伺服器拉取郵件
知識進階:
- 什麼是JavaMailSender和JavaMailSenderImpl?
JavaMailSender和JavaMailSenderImpl 是Spring官方提供的整合郵件服務的介面和實現類,以簡單高效的設計著稱,目前是Java後端傳送郵件和整合郵件服務的主流工具。
- 如何通過JavaMailSenderImpl傳送郵件?
非常簡單,直接在業務類注入JavaMailSenderImpl並呼叫send方法傳送郵件。其中簡單郵件可以通過SimpleMailMessage來傳送郵件,而複雜的郵件(例如新增附件)可以藉助MimeMessageHelper來構建MimeMessage傳送郵件
- 什麼是SMTP?
SMTP全稱為Simple Mail Transfer Protocol(簡單郵件傳輸協議),它是一組用於從源地址到目的地址傳輸郵件的規範,通過它來控制郵件的中轉方式。SMTP認證要求必須提供賬號和密碼才能登陸伺服器,其設計目的在於避免使用者受到垃圾郵件的侵擾。
- 什麼是IMAP?
IMAP全稱為Internet Message Access Protocol(網際網路郵件訪問協議),IMAP允許從郵件伺服器上獲取郵件的資訊、下載郵件等。IMAP與POP類似,都是一種郵件獲取協議。
- 什麼是POP3?
POP3全稱為Post Office Protocol 3(郵局協議),POP3支援客戶端遠端管理伺服器端的郵件。POP3常用於“離線”郵件處理,即允許客戶端下載伺服器郵件,然後伺服器上的郵件將會被刪除。目前很多POP3的郵件伺服器只提供下載郵件功能,伺服器本身並不刪除郵件,這種屬於改進版的POP3協議。
- IMAP和POP3協議有什麼不同呢?
兩者最大的區別在於,IMAP允許雙向通訊,即在客戶端的操作會反饋到伺服器上,例如在客戶端收取郵件、標記已讀等操作,伺服器會跟著同步這些操作。而對於POP協議雖然也允許客戶端下載伺服器郵件,但是在客戶端的操作並不會同步到伺服器上面的,例如在客戶端收取或標記已讀郵件,伺服器不會同步這些操作。
準備工作
申請授權碼,以QQ郵箱為例:登入QQ郵箱,點選頂部設定,開啟賬號皮膚,下拉,開啟SMTP服務,點選生成授權碼。
1、引入mail依賴
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
<!-- 熱部署 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
2、配置檔案application.properties中加入相關配置資訊
注意:這裡以QQ郵箱為例,如果為網易 163 郵箱,對應的SMTP伺服器地址為smtp.163.com
##郵件傳送服務
#SMTP伺服器地址
spring.mail.host=smtp.qq.com
#登陸賬號
spring.mail.username=31**4@qq.com
#或授權碼
spring.mail.password=rbjfrpavuoiec
#郵件發信人(即真實郵箱)
spring.mail.properties.from=31**4@qq.com
3、 郵件資訊類(MailVo) 儲存傳送郵件時的郵件主題、郵件內容等資訊
import java.util.Date;
import org.springframework.web.multipart.MultipartFile;
import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.Data;
/**
*
* 類名稱:MailVo
* 類描述: 儲存傳送郵件時的郵件主題、郵件內容等資訊
* 建立人:Administrator
* 建立時間:2020年4月8日 下午2:53:28
* 修改人:Administrator
* 修改時間:2020年4月8日 下午2:53:28
* 修改備註:
* @version
*/
@Data
public class MailVo {
private String id;//郵件id
private String from;//郵件傳送人
private String to;//郵件接收人(多個郵箱則用逗號","隔開)
private String subject;//郵件主題
private String text;//郵件內容
private Date sentDate;//傳送時間
private String cc;//抄送(多個郵箱則用逗號","隔開)
private String bcc;//密送(多個郵箱則用逗號","隔開)
private String status;//狀態
private String error;//報錯資訊
private String filePath;//資源路徑
private String rscId;//資源id (可能有多個圖片)
private String rscPath;
@JsonIgnore
private MultipartFile[] multipartFiles;//郵件附件
}
4、服務層
import com.ykx.mail.model.MailVo;
public interface MailService {
/**
* 傳送純文字郵件
* @param toAddr 傳送給誰
* @param title 標題
* @param content 內容
*/
public void sendTextMail(MailVo vo);
/**
* 傳送 html 郵件
* @param toAddr
* @param title
* @param content 內容(HTML)
*/
public void sendHtmlMail(MailVo vo);
/**
* 傳送待附件的郵件
* @param toAddr
* @param title
* @param content
* @param filePath 附件地址
*/
public void sendAttachmentsMail(MailVo vo);
/**
* 傳送文字中有靜態資源(圖片)的郵件
* @param toAddr
* @param title
* @param content
* @param rscPath 資源路徑
* @param rscId 資源id (可能有多個圖片)
*/
public void sendInlineResourceMail(MailVo vo);
}
5、服務實現層
import java.io.File;
import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.FileSystemResource;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.JavaMailSenderImpl;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Component;
import com.ykx.mail.model.MailVo;
import com.ykx.mail.service.MailService;
@Component
public class MailServiceImpl implements MailService {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
@Autowired
private JavaMailSender mailSender;
@Autowired
private JavaMailSenderImpl mailSenderImp;//注入郵件工具類
// 注入常量使用者名稱
@Value("${spring.mail.username}")
private String from;
/**
* 傳送文字郵件
*/
@Override
public void sendTextMail(MailVo vo) {
// 純文字郵件物件
SimpleMailMessage message = new SimpleMailMessage();
message.setFrom(from);
message.setTo(vo.getTo().split(","));
message.setSubject(vo.getSubject());
message.setText(vo.getText());
try {
mailSender.send(message);
logger.info("Text郵件已經傳送。");
} catch (Exception e) {
logger.error("傳送Text郵件時發生異常!", e);
}
}
/**
* 傳送html郵件
* @param toAddr
* @param title
* @param content
*/
@Override
public void sendHtmlMail(MailVo vo) {
// html 郵件物件
MimeMessage message = mailSender.createMimeMessage();
try {
//true表示需要建立一個multipart message
MimeMessageHelper helper = new MimeMessageHelper(message, true);
helper.setFrom(from);
helper.setTo(vo.getTo().split(","));
helper.setSubject(vo.getSubject());
helper.setText(vo.getText(), true);
mailSender.send(message);
logger.info("html郵件傳送成功");
} catch (MessagingException e) {
logger.error("傳送html郵件時發生異常!", e);
}
}
/**
* 傳送帶附件的郵件
* @param toAddr
* @param title
* @param content
* @param filePath
*/
public void sendAttachmentsMail(MailVo vo){
MimeMessage message = mailSender.createMimeMessage();
try {
MimeMessageHelper helper = new MimeMessageHelper(message, true);
helper.setFrom(from);
helper.setTo(vo.getTo().split(","));
helper.setSubject(vo.getSubject());
helper.setText(vo.getText(), true);
FileSystemResource file = new FileSystemResource(new File(vo.getFilePath()));
String fileName = vo.getFilePath().substring(vo.getFilePath().lastIndexOf(File.separator));
helper.addAttachment(fileName, file);
//helper.addAttachment("test"+fileName, file);
mailSender.send(message);
logger.info("帶附件的郵件已經傳送。");
} catch (MessagingException e) {
logger.error("傳送帶附件的郵件時發生異常!", e);
}
}
/**
* 傳送正文中有靜態資源(圖片)的郵件
* @param toAddr
* @param title
* @param content
* @param rscPath
* @param rscId
*/
public void sendInlineResourceMail(MailVo vo){
MimeMessage message = mailSender.createMimeMessage();
try {
MimeMessageHelper helper = new MimeMessageHelper(message, true);
helper.setFrom(from);
helper.setTo(vo.getTo().split(","));
helper.setSubject(vo.getSubject());
helper.setText(vo.getText(), true);
FileSystemResource res = new FileSystemResource(new File(vo.getRscPath()));
helper.addInline(vo.getRscId(), res);
mailSender.send(message);
logger.info("嵌入靜態資源的郵件已經傳送。");
} catch (MessagingException e) {
logger.error("傳送嵌入靜態資源的郵件時發生異常!", e);
}
}
//獲取郵件發信人
public String getMailSendFrom() {
return mailSenderImp.getJavaMailProperties().getProperty("from");
}
}
6、控制層MailController
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import com.ykx.mail.model.MailVo;
import com.ykx.mail.service.MailService;
@RestController
public class MailController {
@Autowired
private MailService mailService;
/**
* 傳送純文字郵件
*/
@PostMapping("/send/txt")
public void sendTextMail(@RequestBody MailVo vo) {
mailService.sendTextMail(vo);
}
/**
* 傳送 html 郵件
*/
@PostMapping("/send/html")
public void sendHtmlMail(@RequestBody MailVo vo){
mailService.sendHtmlMail(vo);
}
/**
* 傳送待附件的郵件
*/
@PostMapping("/send/attach")
public void sendAttachmentsMail(@RequestBody MailVo vo){
mailService.sendAttachmentsMail(vo);
}
/**
* 傳送文字中有靜態資源(圖片)的郵件
*/
@PostMapping("/send/line")
public void sendInlineResourceMail(@RequestBody MailVo vo){
mailService.sendInlineResourceMail(vo);
}
}
7、測試傳送郵件
8、常見失敗編碼
如果企業定製了郵件伺服器,自然會記錄郵件日誌,根據錯誤編碼儲存日誌有利於日常維護。
例如這些由網易郵箱提供的錯誤編碼標識:
-
421
421 HL:REP 該IP傳送行為異常,存在接收者大量不存在情況,被臨時禁止連線。請檢查是否有使用者傳送病毒或者垃圾郵件,並核對傳送列表有效性;
421 HL:ICC 該IP同時併發連線數過大,超過了網易的限制,被臨時禁止連線。請檢查是否有使用者傳送病毒或者垃圾郵件,並降低IP併發連線數量;
421 HL:IFC 該IP短期內傳送了大量信件,超過了網易的限制,被臨時禁止連線。請檢查是否有使用者傳送病毒或者垃圾郵件,並降低傳送頻率;
421 HL:MEP 該IP傳送行為異常,存在大量偽造傳送域域名行為,被臨時禁止連線。請檢查是否有使用者傳送病毒或者垃圾郵件,並使用真實有效的域名傳送; -
450
450 MI:CEL 傳送方出現過多的錯誤指令。請檢查發信程式;
450 MI:DMC 當前連線傳送的郵件數量超出限制。請減少每次連線中投遞的郵件數量;
450 MI:CCL 傳送方傳送超出正常的指令數量。請檢查發信程式;
450 RP:DRC 當前連線傳送的收件人數量超出限制。請控制每次連線投遞的郵件數量;
450 RP:CCL 傳送方傳送超出正常的指令數量。請檢查發信程式;
450 DT:RBL 發信IP位於一個或多個RBL裡。請參考http://www.rbls.org/關於RBL的相關資訊;
450 WM:BLI 該IP不在網易允許的傳送地址列表裡;
450 WM:BLU 此使用者不在網易允許的發信使用者列表裡; -
451
451 DT:SPM ,please try again 郵件正文帶有垃圾郵件特徵或傳送環境缺乏規範性,被臨時拒收。請保持郵件佇列,兩分鐘後重投郵件。需調整郵件內容或優化傳送環境;
451 Requested mail action not taken: too much fail authentication 登入失敗次數過多,被臨時禁止登入。請檢查密碼與帳號驗證設定;
451 RP:CEL 傳送方出現過多的錯誤指令。請檢查發信程式;
451 MI:DMC 當前連線傳送的郵件數量超出限制。請控制每次連線中投遞的郵件數量;
451 MI:SFQ 發信人在15分鐘內的發信數量超過限制,請控制發信頻率;
451 RP:QRC 發信方短期內累計的收件人數量超過限制,該發件人被臨時禁止發信。請降低該使用者發信頻率;
•451 Requested action aborted: local error in processing 系統暫時出現故障,請稍後再次嘗試傳送; -
500
500 Error: bad syntaxU 傳送的smtp命令語法有誤;
550 MI:NHD HELO命令不允許為空;
550 MI:IMF 發信人電子郵件地址不合規範。請參考http://www.rfc-editor.org/關於電子郵件規範的定義;
550 MI:SPF 發信IP未被髮送域的SPF許可。請參考http://www.openspf.org/關於SPF規範的定義;
550 MI:DMA 該郵件未被髮信域的DMARC許可。請參考http://dmarc.org/關於DMARC規範的定義;
550 MI:STC 發件人當天的連線數量超出了限定數量,當天不再接受該發件人的郵件。請控制連線次數;
550 RP:FRL 網易郵箱不開放匿名轉發(Open relay);
550 RP:RCL 群發收件人數量超過了限額,請減少每封郵件的收件人數量;
550 RP:TRC 發件人當天內累計的收件人數量超過限制,當天不再接受該發件人的郵件。請降低該使用者發信頻率;
550 DT:SPM 郵件正文帶有很多垃圾郵件特徵或傳送環境缺乏規範性。需調整郵件內容或優化傳送環境;
550 Invalid User 請求的使用者不存在;
550 User in blacklist 該使用者不被允許給網易使用者發信;
550 User suspended 請求的使用者處於禁用或者凍結狀態;
550 Requested mail action not taken: too much recipient 群發數量超過了限額; -
552
552 Illegal Attachment 不允許傳送該型別的附件,包括以.uu .pif .scr .mim .hqx .bhx .cmd .vbs .bat .com .vbe .vb .js .wsh等結尾的附件;
552 Requested mail action aborted: exceeded mailsize limit 傳送的信件大小超過了網易郵箱允許接收的最大限制;
-553
553 Requested action not taken: NULL sender is not allowed 不允許發件人為空,請使用真實發件人傳送;
553 Requested action not taken: Local user only SMTP型別的機器只允許發信人是本站使用者;
553 Requested action not taken: no smtp MX only MX型別的機器不允許發信人是本站使用者;
553 authentication is required SMTP需要身份驗證,請檢查客戶端設定;
-554
554 DT:SPM 傳送的郵件內容包含了未被許可的資訊,或被系統識別為垃圾郵件。請檢查是否有使用者傳送病毒或者垃圾郵件;
554 DT:SUM 信封發件人和信頭髮件人不匹配;
554 IP is rejected, smtp auth error limit exceed 該IP驗證失敗次數過多,被臨時禁止連線。請檢查驗證資訊設定;
554 HL:IHU 發信IP因傳送垃圾郵件或存在異常的連線行為,被暫時掛起。請檢測發信IP在歷史上的發信情況和發信程式是否存在異常;
554 HL:IPB 該IP不在網易允許的傳送地址列表裡;
554 MI:STC 發件人當天內累計郵件數量超過限制,當天不再接受該發件人的投信。請降低發信頻率;
554 MI:SPB 此使用者不在網易允許的發信使用者列表裡;
554 IP in blacklist 該IP不在網易允許的傳送地址列表裡。
附上專案文件結構:
參考文件:
作者:yizhiwazi
連結:https://www.jianshu.com/p/5eb000544dd7
相關文章
- spring boot配置QQ郵箱傳送郵件Spring Boot
- Java實現QQ郵件傳送郵件工具類Java
- Spring Boot整合郵件傳送Spring Boot
- Spring Boot實戰系列(6)郵件傳送Spring Boot
- golang傳送郵件(qq郵箱)Golang
- spring-boot-route(二十二)實現郵件傳送功能Springboot
- Spring Boot中使用JavaMailSender傳送郵件Spring BootJavaAI
- Spring boot學習(九)Spring boot配置郵件傳送Spring Boot
- Spring Boot 郵件傳送的 5 種姿勢!Spring Boot
- 電子郵件協議及GO傳送QQ郵件協議Go
- php 傳送郵件(以QQ為例)PHP
- oracle 傳送郵件 實現方法Oracle
- Django實現傳送郵件功能Django
- 用Perl實現郵件傳送
- python實現傳送郵件Python
- Linux Centos7傳送QQ郵件LinuxCentOS
- python實現郵件的傳送Python
- Java實現QQ郵件傳送客戶端Java客戶端
- Spring Boot 參考指南(驗證&傳送電子郵件)Spring Boot
- Spring AMQP 實戰 - 整合 RabbitMQ 傳送郵件SpringMQ
- Spring AMQP 實戰 – 整合 RabbitMQ 傳送郵件SpringMQ
- JavaMail:java使用QQ郵箱傳送郵件簡單版。JavaAI
- JavaMailSender怎麼傳送163和qq郵件JavaAI
- Spring Boot 2.x 圖文教程 | 整合郵件傳送功能Spring Boot
- 郵件傳送
- 傳送郵件
- 使用Spring的MailSender傳送郵件SpringAI
- 傳送郵件出現問題
- Python 實現郵件傳送功能(進階)Python
- Python 實現郵件傳送功能(初級)Python
- SpringBoot實現傳送電子郵件Spring Boot
- python實現基於smtp傳送郵件Python
- Springboot+Javamail實現郵件傳送Spring BootJavaAI
- 使用多執行緒實現郵件傳送執行緒
- Bugfree郵件傳送設定(以QQ郵箱為例)
- asp.net 郵件傳送提醒功能(接收方包括QQ郵箱等)ASP.NET
- SpringBoot整合Mail傳送郵件&傳送模板郵件Spring BootAI
- Laravel 傳送郵件Laravel