@ -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 + " ] " ;
}
}