Przeglądaj źródła

update hutool 5.8.29 => 5.8.31 解决hutool不兼容jakarta问题

疯狂的狮子Li 10 miesięcy temu
rodzic
commit
ca06a2311d

+ 1 - 1
pom.xml

@@ -26,7 +26,7 @@
         <satoken.version>1.38.0</satoken.version>
         <mybatis-plus.version>3.5.7</mybatis-plus.version>
         <p6spy.version>3.9.1</p6spy.version>
-        <hutool.version>5.8.29</hutool.version>
+        <hutool.version>5.8.31</hutool.version>
         <okhttp.version>4.10.0</okhttp.version>
         <spring-boot-admin.version>3.2.3</spring-boot-admin.version>
         <redisson.version>3.34.1</redisson.version>

+ 1 - 1
ruoyi-common/ruoyi-common-mail/src/main/java/org/dromara/common/mail/config/MailConfig.java

@@ -1,7 +1,7 @@
 package org.dromara.common.mail.config;
 
+import cn.hutool.extra.mail.MailAccount;
 import org.dromara.common.mail.config.properties.MailProperties;
-import org.dromara.common.mail.utils.MailAccount;
 import org.springframework.boot.autoconfigure.AutoConfiguration;
 import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
 import org.springframework.boot.context.properties.EnableConfigurationProperties;

+ 0 - 46
ruoyi-common/ruoyi-common-mail/src/main/java/org/dromara/common/mail/utils/GlobalMailAccount.java

@@ -1,46 +0,0 @@
-package org.dromara.common.mail.utils;
-
-import cn.hutool.core.io.IORuntimeException;
-
-/**
- * 全局邮件帐户,依赖于邮件配置文件{@link MailAccount#MAIL_SETTING_PATHS}
- *
- * @author looly
- */
-public enum GlobalMailAccount {
-    INSTANCE;
-
-    private final MailAccount mailAccount;
-
-    /**
-     * 构造
-     */
-    GlobalMailAccount() {
-        mailAccount = createDefaultAccount();
-    }
-
-    /**
-     * 获得邮件帐户
-     *
-     * @return 邮件帐户
-     */
-    public MailAccount getAccount() {
-        return this.mailAccount;
-    }
-
-    /**
-     * 创建默认帐户
-     *
-     * @return MailAccount
-     */
-    private MailAccount createDefaultAccount() {
-        for (String mailSettingPath : MailAccount.MAIL_SETTING_PATHS) {
-            try {
-                return new MailAccount(mailSettingPath);
-            } catch (IORuntimeException ignore) {
-                //ignore
-            }
-        }
-        return null;
-    }
-}

+ 0 - 108
ruoyi-common/ruoyi-common-mail/src/main/java/org/dromara/common/mail/utils/InternalMailUtil.java

@@ -1,108 +0,0 @@
-package org.dromara.common.mail.utils;
-
-import cn.hutool.core.util.ArrayUtil;
-import jakarta.mail.internet.AddressException;
-import jakarta.mail.internet.InternetAddress;
-import jakarta.mail.internet.MimeUtility;
-
-import java.io.UnsupportedEncodingException;
-import java.nio.charset.Charset;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-
-/**
- * 邮件内部工具类
- *
- * @author looly
- * @since 3.2.3
- */
-public class InternalMailUtil {
-
-    /**
-     * 将多个字符串邮件地址转为{@link InternetAddress}列表<br>
-     * 单个字符串地址可以是多个地址合并的字符串
-     *
-     * @param addrStrs 地址数组
-     * @param charset  编码(主要用于中文用户名的编码)
-     * @return 地址数组
-     * @since 4.0.3
-     */
-    public static InternetAddress[] parseAddressFromStrs(String[] addrStrs, Charset charset) {
-        final List<InternetAddress> resultList = new ArrayList<>(addrStrs.length);
-        InternetAddress[] addrs;
-        for (String addrStr : addrStrs) {
-            addrs = parseAddress(addrStr, charset);
-            if (ArrayUtil.isNotEmpty(addrs)) {
-                Collections.addAll(resultList, addrs);
-            }
-        }
-        return resultList.toArray(new InternetAddress[0]);
-    }
-
-    /**
-     * 解析第一个地址
-     *
-     * @param address 地址字符串
-     * @param charset 编码,{@code null}表示使用系统属性定义的编码或系统编码
-     * @return 地址列表
-     */
-    public static InternetAddress parseFirstAddress(String address, Charset charset) {
-        final InternetAddress[] internetAddresses = parseAddress(address, charset);
-        if (ArrayUtil.isEmpty(internetAddresses)) {
-            try {
-                return new InternetAddress(address);
-            } catch (AddressException e) {
-                throw new MailException(e);
-            }
-        }
-        return internetAddresses[0];
-    }
-
-    /**
-     * 将一个地址字符串解析为多个地址<br>
-     * 地址间使用" "、","、";"分隔
-     *
-     * @param address 地址字符串
-     * @param charset 编码,{@code null}表示使用系统属性定义的编码或系统编码
-     * @return 地址列表
-     */
-    public static InternetAddress[] parseAddress(String address, Charset charset) {
-        InternetAddress[] addresses;
-        try {
-            addresses = InternetAddress.parse(address);
-        } catch (AddressException e) {
-            throw new MailException(e);
-        }
-        //编码用户名
-        if (ArrayUtil.isNotEmpty(addresses)) {
-            final String charsetStr = null == charset ? null : charset.name();
-            for (InternetAddress internetAddress : addresses) {
-                try {
-                    internetAddress.setPersonal(internetAddress.getPersonal(), charsetStr);
-                } catch (UnsupportedEncodingException e) {
-                    throw new MailException(e);
-                }
-            }
-        }
-
-        return addresses;
-    }
-
-    /**
-     * 编码中文字符<br>
-     * 编码失败返回原字符串
-     *
-     * @param text    被编码的文本
-     * @param charset 编码
-     * @return 编码后的结果
-     */
-    public static String encodeText(String text, Charset charset) {
-        try {
-            return MimeUtility.encodeText(text, charset.name(), null);
-        } catch (UnsupportedEncodingException e) {
-            // ignore
-        }
-        return text;
-    }
-}

+ 0 - 483
ruoyi-common/ruoyi-common-mail/src/main/java/org/dromara/common/mail/utils/Mail.java

@@ -1,483 +0,0 @@
-package org.dromara.common.mail.utils;
-
-import cn.hutool.core.builder.Builder;
-import cn.hutool.core.io.FileUtil;
-import cn.hutool.core.io.IORuntimeException;
-import cn.hutool.core.io.IoUtil;
-import cn.hutool.core.util.ArrayUtil;
-import cn.hutool.core.util.ObjectUtil;
-import cn.hutool.core.util.StrUtil;
-import jakarta.activation.DataHandler;
-import jakarta.activation.DataSource;
-import jakarta.activation.FileDataSource;
-import jakarta.activation.FileTypeMap;
-import jakarta.mail.*;
-import jakarta.mail.internet.MimeBodyPart;
-import jakarta.mail.internet.MimeMessage;
-import jakarta.mail.internet.MimeMultipart;
-import jakarta.mail.internet.MimeUtility;
-import jakarta.mail.util.ByteArrayDataSource;
-
-import java.io.*;
-import java.nio.charset.Charset;
-import java.util.Date;
-
-/**
- * 邮件发送客户端
- *
- * @author looly
- * @since 3.2.0
- */
-public class Mail implements Builder<MimeMessage> {
-    @Serial
-    private static final long serialVersionUID = 1L;
-
-    /**
-     * 邮箱帐户信息以及一些客户端配置信息
-     */
-    private final MailAccount mailAccount;
-    /**
-     * 收件人列表
-     */
-    private String[] tos;
-    /**
-     * 抄送人列表(carbon copy)
-     */
-    private String[] ccs;
-    /**
-     * 密送人列表(blind carbon copy)
-     */
-    private String[] bccs;
-    /**
-     * 回复地址(reply-to)
-     */
-    private String[] reply;
-    /**
-     * 标题
-     */
-    private String title;
-    /**
-     * 内容
-     */
-    private String content;
-    /**
-     * 是否为HTML
-     */
-    private boolean isHtml;
-    /**
-     * 正文、附件和图片的混合部分
-     */
-    private final Multipart multipart = new MimeMultipart();
-    /**
-     * 是否使用全局会话,默认为false
-     */
-    private boolean useGlobalSession = false;
-
-    /**
-     * debug输出位置,可以自定义debug日志
-     */
-    private PrintStream debugOutput;
-
-    /**
-     * 创建邮件客户端
-     *
-     * @param mailAccount 邮件帐号
-     * @return Mail
-     */
-    public static Mail create(MailAccount mailAccount) {
-        return new Mail(mailAccount);
-    }
-
-    /**
-     * 创建邮件客户端,使用全局邮件帐户
-     *
-     * @return Mail
-     */
-    public static Mail create() {
-        return new Mail();
-    }
-
-    // --------------------------------------------------------------- Constructor start
-
-    /**
-     * 构造,使用全局邮件帐户
-     */
-    public Mail() {
-        this(GlobalMailAccount.INSTANCE.getAccount());
-    }
-
-    /**
-     * 构造
-     *
-     * @param mailAccount 邮件帐户,如果为null使用默认配置文件的全局邮件配置
-     */
-    public Mail(MailAccount mailAccount) {
-        mailAccount = (null != mailAccount) ? mailAccount : GlobalMailAccount.INSTANCE.getAccount();
-        this.mailAccount = mailAccount.defaultIfEmpty();
-    }
-    // --------------------------------------------------------------- Constructor end
-
-    // --------------------------------------------------------------- Getters and Setters start
-
-    /**
-     * 设置收件人
-     *
-     * @param tos 收件人列表
-     * @return this
-     * @see #setTos(String...)
-     */
-    public Mail to(String... tos) {
-        return setTos(tos);
-    }
-
-    /**
-     * 设置多个收件人
-     *
-     * @param tos 收件人列表
-     * @return this
-     */
-    public Mail setTos(String... tos) {
-        this.tos = tos;
-        return this;
-    }
-
-    /**
-     * 设置多个抄送人(carbon copy)
-     *
-     * @param ccs 抄送人列表
-     * @return this
-     * @since 4.0.3
-     */
-    public Mail setCcs(String... ccs) {
-        this.ccs = ccs;
-        return this;
-    }
-
-    /**
-     * 设置多个密送人(blind carbon copy)
-     *
-     * @param bccs 密送人列表
-     * @return this
-     * @since 4.0.3
-     */
-    public Mail setBccs(String... bccs) {
-        this.bccs = bccs;
-        return this;
-    }
-
-    /**
-     * 设置多个回复地址(reply-to)
-     *
-     * @param reply 回复地址(reply-to)列表
-     * @return this
-     * @since 4.6.0
-     */
-    public Mail setReply(String... reply) {
-        this.reply = reply;
-        return this;
-    }
-
-    /**
-     * 设置标题
-     *
-     * @param title 标题
-     * @return this
-     */
-    public Mail setTitle(String title) {
-        this.title = title;
-        return this;
-    }
-
-    /**
-     * 设置正文<br>
-     * 正文可以是普通文本也可以是HTML(默认普通文本),可以通过调用{@link #setHtml(boolean)} 设置是否为HTML
-     *
-     * @param content 正文
-     * @return this
-     */
-    public Mail setContent(String content) {
-        this.content = content;
-        return this;
-    }
-
-    /**
-     * 设置是否是HTML
-     *
-     * @param isHtml 是否为HTML
-     * @return this
-     */
-    public Mail setHtml(boolean isHtml) {
-        this.isHtml = isHtml;
-        return this;
-    }
-
-    /**
-     * 设置正文
-     *
-     * @param content 正文内容
-     * @param isHtml  是否为HTML
-     * @return this
-     */
-    public Mail setContent(String content, boolean isHtml) {
-        setContent(content);
-        return setHtml(isHtml);
-    }
-
-    /**
-     * 设置文件类型附件,文件可以是图片文件,此时自动设置cid(正文中引用图片),默认cid为文件名
-     *
-     * @param files 附件文件列表
-     * @return this
-     */
-    public Mail setFiles(File... files) {
-        if (ArrayUtil.isEmpty(files)) {
-            return this;
-        }
-
-        final DataSource[] attachments = new DataSource[files.length];
-        for (int i = 0; i < files.length; i++) {
-            attachments[i] = new FileDataSource(files[i]);
-        }
-        return setAttachments(attachments);
-    }
-
-    /**
-     * 增加附件或图片,附件使用{@link DataSource} 形式表示,可以使用{@link FileDataSource}包装文件表示文件附件
-     *
-     * @param attachments 附件列表
-     * @return this
-     * @since 4.0.9
-     */
-    public Mail setAttachments(DataSource... attachments) {
-        if (ArrayUtil.isNotEmpty(attachments)) {
-            final Charset charset = this.mailAccount.getCharset();
-            MimeBodyPart bodyPart;
-            String nameEncoded;
-            try {
-                for (DataSource attachment : attachments) {
-                    bodyPart = new MimeBodyPart();
-                    bodyPart.setDataHandler(new DataHandler(attachment));
-                    nameEncoded = attachment.getName();
-                    if (this.mailAccount.isEncodefilename()) {
-                        nameEncoded = InternalMailUtil.encodeText(nameEncoded, charset);
-                    }
-                    // 普通附件文件名
-                    bodyPart.setFileName(nameEncoded);
-                    if (StrUtil.startWith(attachment.getContentType(), "image/")) {
-                        // 图片附件,用于正文中引用图片
-                        bodyPart.setContentID(nameEncoded);
-                    }
-                    this.multipart.addBodyPart(bodyPart);
-                }
-            } catch (MessagingException e) {
-                throw new MailException(e);
-            }
-        }
-        return this;
-    }
-
-    /**
-     * 增加图片,图片的键对应到邮件模板中的占位字符串,图片类型默认为"image/jpeg"
-     *
-     * @param cid         图片与占位符,占位符格式为cid:${cid}
-     * @param imageStream 图片文件
-     * @return this
-     * @since 4.6.3
-     */
-    public Mail addImage(String cid, InputStream imageStream) {
-        return addImage(cid, imageStream, null);
-    }
-
-    /**
-     * 增加图片,图片的键对应到邮件模板中的占位字符串
-     *
-     * @param cid         图片与占位符,占位符格式为cid:${cid}
-     * @param imageStream 图片流,不关闭
-     * @param contentType 图片类型,null赋值默认的"image/jpeg"
-     * @return this
-     * @since 4.6.3
-     */
-    public Mail addImage(String cid, InputStream imageStream, String contentType) {
-        ByteArrayDataSource imgSource;
-        try {
-            imgSource = new ByteArrayDataSource(imageStream, ObjectUtil.defaultIfNull(contentType, "image/jpeg"));
-        } catch (IOException e) {
-            throw new IORuntimeException(e);
-        }
-        imgSource.setName(cid);
-        return setAttachments(imgSource);
-    }
-
-    /**
-     * 增加图片,图片的键对应到邮件模板中的占位字符串
-     *
-     * @param cid       图片与占位符,占位符格式为cid:${cid}
-     * @param imageFile 图片文件
-     * @return this
-     * @since 4.6.3
-     */
-    public Mail addImage(String cid, File imageFile) {
-        InputStream in = null;
-        try {
-            in = FileUtil.getInputStream(imageFile);
-            return addImage(cid, in, FileTypeMap.getDefaultFileTypeMap().getContentType(imageFile));
-        } finally {
-            IoUtil.close(in);
-        }
-    }
-
-    /**
-     * 设置字符集编码
-     *
-     * @param charset 字符集编码
-     * @return this
-     * @see MailAccount#setCharset(Charset)
-     */
-    public Mail setCharset(Charset charset) {
-        this.mailAccount.setCharset(charset);
-        return this;
-    }
-
-    /**
-     * 设置是否使用全局会话,默认为true
-     *
-     * @param isUseGlobalSession 是否使用全局会话,默认为true
-     * @return this
-     * @since 4.0.2
-     */
-    public Mail setUseGlobalSession(boolean isUseGlobalSession) {
-        this.useGlobalSession = isUseGlobalSession;
-        return this;
-    }
-
-    /**
-     * 设置debug输出位置,可以自定义debug日志
-     *
-     * @param debugOutput debug输出位置
-     * @return this
-     * @since 5.5.6
-     */
-    public Mail setDebugOutput(PrintStream debugOutput) {
-        this.debugOutput = debugOutput;
-        return this;
-    }
-    // --------------------------------------------------------------- Getters and Setters end
-
-    @Override
-    public MimeMessage build() {
-        try {
-            return buildMsg();
-        } catch (MessagingException e) {
-            throw new MailException(e);
-        }
-    }
-
-    /**
-     * 发送
-     *
-     * @return message-id
-     * @throws MailException 邮件发送异常
-     */
-    public String send() throws MailException {
-        try {
-            return doSend();
-        } catch (MessagingException e) {
-            if (e instanceof SendFailedException) {
-                // 当地址无效时,显示更加详细的无效地址信息
-                final Address[] invalidAddresses = ((SendFailedException) e).getInvalidAddresses();
-                final String msg = StrUtil.format("Invalid Addresses: {}", ArrayUtil.toString(invalidAddresses));
-                throw new MailException(msg, e);
-            }
-            throw new MailException(e);
-        }
-    }
-
-    // --------------------------------------------------------------- Private method start
-
-    /**
-     * 执行发送
-     *
-     * @return message-id
-     * @throws MessagingException 发送异常
-     */
-    private String doSend() throws MessagingException {
-        final MimeMessage mimeMessage = buildMsg();
-        Transport.send(mimeMessage);
-        return mimeMessage.getMessageID();
-    }
-
-    /**
-     * 构建消息
-     *
-     * @return {@link MimeMessage}消息
-     * @throws MessagingException 消息异常
-     */
-    private MimeMessage buildMsg() throws MessagingException {
-        final Charset charset = this.mailAccount.getCharset();
-        final MimeMessage msg = new MimeMessage(getSession());
-        // 发件人
-        final String from = this.mailAccount.getFrom();
-        if (StrUtil.isEmpty(from)) {
-            // 用户未提供发送方,则从Session中自动获取
-            msg.setFrom();
-        } else {
-            msg.setFrom(InternalMailUtil.parseFirstAddress(from, charset));
-        }
-        // 标题
-        msg.setSubject(this.title, (null == charset) ? null : charset.name());
-        // 发送时间
-        msg.setSentDate(new Date());
-        // 内容和附件
-        msg.setContent(buildContent(charset));
-        // 收件人
-        msg.setRecipients(MimeMessage.RecipientType.TO, InternalMailUtil.parseAddressFromStrs(this.tos, charset));
-        // 抄送人
-        if (ArrayUtil.isNotEmpty(this.ccs)) {
-            msg.setRecipients(MimeMessage.RecipientType.CC, InternalMailUtil.parseAddressFromStrs(this.ccs, charset));
-        }
-        // 密送人
-        if (ArrayUtil.isNotEmpty(this.bccs)) {
-            msg.setRecipients(MimeMessage.RecipientType.BCC, InternalMailUtil.parseAddressFromStrs(this.bccs, charset));
-        }
-        // 回复地址(reply-to)
-        if (ArrayUtil.isNotEmpty(this.reply)) {
-            msg.setReplyTo(InternalMailUtil.parseAddressFromStrs(this.reply, charset));
-        }
-
-        return msg;
-    }
-
-    /**
-     * 构建邮件信息主体
-     *
-     * @param charset 编码,{@code null}则使用{@link MimeUtility#getDefaultJavaCharset()}
-     * @return 邮件信息主体
-     * @throws MessagingException 消息异常
-     */
-    private Multipart buildContent(Charset charset) throws MessagingException {
-        final String charsetStr = null != charset ? charset.name() : MimeUtility.getDefaultJavaCharset();
-        // 正文
-        final MimeBodyPart body = new MimeBodyPart();
-        body.setContent(content, StrUtil.format("text/{}; charset={}", isHtml ? "html" : "plain", charsetStr));
-        this.multipart.addBodyPart(body);
-
-        return this.multipart;
-    }
-
-    /**
-     * 获取默认邮件会话<br>
-     * 如果为全局单例的会话,则全局只允许一个邮件帐号,否则每次发送邮件会新建一个新的会话
-     *
-     * @return 邮件会话 {@link Session}
-     */
-    private Session getSession() {
-        final Session session = MailUtils.getSession(this.mailAccount, this.useGlobalSession);
-
-        if (null != this.debugOutput) {
-            session.setDebugOut(debugOutput);
-        }
-
-        return session;
-    }
-    // --------------------------------------------------------------- Private method end
-}

+ 0 - 659
ruoyi-common/ruoyi-common-mail/src/main/java/org/dromara/common/mail/utils/MailAccount.java

@@ -1,659 +0,0 @@
-package org.dromara.common.mail.utils;
-
-import cn.hutool.core.util.CharsetUtil;
-import cn.hutool.core.util.ObjectUtil;
-import cn.hutool.core.util.StrUtil;
-import cn.hutool.setting.Setting;
-
-import java.io.Serial;
-import java.io.Serializable;
-import java.nio.charset.Charset;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Properties;
-
-/**
- * 邮件账户对象
- *
- * @author Luxiaolei
- */
-public class MailAccount implements Serializable {
-    @Serial
-    private static final long serialVersionUID = -6937313421815719204L;
-
-    private static final String MAIL_PROTOCOL = "mail.transport.protocol";
-    private static final String SMTP_HOST = "mail.smtp.host";
-    private static final String SMTP_PORT = "mail.smtp.port";
-    private static final String SMTP_AUTH = "mail.smtp.auth";
-    private static final String SMTP_TIMEOUT = "mail.smtp.timeout";
-    private static final String SMTP_CONNECTION_TIMEOUT = "mail.smtp.connectiontimeout";
-    private static final String SMTP_WRITE_TIMEOUT = "mail.smtp.writetimeout";
-
-    // SSL
-    private static final String STARTTLS_ENABLE = "mail.smtp.starttls.enable";
-    private static final String SSL_ENABLE = "mail.smtp.ssl.enable";
-    private static final String SSL_PROTOCOLS = "mail.smtp.ssl.protocols";
-    private static final String SOCKET_FACTORY = "mail.smtp.socketFactory.class";
-    private static final String SOCKET_FACTORY_FALLBACK = "mail.smtp.socketFactory.fallback";
-    private static final String SOCKET_FACTORY_PORT = "smtp.socketFactory.port";
-
-    // System Properties
-    private static final String SPLIT_LONG_PARAMS = "mail.mime.splitlongparameters";
-    //private static final String ENCODE_FILE_NAME = "mail.mime.encodefilename";
-    //private static final String CHARSET = "mail.mime.charset";
-
-    // 其他
-    private static final String MAIL_DEBUG = "mail.debug";
-
-    public static final String[] MAIL_SETTING_PATHS = new String[]{"config/mail.setting", "config/mailAccount.setting", "mail.setting"};
-
-    /**
-     * SMTP服务器域名
-     */
-    private String host;
-    /**
-     * SMTP服务端口
-     */
-    private Integer port;
-    /**
-     * 是否需要用户名密码验证
-     */
-    private Boolean auth;
-    /**
-     * 用户名
-     */
-    private String user;
-    /**
-     * 密码
-     */
-    private String pass;
-    /**
-     * 发送方,遵循RFC-822标准
-     */
-    private String from;
-
-    /**
-     * 是否打开调试模式,调试模式会显示与邮件服务器通信过程,默认不开启
-     */
-    private boolean debug;
-    /**
-     * 编码用于编码邮件正文和发送人、收件人等中文
-     */
-    private Charset charset = CharsetUtil.CHARSET_UTF_8;
-    /**
-     * 对于超长参数是否切分为多份,默认为false(国内邮箱附件不支持切分的附件名)
-     */
-    private boolean splitlongparameters = false;
-    /**
-     * 对于文件名是否使用{@link #charset}编码,默认为 {@code true}
-     */
-    private boolean encodefilename = true;
-
-    /**
-     * 使用 STARTTLS安全连接,STARTTLS是对纯文本通信协议的扩展。它将纯文本连接升级为加密连接(TLS或SSL), 而不是使用一个单独的加密通信端口。
-     */
-    private boolean starttlsEnable = false;
-    /**
-     * 使用 SSL安全连接
-     */
-    private Boolean sslEnable;
-
-    /**
-     * SSL协议,多个协议用空格分隔
-     */
-    private String sslProtocols;
-
-    /**
-     * 指定实现javax.net.SocketFactory接口的类的名称,这个类将被用于创建SMTP的套接字
-     */
-    private String socketFactoryClass = "javax.net.ssl.SSLSocketFactory";
-    /**
-     * 如果设置为true,未能创建一个套接字使用指定的套接字工厂类将导致使用java.net.Socket创建的套接字类, 默认值为true
-     */
-    private boolean socketFactoryFallback;
-    /**
-     * 指定的端口连接到在使用指定的套接字工厂。如果没有设置,将使用默认端口
-     */
-    private int socketFactoryPort = 465;
-
-    /**
-     * SMTP超时时长,单位毫秒,缺省值不超时
-     */
-    private long timeout;
-    /**
-     * Socket连接超时值,单位毫秒,缺省值不超时
-     */
-    private long connectionTimeout;
-    /**
-     * Socket写出超时值,单位毫秒,缺省值不超时
-     */
-    private long writeTimeout;
-
-    /**
-     * 自定义的其他属性,此自定义属性会覆盖默认属性
-     */
-    private final Map<String, Object> customProperty = new HashMap<>();
-
-    // -------------------------------------------------------------- Constructor start
-
-    /**
-     * 构造,所有参数需自行定义或保持默认值
-     */
-    public MailAccount() {
-    }
-
-    /**
-     * 构造
-     *
-     * @param settingPath 配置文件路径
-     */
-    public MailAccount(String settingPath) {
-        this(new Setting(settingPath));
-    }
-
-    /**
-     * 构造
-     *
-     * @param setting 配置文件
-     */
-    public MailAccount(Setting setting) {
-        setting.toBean(this);
-    }
-
-    // -------------------------------------------------------------- Constructor end
-
-    /**
-     * 获得SMTP服务器域名
-     *
-     * @return SMTP服务器域名
-     */
-    public String getHost() {
-        return host;
-    }
-
-    /**
-     * 设置SMTP服务器域名
-     *
-     * @param host SMTP服务器域名
-     * @return this
-     */
-    public MailAccount setHost(String host) {
-        this.host = host;
-        return this;
-    }
-
-    /**
-     * 获得SMTP服务端口
-     *
-     * @return SMTP服务端口
-     */
-    public Integer getPort() {
-        return port;
-    }
-
-    /**
-     * 设置SMTP服务端口
-     *
-     * @param port SMTP服务端口
-     * @return this
-     */
-    public MailAccount setPort(Integer port) {
-        this.port = port;
-        return this;
-    }
-
-    /**
-     * 是否需要用户名密码验证
-     *
-     * @return 是否需要用户名密码验证
-     */
-    public Boolean isAuth() {
-        return auth;
-    }
-
-    /**
-     * 设置是否需要用户名密码验证
-     *
-     * @param isAuth 是否需要用户名密码验证
-     * @return this
-     */
-    public MailAccount setAuth(boolean isAuth) {
-        this.auth = isAuth;
-        return this;
-    }
-
-    /**
-     * 获取用户名
-     *
-     * @return 用户名
-     */
-    public String getUser() {
-        return user;
-    }
-
-    /**
-     * 设置用户名
-     *
-     * @param user 用户名
-     * @return this
-     */
-    public MailAccount setUser(String user) {
-        this.user = user;
-        return this;
-    }
-
-    /**
-     * 获取密码
-     *
-     * @return 密码
-     */
-    public String getPass() {
-        return pass;
-    }
-
-    /**
-     * 设置密码
-     *
-     * @param pass 密码
-     * @return this
-     */
-    public MailAccount setPass(String pass) {
-        this.pass = pass;
-        return this;
-    }
-
-    /**
-     * 获取发送方,遵循RFC-822标准
-     *
-     * @return 发送方,遵循RFC-822标准
-     */
-    public String getFrom() {
-        return from;
-    }
-
-    /**
-     * 设置发送方,遵循RFC-822标准<br>
-     * 发件人可以是以下形式:
-     *
-     * <pre>
-     * 1. user@xxx.xx
-     * 2.  name &lt;user@xxx.xx&gt;
-     * </pre>
-     *
-     * @param from 发送方,遵循RFC-822标准
-     * @return this
-     */
-    public MailAccount setFrom(String from) {
-        this.from = from;
-        return this;
-    }
-
-    /**
-     * 是否打开调试模式,调试模式会显示与邮件服务器通信过程,默认不开启
-     *
-     * @return 是否打开调试模式,调试模式会显示与邮件服务器通信过程,默认不开启
-     * @since 4.0.2
-     */
-    public boolean isDebug() {
-        return debug;
-    }
-
-    /**
-     * 设置是否打开调试模式,调试模式会显示与邮件服务器通信过程,默认不开启
-     *
-     * @param debug 是否打开调试模式,调试模式会显示与邮件服务器通信过程,默认不开启
-     * @return this
-     * @since 4.0.2
-     */
-    public MailAccount setDebug(boolean debug) {
-        this.debug = debug;
-        return this;
-    }
-
-    /**
-     * 获取字符集编码
-     *
-     * @return 编码,可能为{@code null}
-     */
-    public Charset getCharset() {
-        return charset;
-    }
-
-    /**
-     * 设置字符集编码,此选项不会修改全局配置,若修改全局配置,请设置此项为{@code null}并设置:
-     * <pre>
-     * 	System.setProperty("mail.mime.charset", charset);
-     * </pre>
-     *
-     * @param charset 字符集编码,{@code null} 则表示使用全局设置的默认编码,全局编码为mail.mime.charset系统属性
-     * @return this
-     */
-    public MailAccount setCharset(Charset charset) {
-        this.charset = charset;
-        return this;
-    }
-
-    /**
-     * 对于超长参数是否切分为多份,默认为false(国内邮箱附件不支持切分的附件名)
-     *
-     * @return 对于超长参数是否切分为多份
-     */
-    public boolean isSplitlongparameters() {
-        return splitlongparameters;
-    }
-
-    /**
-     * 设置对于超长参数是否切分为多份,默认为false(国内邮箱附件不支持切分的附件名)<br>
-     * 注意此项为全局设置,此项会调用
-     * <pre>
-     * System.setProperty("mail.mime.splitlongparameters", true)
-     * </pre>
-     *
-     * @param splitlongparameters 对于超长参数是否切分为多份
-     */
-    public void setSplitlongparameters(boolean splitlongparameters) {
-        this.splitlongparameters = splitlongparameters;
-    }
-
-    /**
-     * 对于文件名是否使用{@link #charset}编码,默认为 {@code true}
-     *
-     * @return 对于文件名是否使用{@link #charset}编码,默认为 {@code true}
-     * @since 5.7.16
-     */
-    public boolean isEncodefilename() {
-
-        return encodefilename;
-    }
-
-    /**
-     * 设置对于文件名是否使用{@link #charset}编码,此选项不会修改全局配置<br>
-     * 如果此选项设置为{@code false},则是否编码取决于两个系统属性:
-     * <ul>
-     *     <li>mail.mime.encodefilename  是否编码附件文件名</li>
-     *     <li>mail.mime.charset         编码文件名的编码</li>
-     * </ul>
-     *
-     * @param encodefilename 对于文件名是否使用{@link #charset}编码
-     * @since 5.7.16
-     */
-    public void setEncodefilename(boolean encodefilename) {
-        this.encodefilename = encodefilename;
-    }
-
-    /**
-     * 是否使用 STARTTLS安全连接,STARTTLS是对纯文本通信协议的扩展。它将纯文本连接升级为加密连接(TLS或SSL), 而不是使用一个单独的加密通信端口。
-     *
-     * @return 是否使用 STARTTLS安全连接
-     */
-    public boolean isStarttlsEnable() {
-        return this.starttlsEnable;
-    }
-
-    /**
-     * 设置是否使用STARTTLS安全连接,STARTTLS是对纯文本通信协议的扩展。它将纯文本连接升级为加密连接(TLS或SSL), 而不是使用一个单独的加密通信端口。
-     *
-     * @param startttlsEnable 是否使用STARTTLS安全连接
-     * @return this
-     */
-    public MailAccount setStarttlsEnable(boolean startttlsEnable) {
-        this.starttlsEnable = startttlsEnable;
-        return this;
-    }
-
-    /**
-     * 是否使用 SSL安全连接
-     *
-     * @return 是否使用 SSL安全连接
-     */
-    public Boolean isSslEnable() {
-        return this.sslEnable;
-    }
-
-    /**
-     * 设置是否使用SSL安全连接
-     *
-     * @param sslEnable 是否使用SSL安全连接
-     * @return this
-     */
-    public MailAccount setSslEnable(Boolean sslEnable) {
-        this.sslEnable = sslEnable;
-        return this;
-    }
-
-    /**
-     * 获取SSL协议,多个协议用空格分隔
-     *
-     * @return SSL协议,多个协议用空格分隔
-     * @since 5.5.7
-     */
-    public String getSslProtocols() {
-        return sslProtocols;
-    }
-
-    /**
-     * 设置SSL协议,多个协议用空格分隔
-     *
-     * @param sslProtocols SSL协议,多个协议用空格分隔
-     * @since 5.5.7
-     */
-    public void setSslProtocols(String sslProtocols) {
-        this.sslProtocols = sslProtocols;
-    }
-
-    /**
-     * 获取指定实现javax.net.SocketFactory接口的类的名称,这个类将被用于创建SMTP的套接字
-     *
-     * @return 指定实现javax.net.SocketFactory接口的类的名称, 这个类将被用于创建SMTP的套接字
-     */
-    public String getSocketFactoryClass() {
-        return socketFactoryClass;
-    }
-
-    /**
-     * 设置指定实现javax.net.SocketFactory接口的类的名称,这个类将被用于创建SMTP的套接字
-     *
-     * @param socketFactoryClass 指定实现javax.net.SocketFactory接口的类的名称,这个类将被用于创建SMTP的套接字
-     * @return this
-     */
-    public MailAccount setSocketFactoryClass(String socketFactoryClass) {
-        this.socketFactoryClass = socketFactoryClass;
-        return this;
-    }
-
-    /**
-     * 如果设置为true,未能创建一个套接字使用指定的套接字工厂类将导致使用java.net.Socket创建的套接字类, 默认值为true
-     *
-     * @return 如果设置为true, 未能创建一个套接字使用指定的套接字工厂类将导致使用java.net.Socket创建的套接字类, 默认值为true
-     */
-    public boolean isSocketFactoryFallback() {
-        return socketFactoryFallback;
-    }
-
-    /**
-     * 如果设置为true,未能创建一个套接字使用指定的套接字工厂类将导致使用java.net.Socket创建的套接字类, 默认值为true
-     *
-     * @param socketFactoryFallback 如果设置为true,未能创建一个套接字使用指定的套接字工厂类将导致使用java.net.Socket创建的套接字类, 默认值为true
-     * @return this
-     */
-    public MailAccount setSocketFactoryFallback(boolean socketFactoryFallback) {
-        this.socketFactoryFallback = socketFactoryFallback;
-        return this;
-    }
-
-    /**
-     * 获取指定的端口连接到在使用指定的套接字工厂。如果没有设置,将使用默认端口
-     *
-     * @return 指定的端口连接到在使用指定的套接字工厂。如果没有设置,将使用默认端口
-     */
-    public int getSocketFactoryPort() {
-        return socketFactoryPort;
-    }
-
-    /**
-     * 指定的端口连接到在使用指定的套接字工厂。如果没有设置,将使用默认端口
-     *
-     * @param socketFactoryPort 指定的端口连接到在使用指定的套接字工厂。如果没有设置,将使用默认端口
-     * @return this
-     */
-    public MailAccount setSocketFactoryPort(int socketFactoryPort) {
-        this.socketFactoryPort = socketFactoryPort;
-        return this;
-    }
-
-    /**
-     * 设置SMTP超时时长,单位毫秒,缺省值不超时
-     *
-     * @param timeout SMTP超时时长,单位毫秒,缺省值不超时
-     * @return this
-     * @since 4.1.17
-     */
-    public MailAccount setTimeout(long timeout) {
-        this.timeout = timeout;
-        return this;
-    }
-
-    /**
-     * 设置Socket连接超时值,单位毫秒,缺省值不超时
-     *
-     * @param connectionTimeout Socket连接超时值,单位毫秒,缺省值不超时
-     * @return this
-     * @since 4.1.17
-     */
-    public MailAccount setConnectionTimeout(long connectionTimeout) {
-        this.connectionTimeout = connectionTimeout;
-        return this;
-    }
-
-    /**
-     * 设置Socket写出超时值,单位毫秒,缺省值不超时
-     *
-     * @param writeTimeout Socket写出超时值,单位毫秒,缺省值不超时
-     * @return this
-     * @since 5.8.3
-     */
-    public MailAccount setWriteTimeout(long writeTimeout) {
-        this.writeTimeout = writeTimeout;
-        return this;
-    }
-
-    /**
-     * 获取自定义属性列表
-     *
-     * @return 自定义参数列表
-     * @since 5.6.4
-     */
-    public Map<String, Object> getCustomProperty() {
-        return customProperty;
-    }
-
-    /**
-     * 设置自定义属性,如mail.smtp.ssl.socketFactory
-     *
-     * @param key   属性名,空白被忽略
-     * @param value 属性值, null被忽略
-     * @return this
-     * @since 5.6.4
-     */
-    public MailAccount setCustomProperty(String key, Object value) {
-        if (StrUtil.isNotBlank(key) && ObjectUtil.isNotNull(value)) {
-            this.customProperty.put(key, value);
-        }
-        return this;
-    }
-
-    /**
-     * 获得SMTP相关信息
-     *
-     * @return {@link Properties}
-     */
-    public Properties getSmtpProps() {
-        //全局系统参数
-        System.setProperty(SPLIT_LONG_PARAMS, String.valueOf(this.splitlongparameters));
-
-        final Properties p = new Properties();
-        p.put(MAIL_PROTOCOL, "smtp");
-        p.put(SMTP_HOST, this.host);
-        p.put(SMTP_PORT, String.valueOf(this.port));
-        p.put(SMTP_AUTH, String.valueOf(this.auth));
-        if (this.timeout > 0) {
-            p.put(SMTP_TIMEOUT, String.valueOf(this.timeout));
-        }
-        if (this.connectionTimeout > 0) {
-            p.put(SMTP_CONNECTION_TIMEOUT, String.valueOf(this.connectionTimeout));
-        }
-        // issue#2355
-        if (this.writeTimeout > 0) {
-            p.put(SMTP_WRITE_TIMEOUT, String.valueOf(this.writeTimeout));
-        }
-
-        p.put(MAIL_DEBUG, String.valueOf(this.debug));
-
-        if (this.starttlsEnable) {
-            //STARTTLS是对纯文本通信协议的扩展。它将纯文本连接升级为加密连接(TLS或SSL), 而不是使用一个单独的加密通信端口。
-            p.put(STARTTLS_ENABLE, "true");
-
-            if (null == this.sslEnable) {
-                //为了兼容旧版本,当用户没有此项配置时,按照starttlsEnable开启状态时对待
-                this.sslEnable = true;
-            }
-        }
-
-        // SSL
-        if (null != this.sslEnable && this.sslEnable) {
-            p.put(SSL_ENABLE, "true");
-            p.put(SOCKET_FACTORY, socketFactoryClass);
-            p.put(SOCKET_FACTORY_FALLBACK, String.valueOf(this.socketFactoryFallback));
-            p.put(SOCKET_FACTORY_PORT, String.valueOf(this.socketFactoryPort));
-            // issue#IZN95@Gitee,在Linux下需自定义SSL协议版本
-            if (StrUtil.isNotBlank(this.sslProtocols)) {
-                p.put(SSL_PROTOCOLS, this.sslProtocols);
-            }
-        }
-
-        // 补充自定义属性,允许自定属性覆盖已经设置的值
-        p.putAll(this.customProperty);
-
-        return p;
-    }
-
-    /**
-     * 如果某些值为null,使用默认值
-     *
-     * @return this
-     */
-    public MailAccount defaultIfEmpty() {
-        // 去掉发件人的姓名部分
-        final String fromAddress = InternalMailUtil.parseFirstAddress(this.from, this.charset).getAddress();
-
-        if (StrUtil.isBlank(this.host)) {
-            // 如果SMTP地址为空,默认使用smtp.<发件人邮箱后缀>
-            this.host = StrUtil.format("smtp.{}", StrUtil.subSuf(fromAddress, fromAddress.indexOf('@') + 1));
-        }
-        if (StrUtil.isBlank(user)) {
-            // 如果用户名为空,默认为发件人(issue#I4FYVY@Gitee)
-            //this.user = StrUtil.subPre(fromAddress, fromAddress.indexOf('@'));
-            this.user = fromAddress;
-        }
-        if (null == this.auth) {
-            // 如果密码非空白,则使用认证模式
-            this.auth = (false == StrUtil.isBlank(this.pass));
-        }
-        if (null == this.port) {
-            // 端口在SSL状态下默认与socketFactoryPort一致,非SSL状态下默认为25
-            this.port = (null != this.sslEnable && this.sslEnable) ? this.socketFactoryPort : 25;
-        }
-        if (null == this.charset) {
-            // 默认UTF-8编码
-            this.charset = CharsetUtil.CHARSET_UTF_8;
-        }
-
-        return this;
-    }
-
-    @Override
-    public String toString() {
-        return "MailAccount [host=" + host + ", port=" + port + ", auth=" + auth + ", user=" + user + ", pass=" + (StrUtil.isEmpty(this.pass) ? "" : "******") + ", from=" + from + ", startttlsEnable="
-            + starttlsEnable + ", socketFactoryClass=" + socketFactoryClass + ", socketFactoryFallback=" + socketFactoryFallback + ", socketFactoryPort=" + socketFactoryPort + "]";
-    }
-}

+ 0 - 40
ruoyi-common/ruoyi-common-mail/src/main/java/org/dromara/common/mail/utils/MailException.java

@@ -1,40 +0,0 @@
-package org.dromara.common.mail.utils;
-
-import cn.hutool.core.exceptions.ExceptionUtil;
-import cn.hutool.core.util.StrUtil;
-
-import java.io.Serial;
-
-/**
- * 邮件异常
- *
- * @author xiaoleilu
- */
-public class MailException extends RuntimeException {
-    @Serial
-    private static final long serialVersionUID = 8247610319171014183L;
-
-    public MailException(Throwable e) {
-        super(ExceptionUtil.getMessage(e), e);
-    }
-
-    public MailException(String message) {
-        super(message);
-    }
-
-    public MailException(String messageTemplate, Object... params) {
-        super(StrUtil.format(messageTemplate, params));
-    }
-
-    public MailException(String message, Throwable throwable) {
-        super(message, throwable);
-    }
-
-    public MailException(String message, Throwable throwable, boolean enableSuppression, boolean writableStackTrace) {
-        super(message, throwable, enableSuppression, writableStackTrace);
-    }
-
-    public MailException(Throwable throwable, String messageTemplate, Object... params) {
-        super(StrUtil.format(messageTemplate, params), throwable);
-    }
-}

+ 7 - 5
ruoyi-common/ruoyi-common-mail/src/main/java/org/dromara/common/mail/utils/MailUtils.java

@@ -5,6 +5,9 @@ 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;
@@ -17,7 +20,7 @@ import java.io.InputStream;
 import java.util.Collection;
 import java.util.List;
 import java.util.Map;
-
+import java.util.Map.Entry;
 
 /**
  * 邮件工具类
@@ -385,7 +388,7 @@ public class MailUtils {
     public static Session getSession(MailAccount mailAccount, boolean isSingleton) {
         Authenticator authenticator = null;
         if (mailAccount.isAuth()) {
-            authenticator = new UserPassAuthenticator(mailAccount.getUser(), mailAccount.getPass());
+            authenticator = new JakartaUserPassAuthenticator(mailAccount.getUser(), mailAccount.getPass());
         }
 
         return isSingleton ? Session.getDefaultInstance(mailAccount.getSmtpProps(), authenticator) //
@@ -412,7 +415,7 @@ public class MailUtils {
      */
     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 Mail mail = Mail.create(mailAccount).setUseGlobalSession(useGlobalSession);
+        final JakartaMail mail = JakartaMail.create(mailAccount).setUseGlobalSession(useGlobalSession);
 
         // 可选抄送人
         if (CollUtil.isNotEmpty(ccs)) {
@@ -431,7 +434,7 @@ public class MailUtils {
 
         // 图片
         if (MapUtil.isNotEmpty(imageMap)) {
-            for (Map.Entry<String, InputStream> entry : imageMap.entrySet()) {
+            for (Entry<String, InputStream> entry : imageMap.entrySet()) {
                 mail.addImage(entry.getKey(), entry.getValue());
                 // 关闭流
                 IoUtil.close(entry.getValue());
@@ -463,5 +466,4 @@ public class MailUtils {
         return result;
     }
     // ------------------------------------------------------------------------------------------------------------------------ Private method end
-
 }

+ 0 - 33
ruoyi-common/ruoyi-common-mail/src/main/java/org/dromara/common/mail/utils/UserPassAuthenticator.java

@@ -1,33 +0,0 @@
-package org.dromara.common.mail.utils;
-
-import jakarta.mail.Authenticator;
-import jakarta.mail.PasswordAuthentication;
-
-/**
- * 用户名密码验证器
- *
- * @author looly
- * @since 3.1.2
- */
-public class UserPassAuthenticator extends Authenticator {
-
-    private final String user;
-    private final String pass;
-
-    /**
-     * 构造
-     *
-     * @param user 用户名
-     * @param pass 密码
-     */
-    public UserPassAuthenticator(String user, String pass) {
-        this.user = user;
-        this.pass = pass;
-    }
-
-    @Override
-    protected PasswordAuthentication getPasswordAuthentication() {
-        return new PasswordAuthentication(this.user, this.pass);
-    }
-
-}