开发者社区> 问答> 正文

企业邮箱smtp协议自动发送邮件偶发性连接超时

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);

        try{
            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。请问是否存在网络波动以外的原因?以及如果真是因为网络波动所导致,是否只有增加重试机制这唯一的方案?

展开
收起
游客lhznvztbnmkt4 2021-10-13 10:24:28 2055 0
0 条回答
写回答
取消 提交回答
问答排行榜
最热
最新

相关电子书

更多
低代码开发师(初级)实战教程 立即下载
冬季实战营第三期:MySQL数据库进阶实战 立即下载
阿里巴巴DevOps 最佳实践手册 立即下载