gov.nih.nci.cacis.nav.SendEncryptedMail.java Source code

Java tutorial

Introduction

Here is the source code for gov.nih.nci.cacis.nav.SendEncryptedMail.java

Source

/**
 * Copyright 5AM Solutions Inc
 * Copyright SemanticBits LLC
 * Copyright AgileX Technologies, Inc
 * Copyright Ekagra Software Technologies Ltd
 *
 * Distributed under the OSI-approved BSD 3-Clause License.
 * See http://ncip.github.com/cacis/LICENSE.txt for details.
 */
package gov.nih.nci.cacis.nav;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.Security;
import java.security.cert.Certificate;
import java.security.cert.X509Certificate;
import java.util.Enumeration;
import java.util.Properties;

import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.mail.smime.SMIMEEnvelopedGenerator;
import org.bouncycastle.mail.smime.SMIMEException;
import org.bouncycastle.util.Strings;

/**
 * Example that sends an encrypted mail message.
 * 
 * Copyright (c) 2000 - 2011 The Legion Of The Bouncy Castle (http://www.bouncycastle.org)
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
 * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
 * Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
 * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 * 
 * @author vinodh.rc@semanticbits.com
 */
public class SendEncryptedMail extends AbstractSendMail {

    private static final Logger LOG = Logger.getLogger(SendEncryptedMail.class);
    private static final String ERROR_INITALISING_ENCRYPTER = "Error initalising encrypter!";

    private String truststore = null;
    private String storepass = null;

    private KeyStore trustStoreRef;

    /**
     * Initialize Mail Encrypter
     * 
     * @param mailProperties - properties for mail sender
     * @param from - from email address
     * @param host - email server host
     * @param port - email server port
     * @param protocol - email protocol
     * @param truststore - truststore to use for encrypting mail
     * @param storepass - truststore password
     * @throws MessagingException - exception thrown, if any
     * @throws KeyStoreException - exception thrown, if any
     */
    @SuppressWarnings({ "PMD.ExcessiveParameterList" })
    // CHECKSTYLE:OFF
    public SendEncryptedMail(Properties mailProperties, String from, String host, int port, String protocol,
            String truststore, String storepass, String secEmailTempZipLocation)
            throws MessagingException, KeyStoreException {
        super(mailProperties, from, host, port, protocol);
        super.secEmailTempZipLocation = secEmailTempZipLocation;
        this.truststore = truststore;
        this.storepass = storepass;

        init();
    }

    //CHECKSTYLE:ON
    /**
     * Initialize Mail Encrypter. Uses localhost smtp server and default port
     * 
     * @param mailProperties - properties for mail sender
     * @param from - from email address
     * @param truststore - truststore to use for encrypting mail
     * @param storepass - truststore password
     * @throws MessagingException - exception thrown, if any
     * @throws KeyStoreException - exception thrown, if any
     */
    public SendEncryptedMail(Properties mailProperties, String from, String truststore, String storepass,
            String secEmailTempZipLocation) throws MessagingException, KeyStoreException {
        this(mailProperties, from, "localhost", SMTP_PORT, "SMTP", truststore, storepass, secEmailTempZipLocation);
    }

    /**
     * Initialize Mail Encrypter
     * 
     * @param mailProperties - properties for mail sender
     * @param from - from email address
     * @param host - email server host
     * @param port - email server port
     * @param protocol - email protocol
     * @throws MessagingException - exception thrown, if any
     * @throws KeyStoreException - exception thrown, if any
     */
    public SendEncryptedMail(Properties mailProperties, String from, String host, int port, String protocol,
            String secEmailTempZipLocation) throws MessagingException, KeyStoreException {
        super(mailProperties, from, host, port, protocol);
        super.secEmailTempZipLocation = secEmailTempZipLocation;
        init();
    }

    /**
     * Initialize Mail Encrypter. Uses localhost smtp server and default port
     * 
     * @param mailProperties - properties for mail sender
     * @param from - from email address
     * @throws MessagingException - exception thrown, if any
     * @throws KeyStoreException - exception thrown, if any
     */
    public SendEncryptedMail(Properties mailProperties, String from, String secEmailTempZipLocation)
            throws MessagingException, KeyStoreException {
        this(mailProperties, from, "localhost", SMTP_PORT, "SMTP", secEmailTempZipLocation);
    }

    private void init() throws MessagingException, KeyStoreException {
        /* CommandCap setting */
        setCommandCap();

        /* Add BC */
        Security.addProvider(new BouncyCastleProvider());

        if (!StringUtils.isEmpty(truststore)) {
            trustStoreRef = getTrustStoreRef();
        }
    }

    private Certificate getCert(String keyAlias) throws MessagingException {
        Certificate result = null;
        try {
            result = trustStoreRef.getCertificate(keyAlias);
            // CHECKSTYLE:OFF
        } catch (Exception ex) { // NOPMD
            // CHECKSTYLE:ON
            LOG.error(ERROR_INITALISING_ENCRYPTER, ex);
            throw new MessagingException(ERROR_INITALISING_ENCRYPTER, ex);
        }
        if (result == null) {
            throw new IllegalArgumentException(String.format(
                    "Could not find any certificate with key '%s' in truststore '%s'.", keyAlias, truststore));
        }
        return result;
    }

    /**
     * encrypting of mail
     * 
     * @param message - MimeMessage to be encrypted
     * @param keyAlias - keyAlias for the certificate
     * @return MimeMessage - encrypted MimeMessage
     * @throws MessagingException - exception thrown if any
     */
    public MimeMessage encryptMail(MimeMessage message, String keyAlias) throws MessagingException {
        return encryptMail(message, getCert(keyAlias));
    }

    /**
     * encrypting of mail
     * 
     * @param message - MimeMessage to be encrypted
     * @param cert - trusted Certificate
     * @return MimeMessage - encrypted MimeMessage
     */
    public MimeMessage encryptMail(MimeMessage message, Certificate cert) {
        /* Create the message to sign and encrypt */
        final Session session = createSession(getHost(), String.valueOf(getPort()), getMailProperties());
        return encryptMail(message, session, cert);
    }

    /**
     * encrypting of mail
     * 
     * @param message - MimeMessage to be encrypted
     * @param session - Mail Session
     * @param keyAlias - keyAlias for the certificate
     * @return MimeMessage - encrypted MimeMessage
     * @throws MessagingException - exception thrown, if any
     */
    public MimeMessage encryptMail(MimeMessage message, Session session, String keyAlias)
            throws MessagingException {
        return encryptMail(message, session, getCert(keyAlias));
    }

    /**
     * encrypting of mail
     * 
     * @param message - MimeMessage to be encrypted
     * @param session - Mail Session
     * @param cert - trusted Certificate
     * @return MimeMessage - encrypted MimeMessage
     */
    public MimeMessage encryptMail(MimeMessage message, Session session, Certificate cert) {
        try {
            return encryptMessage(message, session, cert);
            // CHECKSTYLE:OFF
        } catch (Exception ex) { // NOPMD
            // CHECKSTYLE:ON
            LOG.error("Error sending secure mail", ex);
        }
        return null;
    }

    private MimeMessage encryptMessage(MimeMessage message, Session session, Certificate cert)
            throws NoSuchAlgorithmException, NoSuchProviderException, SMIMEException, MessagingException,
            IOException {
        /* Create the encrypter */
        final SMIMEEnvelopedGenerator encrypter = new SMIMEEnvelopedGenerator();
        encrypter.addKeyTransRecipient((X509Certificate) cert);

        /* Encrypt the message */
        final MimeBodyPart encryptedPart = encrypter.generate(message, SMIMEEnvelopedGenerator.AES256_CBC,
                PROVIDER_TYPE);

        /*
         * Create a new MimeMessage that contains the encrypted and signed content
         */
        final ByteArrayOutputStream out = new ByteArrayOutputStream();
        encryptedPart.writeTo(out);

        final MimeMessage encryptedMessage = new MimeMessage(session, new ByteArrayInputStream(out.toByteArray()));

        /* Set all original MIME headers in the encrypted message */
        final Enumeration headers = message.getAllHeaderLines();
        while (headers.hasMoreElements()) {
            final String headerLine = (String) headers.nextElement();
            /*
             * Make sure not to override any content-* headers from the original message
             */
            if (!Strings.toLowerCase(headerLine).startsWith("content-")) {
                encryptedMessage.addHeaderLine(headerLine);
            }
        }

        return encryptedMessage;
    }

    private KeyStore getTrustStoreRef() throws KeyStoreException {
        /* Open the truststore */
        KeyStore truststoreRef = null;
        InputStream is = null;
        try {
            truststoreRef = KeyStore.getInstance(STORE_TYPE, PROVIDER_TYPE);
            is = new FileInputStream(truststore);
            truststoreRef.load(is, storepass.toCharArray());
            // CHECKSTYLE:OFF
        } catch (Exception e) { // NOPMD
            // CHECKSTYLE:ON
            throw new KeyStoreException("Error loading truststore!", e);
        } finally {
            if (is != null) {
                try {
                    is.close();
                } catch (IOException e) {
                    LOG.debug("Error closing truststore reading stream!");
                }
            }
        }
        return truststoreRef;
    }
}