基于java实现SMTP发送邮件
·
一、引言
在数字化时代,邮件作为跨场景、高可靠性的信息传递载体,早已深度融入企业业务与个人生活 —— 从用户注册时的身份验证邮件、电商平台的订单通知,到企业内部的流程审批提醒,背后都离不开简单邮件传输协议(SMTP)的支撑。作为后端开发领域的主流语言,Java 凭借成熟的生态体系与稳定的性能,成为实现 SMTP 邮件发送功能的优选技术栈,其提供的 Jakarta Mail(原 JavaMail)工具包更是将复杂的协议交互封装为简洁的 API,让开发者无需深入理解 SMTP 底层细节,即可快速构建邮件发送能力。
然而,在实际开发中,开发者常面临环境配置繁琐、认证机制适配(如 SSL/TLS 加密)、邮件内容(文本 / 附件 / HTML)构建不规范、跨邮箱服务商(如 QQ 邮箱、企业微信邮箱)兼容性差等问题。本文将以 “实用落地” 为核心,从 SMTP 协议的核心工作原理切入,结合 Java 技术栈的实践特性,逐步拆解邮件发送的全流程:先讲解 Jakarta Mail 的环境搭建与依赖配置,再深入剖析邮件会话创建、发送者认证、邮件内容组装、发送逻辑实现等关键步骤,同时针对开发中常见的 “认证失败”“附件乱码”“发送超时” 等问题提供解决方案,帮助开发者高效掌握基于 Java 实现 SMTP 邮件发送的核心能力,为企业级应用的自动化邮件需求提供可落地的技术参考。
二、源码
1、maven
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.lee</groupId>
<artifactId>EmailSender</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>com.sun.mail</groupId>
<artifactId>javax.mail</artifactId>
<version>1.6.2</version>
</dependency>
</dependencies>
</project>
2、EmailSender.java
import javax.activation.DataHandler;
import javax.activation.DataSource;
import javax.activation.FileDataSource;
import javax.mail.*;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
import java.io.File;
import java.io.IOException;
import java.util.Properties;
/**
* @author Lee
* @date 2025-08-15
*/
public class EmailSender {
/**
* 发送带抄送、密送和附件的邮件
*
* @param host SMTP服务器地址
* @param port SMTP服务器端口
* @param username 发件人邮箱账号
* @param password 发件人邮箱密码或授权码
* @param toAddresses 收件人邮箱地址数组
* @param ccAddresses 抄送人邮箱地址数组(可为null)
* @param bccAddresses 密送人邮箱地址数组(可为null)
* @param subject 邮件主题
* @param content 邮件正文内容
* @param filePaths 附件文件路径数组(可为null)
* @throws MessagingException 邮件发送相关异常
* @throws IOException 附件处理相关IO异常
*/
public static void sendEmail(String host, String port, final String username, final String password,
String[] toAddresses, String[] ccAddresses, String[] bccAddresses,
String subject, String content, String[] filePaths)
throws MessagingException, IOException {
// 1. 设置邮件服务器属性
Properties props = new Properties();
props.put("mail.smtp.host", host); // SMTP服务器地址
props.put("mail.smtp.port", port); // SMTP服务器端口
props.put("mail.smtp.auth", "true"); // 需要身份验证
props.setProperty("mail.smtp.ssl.enable", "true"); // 启用SSL
// 2. 创建邮箱验证器,用于服务器身份验证
Authenticator auth = new Authenticator() {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(username, password);
}
};
// 3. 获取邮件会话
Session session = Session.getInstance(props, auth);
session.setDebug(true); // 调试模式,true时会打印详细发送日志
// 4. 创建邮件消息对象
MimeMessage message = new MimeMessage(session);
message.setFrom(new InternetAddress(username)); // 设置发件人
// 5. 设置收件人
if (toAddresses != null && toAddresses.length > 0) {
InternetAddress[] to = new InternetAddress[toAddresses.length];
for (int i = 0; i < toAddresses.length; i++) {
to[i] = new InternetAddress(toAddresses[i]);
}
message.setRecipients(Message.RecipientType.TO, to); // TO:直接收件人
}
// 6. 设置抄送人
if (ccAddresses != null && ccAddresses.length > 0) {
InternetAddress[] cc = new InternetAddress[ccAddresses.length];
for (int i = 0; i < ccAddresses.length; i++) {
cc[i] = new InternetAddress(ccAddresses[i]);
}
message.setRecipients(Message.RecipientType.CC, cc); // CC:抄送
}
// 7. 设置密送人
if (bccAddresses != null && bccAddresses.length > 0) {
InternetAddress[] bcc = new InternetAddress[bccAddresses.length];
for (int i = 0; i < bccAddresses.length; i++) {
bcc[i] = new InternetAddress(bccAddresses[i]);
}
message.setRecipients(Message.RecipientType.BCC, bcc); // BCC:密送
}
// 8. 设置邮件主题
message.setSubject(subject);
// 9. 创建多部分内容(用于同时包含正文和附件)
Multipart multipart = new MimeMultipart();
// 10. 创建正文部分
BodyPart messageBodyPart = new MimeBodyPart();
messageBodyPart.setText(content); // 设置正文内容
multipart.addBodyPart(messageBodyPart); // 将正文添加到多部分内容
// 11. 添加附件(如果有)
if (filePaths != null && filePaths.length > 0) {
for (String filePath : filePaths) {
// 创建附件部分
BodyPart attachmentBodyPart = new MimeBodyPart();
File file = new File(filePath);
// 检查文件是否存在
if (!file.exists() || !file.isFile()) {
throw new IOException("附件文件不存在或不是有效文件: " + filePath);
}
// 配置附件数据源
DataSource source = new FileDataSource(file);
attachmentBodyPart.setDataHandler(new DataHandler(source));
// 设置附件文件名(使用MimeUtility.encodeWord处理中文文件名)
attachmentBodyPart.setFileName(javax.mail.internet.MimeUtility.encodeWord(file.getName()));
// 将附件添加到多部分内容
multipart.addBodyPart(attachmentBodyPart);
}
}
// 12. 将多部分内容设置为邮件内容
message.setContent(multipart);
// 13. 发送邮件
Transport.send(message);
System.out.println("邮件发送成功!");
}
public static void main(String[] args) {
// todo 邮件服务器配置(以163为例,其他邮箱请修改对应参数)
String host = "smtp.163.com";
String port = "465";
String username = "159xxxx819@163.com"; // 发件人邮箱
String password = "****************"; // SMTP授权码
// 收件人信息
String[] toAddresses = {"182xxxx137@163.com"}; // 主收件人
String[] ccAddresses = {"252xxxx428@gmail.com"}; // 抄送人
String[] bccAddresses = {"157xxxx373@qq.com"}; // 密送人
String subject = "带抄送、密送和附件的测试邮件";
String content = "这是一封使用Java发送的带抄送、密送和附件的测试邮件。";
// 附件路径(可指定多个附件)
String[] filePaths = {};
try {
// 发送邮件
sendEmail(host, port, username, password,
toAddresses, ccAddresses, bccAddresses,
subject, content, filePaths);
} catch (MessagingException e) {
System.out.println("邮件发送失败:" + e.getMessage());
e.printStackTrace();
} catch (IOException e) {
System.out.println("附件处理错误:" + e.getMessage());
e.printStackTrace();
}
}
}
3、效果

4 总结解决步骤
- 确认 163 邮箱已开启 SMTP 服务并获取正确授权码
- 验证代码中host(smtp.163.com)、port(465 或 587)和加密配置是否匹配
- 检查网络连通性和端口是否被防火墙屏蔽
- 开启调试模式分析详细日志
三、拓展知识
1、用途
要理解 IMAP、SMTP、POP3 三个协议,核心需先明确其定位:SMTP 负责 “发送” 邮件,IMAP 和 POP3 负责 “接收” 邮件,三者协同实现完整的邮件收发流程
2、IMAP/SMTP/POP3 协议核心信息对比表
| 对比维度 | SMTP (Simple Mail Transfer Protocol) 简单邮件传输协议 | POP3 (Post Office Protocol 3) 邮局协议版本 3 | IMAP (Internet Message Access Protocol) 互联网消息访问协议 |
|---|---|---|---|
| 核心定位 | 邮件「发送 / 传输」协议(仅负责 “投递”,不负责接收 / 存储) | 邮件「接收」协议(本地下载型,服务器仅临时存储) | 邮件「接收」协议(服务器同步型,本地与服务器实时联动) |
| 核心用途 | 1. 从「发件人邮箱服务器」向「收件人邮箱服务器」传输邮件 2. 跨服务器接力投递(如 Gmail 向 QQ 邮箱发信) 3. 支持邮件客户端(如 Outlook、雷鸟)或网页端发送邮件 | 1. 将邮件从「收件人服务器」完整下载到「本地设备」(如电脑 / 手机) 2. 下载后可选择删除服务器副本,仅本地保留邮件 3. 适合单设备管理邮件的场景 | 1. 本地设备与服务器「同步邮件」(不强制完整下载,可只下载标题 / 摘要) 2. 本地操作(读 / 删 / 标星 / 建文件夹)实时同步到服务器 3. 支持多设备(电脑 + 手机 + 平板)协同访问邮件 |
| 工作原理要点 | 1. 依赖「邮件传输代理(MTA)」接力传递(如发件服务器→中转服务器→收件服务器) 2. 不处理邮件的 “读取” 或 “存储”,仅确保邮件到达目标服务器 3. 默认端口:25(非加密)、465(SSL 加密)、587(TLS 加密) | 1. 设备连接服务器后,默认下载「全部未读邮件」到本地 2. 下载完成后,服务器可按设置保留 / 删除副本(默认多为 “保留”) 3. 默认端口:110(非加密)、995(SSL 加密) 4. 仅支持 “收件箱” 同步,不支持其他文件夹(如草稿箱、已发送) | 1. 本地设备仅同步「邮件元数据」(标题、发件人),打开邮件时才下载正文 / 附件 2. 本地与服务器实时双向同步: - 手机删邮件→电脑端同步删除 - 电脑标 “已读”→手机端同步标记 3. 默认端口:143(非加密)、993(SSL 加密) 4. 支持所有文件夹(收件箱 / 草稿 / 已删)同步 |
| 典型应用场景 | 1. 所有邮箱服务的 “发送功能”(如 QQ 邮箱、Gmail 发邮件) 2. 邮件客户端(Outlook、Foxmail)配置发件功能 3. 企业邮件系统的跨域投递(如公司邮箱向客户邮箱发信) | 1. 单设备使用(如仅用旧电脑查收邮件,无需多设备同步) 2. 流量 / 存储有限的场景(如旧手机,仅下载关键邮件) 3. 希望邮件仅本地保存,不占用服务器空间的需求 | 1. 多设备协同(如电脑办公 + 手机通勤查邮件,需同步状态) 2. 工作邮箱(需随时同步邮件进度,避免误删) 3. 对邮件安全性要求高(本地误删可从服务器恢复) |
| 优点 | 1. 标准化程度极高,所有邮箱服务商均支持 2. 支持加密传输(SSL/TLS),防邮件被窃取 3. 可通过 “中继服务器” 解决发件 IP 黑名单问题 | 1. 本地访问速度快(无需依赖网络加载) 2. 节省服务器存储空间(下载后可删除服务器副本) 3. 对网络依赖低(断网可查看已下载邮件) | 1. 多设备实时同步,操作一致性强 2. 邮件安全存储在服务器(本地设备损坏 / 丢失,邮件不丢失) 3. 支持选择性下载(仅下载标题,节省流量) |
| 缺点 | 1. 仅负责 “传输”,不处理接收 / 存储(需配合 IMAP/POP3 用) 2. 易受垃圾邮件 / 钓鱼邮件滥用(需配合反垃圾机制) | 1. 多设备无法同步(如手机删邮件,电脑仍显示) 2. 本地文件丢失 / 损坏则邮件无法恢复 3. 不支持文件夹同步(仅能同步收件箱) | 1. 依赖网络(断网无法访问未同步的邮件内容) 2. 长期占用服务器存储空间(需定期清理) 3. 对服务器性能要求较高(需实时处理同步请求) |
3、 三者如何协同工作?
- 发送邮件:你在 Outlook 写好邮件点击 “发送”→ 客户端通过 SMTP 协议将邮件发送到你的邮箱服务器(如 Gmail 服务器)→ 服务器再通过 SMTP 接力投递到收件人的邮箱服务器(如 QQ 邮箱服务器)。
- 接收邮件:收件人的邮箱服务器存储邮件后→ 收件人通过 Outlook 客户端,用 IMAP 或 POP3 协议从服务器获取邮件:
- 选 IMAP:多设备同步查看,操作实时同步到服务器;
- 选 POP3:仅下载到当前设备,多设备间无关联。
更多推荐


所有评论(0)