You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于JDK的Java提取目录未送达邮件附件.eml方案及代码修复

修复后的EML附件提取代码

原代码存在的问题

  • 仅处理单个.eml文件,未遍历目标目录下所有.eml
  • 循环中修改saveDir变量,导致后续附件路径错误
  • extractEML方法逻辑偏离需求(提取PDF而非嵌套的.eml附件),且存在冗余参数和重复异常声明
  • 创建目录时使用mkdir()无法生成多级目录,容易失败
  • 未处理文件名重复的情况,可能导致文件覆盖
  • 异常处理过于粗暴,直接抛出所有异常,不利于排查问题

修复后的代码

import jakarta.mail.*;
import jakarta.mail.internet.MimeBodyPart;
import jakarta.mail.internet.MimeMessage;

import java.io.*;
import java.util.Properties;

public class EMLAttachmentExtractor {

    // 配置:源目录和目标目录,根据实际修改
    private static final String SOURCE_DIR = "/Users/Documents/old";
    private static final String DEST_DIR = "/Users/Documents/extracted_eml_attachments";

    public static void main(String[] args) {
        // 初始化目标目录
        File destFolder = new File(DEST_DIR);
        if (!destFolder.exists()) {
            if (destFolder.mkdirs()) {
                System.out.println("目标目录已创建:" + DEST_DIR);
            } else {
                System.err.println("无法创建目标目录:" + DEST_DIR);
                return;
            }
        }

        // 遍历源目录下所有.eml文件
        File sourceFolder = new File(SOURCE_DIR);
        File[] emlFiles = sourceFolder.listFiles((dir, name) -> name.toLowerCase().endsWith(".eml"));
        if (emlFiles == null || emlFiles.length == 0) {
            System.err.println("源目录中未找到.eml文件");
            return;
        }

        Properties props = new Properties();
        Session mailSession = Session.getDefaultInstance(props, null);

        for (File emlFile : emlFiles) {
            System.out.println("正在处理文件:" + emlFile.getName());
            try (InputStream is = new FileInputStream(emlFile)) {
                MimeMessage message = new MimeMessage(mailSession, is);
                processMessage(message, destFolder, emlFile.getName());
            } catch (Exception e) {
                System.err.println("处理文件失败:" + emlFile.getName() + ",错误信息:" + e.getMessage());
            }
        }
        System.out.println("所有文件处理完成");
    }

    /**
     * 处理单个邮件消息,提取其中的.eml附件
     */
    private static void processMessage(MimeMessage message, File destFolder, String parentFileName) throws MessagingException, IOException {
        Object content = message.getContent();
        if (content instanceof Multipart multipart) {
            int partCount = multipart.getCount();
            for (int i = 0; i < partCount; i++) {
                BodyPart bodyPart = multipart.getBodyPart(i);
                String disposition = bodyPart.getDisposition();

                // 处理附件
                if (Part.ATTACHMENT.equalsIgnoreCase(disposition)) {
                    String fileName = bodyPart.getFileName();
                    if (fileName != null && fileName.toLowerCase().endsWith(".eml")) {
                        // 处理文件名重复:在文件名前添加原文件前缀
                        String safeFileName = parentFileName.replace(".eml", "_") + fileName;
                        File destFile = new File(destFolder, safeFileName);

                        // 避免文件覆盖
                        int counter = 1;
                        while (destFile.exists()) {
                            String baseName = safeFileName.substring(0, safeFileName.lastIndexOf("."));
                            safeFileName = baseName + "_" + counter + ".eml";
                            destFile = new File(destFolder, safeFileName);
                            counter++;
                        }

                        // 保存附件
                        ((MimeBodyPart) bodyPart).saveFile(destFile);
                        System.out.println("已提取附件:" + destFile.getAbsolutePath());

                        // 递归处理嵌套的.eml附件(如果有的话)
                        processMessage(new MimeMessage(Session.getDefaultInstance(new Properties(), null), new FileInputStream(destFile)), destFolder, safeFileName);
                    }
                } else if (bodyPart.getContent() instanceof Multipart) {
                    // 处理内嵌的multipart(比如邮件正文里的附件)
                    processMessage((MimeMessage) bodyPart.getContent(), destFolder, parentFileName);
                }
            }
        }
    }
}

关键修复点说明

  1. 批量处理文件:使用listFiles过滤器自动遍历源目录下所有.eml文件
  2. 路径管理优化:不再修改全局目录变量,每次生成独立的目标文件路径
  3. 核心逻辑修正:专注提取.eml附件,支持递归处理嵌套在附件里的.eml文件
  4. 目录创建优化:使用mkdirs()创建多级目录,确保目录结构能正常生成
  5. 文件名冲突解决:通过添加原文件名前缀和递增计数器,避免重复文件被覆盖
  6. 异常处理优化:捕获单个文件的处理异常,单个文件失败不中断整个批量任务
  7. 资源自动管理:使用try-with-resources语法自动关闭输入流,避免资源泄漏

依赖说明

注意:jakarta.mail并非JDK自带类库,需要在项目中引入依赖。如果使用Maven,可添加以下依赖:

<dependency>
    <groupId>com.sun.mail</groupId>
    <artifactId>jakarta.mail</artifactId>
    <version>2.0.1</version>
</dependency>

内容的提问来源于stack exchange,提问作者daringfireball

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 06:16:08