项目中有个消息系统,通过 RabbitMQ 发送系统中的邮件时,采用5个固定线程池去发送邮件。发现虽然有消费,但是日志中却没有任何输出相关的成功或失败或抛出异常的信息。
伪代码如下,消费者主线程使用固定线程池发送
@Slf4j
@Component
public class EmailConsumer {
private ExecutorService fixedThreadPool = Executors.newFixedThreadPool(5);
@RabbitListener(queues = MessageMqConstant.SEA_EMAIL_QUEUE_NAME)
@RabbitHandler
public void process(String message) {
log.info("接收到发送邮件任务:{}", message);
fixedThreadPool.execute(new Runnable() {
@Override
public void run() {
try {
//采用spring mail JavaMailSenderImpl
sendMail(message);
} catch (Exception e) {
log.error(e.getMessage(), e);
}
}
});
}
}
配置如下
mail.host=smtp.exmail.qq.com
mail.port=465
mail.properties.mail.smtp.auth=true
mail.properties.mail.smtp.starttls.enable=true
mail.properties.mail.smtp.stattls.required=true
mail.properties.mail.debug=true
mail.properties.mail.smtp.port=465
mail.properties.mail.smtp.socketFactory.port=465
mail.properties.mail.smtp.socketFactory.fallback=false
mail.properties.mail.smtp.socketFactory.class=javax.net.ssl.SSLSocketFactory
运行一段时间,竟然假死。
jstack pid 发现整个线程阻塞。仔细审查下代码配置,怀疑没有设置超时时间。网上demo千篇一律,很少有配置超时时间的。查了资料终于
找到了相关资料。
#连接时间限制,单位毫秒。是关于与邮件服务器建立连接的时间长短的。默认是无限制
mail.smtp.connectiontimeout
#邮件接收时间限制,单位毫秒。这个是有关邮件接收时间长短。默认是无限制
mail.smtp.timeout
#邮件发送时间限制,单位毫秒。有关发送邮件时内容上传的时间长短。默认同样是无限制
mail.smtp.writetimeout
终上所述,总结耗时or网络不可控,尽量都要设置超时时间。修改代码,增加超时时间,超时进行重发,控制失败次数即可。
附上较完整的邮件参数设置
【SMTP - 简单邮件传输协议】
Name | 类型 | 描述 |
---|---|---|
mail.smtp.user | 串 | SMTP的默认用户名。 |
mail.smtp.host | 串 | 要连接的SMTP服务器。 |
mail.smtp.port | INT | 要连接的SMTP服务器端口,如果connect()方法未明确指定一个。默认为25。 |
mail.smtp.connectiontimeout | INT | 套接字连接超时值,以毫秒为单位。默认为无限超时。 |
mail.smtp.timeout | INT | 套接字I / O超时值,以毫秒为单位。默认为无限超时。 |
mail.smtp.from | 串 | 用于SMTP MAIL命令的电子邮件地址。这将设置信封返回地址。默认为msg.getFrom()或InternetAddress.getLocalAddress()。 |
mail.smtp.localhost | 串 | SMTP HELO或EHLO命令中使用的本地主机名。默认为InetAddress.getLocalHost()。getHostName()。如果您的JDK和名称服务配置正确,通常不需要设置。 |
mail.smtp.localaddress | 串 | 创建SMTP套接字时要绑定的本地地址(主机名)。默认为Socket类选择的地址。通常不需要设置。 |
mail.smtp.localport | INT | 创建SMTP套接字时要绑定的本地端口号。默认为Socket类选择的端口号。 |
mail.smtp.ehlo | 布尔 | 如果为false,请勿尝试使用EHLO命令登录。默认为true。 |
mail.smtp.auth | 布尔 | 如果为true,则尝试使用AUTH命令对用户进行身份验证。默认为false。 |
mail.smtp.auth.mechanisms | 串 | 如果设置,则列出要考虑的身份验证机制。仅使用服务器支持并由当前实现支持的机制。默认为“LOGIN PLAIN DIGEST-MD5 NTLM”,其中包括当前实现支持的所有身份验证机制。 |
mail.smtp.auth.login.disable | 布尔 | 如果为true,则阻止使用AUTH LOGIN命令。默认值为false。 |
mail.smtp.auth.plain.disable | 布尔 | 如果为true,则阻止使用AUTH PLAIN命令。默认值为false。 |
mail.smtp.auth.digest-md5.disable | 布尔 | 如果为true,则阻止使用AUTH DIGEST-MD5命令。默认值为false。 |
mail.smtp.auth.ntlm.disable | 布尔 | 如果为true,则阻止使用AUTH NTLM命令。默认值为false。 |
mail.smtp.auth.ntlm.domain | 串 | NTLM身份验证域。 |
mail.smtp.auth.ntlm.flags | INT | NTLM协议特定的标志。 |
mail.smtp.submitter | 串 | 要在MAIL FROM命令中的AUTH标记中使用的提交者。通常由邮件中继使用来传递有关邮件的原始提交者的信息。 |
mail.smtp.dsn.notify | 串 | RCPT命令的NOTIFY选项。永远不会,或成功,失败和延迟的某种组合(以逗号分隔)。 |
mail.smtp.dsn.ret | 串 | MAIL命令的RET选项。FULL或HDRS。 |
mail.smtp.sendpartial | 布尔 | 如果设置为true,并且消息包含一些有效和一些无效地址,则无论如何都要发送消息,并使用SendFailedException报告部分失败。如果设置为false(默认值),则如果收件人地址无效,则不会将邮件发送给任何收件人。 |
mail.smtp.sasl.enable | 布尔 | 如果设置为true,请尝试使用javax.security.sasl包来选择登录的身份验证机制。默认为false。 |
mail.smtp.sasl.mechanisms | 串 | 要尝试使用的空格或逗号分隔的SASL机制名称列表。 |
mail.smtp.sasl.authorizationid | 串 | 要在SASL身份验证中使用的授权标识。如果未设置,则使用验证ID(用户名)。 |
mail.smtp.sasl.realm | 串 | 与DIGEST-MD5身份验证一起使用的领域。 |
mail.smtp.quitwait | 布尔 | 如果设置为false,则发送QUIT命令并立即关闭连接。如果设置为true(默认值),则导致传输等待对QUIT命令的响应。 |
mail.smtp.reportsuccess | 布尔 | 如果设置为true,则导致传输为每个成功的地址包含SMTPAddressSucceededException。 |
mail.smtp.socketFactory | 套接字工厂 | 如果设置为实现javax.net.SocketFactory接口的类,则此类将用于创建SMTP套接字。 |
mail.smtp.socketFactory.class | 串 | 如果设置,则指定实现javax.net.SocketFactory接口的类的名称。此类将用于创建SMTP套接字。 |
mail.smtp.socketFactory.fallback | 布尔 | 如果设置为true,则无法使用指定的套接字工厂类创建套接字将导致使用java.net.Socket类创建套接字。默认为true。 |
mail.smtp.socketFactory.port | INT | 指定使用指定套接字工厂时要连接的端口。如果未设置,将使用默认端口。 |
mail.smtp.ssl.enable | 布尔 | 如果设置为true,则默认情况下使用SSL连接并使用SSL端口。“smtp”协议默认为false,“smtps”协议默认为true。 |
mail.smtp.ssl.checkserveridentity | 布尔 | 如果设置为true,则检查RFC 2595指定的服务器标识。默认为false。 |
mail.smtp.ssl.trust | 串 | 如果设置,并且尚未指定套接字工厂,则启用MailSSLSocketFactory。 如果设置为“*”,则所有主机都是可信的。 如果设置为以空格分隔的主机列表,则这些主机是受信任的。 否则,信任取决于服务器提供的证书。 |
mail.smtp.ssl.socketFactory | SSL套接字工厂 | 如果设置为扩展javax.net.ssl.SSLSocketFactory类的类,则此类将用于创建SMTP SSL套接字。 |
mail.smtp.ssl.socketFactory.class | 串 | 如果设置,则指定扩展javax.net.ssl.SSLSocketFactory类的类的名称。此类将用于创建SMTP SSL套接字。 |
mail.smtp.ssl.socketFactory.port | INT | 指定使用指定套接字工厂时要连接的端口。如果未设置,将使用默认端口。 |
mail.smtp.ssl.protocols | 串 | 指定将为SSL连接启用的SSL协议。属性值是javax.net.ssl.SSLSocket.setEnabledProtocols方法可接受的以空格分隔的标记列表。 |
mail.smtp.starttls.enable | 布尔 | 如果为true,则允许使用STARTTLS命令(如果服务器支持)在发出任何登录命令之前将连接切换到受TLS保护的连接。默认为false。 |
mail.smtp.starttls.required | 布尔 | 如果为true,则需要使用STARTTLS命令。如果服务器不支持STARTTLS命令,或者命令失败,则connect方法将失败。默认为false。 |
mail.smtp.socks.host | 串 | 指定将用于连接到邮件服务器的SOCKS5代理服务器的主机名。 |
mail.smtp.socks.port | 串 | 指定SOCKS5代理服务器的端口号。如果代理服务器未使用标准端口号1080,则只需使用此选项。 |
mail.smtp.mailextension | 串 | 要附加到MAIL命令的扩展字符串。 |
mail.smtp.userset | 布尔 | 如果设置为true,则在isConnected方法中使用RSET命令而不是NOOP命令。在某些情况下,sendmail会在许多NOOP命令后缓慢响应; 使用RSET避免了这个sendmail问题。默认为false。 |
【IMAP - 互联网信息访问协议】
Name | 类型 | 描述 |
---|---|---|
mail.imap.user | 串 | IMAP的默认用户名。 |
mail.imap.host | 串 | 要连接的IMAP服务器。 |
mail.imap.port | INT | 要连接的IMAP服务器端口,如果connect()方法没有显式指定一个。默认为143。 |
mail.imap.partialfetch | 布尔 | 控制是否应使用IMAP部分提取功能。默认为true。 |
mail.imap.fetchsize | INT | 部分提取大小(以字节为单位)。默认为16K。 |
mail.imap.ignorebodystructuresize | 布尔 | IMAP BODYSTRUCTURE响应包括每个身体部位的确切大小。通常,此大小用于确定每个身体部位要获取的数据量。默认为false。 |
mail.imap.connectiontimeout | INT | 套接字连接超时值,以毫秒为单位。默认为无限超时。 |
mail.imap.timeout | INT | 套接字I / O超时值,以毫秒为单位。默认为无限超时。 |
mail.imap.statuscachetimeout | INT | STATUS命令响应缓存的超时值(以毫秒为单位)。默认值为1000(1秒)。零禁用缓存。 |
mail.imap.appendbuffersize | INT | 附加到IMAP文件夹时要在内存中缓冲的消息的最大大小。 |
mail.imap.connectionpoolsize | INT | 连接池中的最大可用连接数。默认值为1。 |
mail.imap.connectionpooltimeout | INT | 连接池连接的超时值(以毫秒为单位)。默认值为45000(45秒)。 |
mail.imap.separatestoreconnection | 布尔 | 用于指示是否对存储命令使用专用存储连接的标志。默认值为false。 |
mail.imap.auth.login.disable | 布尔 | 如果为true,则禁止使用非标准AUTHENTICATE LOGIN命令,而是使用plain LOGIN命令。默认值为false。 |
mail.imap.auth.plain.disable | 布尔 | 如果为true,则阻止使用AUTHENTICATE PLAIN命令。默认值为false。 |
mail.imap.auth.ntlm.disable | 布尔 | 如果为true,则阻止使用AUTHENTICATE NTLM命令。默认值为false。 |
mail.imap.proxyauth.user | 串 | 如果服务器支持PROXYAUTH扩展,则此属性指定要充当的用户的名称。使用管理员凭据对服务器进行身份验证。身份验证后,IMAP提供程序将发出PROXYAUTH命令,其中包含此属性中指定的用户名。 |
mail.imap.localaddress | 串 | 创建IMAP套接字时要绑定的本地地址(主机名)。默认为Socket类选择的地址。 |
mail.imap.localport | INT | 创建IMAP套接字时要绑定的本地端口号。默认为Socket类选择的端口号。 |
mail.imap.sasl.enable | 布尔 | 如果设置为true,请尝试使用javax.security.sasl包来选择登录的身份验证机制。默认为false。 |
mail.imap.sasl.mechanisms | 串 | 要尝试使用的空格或逗号分隔的SASL机制名称列表。 |
mail.imap.sasl.authorizationid | 串 | 要在SASL身份验证中使用的授权标识。如果未设置,则使用验证ID(用户名)。 |
mail.imap.sasl.realm | 串 | 用于需要领域的SASL身份验证机制的领域,例如DIGEST-MD5。 |
mail.imap.auth.ntlm.domain | 串 | NTLM身份验证域。 |
mail.imap.auth.ntlm.flags | INT | NTLM协议特定的标志。 |
mail.imap.socketFactory | 套接字工厂 | 如果设置为实现javax.net.SocketFactory接口的类,则此类将用于创建IMAP套接字。 |
mail.imap.socketFactory.class | 串 | 如果设置,则指定实现javax.net.SocketFactory接口的类的名称。该类将用于创建IMAP套接字。 |
mail.imap.socketFactory.fallback | 布尔 | 如果设置为true,则无法使用指定的套接字工厂类创建套接字将导致使用java.net.Socket类创建套接字。默认为true。 |
mail.imap.socketFactory.port | INT | 指定使用指定套接字工厂时要连接的端口。未设置时使用默认端口。 |
mail.imap.ssl.enable | 布尔 | 如果设置为true,则默认情况下使用SSL连接并使用SSL端口。“imap”协议默认为false,“imaps”协议默认为true。 |
mail.imap.ssl.checkserveridentity | 布尔 | 如果设置为true,请检查RFC 2595指定的服务器标识。默认为false。 |
mail.imap.ssl.trust | 串 | 如果设置,并且尚未指定套接字工厂,则启用MailSSLSocketFactory。 如果设置为“*”,则所有主机都是可信的。 如果设置为以空格分隔的主机列表,则这些主机是受信任的。 否则,信任取决于服务器提供的证书。 |
mail.imap.ssl.socketFactory | SSL套接字工厂 | 如果设置为扩展javax.net.ssl.SSLSocketFactory类的类,则此类将用于创建IMAP SSL套接字。 |
mail.imap.ssl.socketFactory.class | 串 | 如果设置,则指定扩展javax.net.ssl.SSLSocketFactory类的类的名称。此类将用于创建IMAP SSL套接字。 |
mail.imap.ssl.socketFactory.port | INT | 指定使用指定套接字工厂时要连接的端口。如果未设置,将使用默认端口。 |
mail.imap.ssl.protocols | 串 | 指定将为SSL连接启用的SSL协议。属性值是javax.net.ssl.SSLSocket.setEnabledProtocols方法可接受的以空格分隔的标记列表。 |
mail.imap.starttls.enable | 布尔 | 如果为true,则允许使用STARTTLS命令(如果服务器支持)在发出任何登录命令之前将连接切换到受TLS保护的连接。默认值为false。 |
mail.imap.starttls.required | 布尔 | 如果为true,则需要使用STARTTLS命令。如果服务器不支持STARTTLS命令,或者命令失败,则connect方法将失败。默认为false。 |
mail.imap.socks.host | 串 | 指定将用于连接到邮件服务器的SOCKS5代理服务器的主机名。 |
mail.imap.socks.port | 串 | 指定SOCKS5代理服务器的端口号。如果代理服务器未使用标准端口号1080,则只需使用此选项。 |
mail.imap.minidletime | INT | 此属性设置延迟(以毫秒为单位)。如果未设置,则默认值为10毫秒。 |
mail.imap.enableimapevents | 布尔 | 启用特殊的IMAP特定事件以传递到Store的ConnectionListener。如果为true,则在Store的idle方法期间收到的未经请求的响应将作为ConnectionEvents发送,其类型为IMAPStore.RESPONSE。事件的消息将是原始IMAP响应字符串。默认情况下,不会发送这些事件。 |
mail.imap.folder.class | 串 | com.sun.mail.imap.IMAPFolder的子类的类名。子类可用于为其他IMAP命令提供支持。子类必须具有public MyIMAPFolder(String fullName,char separator,IMAPStore store,Boolean isNamespace)和public MyIMAPFolder(ListInfo li,IMAPStore store)形式的公共构造函数 |
【POP3 - 邮局协议】
Name | 类型 | 描述 |
---|---|---|
mail.pop3.user | 串 | POP3的默认用户名。 |
mail.pop3.host | 串 | 要连接的POP3服务器。 |
mail.pop3.port | INT | 要连接的POP3服务器端口,如果connect()方法没有显式指定一个。默认为110。 |
mail.pop3.connectiontimeout | INT | 套接字连接超时值,以毫秒为单位。默认为无限超时。 |
mail.pop3.timeout | INT | 套接字I / O超时值,以毫秒为单位。默认为无限超时。 |
mail.pop3.rsetbeforequit | 布尔 | 在发送QUIT命令之前,在关闭文件夹时发送POP3 RSET命令。默认值为false。 |
mail.pop3.message.class | 串 | com.sun.mail.pop3.POP3Message的子类的类名。子类可用于处理(例如)非标准Content-Type标头。子类必须具有MyPOP3Message(Folder f,int msgno)形式的公共构造函数抛出MessagingException。 |
mail.pop3.localaddress | 串 | 创建POP3套接字时要绑定的本地地址(主机名)。默认为Socket类选择的地址。 |
mail.pop3.localport | INT | 创建POP3套接字时要绑定的本地端口号。默认为Socket类选择的端口号。 |
mail.pop3.apop.enable | 布尔 | 如果设置为true,如果POP3服务器支持APOP,则使用APOP而不是USER / PASS登录POP3服务器。APOP发送密码摘要而不是明文密码。默认为false。 |
mail.pop3.socketFactory | 套接字工厂 | 如果设置为实现javax.net.SocketFactory接口的类,则此类将用于创建POP3套接字。 |
mail.pop3.socketFactory.class | 串 | 如果设置,则指定实现javax.net.SocketFactory接口的类的名称。该类将用于创建POP3套接字。 |
mail.pop3.socketFactory.fallback | 布尔 | 如果设置为true,则无法使用指定的套接字工厂类创建套接字将导致使用java.net.Socket类创建套接字。默认为true。 |
mail.pop3.socketFactory.port | INT | 指定使用指定套接字工厂时要连接的端口。如果未设置,将使用默认端口。 |
mail.pop3.ssl.enable | 布尔 | 如果设置为true,则默认情况下使用SSL连接并使用SSL端口。“pop3”协议默认为false,“pop3s”协议默认为true。 |
mail.pop3.ssl.checkserveridentity | 布尔 | 如果设置为true,请检查RFC 2595指定的服务器标识。默认为false。 |
mail.pop3.ssl.trust | 串 | 如果设置,并且尚未指定套接字工厂,则启用MailSSLSocketFactory。 如果设置为“*”,则所有主机都是可信的。 如果设置为以空格分隔的主机列表,则这些主机是受信任的。 否则,信任取决于服务器提供的证书。 |
mail.pop3.ssl.socketFactory | SSL套接字工厂 | 如果设置为扩展javax.net.ssl.SSLSocketFactory类的类,则此类将用于创建POP3 SSL套接字。 |
mail.pop3.ssl.socketFactory.class | 串 | 如果设置,则指定扩展javax.net.ssl.SSLSocketFactory类的类的名称。此类将用于创建POP3 SSL套接字。 |
mail.pop3.ssl.socketFactory.port | INT | 指定使用指定套接字工厂时要连接的端口。如果未设置,将使用默认端口。 |
mail.pop3.ssl.protocols | 串 | 指定将为SSL连接启用的SSL协议。属性值是javax.net.ssl.SSLSocket.setEnabledProtocols方法可接受的以空格分隔的标记列表。 |
mail.pop3.starttls.enable | 布尔 | 如果为true,则允许使用STLS命令(如果服务器支持)在发出任何登录命令之前将连接切换到受TLS保护的连接。默认为false。 |
mail.pop3.starttls.required | 布尔 | 如果为true,则需要使用STLS命令。如果服务器不支持STLS命令,或者命令失败,则connect方法将失败。默认为false。 |
mail.pop3.socks.host | 串 | 指定将用于连接到邮件服务器的SOCKS5代理服务器的主机名。 |
mail.pop3.socks.port | 串 | 指定SOCKS5代理服务器的端口号。 |
mail.pop3.disabletop | 布尔 | 如果设置为true,则不会使用POP3 TOP命令来获取邮件头。默认为false。 |
mail.pop3.forgettopheaders | 布尔 | 如果设置为true,则将忘记使用POP3 TOP命令检索的标头,并将其替换为作为POP3 RETR命令的一部分检索的标头。默认为false。 |
mail.pop3.filecache.enable | 布尔 | 如果设置为true,POP3提供程序将将消息数据缓存在临时文件中而不是内存中。消息仅在访问消息内容时添加到缓存中。消息头始终缓存在内存中(按需)。文件夹关闭或JVM终止时,将删除文件缓存。默认为false。 |
mail.pop3.filecache.dir | 串 | 如果启用了文件高速缓存,则可以使用此属性覆盖JDK用于临时文件的缺省目录。 |
mail.pop3.cachewriteto | 布尔 | 控制writeTo方法在POP3消息对象上的行为。如果设置为true,并且消息内容尚未缓存,并且ignoreList为null,则在写入之前缓存该消息。否则,消息将直接流式传输到输出流而不进行高速缓存。默认为false。 |
mail.pop3.keepmessagecontent | 布尔 | 如果此属性设置为true,则将保留对缓存内容的硬引用,从而阻止在文件夹关闭或缓存内容显式无效之前重用内存(使用invalidate方法)。默认为false。 |