在Java中如何编写简单邮件模拟程序_Java面向对象项目说明

Java发送邮件必须用JavaMail API(现推荐Eclipse Angus Mail),因JDK不内置该能力;模拟邮件需构造MimeMessage并writeTo输出MIME结构,而非调用Transport.send()。

Java发送邮件必须用JavaMail API吗

是的,标准JDK不内置邮件发送能力,javax.mail(现为com.sun.mail:javax.mail)仍是主流选择。Java 11+ 默认不包含该库,需手动引入依赖。

  • OpenJDK 17+ 用户注意:javamail 已从 Oracle 移交至 Eclipse,推荐使用 org.eclipse.angus:angus-mail(兼容性更好,无 java.activation 依赖)
  • Maven 中排除旧版 javax.activation,否则运行时抛 NoClassDefFoundError: javax/activation/DataSource
  • 若仅做“模拟”(不真发),可跳过 SMTP 配置,直接构造 MimeMessage 对象并打印内容到控制台

如何用MimeMessage模拟一封带文本和附件的邮件

模拟重点是绕过网络发送环节,专注对象构建与结构验证。关键在于不调用 Transport.send(),改用 message.writeTo(OutputStream) 输出原始 MIME 内容。

import javax.mail.internet.MimeMessage;
import javax.mail.internet.InternetAddress;
import javax.mail.Session;
import java.util.Properties;
import java.io.ByteArrayOutputStream;

public class EmailSimulator {
    public static void main(String[] args) throws Exception {
        Properties props = new Properties();
        Session session = Session.getInstance(props); // 空配置即可,不连SMTP
        MimeMessage message = new MimeMessage(session);

        message.setFrom(new InternetAddress("sender@test.com"));
        message.addRecipient(javax.mail.Message.RecipientType.TO,
                new InternetAddress("receiver@test.com"));
        message.setSubject("测试邮件(模拟)");
        message.setText("这是一封纯文本模拟邮件。\n附件已加入,但未上传。");

        // 模拟添加附件(仅构造Part,不读真实文件)
        javax.mail.internet.MimeBodyPart attachment = new javax.mail.internet.MimeBodyPart();
        attachment.setFileName("report.pdf");
        attachment.setText("【模拟附件内容:PDF 文件字节流未加载】");

        javax.mail.Multipart multipart = new javax.mail.internet.MimeMultipart();
        multipart.addBodyPart(new javax.mail.internet.MimeBodyPart()); // 正文Part
        multipart.addBodyPart(attachment);
        message.setContent(multipart);

        // 输出原始邮件内容(含Headers + MIME结构),供人工或工具校验
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        message.writeTo(out);
        System.out.println(out.toString("UTF-8"));
    }
}

为什么用angus-mail替代javax.mail

Oracle 的 javax.mail 在 Java 9+ 模块化后问题频出,常见报错如:Module java.activation not foundClassNotFoundException: javax.activation.DataHandler。Eclipse Angus 是官方继任者,修复了这些兼容性断点。

  • Maven 依赖写法(替换旧版):org.eclipse.angusangus-mail2.0.3
  • 包名完全兼容:仍用 javax.mail.*,无需改代码
  • 自动处理 java.activation 缺失问题,不依赖 java.desktop 模块
  • 若项目强制用 Java 8,可继续用 com.sun.mail:javax.mail:1.6.2,但注意其 mail.smtp.ssl.checkserveridentity 默认为 false,存在中间人风险

模拟程序里怎么验证收件人格式和主题长度

真实邮件服务端会对 TO 字段做 RFC 5322 校验,模拟阶段可提前拦截明显错误,避免后续调试时被 SMTP 拒绝。

  • 邮箱格

    式检查别只用简单正则——^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}$ 能覆盖 95% 场景,但无法识别 "quoted@domain.com" 这类合法形式;建议用 InternetAddress.parse(String) 尝试解析,捕获 AddressException
  • 主题长度超 78 字符会触发 MIME 折行(=?UTF-8?B?...?=),虽不影响送达,但部分老旧客户端显示异常;模拟时可用 message.getSubject().length() > 78 提示警告
  • 中文主题必须用 MimeUtility.encodeText() 编码,否则收件端显示乱码;模拟输出时若看到原始中文,说明编码漏了
实际跑通模拟程序的关键不在“发出去”,而在“结构对不对”。很多人卡在附件没设 Content-ID 却想渲染成内嵌图片,或主题没编码就含 emoji,结果邮件内容完整但展示失败——这些细节,必须在模拟阶段就看见。