关于邮箱的坑,不妨先看一篇幽默的文章(=^ ◡ ^=):救命!我的电子邮件发不到 500 英里以外!
问题背景
一般使用JavaMail发送邮件大致过程如下,创建同邮件服务的Session,配置Session参数等:
// Common variables
String host = "your_smtp_server";
String from = "from_address";
String to = "to_address";
// Set properties
Properties props = new Properties();
props.put("mail.smtp.host", host);
props.put("mail.debug", "true");
// Get session
Session session = Session.getInstance(props);
try {
// Instantiate a message
Message msg = new MimeMessage(session);
// Set the FROM message
msg.setFrom(new InternetAddress(from));
// The recipients can be more than one so we use an array but you can
// use 'new InternetAddress(to)' for only one address.
InternetAddress[] address = {new InternetAddress(to)};
msg.setRecipients(Message.RecipientType.TO, address);
// Set the message subject and date we sent it.
msg.setSubject("Email from JavaMail test");
msg.setSentDate(new Date());
// Set message content
msg.setText("This is the text for this simple demo using JavaMail.");
// Send the message
Transport.send(msg);
}
catch (MessagingException mex) {
mex.printStackTrace();
}
本以为这样就可以愉快地发邮件了。
运行一段时间发现系统总是卡在邮箱发送模块。后来查阅资料发现里面的大坑。
被忽略的参数
关键参数
参数 | 类型 | 解释 |
---|---|---|
mail.smtp.connectiontimeout | int | Socket connection timeout value in milliseconds. This timeout is implemented by java.net.Socket. Default is infinite timeout. |
mail.smtp.timeout | int | Socket read timeout value in milliseconds. This timeout is implemented by java.net.Socket. Default is infinite timeout. |
mail.smtp.writetimeout | int | Socket write timeout value in milliseconds. This timeout is implemented by using a java.util.concurrent.ScheduledExecutorService per connection that schedules a thread to close the socket if the timeout expires. Thus, the overhead of using this timeout is one thread per connection. Default is infinite timeout. |
解析
*注意加粗部分,翻译过来就是“默认时间无穷大”,总之一句话:你要不配置这几个参数,邮箱发送的等待时间可能是无穷大,出现异常后(比如邮箱服务器繁忙)客户端有可能永远在等待往服务器读写消息。这里涉及到跟服务器间的socket交互。*如下图,JavaMail在socket读写过程中有可能无限等待下去
解决方法
把JavaMail重构成异步,避免阻塞核心业务逻辑。
为JavaMail设置超时时间
Properties props = new Properties();
props.put("mail.smtp.timeout", 10000);
props.put("mail.smtp.connectiontimeout", 10000);
props.put("mail.smtp.writetimeout", 10000);
props.put("mail.smtp.host", host);
props.put("mail.debug", "true");
// Get session
Session session = Session.getInstance(props);