Springboot框架开发的程序,部署在本地Centos7虚拟机上。 使用了spring-boot-starter-mail包进行发送邮件。但稳定性不高,偶尔成功偶尔失败。无法解决的失败原因如下:
2021-10-13 00:00:09.055 febs [asyncTaskExecutor-5] ERROR o.s.a.i.SimpleAsyncUncaughtExceptionHandler - Unexpected exception occurred invoking async method: public void cc.mrbird.febs.common.service.impl.MailServiceImpl.sendMail(java.util.List,java.lang.String,java.lang.String)
org.springframework.mail.MailSendException: Mail server connection failed; nested exception is com.sun.mail.util.MailConnectException: Couldn't connect to host, port: smtp.qiye.aliyun.com, 25; timeout 5000;
nested exception is:
java.net.SocketTimeoutException: connect timed out. Failed messages: com.sun.mail.util.MailConnectException: Couldn't connect to host, port: smtp.qiye.aliyun.com, 25; timeout 5000;
nested exception is:
java.net.SocketTimeoutException: connect timed out
at org.springframework.mail.javamail.JavaMailSenderImpl.doSend(JavaMailSenderImpl.java:447)
at org.springframework.mail.javamail.JavaMailSenderImpl.send(JavaMailSenderImpl.java:322)
at org.springframework.mail.javamail.JavaMailSenderImpl.send(JavaMailSenderImpl.java:311)
at cc.mrbird.febs.common.service.impl.MailServiceImpl.sendMail(MailServiceImpl.java:43)
at cc.mrbird.febs.common.service.impl.MailServiceImpl.sendMail(MailServiceImpl.java:74)
at sun.reflect.GeneratedMethodAccessor781.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:343)
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:198)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
at org.springframework.aop.interceptor.AsyncExecutionInterceptor.lambda$invoke$0(AsyncExecutionInterceptor.java:115)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
Caused by: com.sun.mail.util.MailConnectException: Couldn't connect to host, port: smtp.qiye.aliyun.com, 25; timeout 5000
at com.sun.mail.smtp.SMTPTransport.openServer(SMTPTransport.java:2209)
at com.sun.mail.smtp.SMTPTransport.protocolConnect(SMTPTransport.java:740)
at javax.mail.Service.connect(Service.java:366)
at org.springframework.mail.javamail.JavaMailSenderImpl.connectTransport(JavaMailSenderImpl.java:517)
at org.springframework.mail.javamail.JavaMailSenderImpl.doSend(JavaMailSenderImpl.java:436)
... 15 common frames omitted
Caused by: java.net.SocketTimeoutException: connect timed out
at java.net.PlainSocketImpl.socketConnect(Native Method)
at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:350)
at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206)
at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188)
at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
at java.net.Socket.connect(Socket.java:607)
at com.sun.mail.util.WriteTimeoutSocket.connect(WriteTimeoutSocket.java:115)
at com.sun.mail.util.SocketFetcher.createSocket(SocketFetcher.java:357)
at com.sun.mail.util.SocketFetcher.getSocket(SocketFetcher.java:238)
at com.sun.mail.smtp.SMTPTransport.openServer(SMTPTransport.java:2175)
... 19 common frames omitted
相关的springboot的application.yml配置如下:
spring:
mail:
host: smtp.qiye.aliyun.com
protocol: smtp
default-encoding: UTF-8
username: ****@***.com
password: ******
properties:
mail:
smtp:
socketFactory:
class: javax.net.ssl.SSLSocketFactory
port: 465
auth: true
connectiontimeout: 5000
timeout: 3000
writetimeout: 5000
发送邮件相关的java代码如下:
@Service
@Slf4j
public class MailServiceImpl implements MailService {
@Autowired
private JavaMailSender mailSender;
@Value("${spring.mail.username}")
private String from;
@Value("${webHost}")
private String webHost;
public void sendMail(String[] toList, String subject, String text) {
text += "\n系统地址:" + webHost;
SimpleMailMessage message = new SimpleMailMessage();
message.setFrom(from);
message.setTo(toList);
message.setSubject(subject);
message.setText(text);
String errorMessage = String.format("发送邮件失败,目标地址:%s,主题:%s,内容:%s",
String.join("、",toList),subject,text);
mailSender.send(message);
} catch (MailSendException se) {
Exception[] messageExceptions = se.getMessageExceptions();
SendFailedException sendFail;
if (!(messageExceptions[0] instanceof SendFailedException)) {
throw new FebsRuntimeException(errorMessage, se);
sendFail = (SendFailedException) messageExceptions[0];
log.error("send mail error,the invalid mail address:{}", sendFail.getInvalidAddresses());
Address[] address = sendFail.getValidUnsentAddresses();
if (null == address || 0 == address.length) {
throw new FebsRuntimeException(errorMessage, se);
String[] validMails = new String[address.length];
for(int j=0;j<address.length;j++){
validMails[j] = String.valueOf(address[j]);
message.setTo(validMails);
mailSender.send(message);
} catch (Exception e) {
log.error(errorMessage,e);
@Override
@Async
public void sendMail(List<String> toList, String subject, String text) {
if (CollectionUtils.isEmpty(toList)) {
return;
String[] toArray = toList.toArray(new String[] {});
sendMail(toArray,subject,text);
由于有成功发送的情况,所以应该不存在因配置错误而导致的连接不上或者端口被ban的情况。 经排查,在虚拟机上反复执行:telnet smtp.qiye.aliyun.com 25指令,不定期的出现Connection timed out。请问是否存在网络波动以外的原因?以及如果真是因为网络波动所导致,是否只有增加重试机制这唯一的方案?
企业邮箱发送邮件时,若出现投递失败产生退信,内容提示包含如下: the mta server of * reply:550 failed to meet SPF requirements 或者 the mta server of 163.com — 163mx01.mxmail.netease.com(220.181.14.141) reply:550 MI:SPF mx14,QMCowECpA0qTiftVaeB3Cg—.872S2 1442548128 http://mail.163.com/help
302305