使用JavaMail發(fā)送郵件保證成功的方法
前言
相信大家應該都知道,一般的開放的api給我們調(diào)用都會有個返回值或者狀態(tài)碼,來告訴我們執(zhí)行成功與否。但是JavaMail卻沒有提供這樣一個返回值。
所以在調(diào)用JavaMail發(fā)送郵件的時候,我們只能通過catch異常的方式來判斷郵件是否發(fā)送成功。我們認為只要沒有異常發(fā)生,那么郵件就能發(fā)送成功。那么我們就來分析一下JavaMail為什么沒有提供返回值,和通過異常判斷郵件發(fā)送成功狀態(tài)是否靠譜。
JavaMail發(fā)送郵件原理
在使用JavaMail進行發(fā)送郵件時,我們必須提供一個郵件會話。創(chuàng)建郵件會話的過程如下:
Properties props = new Properties(); // 發(fā)送郵件的服務器的IP和端口 props.put("mail.smtp.host", MAIL_SMTP_HOST); props.put("mail.smtp.port", MAIL_SMTP_PORT); // 是否需要身份驗證 props.put("mail.smtp.auth", "true"); props.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory"); Session session = Session.getDefaultInstance(props, new Authenticator() { protected PasswordAuthentication getPasswordAuthentication() { // 登陸郵件發(fā)送服務器的用戶名和密碼 return new PasswordAuthentication(MAIL_SENDER_MAIL, MAIL_SENDER_PASS); } });
分析一下代碼。
在創(chuàng)建Session之前我們先創(chuàng)建一個Properties,這個Properties設置了這樣幾個參數(shù):mail.smtp.host
、mail.smtp.port
、mail.smtp.auth
和mail.smtp.socketFactory.class
。在創(chuàng)建Session的時候還要傳入發(fā)送郵件使用的用戶名及密碼。
發(fā)送郵件代碼如下:
//使用JavaMail發(fā)送郵件的5個步驟 //1、創(chuàng)建session Session session = Session.getInstance(prop); //開啟Session的debug模式,這樣就可以查看到程序發(fā)送Email的運行狀態(tài) session.setDebug(true); //2、通過session得到transport對象 Transport ts = session.getTransport(); //3、使用郵箱的用戶名和密碼連上郵件服務器,發(fā)送郵件時,發(fā)件人需要提交郵箱的用戶名和密碼給smtp服務器,用戶名和密碼都通過驗證之后才能夠正常發(fā)送郵件給收件人。 ts.connect("smtp.sohu.com", "gacl", "郵箱密碼"); //4、創(chuàng)建郵件 Message message = createSimpleMail(session); //5、發(fā)送郵件 ts.sendMessage(message, message.getAllRecipients()); //關閉連接 ts.close();
總結發(fā)送郵件過程主要有以下幾個步驟:
1.創(chuàng)建包含郵件服務器的網(wǎng)絡鏈接的Session對象
2.創(chuàng)建代表郵件內(nèi)容的Message對象
3.創(chuàng)建Transport對象
4.鏈接服務器
5.發(fā)送Message
6.關閉鏈接
由于Transport只是一個抽象類,所以這里在發(fā)送Message的時候用調(diào)用的方法ts.sendMessage
實際上是調(diào)用的Transport的實現(xiàn)類SMTPTransport
的sendMessage
方法。
而SMTPTransport
的sendMessage
方法則依賴SMTP協(xié)議進行郵件的發(fā)送。
所以,當javamail使用smtp服務發(fā)送郵件時,當你把郵件發(fā)送到smtp服務器的時候,你只能得到已經(jīng)發(fā)送到smtp的隊列中的狀態(tài),但是郵件服務器是否能發(fā)送成功,你是得不到的。就是說,你不能保證郵件發(fā)送一定成功。 這就取決于SMTP協(xié)議的內(nèi)容傳輸了。
但是SMTP協(xié)議如果傳輸失敗,是會報錯的。SMTP由TCP提供的可靠的數(shù)據(jù)傳輸服務把郵件消息從發(fā)信人的郵件服務器傳送到收信人的郵件服務器。
所以我們可以認為當我們調(diào)用JavaMail發(fā)送郵件時,如果程序沒有報錯則表示郵件發(fā)送成功。
SMTP工作機制
SMTP通常有兩種工作模式:發(fā)送SMTP和接收SMTP。
具體工作方式為:發(fā)送SMTP在接到用戶的郵件請求后,判斷此郵件是否為本地郵件,若是直接投送到用戶的郵箱,否則向dns查詢遠端郵件服務器的MX紀錄,并建立與遠端接收SMTP之間的一個雙向傳送通道,此后SMTP命令由發(fā)送SMTP發(fā)出,由接收SMTP接收,而應答則反方面?zhèn)魉?。一旦傳送通道建立,SMTP發(fā)送者發(fā)送MAIL命令指明郵件發(fā)送者。如果SMTP接收者可以接收郵件則返回OK應答。SMTP發(fā)送者再發(fā)出RCPT命令確認郵件是否接收到。如果SMTP接收者接收,則返回OK應答;如果不能接收到,則發(fā)出拒絕接收應答(但不中止整個郵件操作),雙方將如此重復多次。當接收者收到全部郵件后會接收到特別的序列,如果接收者成功處理了郵件,則返回OK應答即可。
SMTP工作過程
簡單郵件傳輸協(xié)議(SMTP)是一種基于文本的電子郵件傳輸協(xié)議,是在因特網(wǎng)中用于在郵件服務器之間交換郵件的協(xié)議。SMTP是應用層的服務,可以適應于各種網(wǎng)絡系統(tǒng)。
SMTP的命令和響應都是基于文本,以命令行為單位,換行符為CR/LF。響應信息一般只有一行,由一個3位數(shù)的代碼開始,后面可附上很簡短的文字說明。
SMTP要經(jīng)過建立連接、傳送郵件和釋放連接3個階段。具體為:
(1)建立TCP連接。
(2)客戶端向服務器發(fā)送HELO命令以標識發(fā)件人自己的身份,然后客戶端發(fā)送MAIL命令。
(3)服務器端以OK作為響應,表示準備接收。
(4)客戶端發(fā)送RCPT命令。
(5)服務器端表示是否愿意為收件人接收郵件。
(6)協(xié)商結束,發(fā)送郵件,用命令DATA發(fā)送輸入內(nèi)容。
(7)結束此次發(fā)送,用QUIT命令退出。
SMTP服務器基于DNS中的郵件交換(MX)記錄路由電子郵件。電子郵件系統(tǒng)發(fā)郵件時是根據(jù)收信人的地址后綴來定位郵件服務器的。SMTP通過用戶代理程序(UA)完成郵件的編輯、收取和閱讀等功能;通過郵件傳輸代理程序(MTA)將郵件傳送到目的地。
總結
以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學習或者工作能帶來一定的幫助,如果有疑問大家可以留言交流。
- Java基于JavaMail實現(xiàn)向QQ郵箱發(fā)送郵件
- JavaWeb中使用JavaMail實現(xiàn)發(fā)送郵件功能實例詳解
- 基于SSM框架+Javamail發(fā)送郵件的代碼實例
- Spring框架JavaMailSender發(fā)送郵件工具類詳解
- Spring Boot中利用JavaMailSender發(fā)送郵件的方法示例(附源碼)
- JavaWeb中JavaMail創(chuàng)建郵件和發(fā)送郵件
- SpringBoot整合JavaMail通過阿里云企業(yè)郵箱發(fā)送郵件的實現(xiàn)
- SpringBoot JavaMailSender發(fā)送郵件功能
- 基于java使用JavaMail發(fā)送郵件
- 基于Javamail實現(xiàn)發(fā)送郵件(QQ/網(wǎng)易郵件服務器)
相關文章
Spring處理@Async導致的循環(huán)依賴失敗問題的方案詳解
這篇文章主要為大家詳細介紹了SpringBoot中的@Async導致循環(huán)依賴失敗的原因及其解決方案,文中的示例代碼講解詳細,感興趣的可以學習一下2022-07-07Java編程實現(xiàn)生成給定范圍內(nèi)不重復隨機數(shù)的方法小結
這篇文章主要介紹了Java編程實現(xiàn)生成給定范圍內(nèi)不重復隨機數(shù)的方法,結合實例形式總結分析了java基于數(shù)學運算與判斷實現(xiàn)不重復隨機數(shù)的生成功能,需要的朋友可以參考下2017-07-07Spring Boot Hazelcast Caching 使用和配置詳解
這篇文章主要介紹了Spring Boot Hazelcast Caching 使用和配置詳解,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-09-09詳解SpringBoot 快速整合Mybatis(去XML化+注解進階)
本篇文章主要介紹了詳解SpringBoot 快速整合Mybatis(去XML化+注解進階),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-11-11MyBatis中insert操作返回主鍵的實現(xiàn)方法
在使用MyBatis做持久層時,insert語句默認是不返回記錄的主鍵值,而是返回插入的記錄條數(shù)。這篇文章主要介紹了MyBatis中insert操作返回主鍵的方法,需要的朋友可以參考下2016-09-09