0N/A Notes for use of SSL with JavaMail
0N/A ----------------------------------
0N/AJavaMail now supports accessing mail servers over connections secured
73N/Ausing SSL or TLS. To simplify such access, there are two alternative
73N/Aapproaches to enable use of SSL.
73N/AFirst, and perhaps the simplest, is to set a property to enable use
73N/Aof SSL. For example, to enable use of SSL for SMTP connections, set
73N/AAlternatively, you can configure JavaMail to use one of the SSL-enabled
73N/Aprotocol names. In addition to the non-SSL JavaMail protocols "imap",
0N/A"pop3", and "smtp", the protocols "imaps", "pop3s", and "smtps" can
0N/Abe used to connect to the corresponding services using an SSL
0N/AIn addition, the "imap" and "smtp" protocols support use of the
0N/ASTARTTLS command (see RFC 2487 and RFC 3501) to switch the connection
0N/Ato be secured by TLS.
0N/AUse of the STARTTLS command is preferred in cases where the server
73N/Asupports both SSL and non-SSL connections.
0N/AThis
SSL/TLS support in JavaMail works only when JavaMail is used on
0N/Aa version of J2SE that includes SSL support. We have tested this
73N/Asupport on J2SE 1.4 and newer, which include SSL support. The
0N/ASSL support is provided by the JSSE package, which is also available
0N/Afor earlier versions of J2SE. We have not tested such configurations.
0N/AThe STARTTLS support is available in the standard "imap" and "smtp"
0N/Aprotocols, but must be enabled by setting the appropriate property,
0N/AWhen set, if the server supports the STARTTLS command, it will be
0N/Aused after making the connection and before sending any login
0N/AWhen using the new protocol names, configuration properties must also use
0N/Ato specify the host name of the machine to connect to when using the
73N/A"smtps" protocol for SMTP over SSL. Similarly, to set the IMAP protocol
73N/Atimeout when using the "imaps" protocol for IMAP over SSL, set the property
0N/Aprotocol packages for the list of available properties, which are
0N/Aalways set using property names of the form mail.<protocol>.<property>.
73N/Awhich remains "smtp". To enable SMTP connections over SSL, set the
73N/AAlternatively, to change the default transport protocol
0N/Atransport used for internet addresses (as returned by the
0N/A-- Trusted Certificates
0N/ATo establish an
SSL/TLS connection, the JavaMail client must be able
0N/Ato verify that the security certificate presented by the server
0N/Ait is connecting to is "trusted" by the client. Trusted certificates
0N/Aare maintained in a Java keystore file on the client. The J2SE
0N/ASDK "keytool" command is used to maintain the keystore file.
0N/AThere are two common approaches for verifying server certificates.
0N/AThe first approach is probably most common for servers accessible to
0N/Apartners outside a company. The second approach is probably most
0N/Acommon for servers used within a company.
0N/A1. Server certificates may be signed be a well known public
0N/A Certificate Authority. The default Java keystore file contains
0N/A the public keys of well known Certificate Authorities and can
0N/A verify the server's certificate by following the chain of
0N/A certificates signing the server's certificate back to one of
0N/A these well known CA certificates.
0N/A In this case the client doesn't need to manage certificates
0N/A explicitly but can just use the default keystore file.
0N/A2. Server certificates may be "self-signed". In this case there is
0N/A no chain of signatures to use in verifying the server's certificate.
0N/A Instead, the client will need the server's certificate in the
0N/A client's keystore file. The server's certificate is imported into
0N/A the keystore file once, using the keytool command, and after that
0N/A is used to verify connections to the server. A single keystore file
0N/A may contain certificates of many servers.
0N/A In this case the client will need to set the appropriate System
0N/A properties to point to the client's keystore file containing the
0N/A trusted certificate. These properties can be set when invoking
0N/A the "java" command, or can be set programmatically. For example,
0N/A See the JSSE Reference Guide for details:
93N/A-- Server Identity Check
93N/ARFC 2595 specifies addition checks that must be performed on the
93N/Aserver's certificate to ensure that the server you connected to is
93N/Athe server you intended to connect to. This reduces the risk of
93N/A"man in the middle" attacks. For compatibility with earlier releases
93N/Aof JavaMail, these additional checks are disabled by default. We
93N/Astrongly recommend that you enable these checks when using SSL. To
93N/AIn earlier releases it was necessary to explicitly set a socket
93N/Afactory property to enable use of SSL. In almost all cases, this
93N/Ais no longer necessary. SSL support is built in. However, there
93N/Ais one case where a special socket factory may be needed.
93N/AJavaMail now includes a special SSL socket factory that can simplify
93N/Adealing with servers with self-signed certificates. While the
93N/Arecommended approach is to include the certificate in your keystore
93N/Aas described above, the following approach may be simpler in some cases.
93N/Asimple socket factory that allows trusting all hosts or a specific set
93N/Aof hosts. For example:
93N/A MailSSLSocketFactory sf = new MailSSLSocketFactory();
93N/A // also use following for additional safety
93N/AUse of MailSSLSocketFactory avoids the need to add the certificate to
93N/Ayour keystore as described above, or configure your own TrustManager
0N/ADebugging problems with certificates and keystores can be difficult.
0N/AThe JSSE Reference Guide contains information on debugging utilities
0N/AThere are some debugging options in the JDK that can help, depending
0N/Aon the sorts of problems you're having. Setting the following system
0N/Aproperties will produce additional debugging output:
0N/ASet these on the command line when you run your program using, for example:
0N/AGiven a certificate for the server as used in case #2 above, you can
0N/Aimport this certificate into your Java keystore file using a command
0N/AThe keytool command can also be used to generate a self-signed certificate
0N/Athat can be used by your mail server, if you're setting up your own server.
0N/AOther utilities, such as those included with the OpenSSL package, can also
0N/Abe used to generate such certificates, and they can be imported into the
0N/AJava keystore using keytool.
0N/AFor more information on using the keytool command, see the keytool
0N/A-- Configuring Your Own Trust Manager
0N/AWhen using
SSL/TLS, it's important to ensure that the server you connect
0N/Ato is actually the server you expected to connect to, to prevent "man in
0N/Athe middle" attacks on your communication. The recommended technique is
0N/Ato configure the Java keystore using one of the methods described above.
0N/AIf, for some reason, that approach is not workable, it's also possible
0N/Ato configure the
SSL/TLS implementation to use your own TrustManager
0N/Aclass to evaluate whether to trust the server you've connected to.
0N/AThe following "dummy" classes illustrate the framework necessary to create
0N/Ayour own TrustManager implementation.
0N/AFirst, a replacement for the standard SSLSocketFactory is needed, to allow
0N/Ayou to specify which TrustManager to use:
0N/A * DummySSLSocketFactory
0N/Apublic class DummySSLSocketFactory extends SSLSocketFactory {
0N/A private SSLSocketFactory factory;
0N/A public DummySSLSocketFactory() {
0N/A new TrustManager[] { new DummyTrustManager()},
0N/A } catch(Exception ex) {
0N/A public static SocketFactory getDefault() {
0N/A return new DummySSLSocketFactory();
0N/A public Socket createSocket() throws IOException {
0N/A public Socket createSocket(Socket socket, String s, int i, boolean flag)
0N/A throws IOException {
0N/A public Socket createSocket(InetAddress inaddr, int i,
0N/A InetAddress inaddr1, int j) throws IOException {
0N/A public Socket createSocket(InetAddress inaddr, int i)
0N/A throws IOException {
0N/A public Socket createSocket(String s, int i, InetAddress inaddr, int j)
0N/A throws IOException {
0N/A public Socket createSocket(String s, int i) throws IOException {
0N/A public String[] getDefaultCipherSuites() {
0N/A public String[] getSupportedCipherSuites() {
0N/ANext you need the actual implementation of the TrustManager. This dummy
0N/Atrust manager trusts anything. THIS IS NOT SECURE!!!
0N/A * DummyTrustManager - NOT SECURE
0N/Apublic class DummyTrustManager implements X509TrustManager {
0N/A public void checkClientTrusted(X509Certificate[] cert, String authType) {
0N/A // everything is trusted
0N/A public void checkServerTrusted(X509Certificate[] cert, String authType) {
0N/A // everything is trusted
0N/A public X509Certificate[] getAcceptedIssuers() {
0N/A return new X509Certificate[0];
73N/AFinally, you need to configure JavaMail to use your SSLSocketFactory.
73N/ASet the appropriate protocol-specific property,
e.g.,
0N/A "DummySSLSocketFactory");
0N/ASimilar properties would need to be set to use other protocols.