On my application, the org.springframework.mail.javamail.JavaMailSenderImpl is not configured to send SSL emails (The default value as per https://javamail.java.net/nonav/docs/api/com/sun/mail/smtp/package-summary.html is false).
That being said, I have two types of emails being sent through this JavaMail API, one is prepared a multipart/relative and the other is plain text. Both the emails are successfully sent when deployed on our dev server. But the multipart email fails to be sent on another dev server (A stage server).
The application is deployed on Tomcat6 and runs on JDK 1.6.
I debugged all the private keys and certificates available in the keystore configured for the tomcat server (The web application runs on HTTPS). This looks good (I explored the option of replacing the keystore too).
Now when I send the email, The mail that fails has the below debug from java mail API
DEBUG SMTP: useEhlo true, useAuth false
DEBUG SMTP: trying to connect to host "8570-5cb30915t8.tb.bbossyyy.com", port 25, isSSL false
220 8570-5CB30915T8.TB.bbossyyy.com ESMTP SubEthaSMTP null
DEBUG SMTP: connected to host "8570-5cb30915t8.tb.bbossyyy.com", port: 25
EHLO hqarchs01
250-8570-5CB30915T8.TB.bbossyyy.com
250-8BITMIME
250-AUTH LOGIN
250 Ok
DEBUG SMTP: Found extension "8BITMIME", arg ""
DEBUG SMTP: Found extension "AUTH", arg "LOGIN"
DEBUG SMTP: Found extension "Ok", arg ""
DEBUG SMTP: use8bit false
MAIL FROM:<dfn@bbossyyy.com>
250 Ok
DEBUG SMTP: sendPartial set
RCPT TO:<rp@bbossyyy.com>
250 Ok
RCPT TO:<rp@bbossyyy.com>
250 Ok
RCPT TO:<archo@bbossyyy.com>
250 Ok
DEBUG SMTP: Verified Addresses
DEBUG SMTP: RP <rp@bbossyyy.com>
DEBUG SMTP: RP <rp@bbossyyy.com>
DEBUG SMTP: archo@bbossyyy.com
DATA
354 End data with <CR><LF>.<CR><LF>
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(Unknown Source)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.fatal(Unknown Source)
Now for a successful send, below is are the debug statements
DEBUG: getProvider() returning javax.mail.Provider[TRANSPORT,smtp,com.sun.mail.smtp.SMTPTransport,Sun Microsystems, Inc]
DEBUG SMTP: useEhlo true, useAuth false
DEBUG SMTP: trying to connect to host "8570-5cb30915t8.tb.bbossyyy.com", port 25, isSSL false
220 8570-5CB30915T8.TB.bbossyyy.com ESMTP SubEthaSMTP null
DEBUG SMTP: connected to host "8570-5cb30915t8.tb.bbossyyy.com", port: 25
EHLO hqarchs01
250-8570-5CB30915T8.TB.bbossyyy.com
250-8BITMIME
250-AUTH LOGIN
250 Ok
DEBUG SMTP: Found extension "8BITMIME", arg ""
DEBUG SMTP: Found extension "AUTH", arg "LOGIN"
DEBUG SMTP: Found extension "Ok", arg ""
DEBUG SMTP: use8bit false
MAIL FROM:<archo@bbossyyy.com>
250 Ok
DEBUG SMTP: sendPartial set
RCPT TO:<jmi@bbossyyy.com>
250 Ok
DEBUG SMTP: Verified Addresses
DEBUG SMTP: John Mirabile <jmirabile@bbossyyy.com>
DATA
354 End data with <CR><LF>.<CR><LF>
Date: Wed, 4 Jun 2014 18:06:15 -0400 (EDT)
From: ArchO <archo@bbossyyy.com>
To: JM <jm@bbossyyy.com>
Message-ID: <1680495420.11401919575021.JavaMail.svcaoadmin@hqarchs01>
Subject: PO # 88636 Approval
MIME-Version: 1.0
Content-Type: text/html; charset=us-ascii
Content-Transfer-Encoding: 7bit
<html>
<head>
<title>PO Approval</title>
<style>
* {
font-family:Tahoma,Arial,Verdana,Helvetica,sans-serif;
font-size:10pt;
}
</style>
</head>
<body>
------------------------------
</body>
</html>
.
250 Ok
QUIT
221 Bye
Further, the exception being thrown is a org.springframework.mail.MailSendException and the nested cause is the usual SSL handshake exception stuff
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(Unknown Source)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.fatal(Unknown Source)
at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Unknown Source)
at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Unknown Source)
at com.sun.net.ssl.internal.ssl.ClientHandshaker.serverCertificate(Unknown Source)
at com.sun.net.ssl.internal.ssl.ClientHandshaker.processMessage(Unknown Source)
at com.sun.net.ssl.internal.ssl.Handshaker.processLoop(Unknown Source)
at com.sun.net.ssl.internal.ssl.Handshaker.process_record(Unknown Source)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(Unknown Source)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(Unknown Source)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(Unknown Source)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(Unknown Source)
at sun.net.www.protocol.https.HttpsClient.afterConnect(Unknown Source)
at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(Unknown Source)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(Unknown Source)
at sun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(Unknown Source)
at java.net.URL.openStream(Unknown Source)
at javax.activation.URLDataSource.getInputStream(Unknown Source)
at javax.activation.DataHandler.writeTo(Unknown Source)
at javax.mail.internet.MimeBodyPart.writeTo(MimeBodyPart.java:1350)
at javax.mail.internet.MimeBodyPart.writeTo(MimeBodyPart.java:845)
at javax.mail.internet.MimeMultipart.writeTo(MimeMultipart.java:361)
at com.sun.mail.handlers.multipart_mixed.writeTo(multipart_mixed.java:85)
at javax.activation.ObjectDataContentHandler.writeTo(Unknown Source)
at javax.activation.DataHandler.writeTo(Unknown Source)
at javax.mail.internet.MimeBodyPart.writeTo(MimeBodyPart.java:1350)
at javax.mail.internet.MimeMessage.writeTo(MimeMessage.java:1683)
at com.sun.mail.smtp.SMTPTransport.sendMessage(SMTPTransport.java:585)
... 77 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(Unknown Source)
at sun.security.validator.PKIXValidator.engineValidate(Unknown Source)
at sun.security.validator.Validator.validate(Unknown Source)
at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.validate(Unknown Source)
at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.checkServerTrusted(Unknown Source)
at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.checkServerTrusted(Unknown Source)
... 101 more
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(Unknown Source)
at java.security.cert.CertPathBuilder.build(Unknown Source)
... 107 more
I also retrieved the AdjacencyList from sun.security.provider.certpath.SunCertPathBuilderException to retrieve the sun.security.provider.certpath.BuildStep and printed the certificate details using getCertificate() method. The certificate was a valid one as per the keystore configured with Apache Tomcat server. below are some details from the debug
DEBUG :BS getFullString :Certificate to be tried.
Issuer: CN=bbossyyyIssuingCA, DC=bbossyyy, DC=bbosstest, DC=com
Subject:
SerialNum: 152a754f000000001177
Expires: Fri Apr 22 11:23:39 EDT 2016
SubjKeyID: KeyIdentifier [
0000: 6D E0 32 B3 9E 7C 14 C3 14 B6 63 55 7F C7 4C CB m.2.......cU..L.
0010: 2C 48 F6 DC ,H..
]
AuthKeyID: KeyIdentifier [
0000: B8 21 48 97 A2 7B 0A A2 03 6F 35 4C 9D DB 38 AE .!H......o5L..8.
0010: 6E 3A 6B B6 n:k.
]
Exception: null
Index: 1
DEBUG :BS getIssuerName : CN=bbossyyyIssuingCA, DC=bbossyyy, DC=bbosstest, DC=com
DEBUG :BS verboseToString : Certificate to be tried.
Certificate contains:
Issuer: CN=bbossyyyIssuingCA, DC=bbossyyy, DC=bbosstest, DC=com
Subject:
SerialNum: 152a754f000000001177
Expires: Fri Apr 22 11:23:39 EDT 2016
SubjKeyID: KeyIdentifier [
0000: 6D E0 32 B3 9E 7C 14 C3 14 B6 63 55 7F C7 4C CB m.2.......cU..L.
0010: 2C 48 F6 DC ,H..
]
AuthKeyID: KeyIdentifier [
0000: B8 21 48 97 A2 7B 0A A2 03 6F 35 4C 9D DB 38 AE .!H......o5L..8.
0010: 6E 3A 6B B6 n:k.
]
DEBUG :BS getSigAlgName : SHA256withRSA
DEBUG :BS getSigAlgOID : 1.2.840.113549.1.1.11
DEBUG :BS getType : X.509
DEBUG :BS getIssuerAlternativeNames : null
DEBUG :BS getNonCriticalExtensionOIDs : [2.5.29.14, 1.3.6.1.4.1.311.21.10, 1.3.6.1.4.1.311.21.7, 1.3.6.1.5.5.7.1.1, 2.5.29.31, 2.5.29.37, 2.5.29.35]
DEBUG :BS getNotAfter : Fri Apr 22 11:23:39 EDT 2016
DEBUG :BS getNotBefore : Wed Jun 04 16:34:29 EDT 2014
DEBUG :BS getVersion : 3
I need your help in beating this issue. Request your thoughts on this.
EDIT..............
Due to further learning and comments, re-posting as below Im attempting to send emails with INLINE images from a Apache Tomcat server 6.0 configured for HTTPS. The target SMTP server doesnt have a valid certificate from a trusted CA.
Now, Im able to send the emails WITHOUT attachments successfully to the server and I'm also able to send the emails with attachments when running on HTTP (non secure). But, Im unable to send emails from HTTPS configuration of tomcat to the smtp server.
I'm using Spring's JavaMailSenderImpl for sending the emails. The bean configuration of Mailsender is as below
<bean id="mailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl">
<property name="host"><value>${smtp.server}</value></property>
<property name="javaMailProperties">
<props>
<prop key="mail.smtp.sendpartial">true</prop>
<prop key="mail.debug">true</prop>
</props>
</property>
</bean>
As you can see below, the exception is created as soon as the client starts sending data to the server
DEBUG: JavaMail version 1.4ea
DEBUG: java.io.FileNotFoundException: C:\Program Files\Java\jre6\lib\javamail.providers (The system cannot find the file specified)
DEBUG: !anyLoaded
DEBUG: not loading resource: /META-INF/javamail.providers
DEBUG: successfully loaded resource: /META-INF/javamail.default.providers
DEBUG: Tables of loaded providers
DEBUG: Providers Listed By Class Name: {com.sun.mail.smtp.SMTPSSLTransport=javax.mail.Provider[TRANSPORT,smtps,com.sun.mail.smtp.SMTPSSLTransport,Sun Microsystems, Inc], com.sun.mail.smtp.SMTPTransport=javax.mail.Provider[TRANSPORT,smtp,com.sun.mail.smtp.SMTPTransport,Sun Microsystems, Inc], com.sun.mail.imap.IMAPSSLStore=javax.mail.Provider[STORE,imaps,com.sun.mail.imap.IMAPSSLStore,Sun Microsystems, Inc], com.sun.mail.pop3.POP3SSLStore=javax.mail.Provider[STORE,pop3s,com.sun.mail.pop3.POP3SSLStore,Sun Microsystems, Inc], com.sun.mail.imap.IMAPStore=javax.mail.Provider[STORE,imap,com.sun.mail.imap.IMAPStore,Sun Microsystems, Inc], com.sun.mail.pop3.POP3Store=javax.mail.Provider[STORE,pop3,com.sun.mail.pop3.POP3Store,Sun Microsystems, Inc]}
DEBUG: Providers Listed By Protocol: {imaps=javax.mail.Provider[STORE,imaps,com.sun.mail.imap.IMAPSSLStore,Sun Microsystems, Inc], imap=javax.mail.Provider[STORE,imap,com.sun.mail.imap.IMAPStore,Sun Microsystems, Inc], smtps=javax.mail.Provider[TRANSPORT,smtps,com.sun.mail.smtp.SMTPSSLTransport,Sun Microsystems, Inc], pop3=javax.mail.Provider[STORE,pop3,com.sun.mail.pop3.POP3Store,Sun Microsystems, Inc], pop3s=javax.mail.Provider[STORE,pop3s,com.sun.mail.pop3.POP3SSLStore,Sun Microsystems, Inc], smtp=javax.mail.Provider[TRANSPORT,smtp,com.sun.mail.smtp.SMTPTransport,Sun Microsystems, Inc]}
DEBUG: successfully loaded resource: /META-INF/javamail.default.address.map
DEBUG: !anyLoaded
DEBUG: not loading resource: /META-INF/javamail.address.map
DEBUG: java.io.FileNotFoundException: C:\Program Files\Java\jre6\lib\javamail.address.map (The system cannot find the file specified)
DEBUG: getProvider() returning javax.mail.Provider[TRANSPORT,smtp,com.sun.mail.smtp.SMTPTransport,Sun Microsystems, Inc]
DEBUG SMTP: useEhlo true, useAuth false
DEBUG SMTP: trying to connect to host "appsmtp.bobbsincyyy.com", port 25, isSSL false
220 hqxhubp15.fb.bobbsincyyy.com Microsoft ESMTP MAIL Service ready at Thu, 5 Jun 2014 13:47:10 -0400
DEBUG SMTP: connected to host "appsmtp.bobbsincyyy.com", port: 25
EHLO hqarchd01
250-hqxhubp15.fb.bobbsincyyy.com Hello [172.25.14.13]
250-SIZE 219901952
250-PIPELINING
250-DSN
250-ENHANCEDSTATUSCODES
250-AUTH
250-8BITMIME
250-BINARYMIME
250-CHUNKING
250-XEXCH50
250 XSHADOW
DEBUG SMTP: Found extension "SIZE", arg "219901952"
DEBUG SMTP: Found extension "PIPELINING", arg ""
DEBUG SMTP: Found extension "DSN", arg ""
DEBUG SMTP: Found extension "ENHANCEDSTATUSCODES", arg ""
DEBUG SMTP: Found extension "AUTH", arg ""
DEBUG SMTP: Found extension "8BITMIME", arg ""
DEBUG SMTP: Found extension "BINARYMIME", arg ""
DEBUG SMTP: Found extension "CHUNKING", arg ""
DEBUG SMTP: Found extension "XEXCH50", arg ""
DEBUG SMTP: Found extension "XSHADOW", arg ""
DEBUG SMTP: use8bit false
MAIL FROM:<df@bobbsincyyy.com>
250 2.1.0 Sender OK
DEBUG SMTP: sendPartial set
RCPT TO:<rp@bobbsincyyy.com>
250 2.1.5 Recipient OK
RCPT TO:<rp@bobbsincyyy.com>
250 2.1.5 Recipient OK
RCPT TO:<archo@bobbsincyyy.com>
250 2.1.5 Recipient OK
DEBUG SMTP: Verified Addresses
DEBUG SMTP: RB <rp@bobbsincyyy.com>
DEBUG SMTP: RB <rp@bobbsincyyy.com>
DEBUG SMTP: archo@bobbsincyyy.com
DATA
354 Start mail input; end with <CRLF>.<CRLF>
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(Unknown Source)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.fatal(Unknown Source)
at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Unknown Source)
There is a pretty good description available in http://springinpractice.com/2012/04/29/fixing-pkix-path-building-issues-when-using-javamail-and-smtp . But, this did not work too (Im not sure if the self signed certificate from the smtp server could cause an issue).
I also tried to enable STARTTLS on the javamail properties with a Truststore configuration. That did not work either.
The SMTP server is an intranet server and not exposed to outside world. So, basically Im ok to trust this SMTP even with a self signed certificate.
How to achieve this?