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

匿名 (未验证) 提交于 2019-12-03 02:24:01

问题:

I have written the following code for sending email using javamail API through SMTP as TLS as SSL is not supported but I ended up with the following exception. Please see my code below. I have used debugging mode and below the code you can find the exception as well.

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);         }     } } 

Exception trace

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 

Can anyone help me debug this? Thanks in advance!

回答1:

I resolved this issue by just commenting the below property

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

and the code got executed with no errors or warning or simply delete this line from the above source code. It is working like a charm till date.



回答2:

Commenting-out the property "mail.smtp.starttls.enable" means you fall back to a default and unsecured connection, which would work only if the remote SMTP host also accepts unsecured transport on port 587 (the port for mail submission versus port 25 for end-delivery or relay operations). In my context, TLS is compulsory on 587 and any attempt to open a session without TLS yield the SMTP server error response "530 Must issue a STARTTLS command first". Then setting "mail.smtp.starttls.enable" to "true" alone still yield the same error "Could not convert socket to TLS" but now with a clue: "Server is not trusted". Indeed, you must have either a keystore defined in the JVM start properties that would contain a certificate chain ending onto a trusted root certificate, either enforce trust with this extra property: "mail.smtp.ssl.trust" set to the remote host name.

Configuring the whole stuff in Spring support for javamail for instance (which you can easily map to plain javamail API) requires all of the following:

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


回答3:

Make sure your antivirus software is not blocking the application. In my case Avast was blocking me from sending e-mails in a Java SE application.



回答4:

I had a same issue with smtp.gmail.com and fixed with the following steps

  1. changed my code as per berhauz comments
  2. changed in Gmail settings from this link: https://www.google.com/settings/security/lesssecureapps


回答5:

It looks like the SSL implementation used by your server is not compatible with the SSL implementation in the version of the JDK you're using. The file SSLNOTES.txt (also included in the JavaMail download bundle) has some debugging tips. You might need a JDK SSL expert to sort this out.



回答6:

If you don't want to use SSL, and you're using smtp instead of smtps try these settings

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


回答7:

I had this problem. the reason was our administrator had blocked TLS and SSL protocols.



回答8:

The stack trace reveals that the actual cause of the problem is this:

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

You are running into a limitation of older versions of Java that did not support DH primes longer than 1024 bits, which your SMTP server was probably requiring. Here are the relevant bug entries:

This restriction/limitation was removed in Java 8 (see the release notes).

Note that as has been pointed out already, your "fix" of disabling STARTTLS is not a real fix: It means your password will be sent as plain text, plus this will only work for SMTP servers that allow unencrypted traffic on port 587.



标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!