Răsfoiți Sursa

fix 修复 邮件工具失效问题

疯狂的狮子Li 2 ani în urmă
părinte
comite
9c22f7a0d0

+ 4 - 0
ruoyi-common/ruoyi-common-mail/pom.xml

@@ -26,6 +26,10 @@
             <groupId>jakarta.mail</groupId>
             <artifactId>jakarta.mail-api</artifactId>
         </dependency>
+        <dependency>
+            <groupId>org.eclipse.angus</groupId>
+            <artifactId>jakarta.mail</artifactId>
+        </dependency>
     </dependencies>
 
 </project>

+ 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;

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

@@ -0,0 +1,47 @@
+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 - 1
ruoyi-common/ruoyi-common-mail/src/main/java/org/dromara/common/mail/utils/InternalMailUtil.java

@@ -1,7 +1,6 @@
 package org.dromara.common.mail.utils;
 
 import cn.hutool.core.util.ArrayUtil;
-import cn.hutool.extra.mail.MailException;
 import jakarta.mail.internet.AddressException;
 import jakarta.mail.internet.InternetAddress;
 import jakarta.mail.internet.MimeUtility;

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

@@ -7,7 +7,6 @@ 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 cn.hutool.extra.mail.*;
 import jakarta.activation.DataHandler;
 import jakarta.activation.DataSource;
 import jakarta.activation.FileDataSource;

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

@@ -0,0 +1,657 @@
+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.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 {
+	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 + "]";
+	}
+}

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

@@ -0,0 +1,36 @@
+package org.dromara.common.mail.utils;
+
+import cn.hutool.core.exceptions.ExceptionUtil;
+import cn.hutool.core.util.StrUtil;
+
+/**
+ * 邮件异常
+ * @author xiaoleilu
+ */
+public class MailException extends RuntimeException{
+	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);
+	}
+}

+ 0 - 1
ruoyi-common/ruoyi-common-mail/src/main/java/org/dromara/common/mail/utils/MailUtils.java

@@ -5,7 +5,6 @@ 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.*;
 import org.dromara.common.core.utils.SpringUtils;
 import org.dromara.common.core.utils.StringUtils;
 import lombok.AccessLevel;