MimeMessage.saveChanges真的很慢

由于包含m.saveChanges() ,以下测试大约需要5秒钟才能执行。

 import org.junit.Before; import org.junit.Test; import javax.mail.MessagingException; import javax.mail.Session; import javax.mail.internet.MimeMessage; import java.io.IOException; import java.util.Properties; import static org.junit.Assert.assertEquals; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @Test public void test1() throws MessagingException, IOException { Session s = Session.getDefaultInstance(new Properties()); MimeMessage m = new MimeMessage(s); m.setContent("Hello", "text/html; charset=utf-8"); m.saveChanges(); assertEquals(m.getContent(), "Hello"); assertEquals(m.getContentType(), "text/html; charset=utf-8"); } 

我也用mockito嘲笑了Session,但它没有帮助:

 Session s = mock(Session.class); when(s.getProperties()).thenReturn(new Properties()); 

这里有什么问题? 我可以嘲笑什么来加快速度?

修复人们在代码中首次使用JavaMail时最常犯的错误 。

DNS查找可能会损害某些计算机的性能。 对于JDK,您可以更改用于缓存DNS查找networkaddress.cache.ttlnetworkaddress.cache.negative.ttl的安全属性,或者设置系统属性sun.net.inetaddr.ttlsun.net.inetaddr.negative.ttl 。 JDK 7及更高版本中的默认行为可以很好地缓存。

您最好使用会话属性来避免某些查找。

  1. 设置mail.smtp.localhost的会话属性以防止在HELO命令上进行名称查找。
  2. 设置mail.frommail.host (不是协议版本)的会话属性,因为这将阻止InternetAddress.getLocalAddress(Session)上的名称查找。 调用MimeMessage.saveChanges()MimeMessage.updateHeaders()MimeMessage.updateMessageID()MimeMessage.setFrom()将触发此方法。
  3. 设置mail.smtp.from会话属性以防止在EHLO命令上查找。
  4. 或者,如果您的代码依赖于setFrom() ,则可以将系统属性mail.mime.address.usecanonicalhostname设置为false ,但这应该由#2点处理。
  5. 对于IMAP,您可以尝试将mail.imap.sasl.usecanonicalhostname设置为false ,这是默认值。

由于您没有传输邮件,请通过将您的代码更改为以下内容来应用规则#2:

 @Test public void test1() throws MessagingException, IOException { Properties props = new Properties(); props.put("mail.host", "localhost"); //Or use IP. Session s = Session.getInstance(props); MimeMessage m = new MimeMessage(s); m.setContent("Hello", "text/html; charset=utf-8"); m.saveChanges(); assertEquals(m.getContent(), "Hello"); assertEquals(m.getContentType(), "text/html; charset=utf-8"); } 

如果要传输消息,请合并规则#1,#2和#3,这将阻止访问主机系统进行名称查找。 如果要在传输期间阻止所有DNS查找,则必须使用IP地址。