2024 Java STMP 发送邮件工具类代码 支持腾讯/网易企业邮箱 home 编辑时间 2024/05/21 ![](/api/file/getImage?fileId=664c1d0eda7405001404eb20) <br><br> ## 前言 2年前邮件写过一个类似的笔记 [java 通过 smtp 服务 给指定邮箱发送邮件 可包含附件](https://leanote.zzzmh.cn/blog/post/63688325da740500130169ab) <br> 但是这段代码如今运行起来已经不方便了。 原因比较复杂,简单来说就是 这些年从 `java8` 发展到 `java21` <br><br> 问题1:把 `javax` 部分代码逐渐迁移 `jakarta` 包下 并且不再是自带的,需要引入依赖 问题2:对于 `SSL` 的协议越来越严格,最低要求偏高, 比如 `JDK8` 最高支持到 `TLS1.2` ,从 `JDK11` 开始,最低已经是 `TLS1.2` 了 而网易企业邮箱强制开启 `SSL` ,否则会报错 <br><br> 对应的,现在执行**之前的邮件工具类代码**会出现2个问题 1. 最高只能支持 `JDK1.8` ,如果硬上 `JDK17` ,会因为 `SSL` 协议版本报安全错误,就算是 `JDK1.8`,新版 `OpenJDK` 都不是原生支持,要改 `java.security`,降低最低 `SSL` 版本要求 2. `SSL` 版本不符合最低 `TLS1.2` 要求,当你要开启 `TLS1.2` 的时候,就需要跟上最新版本的 `jakarta.mail` 依赖 <br><br> 综上所述,我百度了2天都没找到适合的代码, CSDN全都是5年前的代码,互相来回抄, 2024年新发布的代码,还有在依赖sun或者javax的, 无奈,只能自己在原来代码的基础上小改一下, 结合外网的资料,缝缝补补又三年。 <br><br> ## 折腾 过程略过,直接上最终结果 这里接入的是网易企业邮箱,你直接套用到类似腾讯企业邮箱也是没问题的 maven依赖 ```pom.xml <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> ``` 工具类代码 ```EmailUtils.java package com.zzzmh.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 zzzmh * @date 2024年5月21日11: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@zzzmh.cn","测试标题","测试简单文本内容"); } } ``` <br><br> 亲测大约10 ~ 20秒后发送成功 ![截图](/api/file/getImage?fileId=664c1b57da7405001404eb03) <br><br> 值得注意的是 这段代码我是特意设计成阻塞允许的,也就是从开始执行到发送成功,大约需要20秒,如果你用在Srpingboot的Controller中,请求会长达20秒以上,一般来说必须用异步处理一下。比如在方法上标注@Async。 ## END 送人玫瑰,手留余香 赞赏 Wechat Pay Alipay 关于2024 如何在 IntelliJ IDEA 2023 中开发 Java 8 Springboot 2.x 的项目 Vue Draggable 入门 网页列表拖动实现排序