问题出现情况
邮件发送时debug用F8逐步运行可以成功发送邮件,但是用F9或者直接运行程序却发送失败
未开启mail的debug模式的报错日志是下面这个:
org.springframework.mail.MailAuthenticationException: Authentication failed; nested exception is javax.mail.AuthenticationFailedException: [EOF]
at org.springframework.mail.javamail.JavaMailSenderImpl.doSend(JavaMailSenderImpl.java:440)
at org.springframework.mail.javamail.JavaMailSenderImpl.send(JavaMailSenderImpl.java:361)
at org.springframework.mail.javamail.JavaMailSenderImpl.send(JavaMailSenderImpl.java:356)
开启了mail的debug日志,然后之前忘了添加超时设置,后续添加了下面超时设置
spring:
#JavaMailSender
mail:
host: smtp.exmail.qq.com
port: 587
username: xxx@xxx.com
password: xxx
default-encoding: UTF-8
properties:
mail.smtp.starttls.enable: true
mail.smtp.timeout: 5000 # 设置连接超时(毫秒)后面加的
mail.smtp.connectiontimeout: 5000 # 设置连接超时(毫秒)后面加的
mail.smtp.writetimeout: 5000 # 设置写入超时(毫秒)后面加的
之后发现是卡在了权限验证AUTH LOGIN,然后无法进行下一步,直到超时,日志如下:
DEBUG SMTP: exception reading response, THROW:
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.SSLSocketInputRecord.read(SSLSocketInputRecord.java:475)
at sun.security.ssl.SSLSocketInputRecord.readHeader(SSLSocketInputRecord.java:469)
at sun.security.ssl.SSLSocketInputRecord.bytesInCompletePacket(SSLSocketInputRecord.java:69)
at sun.security.ssl.SSLSocketImpl.readApplicationRecord(SSLSocketImpl.java:1271)
at sun.security.ssl.SSLSocketImpl.access$300(SSLSocketImpl.java:76)
at sun.security.ssl.SSLSocketImpl$AppInputStream.read(SSLSocketImpl.java:948)
at com.sun.mail.util.TraceInputStream.read(TraceInputStream.java:126)
at java.io.BufferedInputStream.fill(BufferedInputStream.java:246)
at java.io.BufferedInputStream.read(BufferedInputStream.java:265)
at com.sun.mail.util.LineInputStream.readLine(LineInputStream.java:106)
at com.sun.mail.smtp.SMTPTransport.readServerResponse(SMTPTransport.java:2440)
at com.sun.mail.smtp.SMTPTransport.ehlo(SMTPTransport.java:1699)
at com.sun.mail.smtp.SMTPTransport.protocolConnect(SMTPTransport.java:759)
at javax.mail.Service.connect(Service.java:366)
at org.springframework.mail.javamail.JavaMailSenderImpl.connectTransport(JavaMailSenderImpl.java:518)
at org.springframework.mail.javamail.JavaMailSenderImpl.doSend(JavaMailSenderImpl.java:437)
at org.springframework.mail.javamail.JavaMailSenderImpl.send(JavaMailSenderImpl.java:361)
at org.springframework.mail.javamail.JavaMailSenderImpl.send(JavaMailSenderImpl.java:356)
at com.example.demo.mail.MailServiceImpl.send(MailServiceImpl.java:95)
at com.example.demo.mail.MailServiceImpl.send(MailServiceImpl.java:108)
at com.example.demo.schedule.MyRunner.run(MyRunner.java:20)
at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:781)
at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:765)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:319)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1215)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1204)
问题解决过程
在debug过程中发现是在TLS握手时超时导致的权限验证失败,在项目启动时添加:
-Djavax.net.debug=ssl:handshake
添加后查看日志,ServerHello返回的版本是TLSv1.2,但是指定通信的版本是TLSv1.3,成功的日志指定的也是1.3,我尝试配置指定TLS版本为v1.2后发现问题成功解决:
spring:
mail:
host: smtp.exmail.qq.com
port: 587
username: xxx@xxx.com
password: xxx
default-encoding: UTF-8
properties:
mail.smtp.starttls.enable: true
mail.smtp.starttls.required: true
mail.smtp.ssl.protocols: TLSv1.2
mail.smtp.auth: true
mail.smtp.timeout: 5000 # 设置连接超时(毫秒)
mail.smtp.connectiontimeout: 5000 # 设置连接超时(毫秒)
mail.smtp.writetimeout: 5000 # 设置写入超时(毫秒)
后续我通过openssl命令行执行查看server的TLS版本发现是支持v1.3的:
admin@DESKTOP-0SP0F5T MINGW64 ~/Desktop
$ openssl s_client -starttls smtp -crlf -connect smtp.exmail.qq.com:587
Connecting to 119.147.6.199
CONNECTED(00000250)
depth=2 C=US, O=DigiCert Inc, OU=www.digicert.com, CN=DigiCert Global Root CA
verify return:1
depth=1 C=US, O=DigiCert Inc, CN=DigiCert Secure Site CN CA G3
verify return:1
depth=0 C=CN, ST=Guangdong Province, L=Shenzhen, O=Tencent Technology (Shenzhen) Company Limited, CN=*.exmail.qq.com
verify return:1
...省略
No client certificate CA names sent
Peer signing digest: SHA256
Peer signature type: RSA-PSS
Server Temp Key: X25519, 253 bits
---
SSL handshake has read 3871 bytes and written 446 bytes
Verification: OK
---
New, TLSv1.3, Cipher is TLS_AES_256_GCM_SHA384
...省略
---
250 8BITMIME
---
Post-Handshake New Session Ticket arrived:
SSL-Session:
Protocol : TLSv1.3
Cipher : TLS_AES_256_GCM_SHA384
...省略
然而通过ssl-tool在线验证却发现不支持,可自行点击超链接查看
问了chatgpt发现也是:
所以最后解决方法是指定了TLS版本
最后
哪位大佬知道这是为什么吗,最终还是没明白问题出在了哪里,望指点