【问题标题】:Unable to send an email using SMTP (Getting javax.mail.MessagingException: Could not convert socket to TLS;)无法使用 SMTP 发送电子邮件(获取 javax.mail.MessagingException:无法将套接字转换为 TLS;)
【发布时间】:2012-09-26 11:13:42
【问题描述】:

我已经编写了以下代码,用于使用 javamail API 通过 SMTP 作为 TLS 发送电子邮件,因为 SSL 不受支持,但我最终遇到了以下异常。请在下面查看我的代码。我使用了调试模式,在代码下面你也可以找到异常。

import java.util.Properties;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;

public class SendMailTLS {

    public static void main(String[] args) {

        final String username = "---------@mydomain.com";
        final String password = "***********";

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

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

        try {

            Message message = new MimeMessage(session);
            message.setFrom(new 
                  InternetAddress("---------@mydomain.com"));
            message.setRecipients(Message.RecipientType.TO,
            InternetAddress.parse("---------@mydomain.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);
        }
    }
}

异常跟踪

DEBUG: setDebug: JavaMail version 1.4.5
DEBUG: getProvider() returning javax.mail.Provider[TRANSPORT,smtp,com.sun.mail.smtp.SMTPTransport,Sun Microsystems, Inc]
DEBUG SMTP: useEhlo true, useAuth true
DEBUG SMTP: useEhlo true, useAuth true
DEBUG SMTP: trying to connect to host "mail.mydomain.com", port 587, isSSL false
220-cpanel35.per.syra.net.au ESMTP Exim 4.80 #2 Fri, 05 Oct 2012 17:28:56 +0800 
220-We do not authorize the use of this system to transport unsolicited, 
220 and/or bulk e-mail.
DEBUG SMTP: connected to host "mail.mydomain.com", port: 587

EHLO xxxxxx.xxxxx.com
250-cpanel35.per.syra.net.au Hello xxxx.xxxxx.com [xx.xx.xx.xxx]i
250-SIZE 52428800
250-8BITMIME
250-PIPELINING
250-AUTH PLAIN LOGIN
250-STARTTLS
250 HELP
DEBUG SMTP: Found extension "SIZE", arg "52428800"
DEBUG SMTP: Found extension "8BITMIME", arg ""
DEBUG SMTP: Found extension "PIPELINING", arg ""
DEBUG SMTP: Found extension "AUTH", arg "PLAIN LOGIN"
DEBUG SMTP: Found extension "STARTTLS", arg ""
DEBUG SMTP: Found extension "HELP", arg ""
STARTTLS
220 TLS go ahead
Exception in thread "main" java.lang.RuntimeException: javax.mail.MessagingException: Could not convert socket to TLS;
  nested exception is:
    javax.net.ssl.SSLException: java.lang.RuntimeException: Could not generate DH keypair
    at SendMailTLS.main(SendMailTLS.java:52)
Caused by: javax.mail.MessagingException: Could not convert socket to TLS;
  nested exception is:
    javax.net.ssl.SSLException: java.lang.RuntimeException: Could not generate DH keypair
    at com.sun.mail.smtp.SMTPTransport.startTLS(SMTPTransport.java:1918)
    at com.sun.mail.smtp.SMTPTransport.protocolConnect(SMTPTransport.java:652)
    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 SendMailTLS.main(SendMailTLS.java:47)
Caused by: javax.net.ssl.SSLException: java.lang.RuntimeException: Could not generate DH keypair
    at sun.security.ssl.Alerts.getSSLException(Alerts.java:208)
    at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1868)
    at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1826)
    at sun.security.ssl.SSLSocketImpl.handleException(SSLSocketImpl.java:1809)
    at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1328)
    at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1305)
    at com.sun.mail.util.SocketFetcher.configureSSLSocket(SocketFetcher.java:548)
    at com.sun.mail.util.SocketFetcher.startTLS(SocketFetcher.java:485)
    at com.sun.mail.smtp.SMTPTransport.startTLS(SMTPTransport.java:1913)
    ... 7 more
Caused by: java.lang.RuntimeException: Could not generate DH keypair
    at sun.security.ssl.DHCrypt.<init>(DHCrypt.java:123)
    at sun.security.ssl.ClientHandshaker.serverKeyExchange(ClientHandshaker.java:618)
    at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:202)
    at sun.security.ssl.Handshaker.processLoop(Handshaker.java:868)
    at sun.security.ssl.Handshaker.process_record(Handshaker.java:804)
    at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:998)
    at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1294)
    at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1321)
    ... 11 more
Caused by: java.security.InvalidAlgorithmParameterException: Prime size must be multiple of 64, and can only range from 512 to 1024 (inclusive)
    at com.sun.crypto.provider.DHKeyPairGenerator.initialize(DHKeyPairGenerator.java:120)
    at java.security.KeyPairGenerator$Delegate.initialize(KeyPairGenerator.java:658)
    at sun.security.ssl.DHCrypt.<init>(DHCrypt.java:117)
    ... 18 more

谁能帮我调试一下?提前致谢!

【问题讨论】:

    标签: java ssl smtp jakarta-mail


    【解决方案1】:

    注释掉mail.smtp.starttls.enable 属性意味着您回退到默认且不安全的连接,只有当远程 SMTP 主机也接受端口 587 上的不安全传输(邮件提交端口与端口 25最终交付或中继操作)。

    在我的上下文中,TLS 对587 是强制性的,任何尝试打开没有 TLS 的会话都会产生 SMTP 服务器错误响应530 必须首先发出 STARTTLS 命令

    然后将 mail.smtp.starttls.enable 单独设置为 true 仍然会产生相同的错误无法将套接字转换为 TLS,但现在有一个线索:服务器不受信任。实际上,您必须在 JVM 启动属性中定义一个密钥库,该密钥库将包含一个以受信任的根证书结尾的证书链,或者使用此额外属性强制信任:ma​​il.smtp.ssl.trust 设置到远程主机名。

    例如,在 Spring 中配置对 javamail 的支持(您可以轻松地将其映射到普通的 javamail API)需要以下所有内容:

    <bean id="mailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl">
    <property name="host" value="theRemoteSmtpServer" />
    <property name="port" value="587" />
    <property name="username" value="muUserID" />
    <property name="password" value="myPassword" />
    <property name="javaMailProperties">
        <props>
            <prop key="mail.smtp.starttls.enable">true</prop>
            <prop key="mail.smtp.ssl.trust">theRemoteSmtpServer</prop>
            <prop key="mail.smtp.auth">true</prop>
        </props>
    </property>
    </bean>
    

    【讨论】:

    • 这对我有用...非常感谢。我试图在过去的 24 小时内克服这个问题。你的帖子终于救了我!! :)
    • 这对我有用。我错过了“mail.smtp.ssl.trust”属性并添加它为我修复了它。谢谢!
    • 我在 Glassfish 5.0.1(尚未发布)下遇到了同样的问题。 mail.smtp.ssl.trust 属性为我修复了它。
    【解决方案2】:

    我通过注释掉以下属性解决了这个问题

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

    并且代码在没有错误或警告的情况下执行,或者只是从上面的源代码中删除这一行。到目前为止,它的作用就像一个魅力。

    【讨论】:

    • 换句话说,将此属性设置为 mail.smtp.starttls.enable=false
    • 换句话说,您的密码以纯文本形式在互联网上传播。非常糟糕的建议。
    • 是的,这没有加密。它也可能会将您的电子邮件作为垃圾邮件发送。
    • @MartinErlic 你如何发送加密的密码?
    • 您完全失败了使用 TLS 的建议!现在它是一条不安全的消息。
    【解决方案3】:

    确保您的防病毒软件没有阻止该应用程序。就我而言,Avast 阻止我在 Java SE 应用程序中发送电子邮件。

    【讨论】:

    • 请发表英文答案
    • 安德烈安德拉德为我解决了这个问题!就我而言,这是最有用的答案(而且,因为测试这个问题需要 1 分钟,所以每个人都应该先尝试一下,然后再将时间浪费在其他事情上)
    【解决方案4】:

    我在 smtp.gmail.com 上遇到了同样的问题,并通过以下步骤解决了

    1. 根据 berhauz cmets 更改了我的代码
    2. 通过此链接更改了 Gmail 设置:https://www.google.com/settings/security/lesssecureapps

    【讨论】:

      【解决方案5】:

      如果您不想使用 SSL,并且使用 smtp 而不是 smtps,请尝试这些设置

      mail.smtp.starttls.enable=false
      mail.transport.protocol=smtp
      

      【讨论】:

        【解决方案6】:

        也许这个问题与安全有关,并且 smtp.ssl 不受信任,这就是问题发生的原因

        我只需添加一个属性即可解决此问题

        spring.mail.properties.mail.smtp.ssl.trust=smtp.gmail.com
        

        现在它对我来说很好用。

        【讨论】:

          【解决方案7】:

          您的服务器使用的 SSL 实现似乎与您使用的 JDK 版本中的 SSL 实现不兼容。文件SSLNOTES.txt(也包含在JavaMail 下载包中)有一些调试技巧。您可能需要 JDK SSL 专家来解决这个问题。

          【讨论】:

            【解决方案8】:

            我遇到了这个问题。原因是我们的管理员阻止了 TLS 和 SSL 协议。

            【讨论】:

              【解决方案9】:
              session.getProperties().put("mail.smtp.starttls.enable","true");
              props.put("mail.smtp.ssl.trust", "smtp.office365.com(site where your account is)");
              props.put("mail.smtp.starttls.enable", true);
              

              这些代码应该能够启动 ttls 通信并让邮件服务运行。

              除此之外,防病毒软件还会创建一个防火墙来阻止握手的发生。

              【讨论】:

              • 特别是在使用 smtp.office365.com 的情况下,这三行帮助我在尝试了几个小时后从服务器获得了 OK 响应。谢谢!响应:250 2.0.0 OK
              【解决方案10】:

              我在这个错误上花了几个小时,直到我发现 tomcat 使用 TLS 1.1 版本,而 smtp 服务器只支持 TLS 1.2 和 1.3。

              props.put("mail.smtp.ssl.protocols", "TLSv1.2");  
              

              将 TLS 版本设置为 1.2 解决了我的问题

              【讨论】:

              • 这解决了我与 GMail 通信的问题。
              • 哪个tomcat版本
              • 8.0.30 是 tomcat 版本
              【解决方案11】:

              堆栈跟踪显示问题的实际原因是这样的:

              java.security.InvalidAlgorithmParameterException: Prime size must be multiple of 64, and can only range from 512 to 1024 (inclusive)
              

              您遇到了不支持超过 1024 位的 DH 素数的旧版本 Java 的限制,而您的 SMTP 服务器可能需要这种限制。以下是相关的错误条目:

              Java 8 中删除了此限制/限制(请参阅the release notes)。

              请注意,正如已经指出的那样,您禁用 STARTTLS 的“修复”并不是真正的修复:这意味着您的密码将以纯文本形式发送,而且这仅适用于允许端口上未加密流量的 SMTP 服务器587.

              【讨论】:

                【解决方案12】:

                我通过禁用病毒防护解决了这个问题。

                【讨论】:

                  【解决方案13】:

                  经过一整天的战斗,这对我有用(使用 spring boot 、 MailSender 、 aws)

                  spring.mail.host=smtp.gmail.com
                  spring.mail.username=-----------@gmail.com
                  spring.mail.password=--------------
                  spring.mail.properties.mail.transport.protocol=smtp
                  spring.mail.properties.mail.smtp.port=465
                  spring.mail.properties.mail.smtp.auth=true
                  spring.mail.properties.mail.smtp.starttls.enable=true
                  spring.mail.properties.mail.smtp.ssl.enable=true
                  spring.mail.properties.mail.smtp.starttls.required=true
                  spring.mail.properties.mail.smtp.ssl.trust=smtp.gmail.com
                  

                  【讨论】:

                    猜你喜欢
                    • 2023-03-08
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 2017-02-15
                    • 1970-01-01
                    • 2017-10-05
                    • 1970-01-01
                    相关资源
                    最近更新 更多