2012-10-05 23 views
12

Napisałem poniższy kod do wysyłania wiadomości e-mail przy użyciu interfejsu API javamail za pośrednictwem protokołu SMTP jako protokołu TLS, ponieważ protokół SSL nie jest obsługiwany, ale zakończyłem z następującym wyjątkiem. Zobacz mój kod poniżej. Użyłem trybu debugowania i poniżej kodu można znaleźć wyjątek.Nie można wysłać wiadomości e-mail za pomocą protokołu SMTP (pobieranie wyjątku javax.mail.MessagingException: nie można przekonwertować gniazda na protokół TLS;)

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 = "[email protected]"; 
     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("[email protected]")); 
      message.setRecipients(Message.RecipientType.TO, 
      InternetAddress.parse("[email protected]")); 
      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); 
     } 
    } 
} 

ślad Wyjątek

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 

Może ktoś mi pomóc debugowania to? Z góry dziękuję!

Odpowiedz

9

I rozwiązany ten problem, po prostu komentując właściwość poniżej

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

a kod został wykonany bez błędów lub ostrzeżenia lub po prostu usunąć ten wiersz z powyższym kodzie źródłowym. Działa jak urok do daty.

+0

Innymi słowy ustaw tę właściwość jako mail.smtp.starttls.enable = false –

+12

Innymi słowy, twoje hasło przechodzi przez Internet jako zwykły tekst. Bardzo zła rada. – dschulz

+0

Tak, to nie jest zaszyfrowane. Prawdopodobnie wyśle ​​e-maile jako wiadomości-śmieci. – santafebound

2

Wygląda na to, że implementacja protokołu SSL używana przez serwer nie jest zgodna z implementacją protokołu SSL w wersji używanego pakietu JDK. Plik SSLNOTES.txt (dostępny również w pakiecie pobierania JavaMail) ma kilka wskazówek dotyczących debugowania. Aby to rozwiązać, możesz potrzebować eksperta JDK SSL.

+0

Dzięki za odpowiedź Bill. –

1

Jeśli nie chcesz korzystać z protokołu SSL, a używasz SMTP zamiast SMTPS spróbować te ustawienia

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

miałem tego problemu. powodem był nasz administrator zablokował protokoły TLS i SSL.

3

Upewnij się, że oprogramowanie antywirusowe nie blokuje aplikacji. W moim przypadku Avast blokował mi wysyłanie wiadomości e-mail w aplikacji Java SE.

+1

proszę pisać po angielsku odpowiedzi – msrd0

+0

Andre Andrade rozwiązał to dla mnie! W moim przypadku była to najbardziej przydatna odpowiedź (a ponieważ zajmuje to 1 minutę, aby przetestować ten problem, każdy powinien spróbować, zanim zmarnuje godziny na inne rzeczy) – Jake

8

Komentując-out właściwość „mail.smtp.starttls.enable” oznacza, że ​​spadnie z powrotem na domyślny i niezabezpieczonego połączenia, które będzie działać tylko wtedy, gdy zdalny host SMTP akceptuje także transport niezabezpieczonego na porcie 587 (portu dla poczty przesyłanie w porównaniu z portem 25 dla operacji dostarczania końcowego lub przekazywania). W moim kontekście protokół TLS jest obowiązkowy w wersji 587, a każda próba otwarcia sesji bez TLS skutkuje odpowiedzią na błąd serwera SMTP "530 Najpierw należy wydać komendę STARTTLS". Następnie ustawienie opcji "mail.smtp.starttls.enable" na "true" nadal powoduje pojawienie się tego samego błędu "Nie można przekonwertować gniazda na TLS", ale teraz z podpowiedzią "Serwer nie jest zaufany". Rzeczywiście, musisz mieć albo magazyn kluczy zdefiniowany we właściwościach startowych JVM, który zawiera łańcuch certyfikatów kończący się zaufanym certyfikatem głównym, albo wymusić zaufanie tą dodatkową właściwością: "mail.smtp.ssl.trust" ustaw na zdalnym nazwa hosta.

Konfiguracja cały materiał na poparcie Wiosny JavaMail na przykład (który można łatwo mapować do zwykłego JavaMail API) wymaga wszystkie następujące:

<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> 
+0

To zadziałało dla mnie ... Dziękuję bardzo. Próbowałem przezwyciężyć ten problem przez ostatnie 24 godziny. W końcu twój post przyszedł mi na ratunek !! :) –

+0

To zadziałało dla mnie. Brakowało mi właściwości "mail.smtp.ssl.trust" i dodałem ją dla mnie. Dzięki! –

0

Ślad stosu ujawnia, że ​​rzeczywistą przyczyną problemu jest to:

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

używasz do ograniczenia starszych wersji Java, która nie obsługuje DH primes dłuższe niż 1024 bitów, które swoimi Serwer SMTP prawdopodobnie wymagał. Oto odpowiednie wpisy o błędach:

To ograniczenie/ograniczenie zostało usunięte w Java 8 (patrz the release notes).

Należy zauważyć, że jak już wspomniano, "naprawa" wyłączenia STARTTLS nie jest prawdziwą poprawką: Oznacza to, że twoje hasło zostanie wysłane jako zwykły tekst, a to zadziała tylko dla serwerów SMTP, które zezwalają na niezaszyfrowany ruch port 587.

Powiązane problemy