簡體   English   中英

無法使用 SMTP 發送 email(獲取 javax.mail.MessagingException:無法將套接字轉換為 TLS;)

[英]Unable to send an email using SMTP (Getting javax.mail.MessagingException: Could not convert socket to TLS;)

我已經編寫了以下代碼,用於使用 javamail API 到 SMTP 發送 email 作為 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

誰能幫我調試這個? 提前致謝!

我通過注釋掉以下屬性解決了這個問題

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

並且代碼執行時沒有錯誤或警告,或者只是從上面的源代碼中刪除這一行。 迄今為止,它的作用就像一個魅力。

注釋掉屬性mail.smtp.starttls.enable意味着您回退到默認和不安全的連接,只有當遠程 SMTP 主機也接受端口587上的不安全傳輸(郵件提交的端口與結束的端口 25 - 交付或中繼操作)。

在我的上下文中,TLS 在587上是強制性的,任何嘗試在沒有 TLS 的情況下打開會話都會產生 SMTP 服務器錯誤響應530 Must issue a STARTTLS command first

然后單獨將mail.smtp.starttls.enable設置為true仍然會產生相同的錯誤無法將套接字轉換為 TLS但現在有一個線索:服務器不受信任 實際上,您必須在 JVM 啟動屬性中定義一個密鑰庫,該密鑰庫將包含以受信任的根證書結尾的證書鏈,或者使用此額外屬性強制信任: mail.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>

確保您的防病毒軟件沒有阻止該應用程序。 就我而言,Avast 阻止我在 Java SE 應用程序中發送電子郵件。

我在 smtp.gmail.com 上遇到了同樣的問題,並通過以下步驟進行了修復

  1. 根據berhauz評論更改了我的代碼
  2. 從此鏈接更改 Gmail 設置: https : //www.google.com/settings/security/lesssecureapps

如果您不想使用 SSL,並且您使用的是 smtp 而不是 smtps,請嘗試這些設置

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

您的服務器使用的 SSL 實現似乎與您使用的 JDK 版本中的 SSL 實現不兼容。 文件SSLNOTES.txt (也包含在 JavaMail 下載包中)有一些調試技巧。 您可能需要 JDK SSL 專家來解決這個問題。

我有這個問題。 原因是我們的管理員阻止了 TLS 和 SSL 協議。

也許這個與安全相關的問題和smtp.ssl 不受信任,這就是問題發生的原因

我解決這個問題只是添加一個屬性

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

現在它對我來說工作正常。

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 通信並運行郵件服務。

除此之外,防病毒軟件會創建一個防火牆來阻止握手的發生。

堆棧跟蹤顯示問題的實際原因是這樣的:

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

您遇到了舊版本 Java 不支持 DH 素數超過 1024 位的限制,而您的 SMTP 服務器可能需要這種限制。 以下是相關的錯誤條目:

此限制/限制已在 Java 8 中刪除(請參閱發行說明)。

請注意,正如已經指出的那樣,禁用 STARTTLS 的“修復”並不是真正的修復:這意味着您的密碼將以純文本形式發送,而且這僅適用於允許端口 587 上未加密流量的 SMTP 服務器。

我通過禁用病毒防護解決了這個問題。

經過一整天的戰斗后,這對我有用(使用 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

我在這個錯誤上花了幾個小時,直到我發現 tomcat 使用 TLS 1.1 版,而 smtp 服務器僅支持 TLS 1.2 和 1.3。

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

將 TLS 版本設置為 1.2 解決了我的問題

Q) 無法將套接字轉換為 TLS 和服務器不受信任的問題?

答:我也遇到了同樣的問題,只需在application.properties文件中添加以下代碼即可解決。

  1. 下面是 application.yml 文件的代碼。
    spring:  
      mail:  
        host: smtp.gmail.com  
        port: 587
        username: yourid@gmail.com
        password: yourpassword
        protocol: smtp
    properties:
      mail:
        smtp:
          starttls:
            enable: true
            required: true
          auth: true
          ssl:
            trust: smtp.gmail.com
  1. 下面是 application.properties 文件的代碼。
spring.mail.host=smtp.gmail.com
spring.mail.port=587
spring.mail.username=yourid@gmail.com
spring.mail.password=yourpassword
spring.mail.protocol=smtp

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM