關於郵箱的坑,不妨先看一篇幽默的文章(=^ ◡ ^=):救命!我的電子郵件發不到 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);