使用JavaMail發(fā)送郵件保證成功的方法
前言
相信大家應(yīng)該都知道,一般的開放的api給我們調(diào)用都會(huì)有個(gè)返回值或者狀態(tài)碼,來(lái)告訴我們執(zhí)行成功與否。但是JavaMail卻沒(méi)有提供這樣一個(gè)返回值。
所以在調(diào)用JavaMail發(fā)送郵件的時(shí)候,我們只能通過(guò)catch異常的方式來(lái)判斷郵件是否發(fā)送成功。我們認(rèn)為只要沒(méi)有異常發(fā)生,那么郵件就能發(fā)送成功。那么我們就來(lái)分析一下JavaMail為什么沒(méi)有提供返回值,和通過(guò)異常判斷郵件發(fā)送成功狀態(tài)是否靠譜。
JavaMail發(fā)送郵件原理
在使用JavaMail進(jìn)行發(fā)送郵件時(shí),我們必須提供一個(gè)郵件會(huì)話。創(chuàng)建郵件會(huì)話的過(guò)程如下:
Properties props = new Properties();
// 發(fā)送郵件的服務(wù)器的IP和端口
props.put("mail.smtp.host", MAIL_SMTP_HOST);
props.put("mail.smtp.port", MAIL_SMTP_PORT);
// 是否需要身份驗(yàn)證
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ā)送服務(wù)器的用戶名和密碼
return new PasswordAuthentication(MAIL_SENDER_MAIL, MAIL_SENDER_PASS);
}
});
分析一下代碼。
在創(chuàng)建Session之前我們先創(chuàng)建一個(gè)Properties,這個(gè)Properties設(shè)置了這樣幾個(gè)參數(shù):mail.smtp.host、mail.smtp.port、mail.smtp.auth和mail.smtp.socketFactory.class。在創(chuàng)建Session的時(shí)候還要傳入發(fā)送郵件使用的用戶名及密碼。
發(fā)送郵件代碼如下:
//使用JavaMail發(fā)送郵件的5個(gè)步驟
//1、創(chuàng)建session
Session session = Session.getInstance(prop);
//開啟Session的debug模式,這樣就可以查看到程序發(fā)送Email的運(yùn)行狀態(tài)
session.setDebug(true);
//2、通過(guò)session得到transport對(duì)象
Transport ts = session.getTransport();
//3、使用郵箱的用戶名和密碼連上郵件服務(wù)器,發(fā)送郵件時(shí),發(fā)件人需要提交郵箱的用戶名和密碼給smtp服務(wù)器,用戶名和密碼都通過(guò)驗(yàn)證之后才能夠正常發(fā)送郵件給收件人。
ts.connect("smtp.sohu.com", "gacl", "郵箱密碼");
//4、創(chuàng)建郵件
Message message = createSimpleMail(session);
//5、發(fā)送郵件
ts.sendMessage(message, message.getAllRecipients());
//關(guān)閉連接
ts.close();
總結(jié)發(fā)送郵件過(guò)程主要有以下幾個(gè)步驟:
1.創(chuàng)建包含郵件服務(wù)器的網(wǎng)絡(luò)鏈接的Session對(duì)象
2.創(chuàng)建代表郵件內(nèi)容的Message對(duì)象
3.創(chuàng)建Transport對(duì)象
4.鏈接服務(wù)器
5.發(fā)送Message
6.關(guān)閉鏈接
由于Transport只是一個(gè)抽象類,所以這里在發(fā)送Message的時(shí)候用調(diào)用的方法ts.sendMessage實(shí)際上是調(diào)用的Transport的實(shí)現(xiàn)類SMTPTransport的sendMessage方法。
而SMTPTransport的sendMessage方法則依賴SMTP協(xié)議進(jìn)行郵件的發(fā)送。
所以,當(dāng)javamail使用smtp服務(wù)發(fā)送郵件時(shí),當(dāng)你把郵件發(fā)送到smtp服務(wù)器的時(shí)候,你只能得到已經(jīng)發(fā)送到smtp的隊(duì)列中的狀態(tài),但是郵件服務(wù)器是否能發(fā)送成功,你是得不到的。就是說(shuō),你不能保證郵件發(fā)送一定成功。 這就取決于SMTP協(xié)議的內(nèi)容傳輸了。
但是SMTP協(xié)議如果傳輸失敗,是會(huì)報(bào)錯(cuò)的。SMTP由TCP提供的可靠的數(shù)據(jù)傳輸服務(wù)把郵件消息從發(fā)信人的郵件服務(wù)器傳送到收信人的郵件服務(wù)器。
所以我們可以認(rèn)為當(dāng)我們調(diào)用JavaMail發(fā)送郵件時(shí),如果程序沒(méi)有報(bào)錯(cuò)則表示郵件發(fā)送成功。
SMTP工作機(jī)制
SMTP通常有兩種工作模式:發(fā)送SMTP和接收SMTP。
具體工作方式為:發(fā)送SMTP在接到用戶的郵件請(qǐng)求后,判斷此郵件是否為本地郵件,若是直接投送到用戶的郵箱,否則向dns查詢遠(yuǎn)端郵件服務(wù)器的MX紀(jì)錄,并建立與遠(yuǎn)端接收SMTP之間的一個(gè)雙向傳送通道,此后SMTP命令由發(fā)送SMTP發(fā)出,由接收SMTP接收,而應(yīng)答則反方面?zhèn)魉汀R坏﹤魉屯ǖ澜?,SMTP發(fā)送者發(fā)送MAIL命令指明郵件發(fā)送者。如果SMTP接收者可以接收郵件則返回OK應(yīng)答。SMTP發(fā)送者再發(fā)出RCPT命令確認(rèn)郵件是否接收到。如果SMTP接收者接收,則返回OK應(yīng)答;如果不能接收到,則發(fā)出拒絕接收應(yīng)答(但不中止整個(gè)郵件操作),雙方將如此重復(fù)多次。當(dāng)接收者收到全部郵件后會(huì)接收到特別的序列,如果接收者成功處理了郵件,則返回OK應(yīng)答即可。
SMTP工作過(guò)程
簡(jiǎn)單郵件傳輸協(xié)議(SMTP)是一種基于文本的電子郵件傳輸協(xié)議,是在因特網(wǎng)中用于在郵件服務(wù)器之間交換郵件的協(xié)議。SMTP是應(yīng)用層的服務(wù),可以適應(yīng)于各種網(wǎng)絡(luò)系統(tǒng)。
SMTP的命令和響應(yīng)都是基于文本,以命令行為單位,換行符為CR/LF。響應(yīng)信息一般只有一行,由一個(gè)3位數(shù)的代碼開始,后面可附上很簡(jiǎn)短的文字說(shuō)明。
SMTP要經(jīng)過(guò)建立連接、傳送郵件和釋放連接3個(gè)階段。具體為:
(1)建立TCP連接。
(2)客戶端向服務(wù)器發(fā)送HELO命令以標(biāo)識(shí)發(fā)件人自己的身份,然后客戶端發(fā)送MAIL命令。
(3)服務(wù)器端以O(shè)K作為響應(yīng),表示準(zhǔn)備接收。
(4)客戶端發(fā)送RCPT命令。
(5)服務(wù)器端表示是否愿意為收件人接收郵件。
(6)協(xié)商結(jié)束,發(fā)送郵件,用命令DATA發(fā)送輸入內(nèi)容。
(7)結(jié)束此次發(fā)送,用QUIT命令退出。
SMTP服務(wù)器基于DNS中的郵件交換(MX)記錄路由電子郵件。電子郵件系統(tǒng)發(fā)郵件時(shí)是根據(jù)收信人的地址后綴來(lái)定位郵件服務(wù)器的。SMTP通過(guò)用戶代理程序(UA)完成郵件的編輯、收取和閱讀等功能;通過(guò)郵件傳輸代理程序(MTA)將郵件傳送到目的地。
總結(jié)
以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作能帶來(lái)一定的幫助,如果有疑問(wèn)大家可以留言交流。
- Java基于JavaMail實(shí)現(xiàn)向QQ郵箱發(fā)送郵件
- JavaWeb中使用JavaMail實(shí)現(xiàn)發(fā)送郵件功能實(shí)例詳解
- 基于SSM框架+Javamail發(fā)送郵件的代碼實(shí)例
- Spring框架JavaMailSender發(fā)送郵件工具類詳解
- Spring Boot中利用JavaMailSender發(fā)送郵件的方法示例(附源碼)
- JavaWeb中JavaMail創(chuàng)建郵件和發(fā)送郵件
- SpringBoot整合JavaMail通過(guò)阿里云企業(yè)郵箱發(fā)送郵件的實(shí)現(xiàn)
- SpringBoot JavaMailSender發(fā)送郵件功能
- 基于java使用JavaMail發(fā)送郵件
- 基于Javamail實(shí)現(xiàn)發(fā)送郵件(QQ/網(wǎng)易郵件服務(wù)器)
相關(guān)文章
SpringCloud之注冊(cè)中心之Nacos負(fù)載均衡詳解
Nacos提供多種負(fù)載均衡策略,包括權(quán)重、同機(jī)房、同地域、同環(huán)境等,服務(wù)下線和權(quán)重配置可以通過(guò)Nacos管理界面進(jìn)行,同時(shí),Nacos使用Raft算法選舉Leader節(jié)點(diǎn),若IP地址改變可能會(huì)影響Leader選舉,配置同集群優(yōu)先訪問(wèn)可以提高訪問(wèn)速度,通過(guò)配置集群名稱和負(fù)載均衡策略2025-03-03
Java postgresql數(shù)組字段類型處理方法詳解
這篇文章主要介紹了Java postgresql數(shù)組字段類型處理方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-10-10
java jdbc連接mysql數(shù)據(jù)庫(kù)實(shí)現(xiàn)增刪改查操作
這篇文章主要為大家詳細(xì)介紹了java jdbc連接mysql數(shù)據(jù)庫(kù)實(shí)現(xiàn)增刪改查操作,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-07-07
Java使用POI導(dǎo)出大數(shù)據(jù)量Excel的方法
今天需要寫一個(gè)導(dǎo)出的Excel的功能,但是發(fā)現(xiàn)當(dāng)數(shù)據(jù)量到3萬(wàn)條時(shí),列數(shù)在23列時(shí),內(nèi)存溢出,CPU使用100%,測(cè)試環(huán)境直接炸掉。小編給大家分享基于java使用POI導(dǎo)出大數(shù)據(jù)量Excel的方法,感興趣的朋友一起看看吧2019-11-11
SpringBoot后臺(tái)實(shí)現(xiàn)文件上傳下載
這篇文章主要為大家詳細(xì)介紹了SpringBoot后臺(tái)實(shí)現(xiàn)文件上傳下載,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-02-02
出現(xiàn)SLF4J:?Failed?to?load?class?“org.slf4j.impl.StaticLog
本文主要介紹了出現(xiàn)SLF4J:?Failed?to?load?class?“org.slf4j.impl.StaticLoggerBinder“.的解決方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2022-07-07
解決java數(shù)值范圍以及float與double精度丟失的問(wèn)題
下面小編就為大家?guī)?lái)一篇解決java數(shù)值范圍以及float與double精度丟失的問(wèn)題。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-06-06
MyBatis通用Mapper中的通用example(排序)詳解
這篇文章主要介紹了MyBatis通用Mapper中的通用example(排序)詳解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-12-12
Log4j按級(jí)別輸出日志到不同文件的實(shí)現(xiàn)方法
下面小編就為大家?guī)?lái)一篇Log4j按級(jí)別輸出日志到不同文件的實(shí)現(xiàn)方法。2016-11-11

