【问题标题】:Javamail Could not convert socket to TLS GMailJavamail 无法将套接字转换为 TLS GMail
【发布时间】:2013-04-13 11:40:18
【问题描述】:

我正在尝试通过 gmails SMTP 服务器使用 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);
    }

返回一个错误

Could not convert socket to TLS;

完整的堆栈跟踪

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

【问题讨论】:

  • 请提供完整的堆栈跟踪。您的确切代码在我的机器上运行良好
  • @Laabidi 我已经发布了。

标签: java email gmail jakarta-mail


【解决方案1】:
props.put("mail.smtp.ssl.trust", "smtp.gmail.com");

【讨论】:

  • 您能否详细说明您认为该提议的解决方案为何/如何解决该问题?
  • 这个有魔力,但答案可以更好地扩展@Denomales 所说的更多细节。很好的提示。我的猜测是,这个道具告诉你程序盲目信任 ssl 连接是否有正确的证书?
  • 来自 javamail 文档 - mail.smtp.ssl.trust 如果已设置且未指定套接字工厂,则启用 MailSSLSocketFactory。如果设置为“*”,则所有主机都受信任。如果设置为以空格分隔的主机列表,则这些主机是受信任的。否则,信任取决于服务器提供的证书。
  • 对我来说 props.put("mail.smtp.ssl.trust", "*"); 成功了
  • @AryaPourtababaie,没有。他应该依靠操作系统来自动解决这个问题。很可能,实际上很可能,他有一个配置问题。他正在规避现有的保护措施。
【解决方案2】:

我禁用了 10 分钟的 avast 防病毒软件并让它正常工作。

【讨论】:

    【解决方案3】:

    确保您的防病毒程序没有干扰,并确保将排除项添加到您的防火墙。

    【讨论】:

    • 我是这个问题的受害者,我给出的是我自己的解决方案,
    • 说的对。 Avast 正在制造问题。谢谢朋友
    • 同样,Avast 是个问题
    • AVG 版本 18.1.3044(使用 Windows 10)干扰了我的 Spring 应用程序。解决方法:进入AVG的“Web and email”部分,关闭“email protection”。
    • Avast 也是我的问题。停用它 10 分钟,一切正常。
    【解决方案4】:

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

    mail.smtp.ssl.protocols=TLSv1.2

    【讨论】:

    • 非常感谢,这就是我的诀窍;)
    • 是的,就是这样,很好的答案
    • 是的,就是这样。谢谢。
    【解决方案5】:

    @carlos 的第一个答案对我有用:

    session.getProperties().put("mail.smtp.ssl.trust", "smtp.gmail.com");
    

    我已经测试了下面的属性并且对我也很有效:

    session.getProperties().put("mail.smtp.starttls.enable", "true");
    

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

    【讨论】:

      【解决方案6】:

      在我的情况下,问题是通过删除

      解决的
      prop.put("mail.smtp.starttls.enable", "true");
      

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

      【讨论】:

      • 注释 Jave 代码行“htmlEmail.setStartTLSEnabled(true);” (org.apache.commons.mail.HtmlEmail) 也为我解决了这个问题。
      【解决方案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  
      

      以下是通过向 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
      

      【讨论】:

      • 就我而言,它是相同但不同的防病毒软件。谢谢,帮了大忙
      【解决方案8】:

      上面的 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
      

      【讨论】:

      【解决方案9】:

      尝试将端口更改为 465

      mail.smtp.socketFactory.port=465
      mail.smtp.port=465
      

      【讨论】:

        【解决方案10】:

        如果应用程序不支持 SMTP 主机正在使用的 TLS 版本,也可能出现这种情况。

        例如,当您的应用程序(或使用较旧的 javax.mail JAR 的 java 程序)仅支持 TLSv1.1 时,尝试配置使用 TLSv1.2 而没有回退的 SMTP 服务器。

        【讨论】:

          【解决方案11】:

          如果您的上下文是 android 应用程序, 然后确保您的 android 设备时间设置为当前日期和时间。 潜在的例外是 “SSL 证书未通过身份验证。”

          【讨论】:

            【解决方案12】:

            是的,它适用于本地主机:

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

            该错误仅在本地主机上引发,因此您也应该在远程服务器上尝试。通常是上面提到的代码的sn-p在没有ssl.trust属性的情况下运行良好

            【讨论】:

              【解决方案13】:

              这是可行的解决方案兄弟。有保证的

              1) 首先打开您要从中发送邮件的 gmail 帐户,例如“xyz@gmail.com”

              2) 在https://support.google.com/accounts/answer/6010255?hl=en下方打开此链接

              3) 单击“我的帐户”中的“转到“安全性较低的应用程序”部分。”选项

              4) 然后开机

              5)就是这样(:

              这是我的代码

              import javax.mail.*;
              import javax.mail.internet.*;
              import java.util.*;
              
              public class SendEmail {
              
                 final String senderEmailID = "Sender Email id";
              final String senderPassword = "Sender Pass word";
              final String emailSMTPserver = "smtp.gmail.com";
              final String emailServerPort = "465";
              String receiverEmailID = null;
              static String emailSubject = "Test Mail";
              static String emailBody = ":)";
              public SendEmail(String receiverEmailID, String emailSubject, String emailBody)
              {
              this.receiverEmailID=receiverEmailID;
              this.emailSubject=emailSubject;
              this.emailBody=emailBody;
              Properties props = new Properties();
              props.put("mail.smtp.user",senderEmailID);
              props.put("mail.smtp.host", emailSMTPserver);
              props.put("mail.smtp.port", emailServerPort);
              props.put("mail.smtp.starttls.enable", "true");
              props.put("mail.smtp.auth", "true");
              props.put("mail.smtp.socketFactory.port", emailServerPort);
              props.put("mail.smtp.socketFactory.class","javax.net.ssl.SSLSocketFactory");
              props.put("mail.smtp.socketFactory.fallback", "false");
              SecurityManager security = System.getSecurityManager();
              try
              {
              Authenticator auth = new SMTPAuthenticator();
              Session session = Session.getInstance(props, auth);
              MimeMessage msg = new MimeMessage(session);
              msg.setText(emailBody);
              msg.setSubject(emailSubject);
              msg.setFrom(new InternetAddress(senderEmailID));
              msg.addRecipient(Message.RecipientType.TO,
              new InternetAddress(receiverEmailID));
              Transport.send(msg);
              System.out.println("Message send Successfully:)");
              }
              catch (Exception mex)
              {
              mex.printStackTrace();
              }
              }
              public class SMTPAuthenticator extends javax.mail.Authenticator
              {
              public PasswordAuthentication getPasswordAuthentication()
              {
              return new PasswordAuthentication(senderEmailID, senderPassword);
              }
              }
                  public static void main(String[] args) {
                     SendEmail mailSender;
                      mailSender = new SendEmail("Receiver Email id","Testing Code 2 example","Testing Code Body yess");
                  }
              
              }
              

              【讨论】:

                【解决方案14】:

                检查 JavaMail 库的版本(mail.jar 或 javax.mail.jar)。也许你需要一个更新的。 从这里下载最新版本:https://javaee.github.io/javamail/

                【讨论】:

                  【解决方案15】:

                  application.properties 中的以下一组属性对我有用:

                  spring.mail.host=smtp.gmail.com
                  spring.mail.port=587
                  spring.mail.username=<gmail_id>
                  spring.mail.password=<gmail_password>
                  spring.mail.properties.mail.smtp.ssl.trust=smtp.gmail.com
                  spring.mail.properties.mail.smtp.auth=true
                  spring.mail.properties.mail.smtp.starttls.enable=true
                  spring.mail.properties.mail.smtp.starttls.required=true
                  

                  请注意,如果您为您的 Gmail 帐户启用了两步验证,那么上述配置中的gmail_password 不应是普通密码,而是为您的 Google 帐户生成的 16 个字符的应用程序密码。请关注此link 以查看详细信息并生成您的 Google 应用密码。

                  【讨论】:

                    【解决方案16】:

                    就我而言,我使用的是 OpenJDK,当我切换OracleJDK 时,问题得到了解决。

                    【讨论】:

                      【解决方案17】:

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

                      -Dmail.smtp.ssl.protocols=TLSv1.2
                      

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

                      【讨论】:

                        【解决方案18】:

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

                        【讨论】:

                        • 还是不行,我怎么知道我的JDK配置或者网络配置有问题?
                        • 什么还是没有什么?如果 smtpsend 以同样的方式失败,这就是您如何知道问题不在于您的代码,而在于其他东西,很可能是您的 JDK 配置或网络配置。如果您的计算机上运行了防火墙或防病毒软件,请在运行测试时尝试禁用。你用的是什么版本的JDK?尝试重新安装 JDK 看看是否有帮助。
                        【解决方案19】:

                        是什么帮助我解决了这个问题,在此之前我已经尝试了所有方法,就是将我安装的 jre 配置为 JRE 1.8。

                        Eclipse 中的步骤:Windows>preferences>java>已安装 JRE>jre1.8.0

                        如果设置为 jdk,则切换到 jre(这是最新 Java 版本默认设置的)。

                        【讨论】:

                          猜你喜欢
                          • 1970-01-01
                          • 2021-10-06
                          • 2023-03-08
                          • 1970-01-01
                          • 1970-01-01
                          • 2013-06-22
                          • 2016-11-13
                          • 1970-01-01
                          • 2021-10-26
                          相关资源
                          最近更新 更多