首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

JavaMail API 發送與接收郵件完整實戰:從簡單文本到複雜附件、HTML 富文本

     編輯:Java 相關知識

依賴準備

<!-- Maven 坐標 (Jakarta Mail 2.x) -->
<dependency>
    <groupId>com.sun.mail</groupId>
    <artifactId>jakarta.mail</artifactId>
    <version>2.0.1</version>
</dependency>
<!-- 或舊版 javax.mail -->
<dependency>
    <groupId>com.sun.mail</groupId>
    <artifactId>javax.mail</artifactId>
    <version>1.6.2</version>
</dependency>

核心類:Session(連接配置)、Message(郵件對象)、Transport(發送)、Store/Folder(接收)、MimeMessage(MIME 郵件)、MimeMultipart(混合內容)、MimeBodyPart(郵件部件)。

基礎配置:Session 與認證

Properties props = new Properties();
props.put("mail.smtp.auth", "true");
props.put("mail.transport.protocol", "smtp");
props.put("mail.smtp.host", "smtp.126.com");
props.put("mail.smtp.port", "25"); // 或 465(SSL), 587(STARTTLS)

Session session = Session.getInstance(props, new Authenticator() {
    protected PasswordAuthentication getPasswordAuthentication() {
        return new PasswordAuthentication("user@126.com", "password");
    }
});
session.setDebug(true); // 控制台打印 SMTP 交互細節

場景一:純文本郵件

MimeMessage msg = new MimeMessage(session);
msg.setFrom(new InternetAddress("sender@126.com"));
msg.setRecipients(Message.RecipientType.TO, InternetAddress.parse("receiver@qq.com"));
msg.setSubject("測試郵件");
msg.setText("你好,這是純文本內容");
Transport.send(msg);

場景二:多收件人、抄送、密送、HTML 內容

msg.setRecipients(Message.RecipientType.TO, 
    InternetAddress.parse("to1@qq.com, to2@163.com"));
msg.setRecipients(Message.RecipientType.CC, 
    InternetAddress.parse("cc@hotmail.com")); // 抄送,收件人可見
msg.setRecipients(Message.RecipientType.BCC, 
    InternetAddress.parse("bcc@gmail.com"));  // 密送,收件人不可見

msg.setContent("

HTML 富文本

支持圖片、鏈接、樣式

", "text/html;charset=utf-8"); Transport.send(msg);

場景三:複雜郵件 — 附件 + 內嵌圖片 + HTML 正文

MimeMessage msg = new MimeMessage(session);
msg.setFrom(new InternetAddress("sender@126.com", "發件人姓名", "utf-8"));
msg.setSubject("帶附件和圖片的郵件", "utf-8");
msg.setRecipients(Message.RecipientType.TO, InternetAddress.parse("receiver@qq.com"));

// 頂層容器:mixed (附件與正文並列)
MimeMultipart topMultipart = new MimeMultipart("mixed");
msg.setContent(topMultipart);

// --- 附件 1 ---
MimeBodyPart attach1 = new MimeBodyPart();
attach1.attachFile(new File("config.txt")); // JDK 1.6+ 便捷方法
attach1.setFileName(MimeUtility.encodeText("配置文件.txt")); // 中文文件名編碼
topMultipart.addBodyPart(attach1);

// --- 附件 2 ---
MimeBodyPart attach2 = new MimeBodyPart();
attach2.attachFile(new File("photo.jpg"));
attach2.setFileName(MimeUtility.encodeText("照片.jpg"));
topMultipart.addBodyPart(attach2);

// --- 正文區域:related (HTML + 內嵌圖片) ---
MimeMultipart bodyMultipart = new MimeMultipart("related");
MimeBodyPart htmlPart = new MimeBodyPart();
MimeBodyPart imagePart = new MimeBodyPart();

htmlPart.setContent(
    "

報告正文

", // cid 引用內嵌圖片 "text/html;charset=utf-8" ); imagePart.attachFile(new File("chart.png")); imagePart.setContentID(""); // 匹配 cid:chart.png imagePart.setDisposition(MimeBodyPart.INLINE); bodyMultipart.addBodyPart(htmlPart); bodyMultipart.addBodyPart(imagePart); // 將正文區域加入頂層 MimeBodyPart bodyWrapper = new MimeBodyPart(); bodyWrapper.setContent(bodyMultipart); topMultipart.addBodyPart(bodyWrapper); msg.saveChanges(); // 重要:生成 Message-ID 等頭部 Transport.send(msg);

接收郵件:POP3 / IMAP

Properties props = new Properties();
props.put("mail.pop3.ssl.enable", "true");
props.put("mail.pop3.host", "pop.163.com");
props.put("mail.pop3.port", "995");

Session session = Session.getDefaultInstance(props);
Store store = session.getStore("pop3");
store.connect("user@163.com", "password");

Folder inbox = store.getFolder("INBOX");
inbox.open(Folder.READ_ONLY);

Message[] messages = inbox.getMessages();
// 獲取最新一封
Message latest = messages[messages.length - 1];
System.out.println("發件人: " + latest.getFrom()[0]);
System.out.println("主題: " + latest.getSubject());
System.out.println("時間: " + latest.getSentDate());

// 解析內容 (遞歸處理 Multipart)
Object content = latest.getContent();
if (content instanceof Multipart) {
    parseMultipart((Multipart) content);
}

inbox.close(false);
store.close();

常見問題與解決方案

問題原因解決
535 Authentication failed密碼錯誤/未開啟 SMTP/需授權碼郵箱設置開啟 SMTP、使用授權碼而非登錄密碼
中文亂碼未指定 charset所有 setSubject/setContent/setFileName 指定 utf-8,文件名用 MimeUtility.encodeText
大附件發送失敗郵箱限制 (通常 20-50MB)分卷壓縮、雲盤分享鏈接、或分片發送
SSLHandshakeExceptionJDK 信任庫缺少郵件服務器證書使用 STARTTLS (587 端口) 或導入證書
接收超時網絡/防火牆/服務器限制設置連接/讀取超時、嘗試 IMAP (993) 替代 POP3

最佳實踐清單

  • ✅ 生產環境必須用 SSL/TLS (465/587/993/995 端口)
  • ✅ 密碼/授權碼配置中心管理,絕不硬編碼
  • ✅ 發送異常重試機制 (指數退避) + 死信隊列
  • ✅ 批量發送異步化 (消息隊列 + 消費者限流)
  • ✅ 郵件模板外部化 (Thymeleaf/FreeMarker),內容與代碼分離
  • ✅ 關鍵日志:Message-ID、收件人、發送耗時、結果碼
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved