使用javamail api发送邮件的核心步骤包括引入依赖、配置邮件服务器属性、创建session对象、构建邮件内容并发送。2. 安全配置主要包括启用ssl/tls加密传输和smtp认证,使用授权码替代邮箱密码以提升安全性。3. 处理附件和html内容需使用mimemultipart和mimebodypart组合邮件内容,分别设置html正文和附件。4. 邮件发送失败常见原因包括认证失败、连接问题、ssl/tls握手失败、邮件内容格式问题及服务器限流,可通过开启调试日志、检查配置、验证文件路径等方式排查。

在Java里想发邮件,最直接且标准的路子就是用JavaMail API,它底层会帮你搞定SMTP(Simple Mail Transfer Protocol)协议的那些事儿。简单说,就是你告诉JavaMail邮件内容、收件人、发件人,以及连接哪个邮件服务器,它就能帮你把邮件送出去。

要用JavaMail API发邮件,你得先把它引入到你的项目里。Maven用户可以加这个依赖:
<dependency>
<groupId>com.sun.mail</groupId>
<artifactId>jakarta.mail</artifactId>
<version>2.0.1</version> <!-- 或者更高版本 -->
</dependency>或者,如果你还在用老一点的javax.mail,那可能是:
立即学习“Java免费学习笔记(深入)”;

<dependency>
<groupId>javax.mail</groupId>
<artifactId>mail</artifactId>
<version>1.4.7</version> <!-- 或者你用的版本 -->
</dependency>接下来就是核心的发送逻辑了。这块儿其实并不复杂,主要就是配置邮件服务器的信息,然后构造邮件内容,最后发送。
import jakarta.mail.*;
import jakarta.mail.internet.*;
import java.util.Properties;
public class EmailSender {
public static void sendEmail(String to, String from, String subject, String body,
String host, String port, final String username, final String password) throws MessagingException {
// 1. 配置邮件服务器属性
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"); // 启用SSL/TLS加密
props.put("mail.smtp.socketFactory.class", "jakarta.net.ssl.SSLSocketFactory"); // 指定SSL工厂
props.put("mail.smtp.socketFactory.fallback", "false"); // 不允许回退
props.put("mail.smtp.socketFactory.port", port); // 指定SSL端口
// 2. 创建Session对象,用于与邮件服务器交互
Session session = Session.getInstance(props, new Authenticator() {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(username, password);
}
});
// 开启调试模式,可以看到更详细的交互日志
// session.setDebug(true);
try {
// 3. 创建MimeMessage对象,代表一封邮件
MimeMessage message = new MimeMessage(session);
// 设置发件人
message.setFrom(new InternetAddress(from));
// 设置收件人
message.setRecipients(Message.RecipientType.TO, InternetAddress.parse(to));
// 设置邮件主题
message.setSubject(subject);
// 设置邮件内容
message.setText(body); // 默认是纯文本
// 4. 发送邮件
Transport.send(message);
System.out.println("邮件发送成功!");
} catch (MessagingException e) {
System.err.println("邮件发送失败:" + e.getMessage());
throw e; // 抛出异常以便上层处理
}
}
public static void main(String[] args) {
// 示例用法:请替换为你的真实信息
String to = "recipient@example.com"; // 收件人邮箱
String from = "your_email@example.com"; // 发件人邮箱
String subject = "测试邮件主题";
String body = "这是一封通过JavaMail发送的测试邮件。";
// 不同的邮件服务商,SMTP服务器地址和端口可能不同
// 比如:
// QQ邮箱:smtp.qq.com, 465 (SSL)
// 163邮箱:smtp.163.com, 465 (SSL)
// Gmail:smtp.gmail.com, 465 (SSL) 或 587 (TLS)
String host = "smtp.qq.com"; // 邮件服务器主机
String port = "465"; // 邮件服务器端口,SSL通常是465
// 你的邮箱账号和授权码(不是邮箱密码,需要去邮箱设置里开启SMTP服务并获取)
String username = "your_email@example.com";
String password = "your_authorization_code"; // 授权码
try {
sendEmail(to, from, subject, body, host, port, username, password);
} catch (MessagingException e) {
e.printStackTrace();
}
}
}这段代码的核心逻辑就是:配置连接参数,创建会话,构建邮件,然后发送。我个人觉得,这里面最容易出错的,反而不是代码逻辑本身,而是那些邮件服务器的配置,比如端口、是否需要SSL/TLS、以及那个“授权码”的问题。很多新手会直接拿邮箱密码去试,结果总是失败,因为现在大部分邮件服务商都要求用授权码来替代密码进行第三方客户端登录。

在JavaMail发送邮件时,安全性绝对是绕不过去的话题。毕竟邮件里可能包含敏感信息,而且登录邮件服务器也需要凭证。最常见的安全配置主要围绕加密和认证展开。
首先是加密传输。SMTP协议本身是明文传输的,这在信息安全方面是不能接受的。所以我们通常会用到SSL(Secure Sockets Layer)或TLS(Transport Layer Security)来加密通信。
Properties里,你需要设置mail.smtp.ssl.enable为true,并且通常端口是465。我上面代码示例用的就是这种方式。它意味着在连接建立之初,就会进行SSL握手,整个通信通道都是加密的。props.put("mail.smtp.ssl.enable", "true");
props.put("mail.smtp.socketFactory.class", "jakarta.net.ssl.SSLSocketFactory");
props.put("mail.smtp.socketFactory.fallback", "false");
props.put("mail.smtp.socketFactory.port", "465");STARTTLS命令来升级连接为加密模式。如果你的邮件服务器支持,并且端口是587,那么可以这样配置:props.put("mail.smtp.starttls.enable", "true");
props.put("mail.smtp.port", "587");
// 此时 mail.smtp.ssl.enable 不再需要设置为 true,或者设置为 false选择哪种取决于你的邮件服务商支持哪种方式,或者推荐哪种。我个人倾向于优先尝试SSL直连(465端口),因为它更直接。
其次是身份认证。邮件服务器需要知道是谁在尝试发送邮件,以防止垃圾邮件和未经授权的使用。
Properties里,设置mail.smtp.auth为true。props.put("mail.smtp.auth", "true");然后,在创建Session时,通过Authenticator提供你的用户名和密码(授权码)。这是我在示例代码中已经展示的。
一个常被忽略但非常重要的点是授权码。现在很多大型邮件服务商(如QQ邮箱、163邮箱、Gmail等)为了账户安全,不再允许第三方客户端直接使用你的邮箱登录密码进行SMTP认证。它们会要求你到邮箱设置里生成一个“授权码”或“客户端专用密码”,这个码就是你用来代替登录密码进行SMTP认证的。如果你遇到认证失败的问题,第一步就应该检查是不是用了错误的密码,或者压根没用授权码。
最后,一些更高级的安全配置可能包括:
cacerts)中,否则会报SSL握手失败的错误。不过对于公共邮件服务商,通常不需要手动配置。总的来说,安全配置的核心就是“加密”和“认证”,确保数据在传输过程中不被窃听,并且只有授权的用户才能发送邮件。
发送纯文本邮件固然简单,但在实际应用中,我们经常需要发送带有格式的HTML邮件,或者夹带文件附件。JavaMail API在这方面提供了非常灵活的支持,主要通过MimeMultipart和MimeBodyPart这两个类来实现。
发送HTML内容:
发送HTML邮件其实比纯文本多一步,就是告诉邮件客户端你发送的是HTML而不是普通文本。这通过设置Content-Type头部来实现。
// ... (前面的Properties和Session配置不变)
MimeMessage message = new MimeMessage(session);
// ... 设置发件人、收件人、主题
// 设置邮件内容为HTML
message.setContent("<h1>你好!</h1><p>这是一封<b>HTML</b>格式的测试邮件。</p>", "text/html; charset=utf-8");
// ... Transport.send(message);就这么简单!setContent方法的第二个参数就是用来指定内容类型的,text/html表示HTML格式,charset=utf-8则确保中文等字符正确显示。
发送附件:
发送附件稍微复杂一点,因为它涉及到将邮件内容和附件内容组合在一起。这需要用到MimeMultipart(多部分邮件内容)和MimeBodyPart(邮件的每个部分)。
一个典型的带附件的邮件结构是:一个MimeMultipart作为邮件的主体,它里面包含两个或更多MimeBodyPart。其中一个MimeBodyPart是邮件的文本内容(可以是纯文本或HTML),另一个或多个MimeBodyPart是附件。
import jakarta.activation.DataHandler;
import jakarta.activation.FileDataSource;
// ... 其他导入
// ... (前面的Properties和Session配置不变)
MimeMessage message = new MimeMessage(session);
// ... 设置发件人、收件人、主题
// 1. 创建MimeMultipart对象,用于组合邮件的各个部分
MimeMultipart multipart = new MimeMultipart();
// 2. 创建邮件文本部分
MimeBodyPart textPart = new MimeBodyPart();
textPart.setContent("<h1>你好!</h1><p>这是一封带附件的HTML邮件。</p>", "text/html; charset=utf-8");
multipart.addBodyPart(textPart); // 将文本部分添加到multipart中
// 3. 创建附件部分
String filePath = "path/to/your/file.pdf"; // 附件文件的路径
FileDataSource source = new FileDataSource(filePath); // 创建文件数据源
MimeBodyPart attachmentPart = new MimeBodyPart();
attachmentPart.setDataHandler(new DataHandler(source)); // 设置数据处理器
attachmentPart.setFileName(source.getName()); // 设置附件的文件名,邮件客户端会显示这个名字
multipart.addBodyPart(attachmentPart); // 将附件部分添加到multipart中
// 如果有多个附件,可以重复步骤3
// 4. 将multipart设置为邮件的内容
message.setContent(multipart);
// ... Transport.send(message);这里的关键是MimeMultipart,它像一个容器,可以装载不同的MimeBodyPart。MimeBodyPart可以代表文本内容、HTML内容,也可以代表附件。对于附件,我们用FileDataSource来包装文件,然后通过DataHandler设置给MimeBodyPart。setFileName方法则决定了附件在邮件客户端中显示的名字。
需要注意的是,当邮件既有文本/HTML内容又有附件时,邮件的Content-Type通常会被自动设置为multipart/mixed。如果邮件是HTML和纯文本的“多替代”内容(即提供纯文本作为HTML的备用),则会是multipart/alternative。JavaMail API会根据你添加MimeBodyPart的方式智能地处理这些。
我个人觉得,处理附件这块儿最容易犯的错误就是忘了设置setFileName,或者路径不对导致文件找不到。另外,对于非常大的附件,直接在内存中处理可能会导致内存溢出,这时可以考虑流式处理或者使用专门的文件上传服务,但对于普通大小的附件,上述方法足够了。
邮件发送失败是开发中经常遇到的问题,而且原因五花八门。我经历过不少次,每次排查都像侦探破案。不过,总结下来,常见的失败原因也就那么几类,掌握了排查方法,就能事半功倍。
认证失败 (Authentication Failed)
session.setDebug(true):这是我的首选调试工具。在创建Session对象后,调用session.setDebug(true),JavaMail会在控制台输出详细的SMTP交互日志。如果认证失败,你会看到类似535 Authentication Failed或550 Authentication Required的错误信息。连接问题 (Connection Issues)
mail.smtp.host和mail.smtp.port。不同服务商、不同加密方式(SSL/TLS)端口可能不同(如465、587、25)。ping邮件服务器地址,看是否能通。更进一步,可以使用telnet smtp.your-email.com 465(或对应端口)来测试端口是否开放且可连接。如果telnet连接不上,那基本就是网络或防火墙问题了。SSL/TLS握手失败 (SSL/TLS Handshake Failure)
ssl.enable和starttls.enable混淆);Java环境缺少必要的证书;服务器证书过期或不被信任。mail.smtp.ssl.enable或mail.smtp.starttls.enable是否与你使用的端口和服务器要求匹配。不要同时开启两者,或者配置冲突。session.setDebug(true):同样,调试日志会显示SSL握手过程中的详细错误,比如PKIX path building failed通常表示证书信任问题。cacerts文件是否包含必要的根证书。邮件内容或格式问题
InternetAddress.parse()传入的地址是有效的邮箱格式。Transport.send()时抛出MessagingException。错误信息会提示具体的问题。服务器拒绝发送
我个人最喜欢用session.setDebug(true),它能提供最直接的线索。每次遇到邮件发送问题,我都是先开调试模式,看看SMTP服务器到底说了什么,然后根据错误码和信息去定位问题。很多时候,错误信息里已经把原因说得很清楚了,只是我们没仔细看。
以上就是Java邮件发送 Java使用SMTP协议发送邮件教程的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号