上一篇我們掌握了使用 Transport 發送郵件,本文將深入講解 JavaMail 接收端核心 API 體系,並通過完整的 POP3 代碼示例演示如何連接郵箱服務器、獲取郵件夾、解析郵件內容(含純文本、附件、嵌入資源等多種 MIME 類型)。
JavaMail 接收端四大核心類協作關係如下:

Session 獲取指定協議(POP3/IMAP)的 Store 對象store.connect(host, username, password) 登錄郵箱服務器store.getFolder("INBOX") 獲取收件箱 Folder,並以讀寫模式打開folder.getMessages() 獲取 Message[] 陣列,遍歷解析每封郵件import java.util.Properties;
import javax.mail.*;
public class MailReceiverDemo {
public static void main(String[] args) throws Exception {
// 1. 郵箱服務器配置
String pop3Host = "pop.qq.com";
String protocol = "pop3";
String username = "your_email@qq.com";
String authCode = "your_smtp_auth_code"; // 注意:這裡需使用授權碼,非登錄密碼
// 2. 構建 Session
Properties props = new Properties();
props.setProperty("mail.transport.protocol", protocol);
props.setProperty("mail.pop3.host", pop3Host);
// 若需 SSL(QQ 郵箱 POP3 默認 995 端口需 SSL)
props.setProperty("mail.pop3.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
props.setProperty("mail.pop3.socketFactory.fallback", "false");
props.setProperty("mail.pop3.port", "995");
props.setProperty("mail.pop3.socketFactory.port", "995");
Session session = Session.getDefaultInstance(props);
session.setDebug(true); // 開啟調試輸出協議交互細節
// 3. 獲取 Store 並連接
Store store = session.getStore(protocol);
store.connect(pop3Host, username, authCode);
// 4. 獲取收件箱 Folder(POP3 只能訪問 INBOX)
Folder inbox = store.getFolder("INBOX");
inbox.open(Folder.READ_WRITE); // READ_ONLY 亦可
// 5. 獲取所有郵件
Message[] messages = inbox.getMessages();
System.out.println("共收到 " + messages.length + " 封郵件");
// 6. 遍歷解析
for (int i = 0; i < messages.length; i++) {
Message msg = messages[i];
System.out.println("----- 郵件 #" + (i + 1) + " -----");
System.out.println("主題: " + msg.getSubject());
System.out.println("發件人: " + msg.getFrom()[0]);
System.out.println("發送時間: " + msg.getSentDate());
System.out.println("內容類型: " + msg.getContentType());
// 核心:根據 MIME 類型解析正文
Object content = msg.getContent();
parseContent(content, "");
}
// 7. 關閉資源
inbox.close(false); // true 表示刪除已標記為刪除的郵件
store.close();
}
/**
* 遞歸解析郵件內容,處理 multipart、嵌套結構
*/
private static void parseContent(Object content, String indent) {
if (content == null) return;
if (content instanceof String) {
// text/plain 或 text/html
System.out.println(indent + "[文本內容] " + content);
} else if (content instanceof Multipart) {
Multipart mp = (Multipart) content;
for (int j = 0; j < mp.getCount(); j++) {
BodyPart part = mp.getBodyPart(j);
System.out.println(indent + "--- Part #" + j + " 類型: " + part.getContentType());
parseContent(part.getContent(), indent + " ");
}
} else if (content instanceof InputStream) {
// 未識別的流類型,可按需讀取
System.out.println(indent + "[流內容] 需手動讀取 InputStream");
} else {
System.out.println(indent + "[未知類型] " + content.getClass().getName());
}
}
}
| MIME 類型 | 返回 Java 類型 | 處理方式 |
|---|---|---|
| text/plain、text/html | String | 直接作為正文展示 |
| multipart/mixed、multipart/alternative、multipart/related | Multipart 實現類 | 遞歸遍歷 BodyPart,進一步判斷各部分類型 |
| message/rfc822 | Message | 作為嵌套郵件遞歸解析 |
| 其他/未知 | InputStream | 按二進制流處理(如附件下載) |
代碼中只需將 protocol 改為 "imap"、主機改為 imap.qq.com、端口 993(SSL),即可無縫切換到 IMAP。
password 參數填授權碼。mail.*.socketFactory.class。getContent() 導致 OOM,附件下載應使用 part.getInputStream() 分塊寫入磁盤。Folder.close() 與 Store.close() 必須在 finally 塊中調用,防止連接泄漏。=?UTF-8?B?...?=),JavaMail 會自動解碼;若出現亂碼,可手動用 MimeUtility.decodeText() 處理。ScheduledExecutorService 定時執行接收任務,配合 Folder.getMessages(start, end) 分頁獲取。UIDFolder.getUID(message) 記錄已處理郵件 UID,避免重複處理。Apache Commons Pool 管理 Store 連接,減少頻繁握手開銷。JavaMail 接收郵件的核心在於理解 Session → Store → Folder → Message 四層抽象,並掌握 Message.getContent() 多態返回類型的遞歸解析策略。本文提供的完整 POP3/IMAP 代碼模板可直接用於項目,配合 SSL、授權碼、異步處理等最佳實踐,即可構建穩健的郵件接收功能。