init: 导入RuoYi‑Vue‑Plus 6.X完整代码

This commit is contained in:
admin
2026-08-09 17:51:11 +08:00
commit 51cac459b3
914 changed files with 103833 additions and 0 deletions
+37
View File
@@ -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>
@@ -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();
}
}
@@ -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 &lt;user@xxx.xx&gt;
* </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;
}
}
@@ -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;
}
}