雖然現在的交流辦公軟件層出不窮,但是郵件的一些優勢是即時通信軟件無法取代的。郵件可以作爲一個很好的憑證並且可以存檔。在傳輸文件和大型複雜的場景下,大多數人還是會選擇郵件。所以,在我們開發網站的時候肯定也要應用郵件服務。
JavaMail是Sun發佈的用來提供給開發者處理電子郵件相關的編程接口。其中用於處理電子郵件的核心類是: Session, Message, Address, Authenticator, Transport, Store, Folder等。Session定義了一個基本的郵件會話,它需要從 Properties 中讀取類似於郵件服務器,用戶名和密碼等信息。另外,很好的實現了 JavaMail API 的框架有 James、Spring Mail。
一、郵件協議
在使用 Java 實現發送郵件之前,我們應該先弄清有關郵件的各種協議和每種協議包含的屬性,一般的情況下我們使用SMTP協議發送郵件,POP3協議接收郵件:
協議 | 作用 | 端口 |
---|---|---|
SMTP | 用於將郵件發送到服務器的協議 | 25 |
SMTPS | 使用SSL協議加密的SMTP協議 | 465 |
POP3 | 將服務器上的郵件下載到客戶端上並可以刪除服務器上的郵件 | 110 |
POP3S | 使用SSL協議加密的POP3協議 | 995 |
IMAP | 從服務器讀取郵件的協議,不能刪除服務器上的郵件 | 143 |
IMAPS | 使用SSL協議加密的IMAP協議 | 993 |
二、郵件的發送與接收
郵件的服務流程可由下圖所示:
發送郵件時,發件人會發消息給郵件服務器中的 SMTP service 。這時有兩種情況:如果郵件的收信人也是處於同一個域,比如,從 QQ 的郵箱發送給 QQ 的郵箱,SMTP service 只需要保存在自己服務器即可。如果郵件收信人是不同的域,比如,QQ 郵箱發送給 163 郵箱,QQ 的 SMTP service 需要找到 163 的 SMTP service 並使用 SMTP 協議發送。然後,163 服務器中的 SMTP service 收到郵件後保存在存儲空間中,此時收信人可使用 POP3 service 下載郵件。
三、SMTP中的常用頭屬性
在搭建後端或者一些服務的時候,會以發送郵件爲主。所以本文主要介紹關於使用 SMTP 協議發送郵件的實現。有關於 SMTP 協議更多的具體內容,可以參見官方標準文件 RFC 5321
一封郵件主要由郵件頭和郵件體組成.郵件頭包含了發件人、收件人、主題、時間、MIME版本、郵件內容的類型等重要信息。每條信息稱爲一個域。有點類似於我們經常使用的HTTP頭。
域 | 含義 | 示例 |
---|---|---|
Received | 郵件的路由信息,由鏈路中的路由添加 | - |
From | 發件人地址 | From: xxx <[email protected]> |
To | 收件人地址 | To: [email protected] |
CC | 抄送地址 | CC: [email protected] |
BCC | 密送地址 | BCC: [email protected] |
Return-Path | 郵件無法發送的回退地址 | Return-Path: <[email protected]> |
Date | 發件的日期和時間 | Date: Mon, 11 Nov 2020 11:11:11 +0800 (CST) |
MIME-Version | MIME版本 | MIME-Version: 1.0 |
Boundary | 標識分割內容與信息的字符串 | Boundary: “xxxxxxxxxxx” |
Subject | 郵件主題,用 Base64 編碼 | Subject: TWljcm9uIFN0dWRpbw== |
Content-Type | 內容的類型 | Content-Type: text/html;charset=UTF-8 |
X-* | 非標準的、自定義的域以 X- 開頭 | X-Priority: 1 |
三、JavaMail 代碼實現
Maven Repository: javax.mail » javax.mail-api » 1.6.2
包 :
- javax.mail.jar ( 依賴 activation.jar )
- activation.jar
類:
- java.util.Properties
- javax.mail.Session
- javax.mail.Transport
- javax.mail.internet.InternetAddress
- javax.mail.internet.MimeMessage
/*
** MimeMessage.RecipientType.TO 接收人
** MimeMessage.RecipientType.CC 抄送人
** MimeMessage.RecipientType.BCC 密送人
*/
try {
Properties prop = new Properties();//創建Java配置對象
prop.setProperty("mail.transport.protocol", "smtp");//傳輸協議
prop.setProperty("mail.smtp.host", "smtp.xxx.com");//郵箱服務器地址
prop.setProperty("mail.smtp.auth","true");//是否需要身份驗證
prop.setProperty("mail.debug", "true");//是否顯示日誌信息
prop.setProperty("mail.smtp.port", "25");//發送郵件端口號
Session session = Session.getDefaultInstance(prop);//使用配置對象獲取會話對象
MimeMessage msg = new MimeMessage(session);//獲取消息對象
msg.setSentDate(new java.util.Date());//設置發件日期
msg.setFrom(new InternetAddress("[email protected]","xxx"));//設置發件地址
msg.setRecipient(MimeMessage.RecipientType.TO, new InternetAddress("[email protected]"));//設置接收地址
msg.addHeader("X-Company", "Produced By Micron Studio");//自定義頭信息
msg.setSubject("xxxxxxxx");//郵件主題 ( 即郵件標題 )
msg.setContent("<html></html>","text/html");//郵件內容以及 Content-Type
Transport trans = session.getTransport("smtp");//獲取傳輸對象
trans.connect("smtp.xxx.com","[email protected]", "**********");//使用賬戶密碼連接郵件服務器
trans.sendMessage(msg, msg.getAllRecipients());//發送消息
trans.close();//關閉對象
} catch (Exception e) {
//異常處理
}
四、使用 SSL 協議加密 SMTP 報文 (SMTPS)
類:
- com.sun.mail.util.MailSSLSocketFactory
創建以下對象
MailSSLSocketFactory sf = new MailSSLSocketFactory();
sf.setTrustAllHosts(true);
爲 Properties 添加以下屬性
prop.put("mail.smtp.ssl.enable", "true");
prop.put("mail.smtp.ssl.socketFactory", sf);
prop.setProperty("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
prop.setProperty("mail.smtp.socketFactory.fallback", "false");
prop.setProperty("mail.smtp.ssl.enable", "true");
更改發送的端口號
prop.setProperty("mail.smtp.port", "465");