邮件带附件发送
带附件邮件发送全指南:基于 Spring 与 Apache Commons Email 的实现
在日常开发中,带附件的邮件发送是常见需求(如报表推送、文件共享等)。本文将详细讲解两种实现方式:Spring 的 MimeMessageHelper(适合 Spring 生态项目)和 Apache Commons Email(通用 Java 项目),包括依赖配置、核心代码、参数说明及常见问题解决,帮助你快速集成邮件附件功能。
技术选型对比
| 实现方式 | 优势 | 适用场景 |
|---|---|---|
Spring MimeMessageHelper |
与 Spring 无缝集成,API 简洁,支持 HTML 内容 | Spring Boot/SSM 项目 |
| Apache Commons Email | 轻量级,无 Spring 依赖,配置灵活 | 非 Spring 项目或简单 Java 应用 |
Spring 方式:使用 MimeMessageHelper
依赖配置
需引入 Spring 邮件相关依赖(适用于 Spring 项目):
<!-- Spring 邮件支持 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>4.3.29.RELEASE</version> <!-- 版本需与项目 Spring 版本匹配 -->
</dependency>
<!-- JavaMail 核心依赖 -->
<dependency>
<groupId>com.sun.mail</groupId>
<artifactId>javax.mail</artifactId>
<version>1.6.2</version>
</dependency>
核心代码实现
MimeMessageHelper 是 Spring 提供的邮件辅助类,支持附件、HTML 内容等功能:
import org.springframework.mail.javamail.JavaMailSenderImpl;
import org.springframework.mail.javamail.MimeMessageHelper;
import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;
import java.io.File;
import java.util.Properties;
public class SpringMailWithAttachment {
/**
* 发送带附件的邮件
* @param host SMTP 服务器地址(如 QQ 邮箱:smtp.qq.com)
* @param port SMTP 端口(如 QQ 邮箱:587)
* @param username 发件人邮箱账号
* @param password 发件人密码(或授权码,如 QQ 邮箱需用授权码)
* @param to 收件人邮箱(多个用逗号分隔)
* @param cc 抄送人邮箱(可选)
* @param subject 邮件标题
* @param content 邮件内容(支持 HTML)
* @param attachment 附件文件(可选)
* @return 发送成功返回 true
*/
public static boolean sendWithAttachment(String host, int port, String username, String password,
String to, String cc, String subject, String content,
File attachment) {
// 1. 配置邮件发送器
JavaMailSenderImpl sender = new JavaMailSenderImpl();
sender.setHost(host); // SMTP 服务器
sender.setPort(port); // 端口
sender.setUsername(username); // 发件人账号
sender.setPassword(password); // 密码/授权码
sender.setDefaultEncoding("UTF-8"); // 编码
// 2. 配置 SMTP properties(根据邮箱服务商要求调整)
Properties props = sender.getJavaMailProperties();
props.put("mail.smtp.auth", "true"); // 开启认证
props.put("mail.smtp.starttls.enable", "true"); // 启用 TLS(如 QQ、Gmail 需开启)
props.put("mail.debug", "false"); // 调试模式(可选,true 会打印发送日志)
try {
// 3. 创建 MIME 消息(支持附件和 HTML)
MimeMessage mimeMessage = sender.createMimeMessage();
// 第二个参数设为 true,表示支持多部分内容(附件、HTML 等)
MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true, "UTF-8");
// 4. 设置邮件基本信息
helper.setFrom(username); // 发件人
helper.setTo(to.split(",")); // 收件人(支持多个)
if (cc != null && !cc.isEmpty()) {
helper.setCc(cc.split(",")); // 抄送人
}
helper.setSubject(subject); // 标题
// 第二个参数设为 true,表示内容为 HTML 格式
helper.setText(content, true);
// 5. 添加附件(如果存在)
if (attachment != null && attachment.exists()) {
// 第一个参数:附件显示名称(可自定义);第二个参数:附件文件
helper.addAttachment(attachment.getName(), attachment);
}
// 6. 发送邮件
sender.send(mimeMessage);
System.out.println("邮件发送成功!");
return true;
} catch (MessagingException e) {
System.err.println("邮件发送失败:" + e.getMessage());
e.printStackTrace();
return false;
}
}
// 测试方法
public static void main(String[] args) {
// 示例:发送带附件的邮件(以 QQ 企业邮箱为例)
String host = "smtp.exmail.qq.com"; // QQ 企业邮箱 SMTP
int port = 587;
String username = "sender@example.com"; // 发件人邮箱
String password = "yourAuthCode"; // 授权码(非登录密码)
String to = "receiver@example.com"; // 收件人
String cc = "cc@example.com"; // 抄送人
String subject = "测试带附件的邮件";
String content = "<h1>这是一封带附件的测试邮件</h1><p>请查收附件内容</p>";
File attachment = new File("/Users/example/测试附件.pdf"); // 附件路径
sendWithAttachment(host, port, username, password, to, cc, subject, content, attachment);
}
}
关键参数说明
- SMTP 服务器与端口:不同邮箱服务商的配置不同(见下表);
- 授权码:多数邮箱(如 QQ、163)需开启 SMTP 服务并生成授权码,而非使用登录密码;
- 附件处理:
addAttachment方法可多次调用添加多个附件,第一个参数为附件在邮件中显示的名称(可自定义)。
| 邮箱服务商 | SMTP 服务器 | 端口 | 备注 |
|---|---|---|---|
| QQ 邮箱 | smtp.qq.com | 587 | 需开启 SMTP 并获取授权码 |
| 163 邮箱 | smtp.163.com | 25 | 需开启 SMTP 服务 |
| 企业微信 | smtp.exmail.qq.com | 587 | 用企业邮箱账号和密码 |
| Gmail | smtp.gmail.com | 587 | 需开启 TLS 和两步验证 |
通用方式:使用 Apache Commons Email
依赖配置
适用于非 Spring 项目,引入 Apache Commons Email:
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-email</artifactId>
<version>1.5</version> <!-- 稳定版本 -->
</dependency>
核心代码实现
Commons Email 封装了 JavaMail,API 更简洁:
import org.apache.commons.mail.*;
import java.io.File;
public class CommonsEmailWithAttachment {
/**
* 发送带附件的邮件(Commons Email 实现)
*/
public static boolean sendWithAttachment(String host, int port, String username, String password,
String to, String cc, String subject, String content,
File attachment) {
try {
// 1. 创建 MIME 邮件实例(支持附件和 HTML)
MultiPartEmail email = new HtmlEmail(); // 若需 HTML 内容,用 HtmlEmail
email.setHostName(host);
email.setSmtpPort(port);
email.setAuthentication(username, password); // 认证
email.setStartTLSEnabled(true); // 启用 TLS
email.setCharset("UTF-8");
// 2. 设置收件人、抄送人
email.addTo(to); // 收件人(可多次调用添加多个)
if (cc != null && !cc.isEmpty()) {
email.addCc(cc); // 抄送人
}
email.setFrom(username); // 发件人
email.setSubject(subject); // 标题
// 3. 设置内容(若为 HTML,需用 HtmlEmail 的 setHtmlMsg 方法)
if (email instanceof HtmlEmail) {
((HtmlEmail) email).setHtmlMsg(content);
// 可选:设置纯文本备选内容(当收件人不支持 HTML 时显示)
((HtmlEmail) email).setTextMsg("您的邮箱不支持 HTML 内容");
} else {
email.setMsg(content); // 纯文本内容
}
// 4. 添加附件
if (attachment != null && attachment.exists()) {
EmailAttachment emailAttachment = new EmailAttachment();
emailAttachment.setPath(attachment.getAbsolutePath()); // 附件路径
emailAttachment.setDisposition(EmailAttachment.ATTACHMENT);
emailAttachment.setName(attachment.getName()); // 附件显示名称
email.attach(emailAttachment);
}
// 5. 发送邮件
email.send();
System.out.println("邮件发送成功!");
return true;
} catch (EmailException e) {
System.err.println("邮件发送失败:" + e.getMessage());
e.printStackTrace();
return false;
}
}
// 测试方法
public static void main(String[] args) {
// 示例:与 Spring 方式参数相同
String host = "smtp.qq.com";
int port = 587;
String username = "your@qq.com";
String password = "yourAuthCode";
String to = "receiver@example.com";
String content = "<h1>Commons Email 测试</h1><p>附件已添加</p>";
File attachment = new File("/Users/example/附件.txt");
sendWithAttachment(host, port, username, password, to, null, "Commons Email 测试", content, attachment);
}
}
与 Spring 方式的区别
- API 风格:Commons Email 采用链式调用,更接近原生 Java 风格;
- HTML 支持:需使用
HtmlEmail子类,而 Spring 的MimeMessageHelper通过参数控制; - 附件处理:Commons Email 需通过
EmailAttachment类包装附件信息。
多附件发送与高级配置
发送多个附件
两种方式均可通过多次调用附件添加方法实现多附件发送:
// Spring 方式:多次调用 addAttachment
helper.addAttachment("附件1.pdf", new File("file1.pdf"));
helper.addAttachment("附件2.txt", new File("file2.txt"));
// Commons Email 方式:多次调用 attach
email.attach(attachment1);
email.attach(attachment2);
超大附件处理
若附件体积过大(如 >10MB),直接发送可能超时或被邮箱服务商拒绝,建议:
- 先将文件上传至云存储(如 OSS、S3),邮件中只包含下载链接;
- 拆分大文件为多个小文件,分开发送(需在邮件内容中说明)。
异步发送邮件
邮件发送可能耗时(尤其带大附件),建议通过异步方式执行,避免阻塞主线程:
// Spring 异步示例(需开启 @EnableAsync)
public void asyncSendEmail(...) {
sendWithAttachment(...);
}
// 通用异步示例(使用线程池)
ExecutorService executor = Executors.newFixedThreadPool(5);
executor.submit(() -> sendWithAttachment(...));
常见问题与解决方案
1. 认证失败(535 错误)
- 原因:密码或授权码错误,或未开启 SMTP 服务;
- 解决:
- 检查密码是否正确,多数邮箱需用 授权码(如 QQ 邮箱在 “设置 - 账户” 中开启 SMTP 并生成);
- 确认邮箱账号是否开启 SMTP 服务(登录邮箱网页版设置)。
2. 附件中文名称乱码
原因:编码设置不当;
解决:确保创建MimeMessageHelper或HtmlEmail时指定UTF-8编码:
// Spring 方式
new MimeMessageHelper(mimeMessage, true, "UTF-8");
// Commons Email 方式
email.setCharset("UTF-8");
3. 邮件被标记为垃圾邮件
- 原因:内容含敏感词、发件人信誉低、HTML 格式不规范;
- 解决:
- 避免使用 “广告”“优惠” 等敏感词;
- 内容中增加文本说明,减少纯 HTML 代码;
- 发件人邮箱提前与收件人邮箱建立联系(如让收件人将发件人加入白名单)。
4. 发送超时
原因:网络不稳定、SMTP 服务器响应慢、附件过大;
解决:
增加超时配置:
// Spring 方式添加超时参数 props.put("mail.smtp.connectiontimeout", "5000"); // 连接超时(毫秒) props.put("mail.smtp.timeout", "10000"); // 发送超时(毫秒)优化附件大小(压缩或改用链接)。