| 子類型 | 語義 | 典型用途 | 構造方式 |
mixed | 獨立部分,順序呈現 | 正文 + 附件 (最外層) | new MimeMultipart("mixed") |
related | 部分間有關聯 (引用) | HTML 正文 + 內嵌圖片 (CID 引用) | new MimeMultipart("related") |
alternative | 同內容不同格式 | 純文本版 + HTML 版 (郵件客戶端自動選擇) | new MimeMultipart("alternative") |
實戰範例:從簡單到複雜
1. 純文本郵件
public class SimpleTextMail {
public static void main(String[] args) throws Exception {
Session session = Session.getDefaultInstance(new Properties());
MimeMessage msg = new MimeMessage(session);
msg.setFrom(new InternetAddress("sender@qq.com"));
msg.setRecipients(Message.RecipientType.TO, InternetAddress.parse("receiver@163.com"));
msg.setSubject("測試純文本郵件");
msg.setSentDate(new Date());
// 關鍵:setText() 直接設置純文本
msg.setText("這是一封純文本郵件內容。");
msg.saveChanges();
msg.writeTo(new FileOutputStream("simple_text.eml"));
}
}
2. HTML 格式郵件
public class HtmlMail {
public static void main(String[] args) throws Exception {
Session session = Session.getDefaultInstance(new Properties());
MimeMessage msg = new MimeMessage(session);
msg.setFrom(new InternetAddress("sender@qq.com"));
msg.setRecipients(Message.RecipientType.TO, InternetAddress.parse("receiver@163.com"));
msg.setSubject("HTML 格式郵件");
msg.setSentDate(new Date());
String html = "歡迎使用 JavaMail
" +
"這是 HTML 格式內容,支援樣式、連結、圖片。
" +
"JavaMail 專案地址";
// 關鍵:setContent() 指定 MIME 類型
msg.setContent(html, "text/html;charset=UTF-8");
msg.saveChanges();
msg.writeTo(new FileOutputStream("html_mail.eml"));
}
}
3. 內嵌圖片郵件 (related)
public class InlineImageMail {
public static void main(String[] args) throws Exception {
Session session = Session.getDefaultInstance(new Properties());
MimeMessage msg = new MimeMessage(session);
msg.setFrom(new InternetAddress("sender@qq.com"));
msg.setRecipients(Message.RecipientType.TO, InternetAddress.parse("receiver@163.com"));
msg.setSubject("內嵌圖片郵件");
// 1. 建立 related 容器:HTML + 圖片
MimeMultipart related = new MimeMultipart("related");
// 2. HTML 正文部分 (引用 CID)
MimeBodyPart htmlPart = new MimeBodyPart();
String html = "產品展示
" +
"
" +
"圖片通過 CID 引用,不作為附件顯示。
";
htmlPart.setContent(html, "text/html;charset=UTF-8");
related.addBodyPart(htmlPart);
// 3. 圖片部分 (設置 Content-ID)
MimeBodyPart imagePart = new MimeBodyPart();
FileDataSource fds = new FileDataSource("product.jpg");
imagePart.setDataHandler(new DataHandler(fds));
imagePart.setHeader("Content-ID", ""); // 關鍵:CID 標識
imagePart.setDisposition(MimeBodyPart.INLINE); // 內嵌顯示
related.addBodyPart(imagePart);
// 4. 設置郵件內容
msg.setContent(related);
msg.saveChanges();
msg.writeTo(new FileOutputStream("inline_image.eml"));
}
}
4. 複雜混合郵件:HTML + 內嵌圖片 + 多附件 (mixed + related 巢狀)
public class ComplexMail {
public static void main(String[] args) throws Exception {
Session session = Session.getDefaultInstance(new Properties());
MimeMessage msg = createComplexMessage(session);
msg.writeTo(new FileOutputStream("complex_mail.eml"));
}
public static MimeMessage createComplexMessage(Session session) throws Exception {
MimeMessage msg = new MimeMessage(session);
msg.setFrom(new InternetAddress("sender@qq.com"));
msg.setRecipients(Message.RecipientType.TO, InternetAddress.parse("receiver@163.com"));
msg.setSubject("複雜混合郵件:HTML+圖片+附件");
// ===== 第一層:mixed (最外層:正文組合 + 附件們) =====
MimeMultipart mixed = new MimeMultipart("mixed");
// --- 正文組合 (related: HTML + 內嵌圖片) ---
MimeBodyPart contentPart = createContentPart("report.html", "chart.png");
mixed.addBodyPart(contentPart);
// --- 附件 1:PDF 報告 ---
mixed.addBodyPart(createAttachment("quarterly_report.pdf", "quarterly_report.pdf"));
// --- 附件 2:Excel 數據 ---
mixed.addBodyPart(createAttachment("data.xlsx", "raw_data.xlsx"));
msg.setContent(mixed);
msg.saveChanges();
return msg;
}
/** 建立 related 正文:HTML + 內嵌圖片 */
private static MimeBodyPart createContentPart(String htmlFile, String imageFile) throws Exception {
MimeBodyPart contentPart = new MimeBodyPart();
MimeMultipart related = new MimeMultipart("related");
// HTML 部分
MimeBodyPart htmlPart = new MimeBodyPart();
String html = readFile(htmlFile); // 讀取 HTML 模板文件
htmlPart.setContent(html, "text/html;charset=UTF-8");
related.addBodyPart(htmlPart);
// 圖片部分
MimeBodyPart imagePart = new MimeBodyPart();
FileDataSource fds = new FileDataSource(imageFile);
imagePart.setDataHandler(new DataHandler(fds));
imagePart.setHeader("Content-ID", "");
imagePart.setDisposition(MimeBodyPart.INLINE);
related.addBodyPart(imagePart);
contentPart.setContent(related);
return contentPart;
}
/** 建立附件部分 */
private static MimeBodyPart createAttachment(String filePath, String fileName) throws Exception {
MimeBodyPart attachPart = new MimeBodyPart();
FileDataSource fds = new FileDataSource(filePath);
attachPart.setDataHandler(new DataHandler(fds));
// 解決中文附件名亂碼 (RFC 2231 編碼)
attachPart.setFileName(MimeUtility.encodeText(fileName, "UTF-8", "B"));
attachPart.setDisposition(MimeBodyPart.ATTACHMENT);
return attachPart;
}
private static String readFile(String path) throws IOException {
return new String(Files.readAllBytes(Paths.get(path)), StandardCharsets.UTF_8);
}
}
關鍵技術點總結
- Content-ID (CID) 機制:內嵌資源必須設置
Content-ID: <unique-id>,HTML 中用 src="cid:unique-id" 引用
- Disposition 標頭:
INLINE 內嵌顯示,ATTACHMENT 作為附件下載
- 中文附件名編碼:使用
MimeUtility.encodeText(fileName, "UTF-8", "B") 避免亂碼
- 字符集統一 UTF-8:HTML、文本、附件名全鏈路 UTF-8
- saveChanges() 必須調用:生成最終郵件頭 (Message-ID、Date 等),否則 writeTo 輸出不完整
常見問題排查
| 現象 | 原因 | 解決 |
| 圖片顯示為破圖/附件 | CID 不匹配、Disposition 錯誤、Content-ID 格式缺少尖括號 | 檢查 CID 一致性、設置 INLINE、Content-ID 格式 <id> |
| 附件名亂碼 | 未進行 RFC 2231 編碼 | 使用 MimeUtility.encodeText() |
| HTML 樣式失效 | 郵件客戶端剝離 <style>/<link>、不支援外部 CSS | 使用內聯樣式 (style 屬性)、表格佈局 |
| 大附件發送失敗 | 超過郵件伺服器限制 (通常 25MB) | 分卷壓縮、雲存儲連結、分片上傳 |
- 上一篇文章: 資料庫表結構自動生成 JavaBean 神器:第 12 版功能全解析與最佳實踐
- 下一篇文章: Android Studio 專案全紅報錯但可正常運行:快速修復指南
Copyright ©
程式碼之家 All Rights Reserved