Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using Javamail and Greenmail for SMTPS/SSL

I'm trying to write a test that will uses JavaMail SMTP or SMTPS to send a message via SSL and authentication to a Greenmail server that I'm running.

I've written a quick little sub that should do exactly what I'm wanting:

import java.util.Properties;

import javax.mail.Session;
import javax.mail.Transport;

import com.icegreen.greenmail.user.GreenMailUser;
import com.icegreen.greenmail.util.GreenMail;

public class MailTest {
    public static void main(String[] args) throws Exception {
        GreenMail greenmail = new GreenMail();
        try {
            greenmail.start();

            String email = "foo@bar";
            String userid = "user";
            String password = "pa$$word";
            GreenMailUser setUser = greenmail.setUser(email, userid, password);
            setUser.create();
            GreenMailUser user = greenmail.getManagers().getUserManager().getUser(userid);
            System.out.println("User created:" + user.getEmail() + ":" + user.getLogin() + ":" + user.getPassword());

            int portSmtps = greenmail.getSmtps().getPort();
            System.out.println("Smtps started on port:" + portSmtps);

            Properties props = new Properties();
            props.put("mail.smtp.starttls.enable", "true");
            props.put("mail.smtp.auth", "true");
            props.put("mail.smtp.host", "localhost");
            props.put("mail.smtp.socketFactory.port", portSmtps);
            props.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
            props.put("mail.smtp.socketFactory.fallback", "false");
            Session session = Session.getInstance(props);
            Transport transport = session.getTransport("smtp");
            transport.connect("localhost", portSmtps, userid, password);
            System.out.println("Transport is connected: " + transport.isConnected());
        } finally {
            greenmail.stop();
        }
    }
}

My problem is that I get several exceptions:

Exception in thread "Thread-7" java.lang.RuntimeException: javax.net.ssl.SSLException: Connection has been shutdown: javax.net.ssl.SSLHandshakeException: Received fatal alert: certificate_unknown
    at com.icegreen.greenmail.smtp.SmtpHandler.run(Unknown Source)
Caused by: javax.net.ssl.SSLException: Connection has been shutdown: javax.net.ssl.SSLHandshakeException: Received fatal alert: certificate_unknown
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.checkEOF(SSLSocketImpl.java:1293)
    at com.sun.net.ssl.internal.ssl.AppInputStream.read(AppInputStream.java:65)
    at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:264)
    at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:306)
    at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:158)
    at java.io.InputStreamReader.read(InputStreamReader.java:167)
    at java.io.BufferedReader.fill(BufferedReader.java:136)
    at java.io.BufferedReader.readLine(BufferedReader.java:299)
    at java.io.BufferedReader.readLine(BufferedReader.java:362)
    at com.icegreen.greenmail.smtp.SmtpConnection.readLine(Unknown Source)
    at com.icegreen.greenmail.smtp.SmtpHandler.handleCommand(Unknown Source)
    ... 1 more
Caused by: javax.net.ssl.SSLHandshakeException: Received fatal alert: certificate_unknown
    at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Alerts.java:174)
    at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Alerts.java:136)
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.recvAlert(SSLSocketImpl.java:1720)
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:954)
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1138)
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.writeRecord(SSLSocketImpl.java:632)
    at com.sun.net.ssl.internal.ssl.AppOutputStream.write(AppOutputStream.java:59)
    at sun.nio.cs.StreamEncoder.writeBytes(StreamEncoder.java:202)
    at sun.nio.cs.StreamEncoder.implFlushBuffer(StreamEncoder.java:272)
    at sun.nio.cs.StreamEncoder.implFlush(StreamEncoder.java:276)
    at sun.nio.cs.StreamEncoder.flush(StreamEncoder.java:122)
    at java.io.OutputStreamWriter.flush(OutputStreamWriter.java:212)
    at java.io.BufferedWriter.flush(BufferedWriter.java:236)
    at java.io.PrintWriter.flush(PrintWriter.java:276)
    at com.icegreen.greenmail.util.InternetPrintWriter.println(Unknown Source)
    at com.icegreen.greenmail.util.InternetPrintWriter.println(Unknown Source)
    at com.icegreen.greenmail.smtp.SmtpConnection.println(Unknown Source)
    at com.icegreen.greenmail.smtp.SmtpHandler.sendGreetings(Unknown Source)
    ... 1 more
Exception in thread "main" javax.mail.MessagingException: Could not connect to SMTP host: localhost, port: 3465;
  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.smtp.SMTPTransport.openServer(SMTPTransport.java:1934)
    at com.sun.mail.smtp.SMTPTransport.protocolConnect(SMTPTransport.java:638)
    at javax.mail.Service.connect(Service.java:295)
    at MailTest.main(MailTest.java:35)
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 com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Alerts.java:174)
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1649)
    at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Handshaker.java:241)
    at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Handshaker.java:235)
    at com.sun.net.ssl.internal.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1206)
    at com.sun.net.ssl.internal.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:136)
    at com.sun.net.ssl.internal.ssl.Handshaker.processLoop(Handshaker.java:593)
    at com.sun.net.ssl.internal.ssl.Handshaker.process_record(Handshaker.java:529)
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:893)
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1138)
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1165)
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1149)
    at com.sun.mail.util.SocketFetcher.configureSSLSocket(SocketFetcher.java:507)
    at com.sun.mail.util.SocketFetcher.getSocket(SocketFetcher.java:238)
    at com.sun.mail.smtp.SMTPTransport.openServer(SMTPTransport.java:1900)
    ... 3 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:323)
    at sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:217)
    at sun.security.validator.Validator.validate(Validator.java:218)
    at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.validate(X509TrustManagerImpl.java:126)
    at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:209)
    at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:249)
    at com.sun.net.ssl.internal.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1185)
    ... 13 more
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
    at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:174)
    at java.security.cert.CertPathBuilder.build(CertPathBuilder.java:238)
    at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:318)
    ... 19 more

I've tried looking at a few other answers here, but I must be missing something:

  • JavaMail to send secure email through vps - SSLHandshake Exception, PKIX path building failed, etc. - Can't send mail
  • PKIX path building failed: unable to find valid certification path to requested target
  • Using JavaMail with TLS

Sorry for the long post and thanks in advance for any advice.

like image 860
GreenKiwi Avatar asked Jul 01 '11 20:07

GreenKiwi


2 Answers

You should start your GreenMail server like this:

Security.setProperty("ssl.SocketFactory.provider", DummySSLSocketFactory.class.getName());
GreenMail mailServer = new GreenMail(ServerSetupTest.SMTPS);
mailServer.start();
like image 100
anagornyi Avatar answered Oct 04 '22 15:10

anagornyi


The SSL certificate used on the Greenmail server must be signed by a "known" certificate authority, OR you must add the CA certificate that was used to sign the cert to Java's keystore. There's no way to tell Java to not validate the certificate chain up to a known CA.

like image 34
Jim Garrison Avatar answered Oct 01 '22 15:10

Jim Garrison