Search code examples
javaemailsmtpjakarta-mail

JavaMail Could not connect to SMTP host SSL 465: handshake_failure


after my web-server provider disabled old security protocol(versions) and cipher suites, I am no longer able to connect to the smtpserver. this was my original configuration, but no encrypted communication (SSL, TLS) is longer possible.

What could be the source of this problem?

DEBUG: setDebug: JavaMail version 1.5.5 (JDK 1.7)

enter image description here

when I try the same without SSL (commented in code), it works fine, so there has to be a problem with the webserver. Funny fact: Outlook works just fine (with same credentials)!

public static void main(final String[] args) throws Exception {
    System.setProperty("javax.net.debug", "all");

    final Properties props = new Properties();

    // use SSL (worked before ssl-update on mailserver, where old security protocols were disabled)
    props.put("mail.smtp.ssl.socketFactory", "javax.net.ssl.SSLSocketFactory");
    props.put("mail.smtp.socketFactory.port", "465");
    props.put("mail.smtp.socketFactory.fallback", "false");
    props.put("mail.smtp.host", "alfa3022.alfahosting-server.de");
    props.put("mail.smtp.port", "465");
    props.put("mail.smtp.ssl.enable", "true");

    // no ssl (works fine!):
    // props.put("mail.debug", "true");
    // props.put("mail.smtp.host", SMTP_HOST_NAME);
    // props.put("mail.smtp.auth", "true");
    // props.put("mail.smtp.port", 587);

    final Session session = Session.getInstance(props, new javax.mail.Authenticator() {
        @Override
        protected PasswordAuthentication getPasswordAuthentication() {
            return new PasswordAuthentication(getEmailUsername(), getEmailPassword());
        }
    });

    session.setDebug(true);
    final Message msg = new MimeMessage(session);
    final InternetAddress addressFrom = new InternetAddress("[email protected]");
    msg.setFrom(addressFrom);

    // [...] create email object and add contents to msg
    msg.setRecipient(Message.RecipientType.BCC, new InternetAddress("[email protected]"));
    Transport.send(msg);

}

When I execute a Handshake-Simulation of the email-server it tells me that java is not working?? https://www.ssllabs.com/ssltest/analyze.html?d=alfa3022.alfahosting-server.de

enter image description here

What could be the difference or what am I failed to see?


Solution

  • What could be the source of this problem?

    Ans:

    SSLHandshakeException is a subclass of the IOException, so you do not need to catch is explicitly. Most developers will not need an explicit catch, but it may help you more easily diagnose the cause of any IOException.

    When applying the -Djavax.net.debug=all property, the failure associated with this SSLHandshakeException would appear immediately after algorithm negotiation in the logs.

    So, System.setProperty("javax.net.debug", "all"); is making error in your code.

    What is the root cause of occuring SSLHandshakeException? How to prevent it?

    Ans:

    The most likely cause for SSLHandshakeException is algorithm support. The JDK provides a separate package called JCE Unlimited Strength, designed to add stronger algorithm support than what’s available by default. Qualys SSL Labs provides a different server SSL test that will enumerate which algorithms a server supports.

    Adding stronger algorithms: JCE Unlimited Strength

    In a high security environment, one way of strengthening algorithms in the JDK is through the JCE Unlimited Strength policy files. In this particular case, replacing those policy files within JDK 7 allows it to use the stronger variants of existing algorithms and connect successfully.

    JCE Unlimited Strength downloads: JDK 8, JDK 7, or JDK 6.

    Resource Link:

    1. Diagnosing TLS, SSL, and HTTPS

    You can try with it

    you need to set certificate, to access the SMTP port.

    System.setProperty("javax.net.ssl.trustStore","key");
    System.setProperty("javax.net.ssl.trustStorePassword","password");
    

    for generating a KeyStore and TrustStore, follow the tutorial


    From Marvin Pinto's answer,

    The javax.net.ssl.SSLHandshakeException exception is usually thrown when the server you're trying to connect to does not have a valid certificate from an authorized CA.

    Put simply, the server you're attempting to connect to is most likely using a self-signed certificate and you have to accomodate for that in your Java code. This involves creating a custom KeyStore, etc. See this Stack Overflow answer for full implementation details.

    If you want to clarify your conception completely, then read the tutorial which is for use of SSL with JavaMail.

    Related Link:

    1. JAVAMAIL API FAQ
    2. Received fatal alert: handshake_failure through SSLHandshakeException