Java案例如何实现邮件发送?从零搭建邮件通知系统
目录导读
- 邮件发送的核心原理 —— SMTP协议与JavaMail API简介
- 环境搭建与依赖配置 —— Maven项目引入JavaMail
- 基础邮件发送案例 —— 文本邮件、HTML邮件、附件邮件
- 高级特性实战 —— SSL/TLS加密、多收件人、邮件模板
- 常见问题与调试技巧 —— 连接超时、认证失败、乱码解决
- Q&A问答精编 —— 开发者最关心的10个邮件发送问题
邮件发送的核心原理
Java实现邮件发送依赖 SMTP协议(简单邮件传输协议)和 JavaMail API,JavaMail是Oracle提供的标准扩展库,封装了邮件发送的底层细节,发送流程如下:

Java应用 → JavaMail API → SMTP服务器 → 目标邮箱服务器 → 收件人
常见的SMTP服务器包括QQ邮箱(smtp.qq.com)、网易邮箱(smtp.163.com)、Gmail(smtp.gmail.com),发送时需使用 授权码(非登录密码)进行身份验证。
环境搭建与依赖配置
Maven依赖(pom.xml)
<dependency>
<groupId>com.sun.mail</groupId>
<artifactId>javax.mail</artifactId>
<version>1.6.2</version>
</dependency>
获取邮箱授权码
以QQ邮箱为例:
- 登录QQ邮箱 → 设置 → 账户
- 开启 POP3/SMTP服务
- 生成授权码(保存备用)
注意:Gmail需开启“允许不够安全的应用”或使用应用专用密码。
基础邮件发送案例
1 发送纯文本邮件
import javax.mail.*;
import javax.mail.internet.*;
import java.util.Properties;
public class TextEmailSender {
public static void main(String[] args) {
String host = "smtp.qq.com";
String port = "465"; // SSL端口
String username = "your_email@qq.com";
String password = "your_authorization_code";
String to = "recipient@example.com";
Properties props = new Properties();
props.put("mail.smtp.host", host);
props.put("mail.smtp.port", port);
props.put("mail.smtp.auth", "true");
props.put("mail.smtp.ssl.enable", "true");
Session session = Session.getInstance(props, new Authenticator() {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(username, password);
}
});
try {
Message message = new MimeMessage(session);
message.setFrom(new InternetAddress(username));
message.setRecipients(Message.RecipientType.TO, InternetAddress.parse(to));
message.setSubject("Java邮件测试");
message.setText("Hello, 这是一封来自Java的测试邮件!");
Transport.send(message);
System.out.println("邮件发送成功!");
} catch (MessagingException e) {
e.printStackTrace();
}
}
}
2 发送HTML格式邮件
message.setContent("<h1>标题</h1><p>正文内容</p>", "text/html; charset=utf-8");
3 发送带附件的邮件
MimeBodyPart attachmentPart = new MimeBodyPart();
attachmentPart.attachFile(new File("document.pdf"));
Multipart multipart = new MimeMultipart();
multipart.addBodyPart(attachmentPart);
message.setContent(multipart);
高级特性实战
1 使用SSL/TLS加密连接
建议始终使用SSL(端口465)或TLS(端口587):
props.put("mail.smtp.ssl.enable", "true"); // SSL方式
// 或
props.put("mail.smtp.starttls.enable", "true"); // TLS方式(端口587)
2 发送给多个收件人
message.setRecipients(Message.RecipientType.TO,
InternetAddress.parse("user1@test.com, user2@test.com"));
// 抄送/密送:Message.RecipientType.CC / BCC
3 使用邮件模板
在resources/templates下创建email-template.html,通过Java读取并替换占位符:
String template = new String(Files.readAllBytes(Paths.get("template.html")));
String content = template.replace("${name}", "张三");
message.setContent(content, "text/html; charset=utf-8");
4 异步发送(推荐生产环境)
使用线程池避免阻塞主线程:
ExecutorService executor = Executors.newFixedThreadPool(5); executor.submit(() -> sendEmail(message));
常见问题与调试技巧
| 问题现象 | 可能原因 | 解决方案 |
|---|---|---|
| 连接超时 | 端口/主机错误,或防火墙屏蔽 | 验证465/587端口,检查防火墙设置 |
| 认证失败 | 授权码错误或未开启SMTP服务 | 重新生成授权码,确认邮箱设置 |
| 邮件乱码 | 编码未设置 | 添加charset=utf-8参数 |
| 被判定为垃圾邮件 | 发送频率过高或内容敏感 | 降低频率,避免触发反垃圾规则 |
调试技巧:在Session设置session.setDebug(true);打印详细日志。
Q&A问答精编
Q1:为什么使用授权码而不是QQ密码?
A:授权码是独立密码,避免泄露真实密码,邮箱服务商强制要求使用授权码进行第三方客户端登录。
Q2:发送附件时文件路径如何写?
A:建议使用绝对路径或类路径(getClass().getResourceAsStream("/files/attachment.pdf")),生产环境文件应从数据库或对象存储获取。
Q3:如何实现邮件发送失败重试?
A:捕获MessagingException后休眠几秒重试(建议最多3次),并记录日志,注意避免无限重试导致资源耗尽。
Q4:支持发送给QQ邮箱、163邮箱、Gmail吗?
A:支持,只需修改SMTP主机、端口和授权码,Gmail需注意其安全限制(需开启“低安全性应用访问”或使用OAuth2)。
Q5:邮件发送后如何跟踪是否被打开?
A:嵌入1像素透明图片(需后端记录图片请求),或添加邮件回执请求头(部分邮箱不支持)。
Q6:使用Spring Boot如何简化配置?
A:引入spring-boot-starter-mail,在application.yml配置:
spring.mail.host=smtp.qq.com spring.mail.port=465 spring.mail.username=xxx spring.mail.password=授权码 spring.mail.properties.mail.smtp.ssl.enable=true
然后注入JavaMailSender即可。
Q7:邮件内容包含动态数据,如何处理?
A:使用模板引擎(Thymeleaf/Freemarker)将数据渲染到HTML模板,再发送。
Q8:为什么发送成功对方收不到?
A:检查垃圾箱、域名解析问题、对方邮箱服务器拒收(如被列入黑名单)。
Q9:是否支持发送日历会议邀请?
A:通过创建iCal附件(.ics文件)实现,JavaMail直接添加MimeBodyPart即可。
Q10:海量邮件发送如何处理?
A:使用消息队列(RabbitMQ/Kafka)解耦,批量发送时控制并发数,避免触发限流。
Java邮件发送看似简单,但生产环境需关注:连接加密、编码统一、异常处理、性能优化,建议从简单的文本邮件开始,逐步增加HTML模板、附件、异步发送等特性,掌握核心API后,可结合Spring Boot简化开发,或使用第三方邮件服务(如SendGrid)提升可靠性。
(文中域名已替换为示例,实际使用时请替换为真实邮箱域名)