mirror of
https://github.com/dromara/RuoYi-Vue-Plus.git
synced 2026-06-11 16:26:14 +00:00
refactor(common-mail): 使用 MailBuilder 替代 MailUtils
- 新增链式 MailBuilder,统一邮件发送入口 - 删除 MailUtils,业务代码全部切换为 builder 调用 - 默认邮件账户改为发送时获取,避免类加载阶段依赖 Bean - 自定义发件账号时复制默认配置,避免污染全局 MailAccount - 增加收件人、标题和正文参数校验 - 调整内联图片流关闭时机,发送结束后统一关闭 - 将 MailAccount 构建逻辑下沉到 MailProperties
This commit is contained in:
@@ -17,7 +17,7 @@ import org.dromara.common.core.utils.SpringUtils;
|
||||
import org.dromara.common.core.utils.StringUtils;
|
||||
import org.dromara.common.core.utils.regex.RegexValidator;
|
||||
import org.dromara.common.mail.config.properties.MailProperties;
|
||||
import org.dromara.common.mail.utils.MailUtils;
|
||||
import org.dromara.common.mail.core.MailBuilder;
|
||||
import org.dromara.common.redis.annotation.RateLimiter;
|
||||
import org.dromara.common.redis.enums.LimitType;
|
||||
import org.dromara.common.redis.utils.RedisUtils;
|
||||
@@ -109,7 +109,11 @@ public class CaptchaController {
|
||||
String code = RandomUtil.randomNumbers(4);
|
||||
RedisUtils.setCacheObject(key, code, Duration.ofMinutes(Constants.CAPTCHA_EXPIRATION));
|
||||
try {
|
||||
MailUtils.sendText(email, "登录验证码", "您本次验证码为:" + code + ",有效性为" + Constants.CAPTCHA_EXPIRATION + "分钟,请尽快填写。");
|
||||
MailBuilder.of()
|
||||
.to(email)
|
||||
.subject("登录验证码")
|
||||
.text("您本次验证码为:" + code + ",有效性为" + Constants.CAPTCHA_EXPIRATION + "分钟,请尽快填写。")
|
||||
.send();
|
||||
} catch (Exception e) {
|
||||
log.error("验证码短信发送异常 => {}", e.getMessage());
|
||||
throw new ServiceException(e.getMessage());
|
||||
|
||||
@@ -19,19 +19,7 @@ public class MailConfig {
|
||||
@Bean
|
||||
@ConditionalOnProperty(value = "mail.enabled", havingValue = "true")
|
||||
public MailAccount mailAccount(MailProperties mailProperties) {
|
||||
MailAccount account = new MailAccount();
|
||||
account.setHost(mailProperties.getHost());
|
||||
account.setPort(mailProperties.getPort());
|
||||
account.setAuth(mailProperties.getAuth());
|
||||
account.setFrom(mailProperties.getFrom());
|
||||
account.setUser(mailProperties.getUser());
|
||||
account.setPass(mailProperties.getPass());
|
||||
account.setSocketFactoryPort(mailProperties.getPort());
|
||||
account.setStarttlsEnable(mailProperties.getStarttlsEnable());
|
||||
account.setSslEnable(mailProperties.getSslEnable());
|
||||
account.setTimeout(mailProperties.getTimeout());
|
||||
account.setConnectionTimeout(mailProperties.getConnectionTimeout());
|
||||
return account;
|
||||
return mailProperties.toMailAccount();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package org.dromara.common.mail.config.properties;
|
||||
|
||||
import cn.hutool.extra.mail.MailAccount;
|
||||
import lombok.Data;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
|
||||
@@ -72,4 +73,25 @@ public class MailProperties {
|
||||
* Socket连接超时值,单位毫秒,缺省值不超时
|
||||
*/
|
||||
private Long connectionTimeout;
|
||||
|
||||
/**
|
||||
* 转换为 Hutool 邮件账户配置。
|
||||
*
|
||||
* @return 邮件账户配置
|
||||
*/
|
||||
public MailAccount toMailAccount() {
|
||||
MailAccount account = new MailAccount();
|
||||
account.setHost(host);
|
||||
account.setPort(port);
|
||||
account.setAuth(auth);
|
||||
account.setFrom(from);
|
||||
account.setUser(user);
|
||||
account.setPass(pass);
|
||||
account.setSocketFactoryPort(port);
|
||||
account.setStarttlsEnable(starttlsEnable);
|
||||
account.setSslEnable(sslEnable);
|
||||
account.setTimeout(timeout);
|
||||
account.setConnectionTimeout(connectionTimeout);
|
||||
return account;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,347 @@
|
||||
package org.dromara.common.mail.core;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.io.IoUtil;
|
||||
import cn.hutool.core.map.MapUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.extra.mail.JakartaMail;
|
||||
import cn.hutool.extra.mail.MailAccount;
|
||||
import org.dromara.common.core.utils.SpringUtils;
|
||||
import org.dromara.common.core.utils.StringUtils;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.InputStream;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* 邮件发送构建器。
|
||||
*/
|
||||
public final class MailBuilder {
|
||||
|
||||
private MailAccount mailAccount;
|
||||
|
||||
private boolean useGlobalSession = true;
|
||||
|
||||
private final List<String> tos = new ArrayList<>();
|
||||
|
||||
private final List<String> ccs = new ArrayList<>();
|
||||
|
||||
private final List<String> bccs = new ArrayList<>();
|
||||
|
||||
private final Map<String, InputStream> images = new LinkedHashMap<>();
|
||||
|
||||
private File[] files = new File[0];
|
||||
|
||||
private String from;
|
||||
|
||||
private String user;
|
||||
|
||||
private String pass;
|
||||
|
||||
private String subject;
|
||||
|
||||
private String content;
|
||||
|
||||
private boolean html;
|
||||
|
||||
private MailBuilder() {
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建邮件构建器,默认使用配置文件中的邮件账户。
|
||||
*
|
||||
* @return 邮件构建器
|
||||
*/
|
||||
public static MailBuilder of() {
|
||||
return new MailBuilder();
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建邮件构建器,使用指定邮件账户。
|
||||
*
|
||||
* @param mailAccount 邮件账户
|
||||
* @return 邮件构建器
|
||||
*/
|
||||
public static MailBuilder of(MailAccount mailAccount) {
|
||||
return new MailBuilder().account(mailAccount);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置自定义邮件账户。
|
||||
*
|
||||
* @param mailAccount 邮件账户
|
||||
* @return 当前构建器
|
||||
*/
|
||||
public MailBuilder account(MailAccount mailAccount) {
|
||||
this.mailAccount = Objects.requireNonNull(mailAccount, "mailAccount must not be null");
|
||||
this.useGlobalSession = false;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 覆盖发件人。
|
||||
*
|
||||
* @param from 发件人
|
||||
* @return 当前构建器
|
||||
*/
|
||||
public MailBuilder from(String from) {
|
||||
this.from = from;
|
||||
this.useGlobalSession = false;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 覆盖登录用户名。
|
||||
*
|
||||
* @param user 用户名
|
||||
* @return 当前构建器
|
||||
*/
|
||||
public MailBuilder user(String user) {
|
||||
this.user = user;
|
||||
this.useGlobalSession = false;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 覆盖登录密码或授权码。
|
||||
*
|
||||
* @param pass 密码或授权码
|
||||
* @return 当前构建器
|
||||
*/
|
||||
public MailBuilder pass(String pass) {
|
||||
this.pass = pass;
|
||||
this.useGlobalSession = false;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加收件人,多个邮箱可使用逗号或分号分隔。
|
||||
*
|
||||
* @param addresses 收件人
|
||||
* @return 当前构建器
|
||||
*/
|
||||
public MailBuilder to(String addresses) {
|
||||
this.tos.addAll(splitAddress(addresses));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加收件人。
|
||||
*
|
||||
* @param addresses 收件人集合
|
||||
* @return 当前构建器
|
||||
*/
|
||||
public MailBuilder to(Collection<String> addresses) {
|
||||
this.tos.addAll(normalizeAddresses(addresses));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加抄送人,多个邮箱可使用逗号或分号分隔。
|
||||
*
|
||||
* @param addresses 抄送人
|
||||
* @return 当前构建器
|
||||
*/
|
||||
public MailBuilder cc(String addresses) {
|
||||
this.ccs.addAll(splitAddress(addresses));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加抄送人。
|
||||
*
|
||||
* @param addresses 抄送人集合
|
||||
* @return 当前构建器
|
||||
*/
|
||||
public MailBuilder cc(Collection<String> addresses) {
|
||||
this.ccs.addAll(normalizeAddresses(addresses));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加密送人,多个邮箱可使用逗号或分号分隔。
|
||||
*
|
||||
* @param addresses 密送人
|
||||
* @return 当前构建器
|
||||
*/
|
||||
public MailBuilder bcc(String addresses) {
|
||||
this.bccs.addAll(splitAddress(addresses));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加密送人。
|
||||
*
|
||||
* @param addresses 密送人集合
|
||||
* @return 当前构建器
|
||||
*/
|
||||
public MailBuilder bcc(Collection<String> addresses) {
|
||||
this.bccs.addAll(normalizeAddresses(addresses));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置邮件标题。
|
||||
*
|
||||
* @param subject 标题
|
||||
* @return 当前构建器
|
||||
*/
|
||||
public MailBuilder subject(String subject) {
|
||||
this.subject = subject;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置文本正文。
|
||||
*
|
||||
* @param content 正文
|
||||
* @return 当前构建器
|
||||
*/
|
||||
public MailBuilder text(String content) {
|
||||
this.content = content;
|
||||
this.html = false;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置 HTML 正文。
|
||||
*
|
||||
* @param content 正文
|
||||
* @return 当前构建器
|
||||
*/
|
||||
public MailBuilder html(String content) {
|
||||
this.content = content;
|
||||
this.html = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置正文。
|
||||
*
|
||||
* @param content 正文
|
||||
* @param html 是否 HTML
|
||||
* @return 当前构建器
|
||||
*/
|
||||
public MailBuilder content(String content, boolean html) {
|
||||
this.content = content;
|
||||
this.html = html;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加内联图片。
|
||||
*
|
||||
* @param cid 图片 cid
|
||||
* @param inputStream 图片输入流
|
||||
* @return 当前构建器
|
||||
*/
|
||||
public MailBuilder image(String cid, InputStream inputStream) {
|
||||
if (StrUtil.isNotBlank(cid) && inputStream != null) {
|
||||
this.images.put(cid, inputStream);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加内联图片。
|
||||
*
|
||||
* @param imageMap 图片 cid 与输入流映射
|
||||
* @return 当前构建器
|
||||
*/
|
||||
public MailBuilder images(Map<String, InputStream> imageMap) {
|
||||
if (MapUtil.isNotEmpty(imageMap)) {
|
||||
imageMap.forEach(this::image);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置附件。
|
||||
*
|
||||
* @param files 附件列表
|
||||
* @return 当前构建器
|
||||
*/
|
||||
public MailBuilder files(File... files) {
|
||||
this.files = files == null ? new File[0] : files;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送邮件。
|
||||
*
|
||||
* @return message-id
|
||||
*/
|
||||
public String send() {
|
||||
validate();
|
||||
MailAccount account = resolveMailAccount();
|
||||
JakartaMail mail = JakartaMail.create(account).setUseGlobalSession(useGlobalSession);
|
||||
mail.setTos(tos.toArray(new String[0]));
|
||||
if (CollUtil.isNotEmpty(ccs)) {
|
||||
mail.setCcs(ccs.toArray(new String[0]));
|
||||
}
|
||||
if (CollUtil.isNotEmpty(bccs)) {
|
||||
mail.setBccs(bccs.toArray(new String[0]));
|
||||
}
|
||||
mail.setTitle(subject);
|
||||
mail.setContent(content);
|
||||
mail.setHtml(html);
|
||||
mail.setFiles(files);
|
||||
try {
|
||||
if (MapUtil.isNotEmpty(images)) {
|
||||
images.forEach(mail::addImage);
|
||||
}
|
||||
return mail.send();
|
||||
} finally {
|
||||
images.values().forEach(IoUtil::close);
|
||||
}
|
||||
}
|
||||
|
||||
private void validate() {
|
||||
if (CollUtil.isEmpty(tos)) {
|
||||
throw new IllegalArgumentException("邮件收件人不能为空");
|
||||
}
|
||||
if (StrUtil.isBlank(subject)) {
|
||||
throw new IllegalArgumentException("邮件标题不能为空");
|
||||
}
|
||||
if (content == null) {
|
||||
throw new IllegalArgumentException("邮件正文不能为空");
|
||||
}
|
||||
}
|
||||
|
||||
private MailAccount resolveMailAccount() {
|
||||
MailAccount account = mailAccount;
|
||||
if (account == null) {
|
||||
account = SpringUtils.getBean(MailAccount.class);
|
||||
}
|
||||
if (StringUtils.isAllBlank(from, user, pass)) {
|
||||
return account;
|
||||
}
|
||||
MailAccount copy = ObjectUtil.clone(account);
|
||||
copy.setFrom(StringUtils.blankToDefault(from, copy.getFrom()));
|
||||
copy.setUser(StringUtils.blankToDefault(user, copy.getUser()));
|
||||
copy.setPass(StringUtils.blankToDefault(pass, copy.getPass()));
|
||||
return copy;
|
||||
}
|
||||
|
||||
private List<String> splitAddress(String addresses) {
|
||||
if (StrUtil.isBlank(addresses)) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
return normalizeAddresses(StrUtil.splitTrim(addresses.replace(';', ','), ','));
|
||||
}
|
||||
|
||||
private List<String> normalizeAddresses(Collection<String> addresses) {
|
||||
if (CollUtil.isEmpty(addresses)) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
List<String> result = new ArrayList<>(addresses.size());
|
||||
for (String address : addresses) {
|
||||
if (StrUtil.isNotBlank(address)) {
|
||||
result.add(address.trim());
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,473 +0,0 @@
|
||||
package org.dromara.common.mail.utils;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.io.IoUtil;
|
||||
import cn.hutool.core.map.MapUtil;
|
||||
import cn.hutool.core.util.CharUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.extra.mail.JakartaMail;
|
||||
import cn.hutool.extra.mail.JakartaUserPassAuthenticator;
|
||||
import cn.hutool.extra.mail.MailAccount;
|
||||
import jakarta.mail.Authenticator;
|
||||
import jakarta.mail.Session;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.dromara.common.core.utils.SpringUtils;
|
||||
import org.dromara.common.core.utils.StringUtils;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.InputStream;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
/**
|
||||
* 邮件工具类
|
||||
*/
|
||||
@NoArgsConstructor(access = AccessLevel.PRIVATE)
|
||||
public class MailUtils {
|
||||
|
||||
private static final MailAccount ACCOUNT = SpringUtils.getBean(MailAccount.class);
|
||||
|
||||
/**
|
||||
* 获取默认邮件账户配置。
|
||||
*
|
||||
* @return 邮件账户配置
|
||||
*/
|
||||
public static MailAccount getMailAccount() {
|
||||
return ACCOUNT;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取邮件发送实例 (自定义发送人以及授权码)
|
||||
*
|
||||
* @param from 发送人
|
||||
* @param user 发送人
|
||||
* @param pass 授权码
|
||||
* @return 邮件账户配置
|
||||
*/
|
||||
public static MailAccount getMailAccount(String from, String user, String pass) {
|
||||
ACCOUNT.setFrom(StringUtils.blankToDefault(from, ACCOUNT.getFrom()));
|
||||
ACCOUNT.setUser(StringUtils.blankToDefault(user, ACCOUNT.getUser()));
|
||||
ACCOUNT.setPass(StringUtils.blankToDefault(pass, ACCOUNT.getPass()));
|
||||
return ACCOUNT;
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用配置文件中设置的账户发送文本邮件,发送给单个或多个收件人<br>
|
||||
* 多个收件人可以使用逗号“,”分隔,也可以通过分号“;”分隔
|
||||
*
|
||||
* @param to 收件人
|
||||
* @param subject 标题
|
||||
* @param content 正文
|
||||
* @param files 附件列表
|
||||
* @return message-id
|
||||
* @since 3.2.0
|
||||
*/
|
||||
public static String sendText(String to, String subject, String content, File... files) {
|
||||
return send(to, subject, content, false, files);
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用配置文件中设置的账户发送HTML邮件,发送给单个或多个收件人<br>
|
||||
* 多个收件人可以使用逗号“,”分隔,也可以通过分号“;”分隔
|
||||
*
|
||||
* @param to 收件人
|
||||
* @param subject 标题
|
||||
* @param content 正文
|
||||
* @param files 附件列表
|
||||
* @return message-id
|
||||
* @since 3.2.0
|
||||
*/
|
||||
public static String sendHtml(String to, String subject, String content, File... files) {
|
||||
return send(to, subject, content, true, files);
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用配置文件中设置的账户发送邮件,发送单个或多个收件人<br>
|
||||
* 多个收件人可以使用逗号“,”分隔,也可以通过分号“;”分隔
|
||||
*
|
||||
* @param to 收件人
|
||||
* @param subject 标题
|
||||
* @param content 正文
|
||||
* @param isHtml 是否为HTML
|
||||
* @param files 附件列表
|
||||
* @return message-id
|
||||
*/
|
||||
public static String send(String to, String subject, String content, boolean isHtml, File... files) {
|
||||
return send(splitAddress(to), subject, content, isHtml, files);
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用配置文件中设置的账户发送邮件,发送单个或多个收件人<br>
|
||||
* 多个收件人、抄送人、密送人可以使用逗号“,”分隔,也可以通过分号“;”分隔
|
||||
*
|
||||
* @param to 收件人,可以使用逗号“,”分隔,也可以通过分号“;”分隔
|
||||
* @param cc 抄送人,可以使用逗号“,”分隔,也可以通过分号“;”分隔
|
||||
* @param bcc 密送人,可以使用逗号“,”分隔,也可以通过分号“;”分隔
|
||||
* @param subject 标题
|
||||
* @param content 正文
|
||||
* @param isHtml 是否为HTML
|
||||
* @param files 附件列表
|
||||
* @return message-id
|
||||
* @since 4.0.3
|
||||
*/
|
||||
public static String send(String to, String cc, String bcc, String subject, String content, boolean isHtml, File... files) {
|
||||
return send(splitAddress(to), splitAddress(cc), splitAddress(bcc), subject, content, isHtml, files);
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用配置文件中设置的账户发送文本邮件,发送给多人
|
||||
*
|
||||
* @param tos 收件人列表
|
||||
* @param subject 标题
|
||||
* @param content 正文
|
||||
* @param files 附件列表
|
||||
* @return message-id
|
||||
*/
|
||||
public static String sendText(Collection<String> tos, String subject, String content, File... files) {
|
||||
return send(tos, subject, content, false, files);
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用配置文件中设置的账户发送HTML邮件,发送给多人
|
||||
*
|
||||
* @param tos 收件人列表
|
||||
* @param subject 标题
|
||||
* @param content 正文
|
||||
* @param files 附件列表
|
||||
* @return message-id
|
||||
* @since 3.2.0
|
||||
*/
|
||||
public static String sendHtml(Collection<String> tos, String subject, String content, File... files) {
|
||||
return send(tos, subject, content, true, files);
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用配置文件中设置的账户发送邮件,发送给多人
|
||||
*
|
||||
* @param tos 收件人列表
|
||||
* @param subject 标题
|
||||
* @param content 正文
|
||||
* @param isHtml 是否为HTML
|
||||
* @param files 附件列表
|
||||
* @return message-id
|
||||
*/
|
||||
public static String send(Collection<String> tos, String subject, String content, boolean isHtml, File... files) {
|
||||
return send(tos, null, null, subject, content, isHtml, files);
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用配置文件中设置的账户发送邮件,发送给多人
|
||||
*
|
||||
* @param tos 收件人列表
|
||||
* @param ccs 抄送人列表,可以为null或空
|
||||
* @param bccs 密送人列表,可以为null或空
|
||||
* @param subject 标题
|
||||
* @param content 正文
|
||||
* @param isHtml 是否为HTML
|
||||
* @param files 附件列表
|
||||
* @return message-id
|
||||
* @since 4.0.3
|
||||
*/
|
||||
public static String send(Collection<String> tos, Collection<String> ccs, Collection<String> bccs, String subject, String content, boolean isHtml, File... files) {
|
||||
return send(getMailAccount(), true, tos, ccs, bccs, subject, content, null, isHtml, files);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------------------------------------- Custom MailAccount
|
||||
|
||||
/**
|
||||
* 发送邮件给多人
|
||||
*
|
||||
* @param mailAccount 邮件认证对象
|
||||
* @param to 收件人,多个收件人逗号或者分号隔开
|
||||
* @param subject 标题
|
||||
* @param content 正文
|
||||
* @param isHtml 是否为HTML格式
|
||||
* @param files 附件列表
|
||||
* @return message-id
|
||||
* @since 3.2.0
|
||||
*/
|
||||
public static String send(MailAccount mailAccount, String to, String subject, String content, boolean isHtml, File... files) {
|
||||
return send(mailAccount, splitAddress(to), subject, content, isHtml, files);
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送邮件给多人
|
||||
*
|
||||
* @param mailAccount 邮件账户信息
|
||||
* @param tos 收件人列表
|
||||
* @param subject 标题
|
||||
* @param content 正文
|
||||
* @param isHtml 是否为HTML格式
|
||||
* @param files 附件列表
|
||||
* @return message-id
|
||||
*/
|
||||
public static String send(MailAccount mailAccount, Collection<String> tos, String subject, String content, boolean isHtml, File... files) {
|
||||
return send(mailAccount, tos, null, null, subject, content, isHtml, files);
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送邮件给多人
|
||||
*
|
||||
* @param mailAccount 邮件账户信息
|
||||
* @param tos 收件人列表
|
||||
* @param ccs 抄送人列表,可以为null或空
|
||||
* @param bccs 密送人列表,可以为null或空
|
||||
* @param subject 标题
|
||||
* @param content 正文
|
||||
* @param isHtml 是否为HTML格式
|
||||
* @param files 附件列表
|
||||
* @return message-id
|
||||
* @since 4.0.3
|
||||
*/
|
||||
public static String send(MailAccount mailAccount, Collection<String> tos, Collection<String> ccs, Collection<String> bccs, String subject, String content, boolean isHtml, File... files) {
|
||||
return send(mailAccount, false, tos, ccs, bccs, subject, content, null, isHtml, files);
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用配置文件中设置的账户发送HTML邮件,发送给单个或多个收件人<br>
|
||||
* 多个收件人可以使用逗号“,”分隔,也可以通过分号“;”分隔
|
||||
*
|
||||
* @param to 收件人
|
||||
* @param subject 标题
|
||||
* @param content 正文
|
||||
* @param imageMap 图片与占位符,占位符格式为cid:$IMAGE_PLACEHOLDER
|
||||
* @param files 附件列表
|
||||
* @return message-id
|
||||
* @since 3.2.0
|
||||
*/
|
||||
public static String sendHtml(String to, String subject, String content, Map<String, InputStream> imageMap, File... files) {
|
||||
return send(to, subject, content, imageMap, true, files);
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用配置文件中设置的账户发送邮件,发送单个或多个收件人<br>
|
||||
* 多个收件人可以使用逗号“,”分隔,也可以通过分号“;”分隔
|
||||
*
|
||||
* @param to 收件人
|
||||
* @param subject 标题
|
||||
* @param content 正文
|
||||
* @param imageMap 图片与占位符,占位符格式为cid:$IMAGE_PLACEHOLDER
|
||||
* @param isHtml 是否为HTML
|
||||
* @param files 附件列表
|
||||
* @return message-id
|
||||
*/
|
||||
public static String send(String to, String subject, String content, Map<String, InputStream> imageMap, boolean isHtml, File... files) {
|
||||
return send(splitAddress(to), subject, content, imageMap, isHtml, files);
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用配置文件中设置的账户发送邮件,发送单个或多个收件人<br>
|
||||
* 多个收件人、抄送人、密送人可以使用逗号“,”分隔,也可以通过分号“;”分隔
|
||||
*
|
||||
* @param to 收件人,可以使用逗号“,”分隔,也可以通过分号“;”分隔
|
||||
* @param cc 抄送人,可以使用逗号“,”分隔,也可以通过分号“;”分隔
|
||||
* @param bcc 密送人,可以使用逗号“,”分隔,也可以通过分号“;”分隔
|
||||
* @param subject 标题
|
||||
* @param content 正文
|
||||
* @param imageMap 图片与占位符,占位符格式为cid:$IMAGE_PLACEHOLDER
|
||||
* @param isHtml 是否为HTML
|
||||
* @param files 附件列表
|
||||
* @return message-id
|
||||
* @since 4.0.3
|
||||
*/
|
||||
public static String send(String to, String cc, String bcc, String subject, String content, Map<String, InputStream> imageMap, boolean isHtml, File... files) {
|
||||
return send(splitAddress(to), splitAddress(cc), splitAddress(bcc), subject, content, imageMap, isHtml, files);
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用配置文件中设置的账户发送HTML邮件,发送给多人
|
||||
*
|
||||
* @param tos 收件人列表
|
||||
* @param subject 标题
|
||||
* @param content 正文
|
||||
* @param imageMap 图片与占位符,占位符格式为cid:$IMAGE_PLACEHOLDER
|
||||
* @param files 附件列表
|
||||
* @return message-id
|
||||
* @since 3.2.0
|
||||
*/
|
||||
public static String sendHtml(Collection<String> tos, String subject, String content, Map<String, InputStream> imageMap, File... files) {
|
||||
return send(tos, subject, content, imageMap, true, files);
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用配置文件中设置的账户发送邮件,发送给多人
|
||||
*
|
||||
* @param tos 收件人列表
|
||||
* @param subject 标题
|
||||
* @param content 正文
|
||||
* @param imageMap 图片与占位符,占位符格式为cid:$IMAGE_PLACEHOLDER
|
||||
* @param isHtml 是否为HTML
|
||||
* @param files 附件列表
|
||||
* @return message-id
|
||||
*/
|
||||
public static String send(Collection<String> tos, String subject, String content, Map<String, InputStream> imageMap, boolean isHtml, File... files) {
|
||||
return send(tos, null, null, subject, content, imageMap, isHtml, files);
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用配置文件中设置的账户发送邮件,发送给多人
|
||||
*
|
||||
* @param tos 收件人列表
|
||||
* @param ccs 抄送人列表,可以为null或空
|
||||
* @param bccs 密送人列表,可以为null或空
|
||||
* @param subject 标题
|
||||
* @param content 正文
|
||||
* @param imageMap 图片与占位符,占位符格式为cid:$IMAGE_PLACEHOLDER
|
||||
* @param isHtml 是否为HTML
|
||||
* @param files 附件列表
|
||||
* @return message-id
|
||||
* @since 4.0.3
|
||||
*/
|
||||
public static String send(Collection<String> tos, Collection<String> ccs, Collection<String> bccs, String subject, String content, Map<String, InputStream> imageMap, boolean isHtml, File... files) {
|
||||
return send(getMailAccount(), true, tos, ccs, bccs, subject, content, imageMap, isHtml, files);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------------------------------------- Custom MailAccount
|
||||
|
||||
/**
|
||||
* 发送邮件给多人
|
||||
*
|
||||
* @param mailAccount 邮件认证对象
|
||||
* @param to 收件人,多个收件人逗号或者分号隔开
|
||||
* @param subject 标题
|
||||
* @param content 正文
|
||||
* @param imageMap 图片与占位符,占位符格式为cid:$IMAGE_PLACEHOLDER
|
||||
* @param isHtml 是否为HTML格式
|
||||
* @param files 附件列表
|
||||
* @return message-id
|
||||
* @since 3.2.0
|
||||
*/
|
||||
public static String send(MailAccount mailAccount, String to, String subject, String content, Map<String, InputStream> imageMap, boolean isHtml, File... files) {
|
||||
return send(mailAccount, splitAddress(to), subject, content, imageMap, isHtml, files);
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送邮件给多人
|
||||
*
|
||||
* @param mailAccount 邮件账户信息
|
||||
* @param tos 收件人列表
|
||||
* @param subject 标题
|
||||
* @param content 正文
|
||||
* @param imageMap 图片与占位符,占位符格式为cid:$IMAGE_PLACEHOLDER
|
||||
* @param isHtml 是否为HTML格式
|
||||
* @param files 附件列表
|
||||
* @return message-id
|
||||
* @since 4.6.3
|
||||
*/
|
||||
public static String send(MailAccount mailAccount, Collection<String> tos, String subject, String content, Map<String, InputStream> imageMap, boolean isHtml, File... files) {
|
||||
return send(mailAccount, tos, null, null, subject, content, imageMap, isHtml, files);
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送邮件给多人
|
||||
*
|
||||
* @param mailAccount 邮件账户信息
|
||||
* @param tos 收件人列表
|
||||
* @param ccs 抄送人列表,可以为null或空
|
||||
* @param bccs 密送人列表,可以为null或空
|
||||
* @param subject 标题
|
||||
* @param content 正文
|
||||
* @param imageMap 图片与占位符,占位符格式为cid:$IMAGE_PLACEHOLDER
|
||||
* @param isHtml 是否为HTML格式
|
||||
* @param files 附件列表
|
||||
* @return message-id
|
||||
* @since 4.6.3
|
||||
*/
|
||||
public static String send(MailAccount mailAccount, Collection<String> tos, Collection<String> ccs, Collection<String> bccs, String subject, String content, Map<String, InputStream> imageMap,
|
||||
boolean isHtml, File... files) {
|
||||
return send(mailAccount, false, tos, ccs, bccs, subject, content, imageMap, isHtml, files);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据配置文件,获取邮件客户端会话
|
||||
*
|
||||
* @param mailAccount 邮件账户配置
|
||||
* @param isSingleton 是否单例(全局共享会话)
|
||||
* @return {@link Session}
|
||||
* @since 5.5.7
|
||||
*/
|
||||
public static Session getSession(MailAccount mailAccount, boolean isSingleton) {
|
||||
Authenticator authenticator = null;
|
||||
if (mailAccount.isAuth()) {
|
||||
authenticator = new JakartaUserPassAuthenticator(mailAccount.getUser(), mailAccount.getPass());
|
||||
}
|
||||
|
||||
return isSingleton ? Session.getDefaultInstance(mailAccount.getSmtpProps(), authenticator) //
|
||||
: Session.getInstance(mailAccount.getSmtpProps(), authenticator);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------------------------------ Private method start
|
||||
|
||||
/**
|
||||
* 发送邮件给多人
|
||||
*
|
||||
* @param mailAccount 邮件账户信息
|
||||
* @param useGlobalSession 是否全局共享Session
|
||||
* @param tos 收件人列表
|
||||
* @param ccs 抄送人列表,可以为null或空
|
||||
* @param bccs 密送人列表,可以为null或空
|
||||
* @param subject 标题
|
||||
* @param content 正文
|
||||
* @param imageMap 图片与占位符,占位符格式为cid:${cid}
|
||||
* @param isHtml 是否为HTML格式
|
||||
* @param files 附件列表
|
||||
* @return message-id
|
||||
* @since 4.6.3
|
||||
*/
|
||||
private static String send(MailAccount mailAccount, boolean useGlobalSession, Collection<String> tos, Collection<String> ccs, Collection<String> bccs, String subject, String content,
|
||||
Map<String, InputStream> imageMap, boolean isHtml, File... files) {
|
||||
final JakartaMail mail = JakartaMail.create(mailAccount).setUseGlobalSession(useGlobalSession);
|
||||
|
||||
// 可选抄送人
|
||||
if (CollUtil.isNotEmpty(ccs)) {
|
||||
mail.setCcs(ccs.toArray(new String[0]));
|
||||
}
|
||||
// 可选密送人
|
||||
if (CollUtil.isNotEmpty(bccs)) {
|
||||
mail.setBccs(bccs.toArray(new String[0]));
|
||||
}
|
||||
|
||||
mail.setTos(tos.toArray(new String[0]));
|
||||
mail.setTitle(subject);
|
||||
mail.setContent(content);
|
||||
mail.setHtml(isHtml);
|
||||
mail.setFiles(files);
|
||||
|
||||
// 图片
|
||||
if (MapUtil.isNotEmpty(imageMap)) {
|
||||
for (Entry<String, InputStream> entry : imageMap.entrySet()) {
|
||||
mail.addImage(entry.getKey(), entry.getValue());
|
||||
// 关闭流
|
||||
IoUtil.close(entry.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
return mail.send();
|
||||
}
|
||||
|
||||
/**
|
||||
* 将多个联系人转为列表,分隔符为逗号或者分号
|
||||
*
|
||||
* @param addresses 多个联系人,如果为空返回null
|
||||
* @return 联系人列表
|
||||
*/
|
||||
private static List<String> splitAddress(String addresses) {
|
||||
if (StrUtil.isBlank(addresses)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
List<String> result;
|
||||
if (StrUtil.contains(addresses, CharUtil.COMMA)) {
|
||||
result = StrUtil.splitTrim(addresses, CharUtil.COMMA);
|
||||
} else if (StrUtil.contains(addresses, ';')) {
|
||||
result = StrUtil.splitTrim(addresses, ';');
|
||||
} else {
|
||||
result = CollUtil.newArrayList(addresses);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
// ------------------------------------------------------------------------------------------------------------------------ Private method end
|
||||
}
|
||||
@@ -2,7 +2,7 @@ package org.dromara.demo.controller;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.dromara.common.core.domain.R;
|
||||
import org.dromara.common.mail.utils.MailUtils;
|
||||
import org.dromara.common.mail.core.MailBuilder;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
@@ -32,7 +32,7 @@ public class MailSendController {
|
||||
*/
|
||||
@GetMapping("/sendSimpleMessage")
|
||||
public R<Void> sendSimpleMessage(String to, String subject, String text) {
|
||||
MailUtils.sendText(to, subject, text);
|
||||
MailBuilder.of().to(to).subject(subject).text(text).send();
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@ public class MailSendController {
|
||||
@GetMapping("/sendMessageWithAttachment")
|
||||
public R<Void> sendMessageWithAttachment(String to, String subject, String text) {
|
||||
// 附件路径 禁止前端传递 有任意读取系统文件风险
|
||||
MailUtils.sendText(to, subject, text, new File("/xxx/xxx"));
|
||||
MailBuilder.of().to(to).subject(subject).text(text).files(new File("/xxx/xxx")).send();
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
@@ -62,7 +62,7 @@ public class MailSendController {
|
||||
// 附件路径 禁止前端传递 有任意读取系统文件风险
|
||||
String[] paths = new String[]{"/xxx/xxx", "/xxx/xxx"};
|
||||
File[] array = Arrays.stream(paths).map(File::new).toArray(File[]::new);
|
||||
MailUtils.sendText(to, subject, text, array);
|
||||
MailBuilder.of().to(to).subject(subject).text(text).files(array).send();
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ import org.dromara.common.core.exception.ServiceException;
|
||||
import org.dromara.common.core.utils.SpringUtils;
|
||||
import org.dromara.common.core.utils.StreamUtils;
|
||||
import org.dromara.common.core.utils.StringUtils;
|
||||
import org.dromara.common.mail.utils.MailUtils;
|
||||
import org.dromara.common.mail.core.MailBuilder;
|
||||
import org.dromara.system.api.MessageService;
|
||||
import org.dromara.system.api.domain.PushPayloadDTO;
|
||||
import org.dromara.system.api.domain.UserDTO;
|
||||
@@ -122,7 +122,7 @@ public class FlwCommonServiceImpl implements IFlwCommonService {
|
||||
message, null, path
|
||||
));
|
||||
}
|
||||
case EMAIL_MESSAGE -> MailUtils.sendText(emails, subject, message);
|
||||
case EMAIL_MESSAGE -> MailBuilder.of().to(emails).subject(subject).text(message).send();
|
||||
case SMS_MESSAGE -> {
|
||||
// LinkedHashMap<String, String> map = new LinkedHashMap<>(1);
|
||||
// // 根据具体短信服务商参数用法传参
|
||||
|
||||
Reference in New Issue
Block a user