Не удалось отправить электронное письмо с помощью SMTP (получение javax.почта.MessagingException: не удалось преобразовать сокет в TLS;)

Я написал следующий код для отправки электронной почты с помощью 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,"
                + "nn 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

может кто-нибудь помочь мне отладить это? Заранее спасибо!

9 ответов


Я решил эту проблему, просто комментируя приведенное ниже свойство

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

и код был выполнен без ошибок или предупреждения или просто удалить эту строку из вышеуказанного исходного кода. Это работает как шарм до даты.


Commenting-out свойство " почта.протокол SMTP.команду STARTTLS.включить " означает, что вы возвращаетесь к незащищенному соединению по умолчанию, которое будет работать только в том случае, если удаленный узел SMTP также принимает незащищенный транспорт на порту 587 (порт для отправки почты против порта 25 для операций конечной доставки или ретрансляции). В моем контексте TLS является обязательным для 587, и любая попытка открыть сеанс без TLS дает ответ на ошибку SMTP-сервера "530 должен сначала выдать команду STARTTLS". Затем настройка "почта.протокол SMTP.команду STARTTLS.enable" to "true" alone по-прежнему дает ту же ошибку "не удалось преобразовать сокет в TLS", но теперь с подсказкой: "сервер не доверен". Действительно, у вас должно быть либо хранилище ключей, определенное в свойствах запуска JVM, которое будет содержать цепочку сертификатов, заканчивающуюся на доверенный корневой сертификат, либо принудительное доверие с этим дополнительным свойством:"почта.протокол SMTP.использование SSL.доверие " задайте имя удаленного хоста.

настройка всего материала в весенней поддержке javamail например (который вы можете легко сопоставить с обычным API javamail) требует всего следующего:

<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, используемая вашим сервером, несовместима с реализацией SSL в версии JDK, которую вы используете. Файл SSLNOTES.txt (также входит в комплект загрузки JavaMail) имеет некоторые советы по отладке. Возможно, Вам понадобится эксперт JDK SSL, чтобы разобраться в этом.


Если вы не хотите использовать SSL, и вы используете smtp вместо smtps попробуйте эти настройки

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

У меня была эта проблема. причина заключалась в том, что наш администратор заблокировал протоколы TLS и SSL.


трассировка стека показывает, что фактическая причина проблемы такова:

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 не является реальным исправлением: это означает, что ваш пароль будет отправлен как обычный текст, плюс это будет работать только для SMTP-серверов, которые разрешают незашифрованный трафик на порту 587.


Я решил эту проблему, отключив мой virus guard.