问题描述
我们正在使用 org.springframework.mail.javamail.JavaMailSender 通过 Office 365 帐户和 SMTP 在电子邮件服务中发送邮件,并在 application.yml 中设置以下参数:
spring:
mail:
host: ${EMAIL_HOST:smtp.office365.com}
port: ${EMAIL_PORT:587}
username: ${EMAIL_USERNAME}
password: ${EMAIL_PASSWORD}
properties:
mail:
smtp:
auth: true
connectiontimeout: 5000
timeout: 5000
writetimeout: 5000
starttls:
enable: true
socketFactory:
port: 465
class: javax.net.ssl.SSLSocketFactory
奇怪的是:如果我们将connectiontimeout设置为5s,服务会在5s后得到响应。如果我们将其设置为 20 秒,则 o365 会在 20 秒后响应。
我的期望是
有没有人也有这个问题,也许知道如何解决?
我们的发件人服务:
@PostMapping
@ResponseStatus(HttpStatus.ACCEPTED)
public void sendMail(@RequestHeader(name = "X-API-KEY",required = true) String requestApiKey,@Valid @RequestBody EmailSendRequest email,HttpServletResponse response) {
if(!apiKey.equals(requestApiKey)){
LOGGER.error("Unauthorized api key" + requestApiKey);
throw new ResponseStatusException(HttpStatus.UNAUTHORIZED);
}
try {
LOGGER.info("Received request to send mail Subject=[{}] To=[{}] From=[{}]",email.getSubject(),email.getTo(),email.getFrom());
MimeMessage message = mailSender.createMimeMessage();
message.setFrom(new InternetAddress(email.getFrom().getEmail()));
message.addRecipients(Message.RecipientType.TO,toAddressArray(email.getTo()));
message.addRecipients(Message.RecipientType.CC,toAddressArray(email.getCc()));
message.addRecipients(Message.RecipientType.BCC,toAddressArray(email.getBcc()));
message.setSubject(email.getSubject());
message.setSentDate(new Date());
Multipart multipart = new MimeMultipart();
MimeBodyPart messageText = new MimeBodyPart();
messageText.setContent(email.getContent().getValue(),email.getContent().getType() == null ? DEFAULT_CONTENT_MIMETYPE : email.getContent().getType());
multipart.addBodyPart(messageText);
addAttachments(multipart,email.getAttachments());
message.setContent(multipart);
if(message.getRecipients(Message.RecipientType.TO) != null ||
message.getRecipients(Message.RecipientType.CC) != null ||
message.getRecipients(Message.RecipientType.BCC) != null)
{
mailSender.send(message);
}
else {
LOGGER.warn("Email not send! No recipients or all ignored.");
response.setHeader("X-Ignored","true");
}
LOGGER.info("Mail Subject=[{}] To=[{}}] From=[{}] successfully sent.",email.getFrom());
} catch (MessagingException e) {
LOGGER.error("Error sending mail Subject=[{}] To=[{}] From=[{}]:",email.getFrom(),e);
throw new ResponseStatusException(HttpStatus.INTERNAL_SERVER_ERROR);
} catch (MailSendException mailSendException) {
Exception[] exceptions = mailSendException.getMessageExceptions();
for (Exception e : exceptions){
if (e instanceof SMTPSendFailedException && (((SMTPSendFailedException)e).getReturnCode() == 554)){
LOGGER.error("Error sending mail Subject=[{}] To=[{}] From=[{}]: This sender mail address is not allowed.",email.getFrom());
throw new ResponseStatusException(HttpStatus.FORBIDDEN);
}
}
LOGGER.error("Error sending mail Subject=[{}] To=[{}] From=[{}]:",mailSendException);
throw new ResponseStatusException(HttpStatus.INTERNAL_SERVER_ERROR);
} catch (MailAuthenticationException e) {
LOGGER.error("Error sending mail Subject=[{}] To=[{}] From=[{}]: Wrong SMTP login credentials provided. \nMSG:{}",e.getMessage());
throw new ResponseStatusException(HttpStatus.NETWORK_AUTHENTICATION_required);
}
}
解决方法
看来,SocketFactory 是造成这种行为的原因。从 application.yml 中删除以下几行会使应用程序按预期工作:
socketFactory:
port: 465
class: javax.net.ssl.SSLSocketFactory