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

JavaMail 進階:發送內嵌圖片 HTML 郵件與接收解析帶附件郵件

     編輯:Java 相關知識

一、發送帶內嵌圖片的 HTML 郵件

HTML 郵件中引用圖片需採用 CID (Content-ID) 機制:圖片作為附件部分添加,設置 Content-ID 頭,HTML 中用 <img src="cid:xxx"> 引用。

核心步驟

  1. 解析 HTML,提取 <img src="..."> 的本地/網絡路徑。
  2. 將圖片文件作為 MimeBodyPart 添加到 MimeMultipart("related") (related 表示內嵌關係)。
  3. 設置 setHeader("Content-ID", "<img001>") (尖括號必須)。
  4. HTML 中替換為 <img src="cid:img001">。
  5. 文本部分與 related 部分組合到 MimeMultipart("mixed") 頂層容器。

關鍵代碼片段

// 頂層 mixed 容器
MimeMultipart mixed = new MimeMultipart("mixed");

// related 容器:包含 HTML 正文 + 內嵌圖片
MimeMultipart related = new MimeMultipart("related");

// 1. HTML 正文 Part
MimeBodyPart htmlPart = new MimeBodyPart();
htmlPart.setContent(processedHtml, "text/html; charset=UTF-8");
related.addBodyPart(htmlPart);

// 2. 內嵌圖片 Parts
for (int i = 0; i < imageFiles.size(); i++) {
    MimeBodyPart imgPart = new MimeBodyPart();
    FileDataSource fds = new FileDataSource(imageFiles.get(i));
    imgPart.setDataHandler(new DataHandler(fds));
    imgPart.setHeader("Content-ID", "<img" + i + ">"); // 關鍵
    imgPart.setDisposition(MimeBodyPart.INLINE);
    related.addBodyPart(imgPart);
}

// 3. 將 related 整體作為一個 Part 放入 mixed
MimeBodyPart relatedWrapper = new MimeBodyPart();
relatedWrapper.setContent(related);
mixed.addBodyPart(relatedWrapper);

// 4. 普通附件直接加入 mixed
for (File att : attachments) {
    MimeBodyPart attPart = new MimeBodyPart();
    attPart.setDataHandler(new DataHandler(new FileDataSource(att)));
    attPart.setFileName(MimeUtility.encodeWord(att.getName(), "UTF-8", null));
    mixed.addBodyPart(attPart);
}

message.setContent(mixed);

二、郵件標誌位管理

Flags.Flag 定義標準標誌:

標誌含義
ANSWERED已回覆
DELETED標記刪除 (需 folder.close(true) 或 expunge() 生效)
DRAFT草稿
FLAGGED標星/重要
RECENT最近到達 (只讀,由服務器設置)
SEEN已讀
USER用戶自定義關鍵字

操作示例

Message msg = folder.getMessage(1);
// 設置已讀
msg.setFlag(Flags.Flag.SEEN, true);
// 標記刪除
msg.setFlag(Flags.Flag.DELETED, true);
// 批量設置
Flags flags = new Flags(Flags.Flag.ANSWERED, Flags.Flag.FLAGGED);
msg.setFlags(flags, true);
// 檢查
if (msg.isSet(Flags.Flag.SEEN)) { ... }
// 關鍵:expunge() 永久刪除標記為 DELETED 的郵件
folder.close(true); // true 即調用 expunge()

注意:並非所有 IMAP/POP3 服務器支持所有標誌,操作前可用 folder.getPermanentFlags() 檢查。

三、接收並解析帶附件郵件 (Mime 結構遞歸遍歷)

郵件內容可能是巢狀 multipart/* 結構 (如 mixed → related → alternative),需遞歸處理。

通用解析邏輯

public void parseMessage(Part part) throws MessagingException, IOException {
    String contentType = part.getContentType();
    String disposition = part.getDisposition(); // PART.ATTACHMENT / PART.INLINE / null

    if (part.isMimeType("text/*")) {
        // 文本內容 (plain/html)
        String text = (String) part.getContent();
        System.out.println("【文本】" + text);
    }
    else if (part.isMimeType("multipart/*")) {
        // 容器:遞歸處理子 Part
        Multipart mp = (Multipart) part.getContent();
        for (int i = 0; i < mp.getCount(); i++) {
            parseMessage(mp.getBodyPart(i));
        }
    }
    else {
        // 單獨附件 (application/octet-stream, image/*, etc.)
        String fileName = part.getFileName();
        if (fileName != null) {
            fileName = MimeUtility.decodeText(fileName); // 解碼 RFC 2047
        }
        InputStream is = part.getInputStream();
        saveAttachment(fileName, is); // 自行實現保存邏輯
        System.out.println("【附件】" + fileName + " (" + contentType + ")");
    }
}

調用入口

Store store = session.getStore("imaps"); // 或 pop3s
store.connect(host, user, password);
Folder folder = store.getFolder("INBOX");
folder.open(Folder.READ_WRITE); // 需寫入權限以設置標誌

Message[] messages = folder.getMessages();
for (Message msg : messages) {
    System.out.println("=== 郵件: " + msg.getSubject() + " ===");
    parseMessage(msg);
}

// 完成後關閉
folder.close(true);
store.close();

四、實戰注意事項

  • 編碼統一:發送端 MimeUtility.encodeWord,接收端 MimeUtility.decodeText,主題/附件名/內文均指定 UTF-8。
  • 大附件流式處理:part.getInputStream() 直接寫入磁盤,避免 getContent() 將大文件載入內存導致 OOM。
  • 內嵌圖片去重:同一郵件多處引用同一圖片,Content-ID 應一致,解析時可建立 Map 緩存。
  • POP3 vs IMAP:POP3 通常下載後刪除服務器郵件,不支持標誌同步;IMAP 支持服務器端標誌管理、多客戶端同步,企業級應用首選 IMAP。
  • 異常捕獲:網絡中斷、服務器超時、認證失敗均需捕獲 MessagingException 並重試/告警。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved