【问题标题】:Spring Boot email sending throws SocketTimeoutException: Read timed outSpring Boot 电子邮件发送抛出 SocketTimeoutException: Read timed out
【发布时间】:2018-12-02 12:53:27
【问题描述】:

我已经研究了几天这个话题,但我在网上找到的答案都没有对我有用。

上下文:我有一个 Spring Boot Web 应用程序,它使用 Java Mail API 和 Spring Boot Starter Mail 发送自动电子邮件通知。

它正在使用带有 GSuite 帐户的 GMail SMTP 服务器。我最近升级到使用 Spring 5.0.6 和 Spring Boot 2.0.2 并且电子邮件发送停止工作。

一些线索:

  • 发送邮件的Java代码和以前一样
  • Gmail SMTP 仍然可以正常工作(从另一个使用旧版本应用程序且具有相同设置和身份验证的虚拟机,电子邮件可以正常发送)。
  • 除非我遗漏了什么,否则应用程序配置与以前相同

改变的东西:

  • 升级到 Spring 5.0.6
  • 升级到 Spring Boot 2.0.2
  • 在 Java 代码的许多地方进行了更改以匹配此升级并在应用程序的其他部分添加功能
  • VM 的 IP 地址与以前不同(AWS EC2 实例)

以下是 pom.xml 中的相关依赖:

    <!-- https://mvnrepository.com/artifact/javax.mail/javax.mail-api -->
    <dependency>
        <groupId>javax.mail</groupId>
        <artifactId>javax.mail-api</artifactId>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-mail</artifactId>
    </dependency>

这里是与Spring邮件相关的application.yml:

spring:
  mail:
    host: ${FT_MAIL_SMTP_HOST}
     port: ${FT_MAIL_SMTP_PORT}
     username: ${FT_MAIL_SMTP_USERNAME}
     password: ${FT_MAIL_SMTP_PASSWORD}
     debug: false
     properties:
       mail:
         smtp:
           starttls:
             enable: ${FT_MAIL_SMTP_STARTTLS}
             required: ${FT_MAIL_SMTP_TLSREQUIRED}
           auth: ${FT_MAIL_SMTP_AUTH}
           connectiontimeout: ${FT_MAIL_SMTP_CONN_TIMEOUT}
           timeout: ${FT_MAIL_SMTP_TIMEOUT}
           writetimeout: ${FT_MAIL_SMTP_WRITE_TIMEOUT}

这些变量是在环境中定义的:

FT_MAIL_SMTP_HOST=smtp.gmail.com
FT_MAIL_SMTP_PORT=587
FT_MAIL_SMTP_USERNAME=myaccount@myapp.com
FT_MAIL_SMTP_PASSWORD=mypassword

FT_MAIL_SMTP_STARTTLS=true
FT_MAIL_SMTP_TLSREQUIRED=true
FT_MAIL_SMTP_AUTH=true
FT_MAIL_SMTP_CONN_TIMEOUT=5000
FT_MAIL_SMTP_TIMEOUT=5000
FT_MAIL_SMTP_WRITE_TIMEOUT=5000

这是用于发送电子邮件的 Spring @Service(未更改):

@Service
public class EmailServiceImpl {

@Autowired
public JavaMailSender emailSender;

@Autowired
private SpringTemplateEngine templateEngine;

@Value("${myapp.mail.from}")
private String fromAddress;

@Value("${myapp.mail.replyto}")
private String replyToAddress;

public void sendTemplatedMessage(String template, String to, String subject, Map<String, Object> model) throws MailException, MessagingException {  
    sendTemplatedMessage(template, to, fromAddress, replyToAddress, subject, model);
}

public void sendTemplatedMessage(String template, String to, String from, String subject, Map<String, Object> model) throws MailException, MessagingException { 
    sendTemplatedMessage(template, to, from, replyToAddress, subject, model);
}

private void sendTemplatedMessage(String template, String to, String from, String replyTo, String subject, Map<String, Object> model) throws MailException, MessagingException {    

    MimeMessage message = emailSender.createMimeMessage();

    MimeMessageHelper helper = new MimeMessageHelper(message,
            MimeMessageHelper.MULTIPART_MODE_MIXED_RELATED,
            StandardCharsets.UTF_8.name());

    //helper.addAttachment("logo.png", new ClassPathResource("memorynotfound-logo.png"));
    Context context = new Context();
    context.setVariables(model);
    String html = templateEngine.process(template, context);

    helper.setTo(to);
    helper.setFrom(from);
    helper.setReplyTo(from);
    helper.setSubject(subject);
    helper.setText(html, true);

    emailSender.send(message);
}

public void sendSimpleMessage(String to, String from, String subject, String text) {
    try {           
        SimpleMailMessage message = new SimpleMailMessage(); 
        message.setTo(to);
        message.setFrom(from);
        message.setSubject(subject); 
        message.setText(text);
        emailSender.send(message);
    } catch (Exception e) {
        e.printStackTrace();
    }
}
}

现在这是我在尝试发送电子邮件时遇到的错误:

04:42:19.900 [https-jsse-nio-443-exec-3] ERROR c.f.controller.StayController - Could not send Guest confirmation email to gfgorostidi@protonmail.com
org.springframework.mail.MailSendException: Failed to close server connection after message sending; nested exception is javax.mail.MessagingException: Exception reading response;
  nested exception is:
 java.net.SocketTimeoutException: Read timed out
 at org.springframework.mail.javamail.JavaMailSenderImpl.doSend(JavaMailSenderImpl.java:482)
 at org.springframework.mail.javamail.JavaMailSenderImpl.send(JavaMailSenderImpl.java:359)
 at org.springframework.mail.javamail.JavaMailSenderImpl.send(JavaMailSenderImpl.java:354)
 at com.myapp.util.EmailServiceImpl.sendTemplatedMessage(EmailServiceImpl.java:61)
 at com.myapp.util.EmailServiceImpl.sendTemplatedMessage(EmailServiceImpl.java:35)
 at com.myapp.controller.StayController.sendConfirmEmailToGuest(StayController.java:437)
 at com.myapp.controller.StayController.saveStay(StayController.java:383)
 at com.myapp.controller.StayController.createStay(StayController.java:163)
 at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
 ......
 ......
 ......
 at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
 at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1135)
 at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
 at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
 at java.base/java.lang.Thread.run(Thread.java:844)
Caused by: javax.mail.MessagingException: Exception reading response;
  nested exception is:
 java.net.SocketTimeoutException: Read timed out
 at com.sun.mail.smtp.SMTPTransport.readServerResponse(SMTPTransport.java:2202)
 at com.sun.mail.smtp.SMTPTransport.close(SMTPTransport.java:1212)
 at org.springframework.mail.javamail.JavaMailSenderImpl.doSend(JavaMailSenderImpl.java:473)
 ... 104 more
Caused by: java.net.SocketTimeoutException: Read timed out
 at java.base/java.net.SocketInputStream.socketRead0(Native Method)
 at java.base/java.net.SocketInputStream.socketRead(SocketInputStream.java:116)
 at java.base/java.net.SocketInputStream.read(SocketInputStream.java:171)
 at java.base/java.net.SocketInputStream.read(SocketInputStream.java:141)
 at java.base/sun.security.ssl.SSLSocketInputRecord.read(SSLSocketInputRecord.java:425)
 at java.base/sun.security.ssl.SSLSocketInputRecord.bytesInCompletePacket(SSLSocketInputRecord.java:65)
 at java.base/sun.security.ssl.SSLSocketImpl.bytesInCompletePacket(SSLSocketImpl.java:918)
 at java.base/sun.security.ssl.AppInputStream.read(AppInputStream.java:144)
 at com.sun.mail.util.TraceInputStream.read(TraceInputStream.java:124)
 at java.base/java.io.BufferedInputStream.fill(BufferedInputStream.java:252)
 at java.base/java.io.BufferedInputStream.read(BufferedInputStream.java:271)
 at com.sun.mail.util.LineInputStream.readLine(LineInputStream.java:89)
 at com.sun.mail.smtp.SMTPTransport.readServerResponse(SMTPTransport.java:2182)
 ... 106 more
org.springframework.mail.MailSendException: Failed to close server connection after message sending; nested exception is javax.mail.MessagingException: Exception reading response;
  nested exception is:
 java.net.SocketTimeoutException: Read timed out
 at org.springframework.mail.javamail.JavaMailSenderImpl.doSend(JavaMailSenderImpl.java:482)
 at org.springframework.mail.javamail.JavaMailSenderImpl.send(JavaMailSenderImpl.java:359)
 at org.springframework.mail.javamail.JavaMailSenderImpl.send(JavaMailSenderImpl.java:354)
 at com.myapp.util.EmailServiceImpl.sendTemplatedMessage(EmailServiceImpl.java:61)
 at com.myapp.util.EmailServiceImpl.sendTemplatedMessage(EmailServiceImpl.java:35)
 at com.myapp.controller.StayController.sendConfirmEmailToGuest(StayController.java:437)
 at com.myapp.controller.StayController.saveStay(StayController.java:383)
 at com.myapp.controller.StayController.createStay(StayController.java:163)
 at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
 ......
 ......
 ......
 at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1468)
 at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
 at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1135)
 at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
 at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
 at java.base/java.lang.Thread.run(Thread.java:844)
Caused by: javax.mail.MessagingException: Exception reading response;
  nested exception is:
 java.net.SocketTimeoutException: Read timed out
 at com.sun.mail.smtp.SMTPTransport.readServerResponse(SMTPTransport.java:2202)
 at com.sun.mail.smtp.SMTPTransport.close(SMTPTransport.java:1212)
 at org.springframework.mail.javamail.JavaMailSenderImpl.doSend(JavaMailSenderImpl.java:473)
 ... 104 more
Caused by: java.net.SocketTimeoutException: Read timed out
 at java.base/java.net.SocketInputStream.socketRead0(Native Method)
 at java.base/java.net.SocketInputStream.socketRead(SocketInputStream.java:116)
 at java.base/java.net.SocketInputStream.read(SocketInputStream.java:171)
 at java.base/java.net.SocketInputStream.read(SocketInputStream.java:141)
 at java.base/sun.security.ssl.SSLSocketInputRecord.read(SSLSocketInputRecord.java:425)
 at java.base/sun.security.ssl.SSLSocketInputRecord.bytesInCompletePacket(SSLSocketInputRecord.java:65)
 at java.base/sun.security.ssl.SSLSocketImpl.bytesInCompletePacket(SSLSocketImpl.java:918)
 at java.base/sun.security.ssl.AppInputStream.read(AppInputStream.java:144)
 at com.sun.mail.util.TraceInputStream.read(TraceInputStream.java:124)
 at java.base/java.io.BufferedInputStream.fill(BufferedInputStream.java:252)
 at java.base/java.io.BufferedInputStream.read(BufferedInputStream.java:271)
 at com.sun.mail.util.LineInputStream.readLine(LineInputStream.java:89)
 at com.sun.mail.smtp.SMTPTransport.readServerResponse(SMTPTransport.java:2182)
 ... 106 more

我尝试设置错误的 SMTP 服务器或错误的凭据,这导致连接失败,因此我假设服务器和凭据正确无误,并且在连接成功后发生错误。

使用的帐户未达到其限制,因为另一个 VM 使用相同的凭据并毫无问题地发送电子邮件。

我尝试将“启动 TLS”设置更改为 false 并改用端口 465,但这也不起作用。

任何帮助表示赞赏!提前致谢!

【问题讨论】:

    标签: java spring email spring-boot smtp


    【解决方案1】:

    我确实遇到了同样的问题,但我的情况有点不同

    我正在尝试使用石英按计划方式发送

    当我不使用石英时,一切正常,但使用石英时它开始失败

    上述解决方案对我没有帮助,但为我指明了查看我设置的属性的方向。

    增加连接超时对我来说很有效

    从而改变了应用程序属性

    来自:

    spring.mail.properties.mail.smtp.timeout=3000
    

    到:

    spring.mail.properties.mail.smtp.timeout=25000
    

    希望它也适用于其他人

    【讨论】:

      【解决方案2】:

      在对配置进行了多次试验和错误之后,我发现它需要配置中的应用程序属性“spring.mail.protocol”。

      我在 application.yml 中添加了 protocol: smtp 行:

      spring:
        mail:
          protocol: smtp
      

      这解决了读取超时问题,现在可以正确发送电子邮件。希望这可以帮助将来的人。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-10-15
        • 2019-08-18
        • 1970-01-01
        • 2021-08-10
        • 2018-02-02
        • 2021-06-30
        相关资源
        最近更新 更多