19

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!

Nagarajan S R
  • 1,418
  • 2
  • 19
  • 31

14 Answers14

19

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>
Shashank Agrawal
  • 25,161
  • 11
  • 89
  • 121
Bernard Hauzeur
  • 2,317
  • 1
  • 18
  • 25
  • This worked for me... Thank you so much. I was trying to overcome this issue for last 24 hrs. Finally your post came to my rescue!! :) – Sourabh Bhat Apr 12 '15 at 10:46
  • This worked for me. I was missing the 'mail.smtp.ssl.trust' property and adding it fixed it for me. Thanks! – Russ Jackson May 20 '17 at 21:50
  • I was having the same problem under Glassfish 5.0.1 (not released yet). The mail.smtp.ssl.trust property fixed it for me. – AlanObject Dec 27 '18 at 20:47
17

I resolved this issue by just commenting out 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.

Ojonugwa Jude Ochalifu
  • 26,627
  • 26
  • 120
  • 132
Nagarajan S R
  • 1,418
  • 2
  • 19
  • 31
4

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.

Sam
  • 7,252
  • 16
  • 46
  • 65
  • 1
    please post english answers – msrd0 Nov 10 '14 at 18:52
  • Andre Andrade solved it for me! In my case, this was the most useful answer (and, since it takes 1 minute to test this issue, everyone should try it before wasting hours on other things) – Jake Feb 20 '16 at 18:19
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
msrd0
  • 7,816
  • 9
  • 47
  • 82
Sudarsana Kasireddy
  • 922
  • 1
  • 8
  • 24
4

Maybe this issue related to security and smtp.ssl is not trusted that's why issue occurs.

I resolve this issue just add a property

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

Now it is working fine for me.

Abhishek
  • 37
  • 4
3

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
Erich
  • 2,743
  • 1
  • 24
  • 28
2

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.

Bill Shannon
  • 29,579
  • 6
  • 38
  • 40
2

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

Ehsan Mirsaeedi
  • 6,924
  • 1
  • 41
  • 46
2
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);

These codes should be able to start a ttls communication and get the mail service running.

In addition to this the antivirus creates a firewall that stops the handshake from happening.

  • Specifically in the case of using smtp.office365.com this three lines helped me to get an OK response from the server after several hours of trying. Thank you! Response: 250 2.0.0 OK – Ghaamae Jul 10 '20 at 00:11
1

After fighting all day this works for me (using 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
Greenonline
  • 1,330
  • 8
  • 23
  • 31
1

I spent hours on this error, until I found out that tomcat used TLS version 1.1 while the smtp server supports only TLS 1.2 and 1.3.

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

Setting TLS version to 1.2 solved my problem

dimitris tseggenes
  • 3,031
  • 2
  • 16
  • 23
0

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.

Grodriguez
  • 21,501
  • 10
  • 63
  • 107
0

I resolved this issue by disabling my virus guard.

0

Q) Could not convert socket to TLS & Server is not trusted issue?

Ans: I also faced same issue, just add below code in application.properties file then it will resolve.

  1. Below code for application.yml file.
    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. Below code for application.properties file.
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