From 1fa812137dd4b99f2eb559dbb98a0f578026edf5 Mon Sep 17 00:00:00 2001 From: Looly Date: Thu, 26 Sep 2019 17:22:57 +0800 Subject: [PATCH] fix mail bug --- CHANGELOG.md | 1 + .../java/cn/hutool/core/date/SystemClock.java | 2 +- .../java/cn/hutool/core/codec/Base64Test.java | 12 +- .../cn/hutool/extra/mail/MailAccount.java | 202 +++++++++++------- .../java/cn/hutool/extra/mail/MailTest.java | 2 +- .../src/test/resources/config/mail.setting | 8 +- 6 files changed, 139 insertions(+), 88 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e241fb397..4e6a49480 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ * 【core】 ArrayUtil.isEmpty可变长参数改为数组(issue#555@Github) ### Bug修复 +* 【extra】 修复Mail中sslEnable无效问题(pr#74@Gitee) ------------------------------------------------------------------------------------------------------------- diff --git a/hutool-core/src/main/java/cn/hutool/core/date/SystemClock.java b/hutool-core/src/main/java/cn/hutool/core/date/SystemClock.java index 66f991afd..12cbbd5dc 100644 --- a/hutool-core/src/main/java/cn/hutool/core/date/SystemClock.java +++ b/hutool-core/src/main/java/cn/hutool/core/date/SystemClock.java @@ -25,7 +25,7 @@ public class SystemClock { /** * 构造 - * @param period + * @param period 时钟更新间隔,单位毫秒 */ private SystemClock(long period) { this.period = period; diff --git a/hutool-core/src/test/java/cn/hutool/core/codec/Base64Test.java b/hutool-core/src/test/java/cn/hutool/core/codec/Base64Test.java index 27cf77bcc..55fef4ed2 100644 --- a/hutool-core/src/test/java/cn/hutool/core/codec/Base64Test.java +++ b/hutool-core/src/test/java/cn/hutool/core/codec/Base64Test.java @@ -23,7 +23,7 @@ public class Base64Test { String decodeStr = Base64.decodeStr(encode); Assert.assertEquals(a, decodeStr); } - + @Test public void encodeAndDecodeTest2() { String a = "a61a5db5a67c01445ca2-HZ20181120172058/pdf/中国电信影像云单体网关Docker版-V1.2.pdf"; @@ -33,6 +33,16 @@ public class Base64Test { String decodeStr = Base64.decodeStr(encode, CharsetUtil.UTF_8); Assert.assertEquals(a, decodeStr); } + + @Test + public void encodeAndDecodeTest3() { + String a = ":"; + String encode = Base64.encode(a); + Assert.assertEquals("Og==", encode); + + String decodeStr = Base64.decodeStr(encode); + Assert.assertEquals(a, decodeStr); + } @Test public void urlSafeEncodeAndDecodeTest() { diff --git a/hutool-extra/src/main/java/cn/hutool/extra/mail/MailAccount.java b/hutool-extra/src/main/java/cn/hutool/extra/mail/MailAccount.java index 918cb1e39..52ecd116c 100644 --- a/hutool-extra/src/main/java/cn/hutool/extra/mail/MailAccount.java +++ b/hutool-extra/src/main/java/cn/hutool/extra/mail/MailAccount.java @@ -4,15 +4,15 @@ import java.io.Serializable; import java.nio.charset.Charset; import java.util.Properties; +import cn.hutool.core.lang.Console; import cn.hutool.core.util.CharsetUtil; import cn.hutool.core.util.StrUtil; import cn.hutool.setting.Setting; /** * 邮件账户对象 - * - * @author Luxiaolei * + * @author Luxiaolei */ public class MailAccount implements Serializable { private static final long serialVersionUID = -6937313421815719204L; @@ -24,11 +24,11 @@ public class MailAccount implements Serializable { private static final String SMTP_CONNECTION_TIMEOUT = "mail.smtp.connectiontimeout"; private static final String SMTP_TIMEOUT = "mail.smtp.timeout"; - private static final String STARTTTLS_ENABLE = "mail.smtp.starttls.enable"; - private static final String SSL_ENABLE = "mail.smtp.ssl.enable"; - private static final String SOCKEY_FACTORY = "mail.smtp.socketFactory.class"; - private static final String SOCKEY_FACTORY_FALLBACK = "mail.smtp.socketFactory.fallback"; - private static final String SOCKEY_FACTORY_PORT = "smtp.socketFactory.port"; + private static final String STARTTLS_ENABLE = "mail.smtp.starttls.enable"; + private static final String SSL_ENABLE = "mail.smtp.ssl.enable"; + 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"; private static final String MAIL_DEBUG = "mail.debug"; private static final String SPLIT_LONG_PARAMS = "mail.mime.splitlongparameters"; @@ -37,43 +37,76 @@ public class MailAccount implements Serializable { public static final String MAIL_SETTING_PATH2 = "config/mailAccount.setting"; public static final String MAIL_SETTING_PATH3 = "mail.setting"; - /** SMTP服务器域名 */ + /** + * SMTP服务器域名 + */ private String host; - /** SMTP服务端口 */ + /** + * SMTP服务端口 + */ private Integer port; - /** 是否需要用户名密码验证 */ + /** + * 是否需要用户名密码验证 + */ private Boolean auth; - /** 用户名 */ + /** + * 用户名 + */ private String user; - /** 密码 */ + /** + * 密码 + */ private String pass; - /** 发送方,遵循RFC-822标准 */ + /** + * 发送方,遵循RFC-822标准 + */ private String from; - /** 是否打开调试模式,调试模式会显示与邮件服务器通信过程,默认不开启 */ + /** + * 是否打开调试模式,调试模式会显示与邮件服务器通信过程,默认不开启 + */ private boolean debug; - /** 编码用于编码邮件正文和发送人、收件人等中文 */ + /** + * 编码用于编码邮件正文和发送人、收件人等中文 + */ private Charset charset = CharsetUtil.CHARSET_UTF_8; - /** 对于超长参数是否切分为多份,默认为false(国内邮箱附件不支持切分的附件名) */ + /** + * 对于超长参数是否切分为多份,默认为false(国内邮箱附件不支持切分的附件名) + */ private boolean splitlongparameters; - /** 使用 STARTTLS安全连接,STARTTLS是对纯文本通信协议的扩展。它将纯文本连接升级为加密连接(TLS或SSL), 而不是使用一个单独的加密通信端口。 */ - private boolean startttlsEnable = false; - /** 使用 SSL安全连接 */ + /** + * 使用 STARTTLS安全连接,STARTTLS是对纯文本通信协议的扩展。它将纯文本连接升级为加密连接(TLS或SSL), 而不是使用一个单独的加密通信端口。 + */ + private boolean starttlsEnable = false; + /** + * 使用 SSL安全连接 + */ private Boolean sslEnable; - /** 指定实现javax.net.SocketFactory接口的类的名称,这个类将被用于创建SMTP的套接字 */ + /** + * 指定实现javax.net.SocketFactory接口的类的名称,这个类将被用于创建SMTP的套接字 + */ private String socketFactoryClass = "javax.net.ssl.SSLSocketFactory"; - /** 如果设置为true,未能创建一个套接字使用指定的套接字工厂类将导致使用java.net.Socket创建的套接字类, 默认值为true */ + /** + * 如果设置为true,未能创建一个套接字使用指定的套接字工厂类将导致使用java.net.Socket创建的套接字类, 默认值为true + */ private boolean socketFactoryFallback; - /** 指定的端口连接到在使用指定的套接字工厂。如果没有设置,将使用默认端口 */ + /** + * 指定的端口连接到在使用指定的套接字工厂。如果没有设置,将使用默认端口 + */ private int socketFactoryPort = 465; - - /** SMTP超时时长,单位毫秒,缺省值不超时 */ + + /** + * SMTP超时时长,单位毫秒,缺省值不超时 + */ private long timeout; - /** Socket连接超时值,单位毫秒,缺省值不超时 */ + /** + * Socket连接超时值,单位毫秒,缺省值不超时 + */ private long connectionTimeout; // -------------------------------------------------------------- Constructor start + /** * 构造,所有参数需自行定义或保持默认值 */ @@ -82,7 +115,7 @@ public class MailAccount implements Serializable { /** * 构造 - * + * * @param settingPath 配置文件路径 */ public MailAccount(String settingPath) { @@ -91,7 +124,7 @@ public class MailAccount implements Serializable { /** * 构造 - * + * * @param setting 配置文件 */ public MailAccount(Setting setting) { @@ -99,9 +132,10 @@ public class MailAccount implements Serializable { } // -------------------------------------------------------------- Constructor end + /** * 获得SMTP服务器域名 - * + * * @return SMTP服务器域名 */ public String getHost() { @@ -110,7 +144,7 @@ public class MailAccount implements Serializable { /** * 设置SMTP服务器域名 - * + * * @param host SMTP服务器域名 * @return this */ @@ -121,7 +155,7 @@ public class MailAccount implements Serializable { /** * 获得SMTP服务端口 - * + * * @return SMTP服务端口 */ public Integer getPort() { @@ -130,7 +164,7 @@ public class MailAccount implements Serializable { /** * 设置SMTP服务端口 - * + * * @param port SMTP服务端口 * @return this */ @@ -141,7 +175,7 @@ public class MailAccount implements Serializable { /** * 是否需要用户名密码验证 - * + * * @return 是否需要用户名密码验证 */ public Boolean isAuth() { @@ -150,7 +184,7 @@ public class MailAccount implements Serializable { /** * 设置是否需要用户名密码验证 - * + * * @param isAuth 是否需要用户名密码验证 * @return this */ @@ -161,7 +195,7 @@ public class MailAccount implements Serializable { /** * 获取用户名 - * + * * @return 用户名 */ public String getUser() { @@ -170,7 +204,7 @@ public class MailAccount implements Serializable { /** * 设置用户名 - * + * * @param user 用户名 * @return this */ @@ -181,7 +215,7 @@ public class MailAccount implements Serializable { /** * 获取密码 - * + * * @return 密码 */ public String getPass() { @@ -190,7 +224,7 @@ public class MailAccount implements Serializable { /** * 设置密码 - * + * * @param pass 密码 * @return this */ @@ -201,7 +235,7 @@ public class MailAccount implements Serializable { /** * 获取发送方,遵循RFC-822标准 - * + * * @return 发送方,遵循RFC-822标准 */ public String getFrom() { @@ -211,12 +245,12 @@ public class MailAccount implements Serializable { /** * 设置发送方,遵循RFC-822标准
* 发件人可以是以下形式: - * + * *
 	 * 1. user@xxx.xx
 	 * 2.  name 
 	 * 
- * + * * @param from 发送方,遵循RFC-822标准 * @return this */ @@ -227,7 +261,7 @@ public class MailAccount implements Serializable { /** * 是否打开调试模式,调试模式会显示与邮件服务器通信过程,默认不开启 - * + * * @return 是否打开调试模式,调试模式会显示与邮件服务器通信过程,默认不开启 * @since 4.0.2 */ @@ -237,7 +271,7 @@ public class MailAccount implements Serializable { /** * 设置是否打开调试模式,调试模式会显示与邮件服务器通信过程,默认不开启 - * + * * @param debug 是否打开调试模式,调试模式会显示与邮件服务器通信过程,默认不开启 * @since 4.0.2 */ @@ -248,7 +282,7 @@ public class MailAccount implements Serializable { /** * 获取字符集编码 - * + * * @return 编码 */ public Charset getCharset() { @@ -257,7 +291,7 @@ public class MailAccount implements Serializable { /** * 设置字符集编码 - * + * * @param charset 字符集编码 * @return this */ @@ -268,7 +302,7 @@ public class MailAccount implements Serializable { /** * 对于超长参数是否切分为多份,默认为false(国内邮箱附件不支持切分的附件名) - * + * * @return 对于超长参数是否切分为多份 */ public boolean isSplitlongparameters() { @@ -277,7 +311,7 @@ public class MailAccount implements Serializable { /** * 设置对于超长参数是否切分为多份,默认为false(国内邮箱附件不支持切分的附件名) - * + * * @param splitlongparameters 对于超长参数是否切分为多份 */ public void setSplitlongparameters(boolean splitlongparameters) { @@ -286,36 +320,36 @@ public class MailAccount implements Serializable { /** * 是否使用 STARTTLS安全连接,STARTTLS是对纯文本通信协议的扩展。它将纯文本连接升级为加密连接(TLS或SSL), 而不是使用一个单独的加密通信端口。 - * + * * @return 是否使用 STARTTLS安全连接 */ - public boolean isStartttlsEnable() { - return this.startttlsEnable; + public boolean isStarttlsEnable() { + return this.starttlsEnable; } /** * 设置是否使用STARTTLS安全连接,STARTTLS是对纯文本通信协议的扩展。它将纯文本连接升级为加密连接(TLS或SSL), 而不是使用一个单独的加密通信端口。 - * + * * @param startttlsEnable 是否使用STARTTLS安全连接 * @return this */ - public MailAccount setStartttlsEnable(boolean startttlsEnable) { - this.startttlsEnable = startttlsEnable; + 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 */ @@ -326,8 +360,8 @@ public class MailAccount implements Serializable { /** * 获取指定实现javax.net.SocketFactory接口的类的名称,这个类将被用于创建SMTP的套接字 - * - * @return 指定实现javax.net.SocketFactory接口的类的名称,这个类将被用于创建SMTP的套接字 + * + * @return 指定实现javax.net.SocketFactory接口的类的名称, 这个类将被用于创建SMTP的套接字 */ public String getSocketFactoryClass() { return socketFactoryClass; @@ -335,7 +369,7 @@ public class MailAccount implements Serializable { /** * 设置指定实现javax.net.SocketFactory接口的类的名称,这个类将被用于创建SMTP的套接字 - * + * * @param socketFactoryClass 指定实现javax.net.SocketFactory接口的类的名称,这个类将被用于创建SMTP的套接字 * @return this */ @@ -346,8 +380,8 @@ public class MailAccount implements Serializable { /** * 如果设置为true,未能创建一个套接字使用指定的套接字工厂类将导致使用java.net.Socket创建的套接字类, 默认值为true - * - * @return 如果设置为true,未能创建一个套接字使用指定的套接字工厂类将导致使用java.net.Socket创建的套接字类, 默认值为true + * + * @return 如果设置为true, 未能创建一个套接字使用指定的套接字工厂类将导致使用java.net.Socket创建的套接字类, 默认值为true */ public boolean isSocketFactoryFallback() { return socketFactoryFallback; @@ -355,7 +389,7 @@ public class MailAccount implements Serializable { /** * 如果设置为true,未能创建一个套接字使用指定的套接字工厂类将导致使用java.net.Socket创建的套接字类, 默认值为true - * + * * @param socketFactoryFallback 如果设置为true,未能创建一个套接字使用指定的套接字工厂类将导致使用java.net.Socket创建的套接字类, 默认值为true * @return this */ @@ -366,7 +400,7 @@ public class MailAccount implements Serializable { /** * 获取指定的端口连接到在使用指定的套接字工厂。如果没有设置,将使用默认端口 - * + * * @return 指定的端口连接到在使用指定的套接字工厂。如果没有设置,将使用默认端口 */ public int getSocketFactoryPort() { @@ -375,7 +409,7 @@ public class MailAccount implements Serializable { /** * 指定的端口连接到在使用指定的套接字工厂。如果没有设置,将使用默认端口 - * + * * @param socketFactoryPort 指定的端口连接到在使用指定的套接字工厂。如果没有设置,将使用默认端口 * @return this */ @@ -383,9 +417,10 @@ public class MailAccount implements Serializable { this.socketFactoryPort = socketFactoryPort; return this; } - + /** * 设置SMTP超时时长,单位毫秒,缺省值不超时 + * * @param timeout SMTP超时时长,单位毫秒,缺省值不超时 * @return this * @since 4.1.17 @@ -397,6 +432,7 @@ public class MailAccount implements Serializable { /** * 设置Socket连接超时值,单位毫秒,缺省值不超时 + * * @param connectionTimeout Socket连接超时值,单位毫秒,缺省值不超时 * @return this * @since 4.1.17 @@ -408,51 +444,51 @@ public class MailAccount implements Serializable { /** * 获得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) { + if (this.timeout > 0) { p.put(SMTP_TIMEOUT, String.valueOf(this.timeout)); } - if(this.connectionTimeout > 0) { + if (this.connectionTimeout > 0) { p.put(SMTP_CONNECTION_TIMEOUT, String.valueOf(this.connectionTimeout)); } p.put(MAIL_DEBUG, String.valueOf(this.debug)); - if (this.startttlsEnable) { + if (this.starttlsEnable) { //STARTTLS是对纯文本通信协议的扩展。它将纯文本连接升级为加密连接(TLS或SSL), 而不是使用一个单独的加密通信端口。 - p.put(STARTTTLS_ENABLE, String.valueOf(this.startttlsEnable)); - - if(null == this.sslEnable) { - //为了兼容旧版本,当用户没有此项配置时,按照startttlsEnable开启状态时对待 + p.put(STARTTLS_ENABLE, String.valueOf(this.starttlsEnable)); + + if (null == this.sslEnable) { + //为了兼容旧版本,当用户没有此项配置时,按照starttlsEnable开启状态时对待 this.sslEnable = true; } } - + // SSL - if(null != this.sslEnable && this.sslEnable) { - p.put(SSL_ENABLE, sslEnable); - p.put(SOCKEY_FACTORY, socketFactoryClass); - p.put(SOCKEY_FACTORY_FALLBACK, String.valueOf(this.socketFactoryFallback)); - p.put(SOCKEY_FACTORY_PORT, String.valueOf(this.socketFactoryPort)); + 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)); } - + return p; } /** * 如果某些值为null,使用默认值 - * + * * @return this */ public MailAccount defaultIfEmpty() { @@ -486,6 +522,6 @@ public class MailAccount implements Serializable { @Override public String toString() { return "MailAccount [host=" + host + ", port=" + port + ", auth=" + auth + ", user=" + user + ", pass=" + (StrUtil.isEmpty(this.pass) ? "" : "******") + ", from=" + from + ", startttlsEnable=" - + startttlsEnable + ", socketFactoryClass=" + socketFactoryClass + ", socketFactoryFallback=" + socketFactoryFallback + ", socketFactoryPort=" + socketFactoryPort + "]"; + + starttlsEnable + ", socketFactoryClass=" + socketFactoryClass + ", socketFactoryFallback=" + socketFactoryFallback + ", socketFactoryPort=" + socketFactoryPort + "]"; } } diff --git a/hutool-extra/src/test/java/cn/hutool/extra/mail/MailTest.java b/hutool-extra/src/test/java/cn/hutool/extra/mail/MailTest.java index 998bed40f..bb7c166ec 100644 --- a/hutool-extra/src/test/java/cn/hutool/extra/mail/MailTest.java +++ b/hutool-extra/src/test/java/cn/hutool/extra/mail/MailTest.java @@ -40,7 +40,7 @@ public class MailTest { } @Test - @Ignore +// @Ignore public void sendHtmlTest() { MailUtil.send("hutool@foxmail.com", "测试", "

邮件来自Hutool测试

", true); } diff --git a/hutool-extra/src/test/resources/config/mail.setting b/hutool-extra/src/test/resources/config/mail.setting index de00bdfd8..fcdd036f4 100644 --- a/hutool-extra/src/test/resources/config/mail.setting +++ b/hutool-extra/src/test/resources/config/mail.setting @@ -14,5 +14,9 @@ from = 小磊 user = hutool # 密码 pass = q1w2e3 -#使用 STARTTLS安全连接 -startttlsEnable = true \ No newline at end of file +# 使用 STARTTLS安全连接 +starttlsEnable = true +# 是否开启SSL +sslEnable = true +# 调试模式 +debug = true \ No newline at end of file