Search code examples
jsfjakarta-mailtruststore

JavaMail problems after using Key Store


I'm having a weird problem with a JSF application I'm currently working on. It seems like there are two parts of my programm which are colliding.

There are two parts:

  • the "banking" functionality
  • the mail functionality

The relevant part of the banking functionality (It's a fake bank just for this exercise):

String path = FacesContext.getCurrentInstance().getExternalContext()                .getRealPath("/") + "/WEB-INF/sec/certs.jks";

ErrorHandler.trace(path);

System.setProperty("javax.net.ssl.trustStore", path);

Here it's setting the Trust Store with the certificate for the bank server.

The mail part looks like this:

Properties props = new Properties();
props.put("mail.smtp.auth", this.smtpServer.isAuthenticated());
props.put("mail.smtp.starttls.enable", this.smtpServer.isTls());
props.put("mail.smtp.host", this.smtpServer.getHostaddr());
props.put("mail.smtp.port", this.smtpServer.getPort());
props.put("mail.smtps.auth", "true");
props.put("mail.smtp.debug", "true");

final String username = this.smtpServer.getUsername();
final String password = this.smtpServer.getPassword();

Session session = Session.getDefaultInstance(props,
        new javax.mail.Authenticator() {
            @Override
            protected PasswordAuthentication getPasswordAuthentication() {
                return new PasswordAuthentication(username, password);
            }
        });

session.setDebug(true);

One way to reproduce the problem:

The problem I'm facing is that if I start the application and, for example, use the "change mail" functionality I'll get my notification mail immediately. No problem there. Then I'll try to buy a product thus triggering the bank functionality.

That's where the problem shows up:

Communication Error: javax.ws.rs.WebApplicationException: javax.xml.bind.MarshalException
 - with linked exception:
[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]

Another way to reproduce the problem:

Now let's say I restart my application and try to order something, this time it'll work but the mail functionality is broken with this error message:

DEBUG: setDebug: JavaMail version 1.4.7
DEBUG: getProvider() returning javax.mail.Provider[TRANSPORT,smtps,com.sun.mail.smtp.SMTPSSLTransport,Oracle]
DEBUG SMTP: useEhlo true, useAuth true
DEBUG SMTP: trying to connect to host "smtp.gmail.com", port 465, isSSL true
TRACE Error Could not connect to SMTP host: smtp.gmail.com, port: 465

Bottom line:

If I trigger bank and then mail -> mail not working If I trigger mail and then bank -> bank not working

Anyone who could find a problem there?

Thank you!


Solution

  • Your "banking functionality" is changing the trust store. That new trust store needs to have the certificates necessary to validate the SSL connection with your mail server. You can initialize your trust store with all the CA certificates from the JDK default trust store, or you can add just the specific certificate for your mail server - see the InstallCert program. Finally, you can configure JavaMail to use a separate trust store, or change your banking functionality to use a trust store explicitly rather than overriding the default trust store; those are probably more complicated.