Java SMTP发送邮件不适用于Office 365

Java SMTP发送邮件不适用于Office 365,java,office365,jakarta-mail,Java,Office365,Jakarta Mail,这里有一个特殊的问题。目的是通过SMTP为office365发送邮件 我一直能够从本地的笔记本电脑发送邮件 但是当部署在我们的服务器上(防火墙后面)时,它不会成功注意:smtp.office365.com的端口587可在服务器上访问并确认。以下是从我的本地计算机成功运行的属性 Properties props = new Properties(); props.put("mail.smtp.starttls.enable", "true"); props.put("mail.smtp.conne

这里有一个特殊的问题。目的是通过SMTP为office365发送邮件

我一直能够从本地的笔记本电脑发送邮件

但是当部署在我们的服务器上(防火墙后面)时,它不会成功注意:smtp.office365.com的端口587可在服务器上访问并确认。以下是从我的本地计算机成功运行的属性

Properties props = new Properties();
props.put("mail.smtp.starttls.enable", "true");
props.put("mail.smtp.connectiontimeout", MAIL_TIMEOUT);
props.put("mail.smtp.timeout", MAIL_TIMEOUT);
props.put("mail.debug", true);
this.session = Session.getInstance(props);
session.setDebug(true);

Transport transport  = session.getTransport();
transport.connect("smtp.office365.com", 587, email, pass);
但在服务器上失败。以下是服务器调试日志:

DEBUG: setDebug: JavaMail version 1.6.2
DEBUG: getProvider() returning javax.mail.Provider[TRANSPORT,smtp,com.sun.mail.smtp.SMTPTransport,Oracle]
DEBUG SMTP: useEhlo true, useAuth false
DEBUG SMTP: trying to connect to host "smtp.office365.com", port 587, isSSL false
220 PN1PR0101CA0017.outlook.office365.com Microsoft ESMTP MAIL Service ready at Fri, 28 Jun 2019 06:39:41 +0000
DEBUG SMTP: connected to host "smtp.office365.com", port: 587
EHLO appqa
250-PN1PR0101CA0017.outlook.office365.com Hello [182.73.191.100]
250-SIZE 157286400
250-PIPELINING
250-DSN
250-ENHANCEDSTATUSCODES
250-STARTTLS
250-8BITMIME
250-BINARYMIME
250-CHUNKING
250 SMTPUTF8
DEBUG SMTP: Found extension "SIZE", arg "157286400"
DEBUG SMTP: Found extension "PIPELINING", arg ""
DEBUG SMTP: Found extension "DSN", arg ""
DEBUG SMTP: Found extension "ENHANCEDSTATUSCODES", arg ""
DEBUG SMTP: Found extension "STARTTLS", arg ""
DEBUG SMTP: Found extension "8BITMIME", arg ""
DEBUG SMTP: Found extension "BINARYMIME", arg ""
DEBUG SMTP: Found extension "CHUNKING", arg ""
DEBUG SMTP: Found extension "SMTPUTF8", arg ""
STARTTLS
220 2.0.0 SMTP server ready
Exception in thread "main" javax.mail.MessagingException: Could not convert socket to TLS;
  nested exception is:
java.net.SocketTimeoutException: Read timed out
at com.sun.mail.smtp.SMTPTransport.startTLS(SMTPTransport.java:2155)
at com.sun.mail.smtp.SMTPTransport.protocolConnect(SMTPTransport.java:752)
at javax.mail.Service.connect(Service.java:366)
at com.company.app.MailReader.getTransport(MailReader.java:269)
at io.vavr.control.Try.of(Try.java:75)
at com.company.app.MailReader.<init>(MailReader.java:59)
at com.company.services.MailService.getNewMailReader(MailService.java:82)
at com.company.services.MailService.start(MailService.java:46)
at com.company.Main.main(Main.java:34)
Caused by: java.net.SocketTimeoutException: Read timed out
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.socketRead(SocketInputStream.java:116)
at java.net.SocketInputStream.read(SocketInputStream.java:171)
at java.net.SocketInputStream.read(SocketInputStream.java:141)
at sun.security.ssl.InputRecord.readFully(InputRecord.java:465)
at sun.security.ssl.InputRecord.readV3Record(InputRecord.java:593)
at sun.security.ssl.InputRecord.read(InputRecord.java:529)
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:975)
at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1367)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1395)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1379)
at com.sun.mail.util.SocketFetcher.configureSSLSocket(SocketFetcher.java:626)
at com.sun.mail.util.SocketFetcher.startTLS(SocketFetcher.java:553)
at com.sun.mail.smtp.SMTPTransport.startTLS(SMTPTransport.java:2150)
... 8 more
DEBUG:setDebug:JavaMail版本1.6.2
调试:getProvider()返回javax.mail.Provider[TRANSPORT,smtp,com.sun.mail.smtp.SMTPTransport,Oracle]
调试SMTP:useEhlo true,useAuth false
调试SMTP:尝试连接到主机“SMTP.office365.com”,端口587,isSSL false
220 PN1PR0101CA0017.outlook.office365.com Microsoft ESMTP邮件服务于2019年6月28日星期五06:39:41+0000准备就绪
调试SMTP:已连接到主机“SMTP.office365.com”,端口:587
埃洛阿帕卡酒店
250-PN1PR0101CA0017.outlook.office365.com您好[182.73.191.100]
250号157286400
250-流水线
250-DSN
250-增强状态码
250-STARTTLS
250-8比特
250-BINARYMIME
250-分块
250 SMTPUTF8
调试SMTP:找到扩展名“SIZE”,arg“157286400”
调试SMTP:找到扩展名“管道”,arg“”
调试SMTP:找到扩展名“DSN”,参数“”
调试SMTP:找到扩展名“ENHANCEDSTATUSCODES”,arg“”
调试SMTP:找到扩展名“STARTTLS”,arg“”
调试SMTP:找到扩展名“8BITMIME”,参数“”
调试SMTP:找到扩展名“BINARYMIME”,arg“”
调试SMTP:找到扩展名“分块”,arg“”
调试SMTP:找到扩展名“SMTPUTF8”,arg“”
STARTTLS
220 2.0.0 SMTP服务器就绪
线程“main”javax.mail.MessaginException中出现异常:无法将套接字转换为TLS;
嵌套异常是:
java.net.SocketTimeoutException:读取超时
在com.sun.mail.smtp.SMTPTransport.startTLS上(SMTPTransport.java:2155)
在com.sun.mail.smtp.SMTPTransport.protocolConnect(SMTPTransport.java:752)上
在javax.mail.Service.connect(Service.java:366)
在com.company.app.MailReader.getTransport上(MailReader.java:269)
at io.vavr.control.Try.of(Try.java:75)
在com.company.app.MailReader上(MailReader.java:59)
位于com.company.services.MailService.getNewMailReader(MailService.java:82)
位于com.company.services.MailService.start(MailService.java:46)
位于com.company.Main.Main(Main.java:34)
原因:java.net.SocketTimeoutException:读取超时
位于java.net.SocketInputStream.socketRead0(本机方法)
位于java.net.SocketInputStream.socketRead(SocketInputStream.java:116)
位于java.net.SocketInputStream.read(SocketInputStream.java:171)
位于java.net.SocketInputStream.read(SocketInputStream.java:141)
位于sun.security.ssl.InputRecord.readfull(InputRecord.java:465)
位于sun.security.ssl.InputRecord.readV3Record(InputRecord.java:593)
位于sun.security.ssl.InputRecord.read(InputRecord.java:529)
位于sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:975)
位于sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1367)
位于sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1395)
位于sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1379)
位于com.sun.mail.util.SocketFetcher.configureSSLSocket(SocketFetcher.java:626)
位于com.sun.mail.util.SocketFetcher.startTLS(SocketFetcher.java:553)
在com.sun.mail.smtp.SMTPTransport.startTLS上(SMTPTransport.java:2150)
... 8个以上

尝试将其添加到您的属性中,它应该可以做到这一点

props.getProperties().put("mail.smtp.ssl.trust", "smtp.office365.com");

检查服务器是否具有与本地计算机相同的证书集

Properties props = new Properties();
props.put("mail.smtp.starttls.enable", "true");
props.put("mail.smtp.connectiontimeout", MAIL_TIMEOUT);
props.put("mail.smtp.timeout", MAIL_TIMEOUT);
props.put("mail.debug", true);
this.session = Session.getInstance(props);
session.setDebug(true);

Transport transport  = session.getTransport();
transport.connect("smtp.office365.com", 587, email, pass);
来自服务器的220响应并不意味着TLS会话已经建立,它只是意味着客户端可以开始协商它:

在收到对STARTTLS命令的220响应后,客户端必须在发出任何其他SMTP命令之前启动TLS协商。如果在发出STARTTLS命令后,客户端发现某些故障阻止它实际启动TLS握手,那么它应该中止连接。 (来自RFC3207)


此时,最可能的问题是缺少证书。

检查服务器上的JRE版本,并将其与本地计算机的版本进行比较

Properties props = new Properties();
props.put("mail.smtp.starttls.enable", "true");
props.put("mail.smtp.connectiontimeout", MAIL_TIMEOUT);
props.put("mail.smtp.timeout", MAIL_TIMEOUT);
props.put("mail.debug", true);
this.session = Session.getInstance(props);
session.setDebug(true);

Transport transport  = session.getTransport();
transport.connect("smtp.office365.com", 587, email, pass);
这是一个与环境相关的问题,因为相同的代码在不同的机器上表现不同。没有全貌,我无法肯定地回答。但我希望为进一步调查提供一些见解。我的分析如下:

  • 首先,我认为这不是SSL证书问题,根本原因很清楚:
这意味着套接字已建立,但将套接字转换为TLS的握手阶段失败。如果证书无效,握手后会报告,让我们看看SocketFetcher.java类中的代码:

/*
*现在强制握手,以便我们可以报告任何
*startTLS调用方的错误(例如,证书错误)
*方法。
*/
sslsocket.startHandshake();
/*
*检查服务器标识和信任。
*/
boolean idCheck=PropUtil.getBooleanProperty(props,
前缀+“.ssl.checkserveridentity”,false);
如果(idCheck)
checkServerIdentity(主机、sslsocket);
if(邮件的sf实例LSocketFactory){
MailSSLSocketFactory msf=(MailSSLSocketFactory)sf;
如果(!msf.isServerTrusted(主机,sslsocket)){
抛掷清理工具(sslsocket,
新IOException(“服务器不受信任:+主机”);
}
}
}
套接字在以下行遇到超时:
sslsocket.startHandshake()
,该行在证书验证之前

  • 其次,您已经提到防火墙已禁用,我们可以看到前面的套接字已正确建立,telnet命令也已正确建立,因此我认为这也不是防火墙问题

  • 这似乎是一个协议问题,主要是因为发生了这种情况