So you had your little program that would use AWS to send emails, and all of a sudden after a Java 7 update you get a stack trace like this:
javax.mail.MessagingException: Could not connect to SMTP host: email-smtp.us-east-1.amazonaws.com, port: 465; nested exception is: javax.net.ssl.SSLException: Server key at com.sun.mail.smtp.SMTPTransport.openServer(SMTPTransport.java:1962) at com.sun.mail.smtp.SMTPTransport.protocolConnect(SMTPTransport.java:654) at javax.mail.Service.connect(Service.java:295) at javax.mail.Service.connect(Service.java:176) at javax.mail.Service.connect(Service.java:196) ... Caused by: javax.net.ssl.SSLException: Server key at sun.security.ssl.Handshaker.throwSSLException(Handshaker.java:1274) ... Caused by: java.security.spec.InvalidKeySpecException: Could not create EC public key at sun.security.pkcs11.P11ECKeyFactory.engineGeneratePublic(P11ECKeyFactory.java:169) at java.security.KeyFactory.generatePublic(KeyFactory.java:334) ... Caused by: sun.security.pkcs11.wrapper.PKCS11Exception: CKR_DOMAIN_PARAMS_INVALID at sun.security.pkcs11.wrapper.PKCS11.C_CreateObject(Native Method) at sun.security.pkcs11.P11ECKeyFactory.generatePublic(P11ECKeyFactory.java:233)
It seems like the SSL Socket Factory in Java 7 is missing some of the Ciphers when it comes to setting up SSL socket cipher suits (see SSLSocket.setEnabledCipherSuites)
so… the question is now,
how do I tell java mail to use the cipher suit I used to use in java 6?
Easy, when you’re setting up your Session properties, make sure to include the following key:
properties.put("mail.smtp.ssl.ciphersuites","SSL_RSA_WITH_RC4_128_MD5 SSL_RSA_WITH_RC4_128_SHA TLS_RSA_WITH_AES_128_CBC_SHA TLS_DHE_RSA_WITH_AES_128_CBC_SHA TLS_DHE_DSS_WITH_AES_128_CBC_SHA SSL_RSA_WITH_3DES_EDE_CBC_SHA SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA SSL_RSA_WITH_DES_CBC_SHA SSL_DHE_RSA_WITH_DES_CBC_SHA SSL_DHE_DSS_WITH_DES_CBC_SHA SSL_RSA_EXPORT_WITH_RC4_40_MD5 SSL_RSA_EXPORT_WITH_DES40_CBC_SHA SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA TLS_EMPTY_RENEGOTIATION_INFO_SCSV");
which specifies in a space separated String a list of tokens that represent the cipher suites the SSL sockets will use. At some point that list gets split into a String[] and passed to SSLSocket.setEnabledCipherSuites.
This is how my session properties look like in case you want to know:
Properties properties = new Properties(); properties.put("mail.transport.protocol", "smtp"); properties.put("mail.smtp.auth", true); properties.put("mail.smtp.ssl.enable",true); properties.put("mail.smtp.port", emailSMTPPort); properties.put("mail.smtp.host", emailSMTPHost); properties.put("mail.smtp.ssl.ciphersuites","SSL_RSA_WITH_RC4_128_MD5 SSL_RSA_WITH_RC4_128_SHA TLS_RSA_WITH_AES_128_CBC_SHA TLS_DHE_RSA_WITH_AES_128_CBC_SHA TLS_DHE_DSS_WITH_AES_128_CBC_SHA SSL_RSA_WITH_3DES_EDE_CBC_SHA SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA SSL_RSA_WITH_DES_CBC_SHA SSL_DHE_RSA_WITH_DES_CBC_SHA SSL_DHE_DSS_WITH_DES_CBC_SHA SSL_RSA_EXPORT_WITH_RC4_40_MD5 SSL_RSA_EXPORT_WITH_DES40_CBC_SHA SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA TLS_EMPTY_RENEGOTIATION_INFO_SCSV");
Cheers, don’t forget to tip If I saved your ass.