Javamail无法将套接字转换为TLS GMail

use*_*206 45 java email gmail jakarta-mail

我试图通过gmails SMTP Server使用JavaMail发送电子邮件.但是这段代码.

final String username = "mygmail@gmail.com";
    final String password = "mygmailpassword";

    Properties props = new Properties();
    props.put("mail.smtp.auth", true);
    props.put("mail.smtp.starttls.enable", true);
    props.put("mail.smtp.host", "smtp.gmail.com");
    props.put("mail.smtp.port", "587");

    Session session = Session.getInstance(props,
            new javax.mail.Authenticator() {
                protected PasswordAuthentication getPasswordAuthentication() {
                    return new PasswordAuthentication(username, password);
                }
            });

    try {

        Message message = new MimeMessage(session);
        message.setFrom(new InternetAddress("no-reply@gmail.com"));
        message.setRecipients(Message.RecipientType.TO,
                InternetAddress.parse("test@gmail.com"));
        message.setSubject("Testing Subject");
        message.setText("Dear Mail Crawler,"
                + "\n\n No spam to my email, please!");

        Transport.send(message);

        System.out.println("Done");

    } catch (MessagingException e) {
        throw new RuntimeException(e);
    }
Run Code Online (Sandbox Code Playgroud)

返回此错误

Could not convert socket to TLS;
Run Code Online (Sandbox Code Playgroud)

完整的Stacktrace

Exception in thread "main" java.lang.RuntimeException: javax.mail.MessagingException: Could not convert socket to TLS;
  nested exception is:
    javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
    at Test.main(Test.java:43)
Caused by: javax.mail.MessagingException: Could not convert socket to TLS;
  nested exception is:
    javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
    at com.sun.mail.smtp.SMTPTransport.startTLS(SMTPTransport.java:1907)
    at com.sun.mail.smtp.SMTPTransport.protocolConnect(SMTPTransport.java:666)
    at javax.mail.Service.connect(Service.java:317)
    at javax.mail.Service.connect(Service.java:176)
    at javax.mail.Service.connect(Service.java:125)
    at javax.mail.Transport.send0(Transport.java:194)
    at javax.mail.Transport.send(Transport.java:124)
    at Test.main(Test.java:38)
Caused by: javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
    at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Alerts.java:174)
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1649)
    at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Handshaker.java:241)
    at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Handshaker.java:235)
    at com.sun.net.ssl.internal.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1206)
    at com.sun.net.ssl.internal.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:136)
    at com.sun.net.ssl.internal.ssl.Handshaker.processLoop(Handshaker.java:593)
    at com.sun.net.ssl.internal.ssl.Handshaker.process_record(Handshaker.java:529)
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:893)
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1138)
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1165)
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1149)
    at com.sun.mail.util.SocketFetcher.configureSSLSocket(SocketFetcher.java:549)
    at com.sun.mail.util.SocketFetcher.startTLS(SocketFetcher.java:486)
    at com.sun.mail.smtp.SMTPTransport.startTLS(SMTPTransport.java:1902)
    ... 7 more
Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
    at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:323)
    at sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:217)
    at sun.security.validator.Validator.validate(Validator.java:218)
    at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.validate(X509TrustManagerImpl.java:126)
    at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:209)
    at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:249)
    at com.sun.net.ssl.internal.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1185)
    ... 17 more
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
    at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:174)
    at java.security.cert.CertPathBuilder.build(CertPathBuilder.java:238)
    at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:318)
    ... 23 more
Run Code Online (Sandbox Code Playgroud)

小智 119

props.put("mail.smtp.ssl.trust", "smtp.gmail.com");
Run Code Online (Sandbox Code Playgroud)

  • 您是否可以扩展为什么/如何认为此提议的解决方案将解决问题? (10认同)
  • 从javamail docs - `mail.smtp.ssl.trust`如果设置,并且尚未指定套接字工厂,则启用MailSSLSocketFactory.如果设置为"*",则所有主机都是可信的.如果设置为以空格分隔的主机列表,则这些主机是受信任的.否则,信任取决于服务器提供的证书. (8认同)
  • 对我来说 `props.put("mail.smtp.ssl.trust", "*");` 成功了 (3认同)
  • 这个做了魔术,但答案可以更好地扩展一些像@Denomales说的更多细节.好的提示虽然.我的猜测是,这个道具告诉你程序盲目信任ssl连接是否有正确的证书? (2认同)

小智 24

我禁用avast防病毒10分钟,让它工作.


shi*_*raj 23

确保您的防病毒程序没有干扰,并确保在防火墙中添加排除项.

  • 真的说.Avast正在制造问题.Thanx哥们 (4认同)
  • 我是这个问题的受害者,我给的是我自己的解决方案, (3认同)
  • 同样在这里,Avast 不知何故是问题所在 (3认同)

Del*_*nte 16

当用于发送电子邮件的默认 SSL 协议设置为 TLSv1 并且 smtp 服务器不再支持此协议时,我遇到了类似的问题。技巧是使用较新的协议:

mail.smtp.ssl.protocols=TLSv1.2


Vla*_*adi 9

检查您是否拥有所有这些字段

Properties props = new Properties();
    props.put("mail.smtp.host", "smtp.gmail.com");
    props.put("mail.smtp.port", "587");
    props.put("mail.smtp.auth", "true");
    props.put("mail.smtp.ssl.protocols", "TLSv1.2");
    props.put("mail.smtp.starttls.enable", "true");
Run Code Online (Sandbox Code Playgroud)


ℛɑƒ*_*ƒæĿ 8

@carlos的第一个答案为我工作:

session.getProperties().put("mail.smtp.ssl.trust", "smtp.gmail.com");
Run Code Online (Sandbox Code Playgroud)

我已经测试了下面的属性并且对我来说也很完美:

session.getProperties().put("mail.smtp.starttls.enable", "true");
Run Code Online (Sandbox Code Playgroud)

这两个属性单独解决了这类问题,但保证我同时使用了这两个问题.


Pet*_*ski 7

经过一整天的搜索,我禁用了 Avast 10 分钟和 Windows 防火墙(重要),一切都开始工作了!

这是我的错误:

Mail server connection failed; nested exception is javax.mail.MessagingException: Could not convert socket to TLS; nested exception is: javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target. Failed messages: javax.mail.MessagingException: Could not convert socket to TLS; nested exception is: javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target  
Run Code Online (Sandbox Code Playgroud)

以下是通过向 SMTP 端口 587(或您的应用程序使用的任何端口)添加排除项来解决 Avast 19.8.2393 中的问题的方法:

  1. 打开 Avast

  2. 点击“设置”

  3. 单击“疑难解答”,然后单击“打开旧设置”

在此处输入图片说明

  1. 再次单击“疑难解答”,向下滚动到“重定向设置”并删除您的应用程序使用的端口。

在此处输入图片说明

就我而言,我刚刚从 SMTP 端口中删除了 587。

现在我可以使用 Avast 并打开我的 Windows 防火墙(无需为防火墙添加额外的排除项)。

这是我的application.properties电子邮件属性:

###### I am using a Google App Password which I generated in my Gmail Security settings ######
spring.mail.host = smtp.gmail.com
spring.mail.port = 587
spring.mail.protocol = smtp
spring.mail.username = gmail account
spring.mail.password = password
spring.mail.properties.mail.smtp.auth=true
spring.mail.properties.mail.smtp.starttls.enable=true
spring.mail.properties.mail.smtp.connectiontimeout=5000
spring.mail.properties.mail.smtp.timeout=5000
spring.mail.properties.mail.smtp.writetimeout=5000
Run Code Online (Sandbox Code Playgroud)


Pri*_*agh 7

上面的 application.properties 对我来说效果惊人:

spring.mail.properties.mail.smtp.starttls.enable=true
spring.mail.properties.mail.smtp.starttls.required=true
spring.mail.properties.mail.smtp.auth=true
spring.mail.properties.mail.smtp.ssl.trust=smtp.gmail.com
Run Code Online (Sandbox Code Playgroud)


nur*_*urb 6

在我的情况下,问题是通过删除该行来解决的

prop.put("mail.smtp.starttls.enable", "true");
Run Code Online (Sandbox Code Playgroud)

可能是因为电子邮件服务器上的一些 ssl 配置错误,我不确定。电子邮件服务器管理员从不承认这一点,并且总是责怪托管服务提供商 :)


isa*_*pir 5

这取决于“嵌套异常”。如果嵌套异常是“没有适当的协议”,则在系统属性中指定协议:

-Dmail.smtp.ssl.protocols=TLSv1.2
Run Code Online (Sandbox Code Playgroud)

我看到有些人建议在创建 STMP 会话的代码中设置它,但如果您想将来更新该值,则需要修补和部署。使用系统属性允许您在不更改代码的情况下更新它。


Bil*_*non -1

尝试使用 JavaMail 附带的 smtpsend 程序,如此处所述。如果同样失败,则说明您的 JDK 配置或网络配置有问题。