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

JavaMail 實戰 (二):從純文本到複雜多部分郵件構建完全指南

     編輯:Java 綜合教學

JavaMail 郵件構建完全指南:MimeMessage、MimeBodyPart、MimeMultipart 三大核心類深度解析

本文為 JavaMail 系列第二篇,系統講解如何構建純文本、HTML、內嵌圖片、帶附件、混合複雜郵件,掌握三大核心類的協作關係,為後續發送郵件打下堅實基礎。

核心類關係圖譜

類別角色繼承關係核心方法
MimeMessage整封郵件容器Message → MimeMessagesetContent(), setFrom(), setRecipients(), setSubject()
MimeBodyPart單個 MIME 部分 (正文/附件/圖片)Part → MimePart → MimeBodyPartsetContent(), setDataHandler(), setFileName()
MimeMultipart多部分組合容器Multipart → MimeMultipartaddBodyPart(), setSubType()

三大類協作關係圖

類繼承關係與常用方法

MimeMultipart 子類型與組合語義

Multipart 子類型組合關係

實戰範例:從簡單到複雜

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);
    }
}

關鍵技術點總結

  1. Content-ID (CID) 機制:內嵌資源必須設置 Content-ID: <unique-id>,HTML 中用 src="cid:unique-id" 引用
  2. Disposition 標頭:INLINE 內嵌顯示,ATTACHMENT 作為附件下載
  3. 中文附件名編碼:使用 MimeUtility.encodeText(fileName, "UTF-8", "B") 避免亂碼
  4. 字符集統一 UTF-8:HTML、文本、附件名全鏈路 UTF-8
  5. saveChanges() 必須調用:生成最終郵件頭 (Message-ID、Date 等),否則 writeTo 輸出不完整

常見問題排查

子類型語義典型用途構造方式
mixed獨立部分,順序呈現正文 + 附件 (最外層)new MimeMultipart("mixed")
related部分間有關聯 (引用)HTML 正文 + 內嵌圖片 (CID 引用)new MimeMultipart("related")
alternative同內容不同格式純文本版 + HTML 版 (郵件客戶端自動選擇)new MimeMultipart("alternative")
現象原因解決
圖片顯示為破圖/附件CID 不匹配、Disposition 錯誤、Content-ID 格式缺少尖括號檢查 CID 一致性、設置 INLINE、Content-ID 格式 <id>
附件名亂碼未進行 RFC 2231 編碼使用 MimeUtility.encodeText()
HTML 樣式失效郵件客戶端剝離 <style>/<link>、不支援外部 CSS使用內聯樣式 (style 屬性)、表格佈局
大附件發送失敗超過郵件伺服器限制 (通常 25MB)分卷壓縮、雲存儲連結、分片上傳
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved