Java STMP 发送邮件工具类代码 支持腾讯/网易企业邮箱
文章目录[隐藏]

2年前邮件写过一个类似的笔记
java 通过 smtp 服务 给指定邮箱发送邮件 可包含附件
但是这段代码如今运行起来已经不方便了。
原因比较复杂,简单来说就是
这些年从 java8
发展到 java21
问题1:把 javax
部分代码逐渐迁移 jakarta
包下
并且不再是自带的,需要引入依赖
问题2:对于 SSL
的协议越来越严格,最低要求偏高,
比如 JDK8
最高支持到 TLS1.2
,从 JDK11
开始,最低已经是 TLS1.2
了
而网易企业邮箱强制开启 SSL
,否则会报错
对应的,现在执行之前的邮件工具类代码会出现2个问题
1. 最高只能支持 JDK1.8
,如果硬上 JDK17
,会因为 SSL
协议版本报安全错误,就算是 JDK1.8
,新版 OpenJDK
都不是原生支持,要改 java.security
,降低最低 SSL
版本要求
2. SSL
版本不符合最低 TLS1.2
要求,当你要开启 TLS1.2
的时候,就需要跟上最新版本的 jakarta.mail
依赖
综上所述,我百度了2天都没找到适合的代码,
CSDN全都是5年前的代码,互相来回抄,
2024年新发布的代码,还有在依赖sun或者javax的,
无奈,只能自己在原来代码的基础上小改一下,
结合外网的资料,缝缝补补又三年。
折腾
过程略过,直接上最终结果
这里接入的是网易企业邮箱,你直接套用到类似腾讯企业邮箱也是没问题的
maven依赖
<dependency>
<groupId>jakarta.mail</groupId>
<artifactId>jakarta.mail-api</artifactId>
<version>2.1.3</version>
</dependency>
<dependency>
<groupId>org.eclipse.angus</groupId>
<artifactId>jakarta.mail</artifactId>
<version>1.0.0</version>
</dependency>
工具类代码
package com.xiaoliu.utils;
import com.sun.mail.util.MailSSLSocketFactory;
import jakarta.mail.*;
import jakarta.mail.internet.*;
import org.apache.commons.lang3.StringUtils;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.util.Date;
import java.util.Properties;
/**
* 网易企业邮箱工具类
* @author xiaoliu
* @date 2025年2月5日0:39:08
*/
public class EmailUtils {
// smtp协议一般不用改
private static final String protocol = "smtp";
// 这里的域名和端口根据你接入哪一家决定 我这是网易企业邮箱的
private static final String host = "smtp.qiye.163.com";
private static final String port = "994";
// 这里要改成你的账户名 一般是个邮箱地址
private static final String username = "xxx@xxx.com";
// 这里要改成你的密码 一般在邮箱设置里
private static final String password = "xxxxxxxxxxxxxxxx";
// 这里改成你的邮箱发送者名称 你自己起一个就行
private static final String personal = "xxxxxxxxxxxxxx";
// 身份验证
static class UserAuthenticator extends Authenticator {
String u = null;
String p = null;
public UserAuthenticator(String u, String p) {
this.u = u;
this.p = p;
}
@Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(u, p);
}
}
/** 请求参数 */
private static Properties getProperties() throws GeneralSecurityException {
Properties prop = new Properties();
// 协议
prop.setProperty("mail.transport.protocol", protocol);
// 域名
prop.setProperty("mail.smtp.host", host);
// 端口
prop.setProperty("mail.smtp.port", port);
// 使用smtp身份验证
prop.setProperty("mail.smtp.auth", "true");
// 使用SSL,企业邮箱必需!
MailSSLSocketFactory mailSSLSocketFactory = new MailSSLSocketFactory();
mailSSLSocketFactory.setTrustAllHosts(true);
prop.put("mail.smtp.ssl.socketFactory", mailSSLSocketFactory);
prop.put("mail.smtp.ssl.enable", "true");
return prop;
}
/** 请求消息体 */
public static MimeMessage getMimeMessage(String subject, String content, String filePath, String fileName) throws GeneralSecurityException {
Properties prop = getProperties();
Session session = Session.getDefaultInstance(prop, new UserAuthenticator(username, password));
session.setDebug(false);
MimeMessage mimeMessage = new MimeMessage(session);
try {
// 发件人
if (StringUtils.isNotBlank(personal)) {
// 可以设置发件人的别名
mimeMessage.setFrom(new InternetAddress(username, personal));
} else {
// 如果不需要就省略
mimeMessage.setFrom(new InternetAddress(username));
}
// 主题
mimeMessage.setSubject(subject);
// 时间
mimeMessage.setSentDate(new Date());
// 容器类,可以包含多个MimeBodyPart对象
Multipart mp = new MimeMultipart();
// MimeBodyPart可以包装文本,图片,附件
MimeBodyPart body = new MimeBodyPart();
// HTML正文
body.setContent(content, "text/html; charset=UTF-8");
mp.addBodyPart(body);
// 添加图片&附件
if (StringUtils.isNotBlank(filePath)) {
MimeBodyPart mbp = new MimeBodyPart();
mbp.attachFile(filePath);
mbp.setFileName(MimeUtility.encodeWord(fileName));
mp.addBodyPart(mbp);
}
// 设置邮件内容
mimeMessage.setContent(mp);
mimeMessage.saveChanges();
return mimeMessage;
} catch (MessagingException | IOException e) {
e.printStackTrace();
}
return null;
}
/**
* 发送邮件基本方法 (单发 含文件)
* 需要注意的是这里发送过程会很慢大约10~20秒
* 并且会阻塞线程,我这里就是这样设计的
* 如果你用在接口中,建议用@Async方案做成异步处理
*/
public static void sendEmail(String recipient, String subject, String content, String filePath, String fileName) {
try {
MimeMessage mimeMessage = getMimeMessage(subject, content, filePath, fileName);
// 单个收件人
mimeMessage.addRecipient(Message.RecipientType.TO, new InternetAddress(recipient));
Transport.send(mimeMessage);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 简化版
* @param recipient 对方邮箱地址
* @param subject 标题
* @param content 内容文本
*/
public static void sendEmail(String recipient, String subject, String content) {
sendEmail(recipient, subject, content, null, null);
}
public static void main(String[] args) {
sendEmail("admin@xiaoliu.wiki","测试标题","测试简单文本内容");
}
}
亲测大约10 ~ 20秒后发送成功
值得注意的是
这段代码我是特意设计成阻塞允许的,也就是从开始执行到发送成功,大约需要20秒,如果你用在Srpingboot的Controller中,请求会长达20秒以上,一般来说必须用异步处理一下。比如在方法上标注@Async。