I've search far and long and can't find the answer.
I'm using Glassfish and want to send an email via our smtp server.
I've obtained the server's certificate:
openssl s_client -connect mail.example.com:587 -starttls smtp > our.cer
I've cleaned up the cer file to only contain the certificate data.
I've import it everywhere:
keytool -import -alias mail.example.com -file our.cer -keystore c:\Progra~1\Java\jre7\lib\security\cacerts
keytool -import -alias mail.example.com -file our.cer -keystore c:\Progra~1\Java\JDK17~1.0_4\jre\lib\security\cacerts
keytool -import -alias mail.example.com -file our.cer -keystore c:\PROGRA~1\GLASSF~1.0\GLASSF~1\domains\domain1\config\cacerts.jks
But I get the following error:
javax.mail.MessagingException: Could not convert socket to TLS;
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
...
Caused by...
...
Caused by...
...
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
My code snippet:
...
Properties properties = System.getProperties();
properties.put("mail.smtp.starttls.enable", "true");
properties.put("mail.smtp.host", "mail.example.com");
properties.put("mail.smtp.user", "[email protected]");
properties.put("mail.smtp.password", "some.password");
properties.put("mail.smtp.port", "587"));
properties.put("mail.smtp.auth", "true"));
properties.put("mail.smtp.from", "[email protected]"));
properties.put("mail.transport", "smtp"));
...
Authenticator mailAuthenticator = new Authenticator()
{
@Override
protected PasswordAuthentication getPasswordAuthentication()
{
return new PasswordAuthentication(properties.getProperty("mail.smtp.user"),
properties.getProperty("mail.smtp.password"));
}
};
try
{
// Get the default Session object.
Session session = Session.getDefaultInstance(properties, mailAuthenticator);
MimeMessage mimeMessage = new MimeMessage(session);
mimeMessage.setSubject("Hallo world!");
mimeMessage.setFrom(new InternetAddress(properties.getProperty("mail.smtp.from")));
mimeMessage.setRecipient(Message.RecipientType.TO, new InternetAddress("[email protected]"));
mimeMessage.setText("Some text message...");
Transport transport = session.getTransport(properties.getProperty("mail.transport"));//"smtp"
int port = Integer.parseInt(properties.getProperty("mail.smtp.port"));//587
transport.connect(properties.getProperty("mail.smtp.host"),//"mail.example.com"
port,
properties.getProperty("mail.smtp.user"),//"[email protected]"
properties.getProperty("mail.smtp.password"));//Clear text password
transport.sendMessage(mimeMessage, mimeMessage.getAllRecipients());
LOG.info("...done sending email");
}
catch (AddressException e)
{
LOG.log(Level.SEVERE, "Error while sending email", e);
}
catch (MessagingException e)
{
LOG.log(Level.SEVERE, "Error while sending email", e);
}
catch (Exception e)
{
LOG.log(Level.SEVERE, "Error while sending email", e);
}
I've also tried Mkyong's suggestion to run InstallCert (source) against the mail server but I get:
javax.net.ssl.SSLException: Unrecognized SSL message, plaintext connection?
UPDATE 1
I've loaded the certificate in the following additional places:
keytool -import -alias mail.example.com -file our.cer -keystore c:\PROGRA~1\GLASSF~1.0\GLASSF~1\domains\domain1\config\keystore.jks
keytool -import -alias mail.example.com -file our.cer -keystore c:\GLASSFISH\config\keystore.jks
keytool -import -alias mail.example.com -file our.cer -keystore c:\GLASSFISH\config\cacerts.jks
I've also set these properties:
System.setProperty("javax.net.ssl.keyStore", "c:\\GLASSFISH\\config\\keystore.jks");
System.setProperty("javax.net.ssl.keyStorePassword", "changeit");
System.setProperty("javax.net.ssl.trustStore", "c:\\GLASSFISH\\config\\cacerts.jks");
System.setProperty("javax.net.ssl.trustStorePassword", "changeit");
I've also switched on debugging for ssl (Glassfish console, server, properties) javax.net.debug=ssl
.
It works in a standalone test application (Java SE) but not in Glassfish.
UPDATE 2
Using the javax.net.debug=ssl
and examining the log out put I can see that even-though I've loaded the certificate "everywhere" or if I point Glassfish to the java keystore, Glassfish is missing this certificate. The stand alone test app has it:
adding as trusted cert:
Subject: CN=avast! Web/Mail Shield Root, O=avast! Web/Mail Shield, OU=generated by avast! antivirus for SSL/TLS scanning
Issuer: CN=avast! Web/Mail Shield Root, O=avast! Web/Mail Shield, OU=generated by avast! antivirus for SSL/TLS scanning
Algorithm: RSA; Serial number: 0x14128fa09c50b64ba6d5c99875872673
Valid from Wed Feb 04 08:56:17 CAT 2015 until Sat Feb 01 08:56:17 CAT 2025
(Note the Serial number...)
It seems to be the certificate missing from Glassfish; because the stand alone test app finds it:
Found trusted certificate:
[
[
Version: V3
Subject: CN=avast! Web/Mail Shield Root, O=avast! Web/Mail Shield, OU=generated by avast! antivirus for SSL/TLS scanning
Signature Algorithm: SHA1withRSA, OID = 1.2.840.113549.1.1.5
Key: Sun RSA public key, 2048 bits
modulus: ---8<---
public exponent: 65537
Validity: [From: Wed Feb 04 08:56:17 CAT 2015, : Sat Feb 01 08:56:17 CAT 2025]
Issuer: CN=avast! Web/Mail Shield Root, O=avast! Web/Mail Shield, OU=generated by avast! antivirus for SSL/TLS scanning
SerialNumber: [ 14128fa0 9c50b64b a6d5c998 75872673]
...
(Look at the SerialNumber...)
Please help
Okey dokey! I've figured it out. Here is how my 5 day journey ended today, in brief...
First I dumped all the certificates from the Java keystore, as it was working using that keystore:
keytool -list -v -keystore c:\Progra~1\Java\jre7\lib\security\cacerts > allJavaCerts.txt
Then I dumped all the certificates from the Glassfish keystore, to see if the certificate was correctly imported:
keytool -list -v -keystore c:\WORKSP~1\GLASS\config\cacerts.jks > allGFCerts.txt
In the Java keystore list I notice that the mail server's certificate was issued by Avast... weird, right?
Issuer: CN=avast! Web/Mail Shield Root, O=avast! Web/Mail Shield, OU=generated by avast! antivirus for SSL/TLS scanning
And in the Java keystore list there is a certificate for Alias name: avastsslscannerroot
but not in the Glassfish keystore list - Thank you Beyond Compare v3
So I exported the avastsslscannerroot certificate from the Java keystore and import it into the Glassfish keystore:
keytool -export -keystore c:\Progra~1\Java\jre7\lib\security\cacerts -alias avastsslscannerroot -file avastsslscannerroot.cer
keytool -import -alias avastsslscannerroot -file avastsslscannerroot.cer -keystore c:\WORKSP~1\GLASS\config\keystore.jks
keytool -import -alias avastsslscannerroot -file avastsslscannerroot.cer -keystore c:\WORKSP~1\GLASS\config\cacerts.jks
And now it works...
And then it didn't on the server... After some search I came across this:
mail.smtp.ssl.trust="*"
Property and it works for us as we are connection from our web server to our mail server...