Springboot整合實現(xiàn)郵件發(fā)送的原理詳解
通常在實際項目中,也有其他很多地方會用到郵件發(fā)送,比如通過郵件注冊賬戶/找回密碼,通過郵件發(fā)送訂閱信息等等。SpringBoot集成郵件服務(wù)非常簡單,通過簡單的學(xué)習(xí)即可快速掌握郵件業(yè)務(wù)類的核心邏輯和企業(yè)郵件的日常服務(wù)
開發(fā)前準(zhǔn)備
首先注冊發(fā)件郵箱并設(shè)置客戶端授權(quán)碼,這里以QQ 免費郵箱為例,其他的郵箱的配置也大同小異。
登錄 QQ 郵箱,點擊設(shè)置->賬戶,開啟IMAP/SMTP服務(wù),并生成授權(quán)碼。
基礎(chǔ)知識
電子郵件需要在郵件客戶端和郵件服務(wù)器之間,以及兩個郵件服務(wù)器之間進行郵件傳遞,那就必須要遵守一定的規(guī)則,這個規(guī)則就是郵件傳輸協(xié)議。下面我們分別簡單介紹幾種協(xié)議:
- 什么是SMTP? SMTP全稱為Simple Mail Transfer Protocol(簡單郵件傳輸協(xié)議),它是一組用于從源地址到目的地址傳輸郵件的規(guī)范,通過它來控制郵件的中轉(zhuǎn)方式。SMTP認證要求必須提供賬號和密碼才能登陸服務(wù)器,其設(shè)計目的在于避免用戶受到垃圾郵件的侵擾。
- 什么是IMAP? IMAP全稱為Internet Message Access Protocol(互聯(lián)網(wǎng)郵件訪問協(xié)議),IMAP允許從郵件服務(wù)器上獲取郵件的信息、下載郵件等。IMAP與POP類似,都是一種郵件獲取協(xié)議。
- 什么是POP3? POP3全稱為Post Office Protocol 3(郵局協(xié)議),POP3支持客戶端遠程管理服務(wù)器端的郵件。POP3常用于“離線”郵件處理,即允許客戶端下載服務(wù)器郵件,然后服務(wù)器上的郵件將會被刪除。目前很多POP3的郵件服務(wù)器只提供下載郵件功能,服務(wù)器本身并不刪除郵件,這種屬于改進版的POP3協(xié)議。
- IMAP和POP3協(xié)議有什么不同呢? 兩者最大的區(qū)別在于,IMAP允許雙向通信,即在客戶端的操作會反饋到服務(wù)器上,例如在客戶端收取郵件、標(biāo)記已讀等操作,服務(wù)器會跟著同步這些操作。而對于POP協(xié)議雖然也允許客戶端下載服務(wù)器郵件,但是在客戶端的操作并不會同步到服務(wù)器上面的,例如在客戶端收取或標(biāo)記已讀郵件,服務(wù)器不會同步這些操作。
用戶要在Internet上提供電子郵件功能,必須有專門的電子郵件服務(wù)器。這些郵件服務(wù)器就類似于現(xiàn)實生活中的郵局,它主要負責(zé)接收用戶投遞過來的郵件,并把郵件投遞到郵件接收者的電子郵箱中。
郵件服務(wù)器就好像是互聯(lián)網(wǎng)世界的郵局。按照功能劃分,郵件服務(wù)器可以劃分為兩種類型:
SMTP郵件服務(wù)器:用戶替用戶發(fā)送郵件和接收外面發(fā)送給本地用戶的郵件。 POP3/IMAP郵件服務(wù)器:用戶幫助用戶讀取SMTP郵件服務(wù)器接收進來的郵件。
進階知識
- 什么是
JavaMailSender
和JavaMailSenderImpl
?JavaMailSender
和JavaMailSenderImpl
是Spring官方提供的集成郵件服務(wù)的接口和實現(xiàn)類,以簡單高效的設(shè)計著稱,目前是Java后端發(fā)送郵件和集成郵件服務(wù)的主流工具。 - 如何通過
JavaMailSenderImpl
發(fā)送郵件? 非常簡單,直接在業(yè)務(wù)類注入JavaMailSenderImpl
并調(diào)用send
方法發(fā)送郵件。其中簡單郵件可以通過SimpleMailMessage
來發(fā)送郵件,而復(fù)雜的郵件(例如添加附件)可以借助MimeMessageHelper
來構(gòu)建MimeMessage
發(fā)送郵件。例如:
@Autowired private JavaMailSenderImpl mailSender; @Override public void sendInlineAndAttachMail(String to, String subject, String content, String filePath,String rscPath, String rscId) { logger.info("發(fā)送帶圖片郵件開始:{},{},{},{},{}", to, subject, content, rscPath, rscId); MimeMessage message = mailSender.createMimeMessage(); MimeMessageHelper helper; try { helper = new MimeMessageHelper(message, true); helper.setFrom(from); helper.setTo(to); helper.setSubject(subject); helper.setText(content, true); FileSystemResource file = new FileSystemResource(new File(filePath)); String fileName = file.getFilename(); helper.addAttachment(fileName, file); FileSystemResource res = new FileSystemResource(new File(rscPath)); helper.addInline(rscId, res);//重復(fù)使用添加多個圖片 mailSender.send(message); logger.info("發(fā)送帶圖片和附件郵件成功"); } catch (MessagingException e) { logger.error("發(fā)送帶圖片和附件郵件失敗", e); } }
為什么JavaMailSenderImpl
能夠開箱即用 ? 所謂開箱即用其實就是基于官方內(nèi)置的自動配置,翻看源碼可知曉郵件自動配置類(MailSenderPropertiesConfiguration)
為上下文提供了郵件服務(wù)實例(JavaMailSenderImpl)
。具體源碼如下:
@Configuration @ConditionalOnProperty(prefix = "spring.mail", name = "host") class MailSenderPropertiesConfiguration { private final MailProperties properties; MailSenderPropertiesConfiguration(MailProperties properties) { this.properties = properties; } @Bean @ConditionalOnMissingBean public JavaMailSenderImpl mailSender() { JavaMailSenderImpl sender = new JavaMailSenderImpl(); applyProperties(sender); return sender; }
其中MailProperties
是關(guān)于郵件服務(wù)器的配置信息,具體源碼如下:
@ConfigurationProperties(prefix = "spring.mail") public class MailProperties { private static final Charset DEFAULT_CHARSET = StandardCharsets.UTF_8; private String host; private Integer port; private String username; private String password; private String protocol = "smtp"; private Charset defaultEncoding = DEFAULT_CHARSET; private Map<String, String> properties = new HashMap<>(); }
Spring Boot 集成郵件發(fā)送主要分為以下三步:
加入依賴
pom.xml依賴spring-boot-starter-mail模塊:
<!--javax.mail 郵件發(fā)送--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-mail</artifactId> </dependency>
配置郵件
在配置文件 application.properties
中配置郵件的相關(guān)參數(shù),其中指定了郵件的協(xié)議、端口以及郵件賬戶和授權(quán)碼等。具體內(nèi)容如下:
#郵件配置 #SMTP服務(wù)器地址 spring.mail.host=smtp.qq.com #登陸賬號 spring.mail.username=2590742958@qq.com #注意這里不是郵箱密碼,而是SMTP授權(quán)密碼 spring.mail.password=lvlpxkujplqbdh spring.mail.default-encoding=UTF-8 #開啟加密驗證 spring.mail.properties.mail.smtp.ssl.enable=true #以下項不用改動 spring.mail.properties.mail.smtp.starttls.enable: true spring.mail.roperties.mail.smtp.starttls.required: true
編寫郵件發(fā)送service
,contorller類等。
public class MailServiceImpl implements MailService { private final Logger logger = LoggerFactory.getLogger(MailServiceImpl.class); //使用@Value注入application.properties中指定的用戶名 @Value("${spring.mail.username}") private String from; @Autowired //用于發(fā)送文件 private JavaMailSender mailSender; @Override public void sendAttachmentMail(String to, String subject, String content, String filePath) { logger.info("發(fā)送帶附件郵件開始:{},{},{},{}", to, subject, content, filePath); MimeMessage message = mailSender.createMimeMessage(); MimeMessageHelper helper; try { helper = new MimeMessageHelper(message, true); helper.setFrom(from); helper.setTo(to); helper.setSubject(subject); helper.setText(content, true); FileSystemResource file = new FileSystemResource(new File(filePath)); String fileName = file.getFilename(); helper.addAttachment(fileName, file);//添加附件,可多次調(diào)用該方法添加多個附件 mailSender.send(message); logger.info("發(fā)送帶附件郵件成功"); } catch (MessagingException e) { logger.error("發(fā)送帶附件郵件失敗", e); }
在發(fā)送郵件的同時,我們可以自定義參數(shù)從而生成豐富多彩的郵件,如下
public interface MailService { /** * 發(fā)送普通文本郵件 * @param to 收件人 * @param subject 主題 * @param content 內(nèi)容 */ void sendSimpleMail(String to, String subject, String content); /** * 發(fā)送HTML郵件 * @param to 收件人 * @param subject 主題 * @param content 內(nèi)容(可以包含<html>等標(biāo)簽) */ void sendHtmlMail(String to, String subject, String content); /** * 發(fā)送帶附件的郵件 * @param to 收件人 * @param subject 主題 * @param content 內(nèi)容 * @param filePath 附件路徑 */ void sendAttachmentMail(String to, String subject, String content, String filePath); /** * 發(fā)送帶圖片的郵件 * @param to 收件人 * @param subject 主題 * @param content 文本 * @param rscPath 圖片路徑 * @param rscId 圖片ID,用于在<img>標(biāo)簽中使用,從而顯示圖片 */ void sendInlineResourceMail(String to, String subject, String content, String rscPath, String rscId); /** * 發(fā)送帶圖片的郵件 * @param to 收件人 * @param subject 主題 * @param content 文本 * @param rscPath 圖片路徑 * @param filePath 附件路徑 * @param rscId 圖片ID,用于在<img>標(biāo)簽中使用,從而顯示圖片 */ void sendInlineAndAttachMail(String to, String subject, String content,String filePath, String rscPath, String rscId); }
測試郵件發(fā)送
編寫控制器層,這里使用的是Thymeleaf模板郵件,是常見的模板郵件,比如說我們注冊賬戶,登錄認證所收到的郵件即為模板郵件,特點就是內(nèi)容不變,只是一些特點信息比如說驗證碼、認證鏈接等是動態(tài)變化的。在模板頁面中,id是動態(tài)變化的,需要我們傳參設(shè)置,其實就是傳參后,將頁面解析為HTML字符串,作為我們郵件發(fā)送的主體內(nèi)容
@Controller public class MailContorller { @Autowired private MailService mailService; @Autowired private TemplateEngine templateEngine; @Resource private UserService userService; //這一步是獲取application.properties中設(shè)置的發(fā)件人郵箱地址 @Value("${spring.mail.username}") private String Email; @RequestMapping("/sendTemplate") /** 指定模板發(fā)送郵件 */ public String sendTemplate(@RequestParam("Email") String Email, Model model) { //具體的業(yè)務(wù) User usermail= userService.retrieve(Email); System.out.println(usermail); if (usermail !=null){ //向Thymeleaf模板傳值,并解析成字符串 //通過Context構(gòu)造模版中變量需要的值 Context context = new Context(); context.setVariable("id", "001"); String emailContent = templateEngine.process("emailTemplate", context); mailService.sendHtmlMail(Email,"密碼找回驗證", emailContent); return "Login"; } else if(StringUtils.isEmpty(Email)){ model.addAttribute("yuoxiang","郵箱信息不能為空"); return "Login"; } else { model.addAttribute("yuoxiang","郵箱錯誤或者與綁定賬號不一致"); return "Login"; } }
然后我們需要在template文件夾下創(chuàng)建emailTemplate.html,設(shè)計我們需求的模板樣式
<!DOCTYPE html> <html lang="en" xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"> <title>密碼驗證</title> </head> <body> <span style="color:#5ed02b;font-weight:600;font-size: 18px">您好,歡迎您的查看,這是一封驗證郵件,請根據(jù)下面系統(tǒng)找回的密碼完成登錄,感謝您的支持!</span><br> </body> </html>
調(diào)用發(fā)送復(fù)雜郵件方法后,根據(jù)獲取動態(tài)輸入的郵箱地址,成功后就可以在 QQ 郵箱中收到郵件:
總結(jié):Springboot整合郵件發(fā)送的原理和實現(xiàn)
以上就是Springboot整合實現(xiàn)郵件發(fā)送的原理詳解的詳細內(nèi)容,更多關(guān)于Springboot郵件發(fā)送的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
約定優(yōu)于配置_動力節(jié)點Java學(xué)院整理
以前做項目,總是寫Ant配置文件,滿足于自己更靈活的配置,而沒有去思考,這么做到底值不值得2017-08-08JAVA中常用的設(shè)計模式:單例模式,工廠模式,觀察者模式
設(shè)計模式(Design pattern)代表了最佳的實踐,通常被有經(jīng)驗的面向?qū)ο蟮能浖_發(fā)人員所采用。設(shè)計模式是軟件開發(fā)人員在軟件開發(fā)過程中面臨的一般問題的解決方案。這些解決方案是眾多軟件開發(fā)人員經(jīng)過相當(dāng)長的一段時間的試驗和錯誤總結(jié)出來的。2020-04-04Spring Boot結(jié)合ECharts案例演示示例
本文主要主要介紹了Spring Boot結(jié)合ECharts案例演示示例,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-06-06Java實現(xiàn)字符串和輸入流的相互轉(zhuǎn)換
這篇文章主要介紹了Java實現(xiàn)字符串和輸入流的相互轉(zhuǎn)換方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-08-08詳解Java異常處理中throw與throws關(guān)鍵字的用法區(qū)別
這篇文章主要介紹了詳解Java異常處理中throw與throws關(guān)鍵字的用法區(qū)別,這也是Java面試題目中的???需要的朋友可以參考下2015-11-11springboot調(diào)用webservice-soap接口的實現(xiàn)
接口協(xié)議目前廣泛使用的有http協(xié)議和RPC協(xié)議和webservice,本文主要介紹了springboot調(diào)用webservice-soap接口的實現(xiàn),具有一定的參考價值,感興趣的可以了解一下2024-03-03Java的Swing編程中使用SwingWorker線程模式及頂層容器
這篇文章主要介紹了在Java的Swing編程中使用SwingWorker線程模式及頂層容器的方法,適用于客戶端圖形化界面軟件的開發(fā),需要的朋友可以參考下2016-01-01