init: 导入RuoYi‑Vue‑Plus 6.X完整代码
This commit is contained in:
@@ -0,0 +1,37 @@
|
||||
<?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">
|
||||
<parent>
|
||||
<groupId>org.dromara</groupId>
|
||||
<artifactId>ruoyi-common</artifactId>
|
||||
<version>${revision}</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>ruoyi-common-mail</artifactId>
|
||||
|
||||
<description>
|
||||
ruoyi-common-mail 邮件模块
|
||||
</description>
|
||||
|
||||
<dependencies>
|
||||
<!-- 核心模块 -->
|
||||
<dependency>
|
||||
<groupId>org.dromara</groupId>
|
||||
<artifactId>ruoyi-common-core</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- 邮件接口 -->
|
||||
<dependency>
|
||||
<groupId>jakarta.mail</groupId>
|
||||
<artifactId>jakarta.mail-api</artifactId>
|
||||
</dependency>
|
||||
<!-- 邮件实现 -->
|
||||
<dependency>
|
||||
<groupId>org.eclipse.angus</groupId>
|
||||
<artifactId>jakarta.mail</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
package org.dromara.common.mail.config;
|
||||
|
||||
import cn.hutool.extra.mail.MailAccount;
|
||||
import org.dromara.common.mail.config.properties.MailProperties;
|
||||
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
|
||||
/**
|
||||
* JavaMail 配置
|
||||
*
|
||||
* @author Michelle.Chung
|
||||
*/
|
||||
@AutoConfiguration
|
||||
@EnableConfigurationProperties(MailProperties.class)
|
||||
public class MailConfig {
|
||||
|
||||
/**
|
||||
* 创建邮件账户配置。
|
||||
*
|
||||
* @param mailProperties 邮件配置属性
|
||||
* @return 邮件账户
|
||||
*/
|
||||
@Bean
|
||||
@ConditionalOnProperty(value = "mail.enabled", havingValue = "true")
|
||||
public MailAccount mailAccount(MailProperties mailProperties) {
|
||||
return mailProperties.toMailAccount();
|
||||
}
|
||||
|
||||
}
|
||||
+97
@@ -0,0 +1,97 @@
|
||||
package org.dromara.common.mail.config.properties;
|
||||
|
||||
import cn.hutool.extra.mail.MailAccount;
|
||||
import lombok.Data;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
|
||||
/**
|
||||
* JavaMail 配置属性
|
||||
*
|
||||
* @author Michelle.Chung
|
||||
*/
|
||||
@Data
|
||||
@ConfigurationProperties(prefix = "mail")
|
||||
public class MailProperties {
|
||||
|
||||
/**
|
||||
* 过滤开关
|
||||
*/
|
||||
private Boolean enabled;
|
||||
|
||||
/**
|
||||
* SMTP服务器域名
|
||||
*/
|
||||
private String host;
|
||||
|
||||
/**
|
||||
* SMTP服务端口
|
||||
*/
|
||||
private Integer port;
|
||||
|
||||
/**
|
||||
* 是否需要用户名密码验证
|
||||
*/
|
||||
private Boolean auth;
|
||||
|
||||
/**
|
||||
* 用户名
|
||||
*/
|
||||
private String user;
|
||||
|
||||
/**
|
||||
* 密码
|
||||
*/
|
||||
private String pass;
|
||||
|
||||
/**
|
||||
* 发送方,遵循RFC-822标准<br>
|
||||
* 发件人可以是以下形式:
|
||||
*
|
||||
* <pre>
|
||||
* 1. user@xxx.xx
|
||||
* 2. name <user@xxx.xx>
|
||||
* </pre>
|
||||
*/
|
||||
private String from;
|
||||
|
||||
/**
|
||||
* 使用 STARTTLS安全连接,STARTTLS是对纯文本通信协议的扩展。它将纯文本连接升级为加密连接(TLS或SSL), 而不是使用一个单独的加密通信端口。
|
||||
*/
|
||||
private Boolean starttlsEnable;
|
||||
|
||||
/**
|
||||
* 使用 SSL安全连接
|
||||
*/
|
||||
private Boolean sslEnable;
|
||||
|
||||
/**
|
||||
* SMTP超时时长,单位毫秒,缺省值不超时
|
||||
*/
|
||||
private Long timeout;
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
}
|
||||
+409
@@ -0,0 +1,409 @@
|
||||
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;
|
||||
|
||||
/**
|
||||
* 是否 HTML 内容。
|
||||
*/
|
||||
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("邮件正文不能为空");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析实际使用的邮件账户。
|
||||
*
|
||||
* @return 邮件账户
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 拆分逗号或分号分隔的邮箱地址。
|
||||
*
|
||||
* @param addresses 邮箱地址字符串
|
||||
* @return 邮箱地址列表
|
||||
*/
|
||||
private List<String> splitAddress(String addresses) {
|
||||
if (StrUtil.isBlank(addresses)) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
return normalizeAddresses(StrUtil.splitTrim(addresses.replace(';', ','), ','));
|
||||
}
|
||||
|
||||
/**
|
||||
* 过滤并标准化邮箱地址集合。
|
||||
*
|
||||
* @param addresses 邮箱地址集合
|
||||
* @return 标准化后的邮箱地址列表
|
||||
*/
|
||||
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
@@ -0,0 +1 @@
|
||||
org.dromara.common.mail.config.MailConfig
|
||||
Reference in New Issue
Block a user