Samantha W
Samantha W

Reputation: 11

SSL handshake error while trying to connect to gmail via JavaMail

Trying to fetch mail from gmail via POP3 using the JavaMail library and output it but a SSL handshake error occurs. How do you make the SSL handshake happen?

Any help would be greatly appreciated

code:

import java.util.Properties;
import javax.mail.Folder;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.NoSuchProviderException;
import javax.mail.Session;
import javax.mail.Store;

public class CheckingMails {

public static void check(String host, String storeType, String user,
  String password) 
{
  try {


  Properties properties = new Properties();

  properties.put("mail.pop3.host", host);
  properties.put("mail.pop3.port", "995");
  properties.put("mail.pop3.starttls.enable", "true");
  Session emailSession = Session.getDefaultInstance(properties);


  Store store = emailSession.getStore("pop3s");

  store.connect(host, user, password);


  Folder emailFolder = store.getFolder("INBOX");
  emailFolder.open(Folder.READ_ONLY);


  Message[] messages = emailFolder.getMessages();
  System.out.println("messages.length---" + messages.length);

  for (int i = 0, n = messages.length; i < n; i++) {
     Message message = messages[i];
     System.out.println("---------------------------------");
     System.out.println("Email Number " + (i + 1));
     System.out.println("Subject: " + message.getSubject());
     System.out.println("From: " + message.getFrom()[0]);
     System.out.println("Text: " + message.getContent().toString());

  }

  //close the store and folder objects
  emailFolder.close(false);
  store.close();

  } catch (NoSuchProviderException e) {
     e.printStackTrace();
  } catch (MessagingException e) {
     e.printStackTrace();
  } catch (Exception e) {
     e.printStackTrace();
  }} public static void main(String[] args) {

  String host = "pop.gmail.com";
  String mailStoreType = "pop3";
  String username = "[email protected]";
  String password = "xxx";

  check(host, mailStoreType, username, password);}}

output:

javax.mail.MessagingException: Connect failed;
  nested exception is:
    javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
    at com.sun.mail.pop3.POP3Store.protocolConnect(POP3Store.java:213)
    at javax.mail.Service.connect(Service.java:366)
    at javax.mail.Service.connect(Service.java:246)
    at reademail.CheckingMails.check(CheckingMails.java:30)
    at reademail.CheckingMails.main(CheckingMails.java:70)
Caused by: javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
    at sun.security.ssl.Alerts.getSSLException(Alerts.java:192)
    at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1937)
    at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:302)
    at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:296)
    at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1478)
    at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:212)
    at sun.security.ssl.Handshaker.processLoop(Handshaker.java:979)
    at sun.security.ssl.Handshaker.process_record(Handshaker.java:914)
    at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1050)
    at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1363)
    at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1391)
    at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1375)
    at com.sun.mail.util.SocketFetcher.configureSSLSocket(SocketFetcher.java:598)
    at com.sun.mail.util.SocketFetcher.createSocket(SocketFetcher.java:372)
    at com.sun.mail.util.SocketFetcher.getSocket(SocketFetcher.java:238)
    at com.sun.mail.pop3.Protocol.<init>(Protocol.java:112)
    at com.sun.mail.pop3.POP3Store.getPort(POP3Store.java:265)
    at com.sun.mail.pop3.POP3Store.protocolConnect(POP3Store.java:207)
    ... 4 more
Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
    at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:387)
    at sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:292)
    at sun.security.validator.Validator.validate(Validator.java:260)
    at sun.security.ssl.X509TrustManagerImpl.validate(X509TrustManagerImpl.java:324)
    at sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:229)
    at sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:124)
    at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1460)
    ... 17 more
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
    at sun.security.provider.certpath.SunCertPathBuilder.build(SunCertPathBuilder.java:145)
    at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:131)
    at java.security.cert.CertPathBuilder.build(CertPathBuilder.java:280)
    at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:382)
    ... 23 more

Upvotes: 1

Views: 2746

Answers (2)

Lanthar Dalton
Lanthar Dalton

Reputation: 11

For others struggling with similar issues... If this gives write:errno=104, then TLS 1.0 is disabled, and you need to force the mail connection protocols to skip it. Changing this in java.security tls.disabledAlgorithms or other properties will not make the mail.pop3 protocol skip TLS1.0, it will just skip all TLS and give up as no protocols supported. You can check others like -tls1_1, -ssl3, or disable like -no_tls1_1, etc.

openssl s_client -connect somemailserver.domain.com:995 -tls1

Instead, add this additional property that specifies which protocols your target server does allow.

props.setProperty("mail.pop3.ssl.protocols","TLSv1.2");

Our stack was similar, but like this:

javax.mail.MessagingException: Connect failed; 
  nested exception is: 
        javax.net.ssl.SSLException: Connection reset 
        at com.sun.mail.pop3.POP3Store.protocolConnect(POP3Store.java:210) 
        at javax.mail.Service.connect(Service.java:295) 
        at javax.mail.Service.connect(Service.java:176) 
        at javax.mail.Service.connect(Service.java:125) 
        at ABC.Classname.Classname.vAccess(Classname.java:163) 
        at ABC.Classname.Classname.<init>(Classname.java:63) 
        at ABC.Classname.Classname.main(Classname.java:156) 
Caused by: javax.net.ssl.SSLException: Connection reset 
        at sun.security.ssl.Alert.createSSLException(Alert.java:127) 
        at sun.security.ssl.TransportContext.fatal(TransportContext.java:327) 
        at sun.security.ssl.TransportContext.fatal(TransportContext.java:270) 
        at sun.security.ssl.TransportContext.fatal(TransportContext.java:265) 
        at sun.security.ssl.SSLTransport.decode(SSLTransport.java:141) 
        at sun.security.ssl.SSLSocketImpl.decode(SSLSocketImpl.java:1198) 
        at sun.security.ssl.SSLSocketImpl.readHandshakeRecord(SSLSocketImpl.java:1107) 
        at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:400) 
        at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:372) 
        at com.sun.mail.util.SocketFetcher.configureSSLSocket(SocketFetcher.java:507) 
        at com.sun.mail.util.SocketFetcher.getSocket(SocketFetcher.java:238) 
        at com.sun.mail.pop3.Protocol.<init>(Protocol.java:107) 
        at com.sun.mail.pop3.POP3Store.getPort(POP3Store.java:261) 
        at com.sun.mail.pop3.POP3Store.protocolConnect(POP3Store.java:206) 
        ... 6 more 
        Suppressed: java.net.SocketException: Broken pipe (Write failed) 
                at java.net.SocketOutputStream.socketWrite0(Native Method) 
                at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:111) 
                at java.net.SocketOutputStream.write(SocketOutputStream.java:155) 
                at sun.security.ssl.SSLSocketOutputRecord.encodeAlert(SSLSocketOutputRecord.java:81) 
                at sun.security.ssl.TransportContext.fatal(TransportContext.java:358)

answer found courtesy of: How to force JavaMailSenderImpl to use TLS1.2?

Upvotes: 0

sdsc81
sdsc81

Reputation: 570

If anyone stumble with this question later, like I did, the solution is:

properties.put("mail.pop3.host", host);
properties.put("mail.pop3.port", "995");
properties.put("mail.pop3.starttls.enable", "true");
props.put( "mail.pop3s.ssl.trust", host); // add this line
Session emailSession = Session.getDefaultInstance(properties);

You could add the fourth line to trust the host you're trying to connect. Do not ever substitute the host parameter for "*".

Other way to get around of this problem is adding the ssl certificate to your java cacerts

To do that, you have to:

  1. Using Firefox, export the ".crt" file from the page (ex. gmail.com), by clicking in the green padlock at the adrress bar.
  2. In Windows, open CMD with administrator privileges.
  3. Execute the following (ex, for google gmail certificate)

    keytool -import -trustcacerts -alias googlemail -file mailgooglecom.crt -noprompt -keystore cacerts

Done.

Upvotes: 1

Related Questions