1. 引言

本文将介绍如何使用Java读取邮件正文中的文本内容。我们将借助JavaMail API连接邮件服务器、获取邮件并解析正文内容。

2. 环境准备

首先需要在pom.xml中添加jakarta.mail依赖:

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

JavaMail API提供了一套完整的邮件处理框架,包含连接服务器、收发邮件等核心功能。该库封装了邮件操作的底层细节,让开发者能专注于业务逻辑。

3. 连接邮件服务器

建立连接需要创建Session对象,它作为应用与邮件服务器的通信桥梁。该会话通过Store对象建立与邮件服务器的实际连接

// 配置JavaMail参数
Properties props = new Properties();
props.put("mail.smtp.host", "smtp.gmail.com");
props.put("mail.smtp.port", "587");
props.put("mail.smtp.auth", "true");
props.put("mail.smtp.starttls.enable", "true");

Session session = Session.getInstance(props, new Authenticator() {
    @Override
    protected PasswordAuthentication getPasswordAuthentication() {
        return new PasswordAuthentication("your_email@gmail.com", "your_password");
    }
});

// 连接邮件服务器
try (Store store = session.getStore("imaps")){
    store.connect("imap.gmail.com", "your_email@gmail.com", "your_password");

    // ...后续操作
} catch (MessagingException e) {
    // 异常处理
}

关键步骤说明:

  1. 配置SMTP服务器参数(主机、端口、认证方式等)
  2. 通过Authenticator提供认证凭据
  3. Authenticator返回包含邮箱密码的PasswordAuthentication对象
  4. 使用try-with-resources管理Store对象生命周期,确保资源自动释放

⚠️ 注意:生产环境中密码应使用环境变量或密钥库管理,避免硬编码

4. 获取邮件

连接建立后,下一步是从收件箱获取邮件。这需要使用Folder类访问收件箱文件夹,然后获取其中的邮件

//...(连接服务器代码同上)

// 打开收件箱
try (Folder inbox = store.getFolder("inbox")){
    inbox.open(Folder.READ_ONLY);

    // 获取所有邮件
    Message[] messages = inbox.getMessages();

} catch (MessagingException e) {
    // 异常处理
}

操作要点:

  1. 通过store.getFolder("inbox")获取收件箱对象
  2. 以只读模式(Folder.READ_ONLY)打开文件夹,避免意外修改邮件
  3. getMessages()返回所有邮件的Message数组

✅ 建议实际应用中添加分页逻辑,避免一次性加载过多邮件导致内存问题

5. 读取邮件内容

获取Message数组后,遍历每个邮件对象读取内容。需要处理MultipartBodyPart等核心类:

void retrieveEmails() throws MessagingException {
    // ...连接和打开收件箱代码

    for (Message message : messages) {
        try {
            Object content = message.getContent();

            if (content instanceof Multipart) {
                Multipart multipart = (Multipart) content;

                for (int i = 0; i < multipart.getCount(); i++) {
                    BodyPart bodyPart = multipart.getBodyPart(i);
                    if (bodyPart.getContentType().toLowerCase().startsWith("text/plain")) {
                        plainContent = (String) bodyPart.getContent();
                    } else if (bodyPart.getContentType().toLowerCase().startsWith("text/html")) {
                        // 处理HTML内容
                    } else {
                       // 处理附件
                    }
                }
            } else {
                plainContent = (String) content;
            }
        } catch (IOException | MessagingException e) {
            // 异常处理
        }
    }
}

处理逻辑说明:

  1. 通过getContent()获取邮件内容,返回类型可能是String(纯文本)或Multipart(多部分)
  2. 纯文本邮件直接转换为String
  3. **多部分邮件需要遍历每个BodyPart**:
    • text/plain类型:纯文本正文
    • text/html类型:HTML正文
    • 其他类型:附件文件

❌ 常见误区:直接强制转换contentString会导致多部分邮件解析失败

6. 处理HTML内容

对于HTML格式的邮件正文,推荐使用Jsoup库解析并提取文本:

try (InputStream inputStream = bodyPart.getInputStream()) {
    String htmlContent = new String(inputStream.readAllBytes(), "UTF-8");     
    Document doc = Jsoup.parse(htmlContent);     
    htmlContent = doc.text();
} catch (IOException e) {
    // 异常处理
}

处理步骤:

  1. BodyPart获取输入流
  2. 读取完整HTML内容
  3. 使用Jsoup解析并提取纯文本
  4. doc.text()方法会自动去除HTML标签

✅ 优势:Jsoup能处理格式不规范的实际HTML,比正则表达式更可靠

7. 处理嵌套Multipart

JavaMail中可能出现Multipart嵌套的情况(如带附件的HTML邮件)。需要使用递归遍历整个嵌套结构

首先创建消息内容提取方法:

String extractTextContent(Message message) throws MessagingException, IOException {
    Object content = message.getContent();
    return getTextFromMessage(content);
}

然后实现递归解析逻辑:

String getTextFromMessage(Object content) throws MessagingException, IOException {
    if (content instanceof Multipart) {
        Multipart multipart = (Multipart) content;
        StringBuilder text = new StringBuilder();
        for (int i = 0; i < multipart.getCount(); i++) {
            BodyPart bodyPart = multipart.getBodyPart(i);
            text.append(getTextFromMessage(bodyPart.getContent()));
        }
        return text.toString();
    } else if (content instanceof String) {
        return (String) content;
    }
    return "";
}

关键设计:

  1. 递归处理Multipart中的每个部分
  2. 遇到String直接追加到结果
  3. 使用StringBuilder高效拼接文本
  4. 非文本类型返回空字符串

⚠️ 注意:递归深度过大可能导致栈溢出,实际应用中可考虑改用迭代方式

8. 测试验证

我们发送包含纯文本和HTML部分的测试邮件:

测试邮件示例

测试代码验证内容提取:

EmailService es = new EmailService(session);
es.retrieveEmails();
assertEquals("This is a text body", es.getPlainContent());
assertEquals("This is an HTML body", es.getHTMLContent());

测试要点:

  1. 验证纯文本部分正确提取
  2. 验证HTML部分正确解析
  3. 确保附件不影响正文提取

✅ 建议增加边界测试:空邮件、超大附件、特殊字符等场景

9. 总结

本文系统介绍了使用Java读取邮件正文的核心技术:

  • JavaMail API基础配置
  • 邮件服务器连接与认证
  • 多格式邮件内容解析
  • HTML内容处理技巧
  • 嵌套结构递归方案

完整示例代码可在GitHub获取。实际应用中还需考虑:

  • 邮件分页加载
  • 异常重试机制
  • 敏感信息脱敏
  • 性能优化方案

掌握这些技术后,可以轻松实现邮件归档、内容分析等高级功能。


原始标题:How to Read Text Inside Mail Body | Baeldung