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

Java 解析本地郵件文件:JavaMail API 實戰指南

     編輯:程式設計綜合問答

需求場景

領導要求直接解析本地 `.eml` / `.msg` 郵件文件,而非通過 IMAP/POP3 連接郵箱服務器。適用於郵件歸檔、合規審計、數據遷移、離線分析等場景。

核心方案:JavaMail + MimeMessage

1. 依賴配置 (Maven)

<dependency>
    <groupId>com.sun.mail</groupId>
    <artifactId>jakarta.mail</artifactId>
    <version>2.0.1</version>
</dependency>
<!-- 解析 .msg (Outlook) 需額外依賴 -->
<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi-scratchpad</artifactId>
    <version>5.2.3</version>
</dependency>

2. 解析 .eml 文件完整代碼

import jakarta.mail.*;
import jakarta.mail.internet.*;
import java.io.*;
import java.util.*;

public class LocalEmailParser {
    public static void main(String[] args) throws Exception {
        File emlFile = new File("D:/emails/sample.eml");
        parseEml(emlFile);
    }

    public static void parseEml(File file) throws Exception {
        // 1. 創建 Session (無需郵箱服務器)
        Properties props = new Properties();
        Session session = Session.getDefaultInstance(props, null);

        // 2. 從文件輸入流構建 MimeMessage
        try (FileInputStream fis = new FileInputStream(file)) {
            MimeMessage message = new MimeMessage(session, fis);
            
            // 3. 提取基本信息
            System.out.println("主題: " + MimeUtility.decodeText(message.getSubject()));
            System.out.println("發件人: " + message.getFrom()[0]);
            System.out.println("收件人: " + Arrays.toString(message.getRecipients(Message.RecipientType.TO)));
            System.out.println("抄送: " + Arrays.toString(message.getRecipients(Message.RecipientType.CC)));
            System.out.println("發送時間: " + message.getSentDate());
            System.out.println("Message-ID: " + message.getMessageID());

            // 4. 遞歸解析內容 (處理 multipart/alternative/mixed)
            parsePart(message);
        }
    }

    private static void parsePart(Part part) throws Exception {
        String contentType = part.getContentType();
        System.out.println("\n--- Part Content-Type: " + contentType + " ---");

        if (part.isMimeType("text/plain")) {
            System.out.println("【純文本】: " + part.getContent());
        }
        else if (part.isMimeType("text/html")) {
            String html = (String) part.getContent();
            System.out.println("【HTML】長度: " + html.length());
            // 可用 Jsoup 解析 HTML 提取純文本
        }
        else if (part.isMimeType("multipart/*")) {
            Multipart mp = (Multipart) part.getContent();
            for (int i = 0; i < mp.getCount(); i++) {
                parsePart(mp.getBodyPart(i));
            }
        }
        else if (Part.ATTACHMENT.equalsIgnoreCase(part.getDisposition())) {
            // 附件處理
            String fileName = MimeUtility.decodeText(part.getFileName());
            System.out.println("【附件】: " + fileName + " 大小: " + part.getSize());
            // 保存附件
            // try (InputStream is = part.getInputStream(); FileOutputStream fos = new FileOutputStream(fileName)) { ... }
        }
        else {
            // 其他類型 (inline image 等)
            Object content = part.getContent();
            System.out.println("【其他】類型: " + content.getClass().getName());
        }
    }
}

3. 解析 .msg (Outlook) 文件

import org.apache.poi.hsmf.MAPIMessage;
import java.io.File;

public class MsgParser {
    public static void parseMsg(File file) throws Exception {
        MAPIMessage msg = new MAPIMessage(file);
        System.out.println("主題: " + msg.getSubject());
        System.out.println("發件人: " + msg.getDisplayFrom());
        System.out.println("收件人: " + msg.getDisplayTo());
        System.out.println("正文 (RTF): " + msg.getBody());
        // 附件遍歷
        for (int i = 0; i < msg.getAttachmentCount(); i++) {
            MAPIMessage.Attachment att = msg.getAttachment(i);
            System.out.println("附件: " + att.getLongFileName() + " 大小: " + att.getAttachmentSize());
        }
    }
}

關鍵技術難點與解決

難點解決方案
編碼亂碼 (GB2312/UTF-8 混雜)統一使用 MimeUtility.decodeText() 解碼主題/文件名;正文指定 charset 讀取
嵌套 Multipath 結構複雜遞歸遍歷 Multipart,按 Content-Type 分派處理
內嵌圖片 (cid:) 關聯構建 Content-ID 到 Part 的映射表,HTML 渲染時替換 src
大郵件內存溢出使用 SharedFileInputStream 或臨時文件流,避免全量載入內存
.msg 格式專有Apache POI-HSMF 僅支持舊版 .msg,新版需 Aspose.Email (商業) 或 LibreOffice 轉換

工程化封裝建議

public interface EmailParser {
    EmailContent parse(File file) throws ParseException;
}

public class EmailContent {
    String subject, from, to, cc, bcc, messageId;
    Date sentDate;
    String textBody, htmlBody;
    List attachments;
    Map inlineImages; // cid -> Part
}

public class Attachment {
    String fileName, contentType, contentId;
    long size;
    InputStream contentStream; // 延遲加載
}

參考資源

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved