一、组件版本
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Hoxton.RELEASE</version>
<!-- 邮件服务 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
spring-boot-starter-mail 内部依赖的是 jakarta.mail 1.6.4版本。
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>2.2.1.RELEASE</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>5.2.1.RELEASE</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.sun.mail</groupId>
<artifactId>jakarta.mail</artifactId>
<version>1.6.4</version>
<scope>compile</scope>
</dependency>
</dependencies>
jakarta.mail 是 javax.mail 1.6版本后的重命名。
二、场景描述
在使用 JavaMailSender.send(mimeMessage); 发送邮件时,时间太久,至少18s以上。
三、问题展现
通过在代码中,设置mail中Session的debug日志分析,主要是两处源码耗时太久。
1. com.sun.mail.smtp.SMTPTransport 类中的726行 getLocalHost() 从而获取 CanonicalHostName
2. org.springframework.mail.javamail.JavaMailSenderImpl 中 mimeMessage.saveChanges()
中,内部深处也是使用了 getLocalHostName() 而获取 CanonicalHostName
三、解决方案
解决方案有两种。
1. 在本地的hosts文件中,配置 本地的ip与域名(或计算机名),使其可以快速获取到CanonicalHostName.
例如
192.168.56.1 localhost1
2. 通过在程序代码中添加系统变量以及mail的Session的变量,从而绕过,不获取CanonicalHostName。
session.getProperties().setProperty("mail.smtp.localhost", "自定义");System.getProperties().setProperty("mail.mime.address.usecanonicalhostname", "false");
伪代码:
@Autowired
private JavaMailSender mailSender;
public Boolean sendComplexEmail2(EmailBo email) throws MessagingException, IOException {
// 解决本地DNS未配置 ip->域名场景下,邮件发送太慢的问题
System.getProperties().setProperty("mail.mime.address.usecanonicalhostname", "false");
// 获取 MimeMessage
MimeMessage mimeMessage = mailSender.createMimeMessage();
Session session = mimeMessage.getSession();
// 设置 日志打印控制器
session.setDebug(true);
// 解决本地DNS未配置 ip->域名场景下,邮件发送太慢的问题
session.getProperties().setProperty("mail.smtp.localhost", "myComputer");
。。。。。。
}
目前只为解决问题,等有时间再深入挖掘 使用 canonicalhostname 的原因。