在测试通过邮件发送验证码的功能时,出现了如下错误:
Mail server connection failed; nested exception is com.sun.mail.util.MailConnectException:
Couldn't connect to host, port: localhost, 25; timeout -1;
我出现该问题的原因,简化后来说就是JavaMailSend类没有通过IOC容器注入,而是自己new了一个,出现错误情况的复盘代码:
@SpringBootTest
class DemoApplicationTests {
@Test
void sendMail() {
//错误原因在这里!!!
JavaMailSender mailSender = new JavaMailSenderImpl();
SimpleMailMessage message = new SimpleMailMessage();
message.setSubject("木同的小心情验证码");
message.setFrom("[email protected]");
message.setTo("[email protected]");
message.setSentDate(new Date());
message.setText("您的验证码是:" + 444 + ",五分钟内有效,请勿外泄!");
mailSender.send(message);
}
}
正确写法如下:
@SpringBootTest
class DemoApplicationTests {
@Autowired
JavaMailSender mailSender;
@Test
void sendMail() {
SimpleMailMessage message = new SimpleMailMessage();
message.setSubject("木同的小心情验证码");
message.setFrom("[email protected]");
message.setTo("[email protected]");
message.setSentDate(new Date());
message.setText("您的验证码是:" + 444 + ",五分钟内有效,请勿外泄!");
mailSender.send(message);
}
}
简单而言,通过IOC容器获取的对象带有自动配置的配置信息,而自己直接new出来的对象没有配置信息。可以简单写个测试验证一下(这个问题应该都知道…)
直接new一个对象:
@SpringBootTest
class DemoApplicationTests {
@Test
void sendMail() {
JavaMailSenderImpl mailSender = new JavaMailSenderImpl();
String host = mailSender.getHost();
int port = mailSender.getPort();
System.out.println(host + " " + port);
}
}
此时的结果:
null -1
通过注入获取对象:
@SpringBootTest
class DemoApplicationTests {
@Autowired
JavaMailSenderImpl mailSender;
@Test
void sendMail() {
String host = mailSender.getHost();
int port = mailSender.getPort();
System.out.println(host + " " + port);
}
}
此时的结果:
smtp.163.com 465
测试中将接口直接写成了实现类,对功能实现没有影响。
properties文件有关mail的简单配置如下,详细配置信息可以参见官方文档:
mail:
host: smtp.163.com
# SSL端口465、994,非SSL端口25
port: 465
username: 13026324616@163.com
password: WFULDPOQIRUFAEDP
default-encoding: UTF-8
protocol: smtps
在不指定协议的情况下默认采用smtp协议,此时端口号应为25,否则会出现如下错误:
Got bad greeting from SMTP host: smtp.163.com, port: 465, response: [EOF].
Failed messages: javax.mail.MessagingException: Got bad greeting from SMTP host:
smtp.163.com, port: 465, response: [EOF]
如果指定了协议为smtps,但是端口指定为25,在报错信息中会出现有关协议的错误提示:
javax.net.ssl.SSLException: Unrecognized SSL message, plaintext connection?
另外在刚出现该问题时,搜索了一下该问题,现有的有关该问题的解决方案大致分为三种情况:
1)利用云服务器自己搭建的邮件服务,服务器提供商因为安全等原因关闭了25端口;
没有这种情况的实践经验,与该情况类似的可以参见有关回答。
2)properties中端口号配置错误;
自己尝试的结果是端口号配置错误只会出现前述两种错误,与本次遇到的错误描述不同(前提是使用第三方提供的服务,自己本地搭的没实践过。。。)。
3)本地关闭了25端口,需要将25端口打开。
该情况应该是自己在本地搭建邮箱服务可能碰到的吧,也没有遇到过。。。