Reputation: 4246
I have a java method on a server attempting to connect to the server's SMTP mail server, and I'm getting this error:
stack trace: org.apache.commons.mail.EmailException: Sending the email
to the following server failed : mail.mycompanyname.com:465
After retrieving the full stack trace, I notice the following line, which repeated 3 times/attempts:
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
The server has a certificate installed on Apache Server. However, I use GlassFish as app server for the web app (at client) that accesses the java method, and GlassFish sits behind Apache Server. I haven't adjusted anything on GlassFish for this certificate.
I see some other questions and answers similar such as here, but I don't understand how to implement it:
PKIX path building failed: unable to find valid certification path to requested target
Also, there's this as well, but again I don't know how to use it in my situation, if appropriate:
Unable to find valid certification path to requested target - error even after cert imported
So my question is, what do I need to do, from a Java perspective, to clear this error?
Do I just need to create a properties file, as shown here?:
Which is the default location for keystore/truststore of Java applications?
Or, do I also need to set a TrustStore?
Do I need to set anything on GlassFish?
Hoping someone can help me with the basics here. Thanks in advance for any comments.
UPDATE:
OK, finally figured it out with Hiro2K's excellent help below. All that was missing was to import the certificate used by the Apache Webserver's SMTP mail server into GlassFish. Hiro2k's commands below worked fine, but my trouble was finding the right certificate.
Using WHM, I could see the mail server, which is Exim in my case, referred to host1.mycompany.com, so I naturally went for the certification name host1.mycompany.com.crt, which is self-signed. However, this certificate was expired, so it didn't work. I had to go into the configuration files for Exim to locate its certificate, which was named exim.crt, and import that one into GlassFish. Then it worked.
Note also there are many many cert's on the server, including ones for imap (e.g. imapd.pem) and pop3 (pop3.pem), etc. Very confusing.
Upvotes: 2
Views: 3851
Reputation: 5587
So port 465 is used by SMTP SSL, which means that in order for the client to connect to the server, it must trust the server's certificate. Java and Glassfish have a default truststore which will work for any certificate signed by any of the big Cetificate Authorities (Thawt, Verisign, etc..), and since it's not working as is this leads me to believe that your server is using a self signed SSL certificate.
This isn't a problem, and is fully supported by lots of internal applications that don't want to pay for those certs. The issue is that GlassFish doesn't know about that self signed certificate so you must import it into the default glassfish truststore. You will find it at $GLASFISH_INSTALL_DIR$/domains/domain1/config/cacerts.jks
To import a certificate you can use the keytool that comes with the java.
keytool -importcert -v -noprompt -alias smtp.server.name -file
/path/to/smtp.server.der -keystore
$GLASFISH_INSTALL_DIR$/domains/domain1/config/cacerts.jks -storepass changeit
The only thing you need to be careful of is the format of the certificate. Keytool only supports the binary DER format, and a lot of linux servers use the OpenSSL text format called PEM. It's easy to convert from one to the other using OpenSSL.
openssl x509 -in input.crt -inform PEM –out output.der -outform DER
Upvotes: 3