Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Glassfish, Java email and certificate

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

like image 497
TungstenX Avatar asked Feb 19 '26 20:02

TungstenX


1 Answers

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...

like image 115
TungstenX Avatar answered Feb 21 '26 15:02

TungstenX



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!