ch.entwine.weblounge.kernel.mail.SmtpService.java Source code

Java tutorial

Introduction

Here is the source code for ch.entwine.weblounge.kernel.mail.SmtpService.java

Source

/*
 *  Weblounge: Web Content Management System
 *  Copyright (c) 2012 The Weblounge Team
 *  http://weblounge.o2it.ch
 *
 *  This program is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public License
 *  as published by the Free Software Foundation; either version 2
 *  of the License, or (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public License
 *  along with this program; if not, write to the Free Software Foundation
 *  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 */

package ch.entwine.weblounge.kernel.mail;

import org.apache.commons.lang.StringUtils;
import org.osgi.service.cm.ConfigurationException;
import org.osgi.service.cm.ManagedService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Dictionary;
import java.util.Properties;

import javax.mail.Message.RecipientType;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;

/**
 * OSGi service that allows to send e-mails using <code>javax.mail</code>.
 */
public class SmtpService implements ManagedService {

    /** The logging facility */
    private static final Logger logger = LoggerFactory.getLogger(SmtpService.class);

    /** Parameter prefix common to all "mail" properties */
    private static final String OPT_SMTP_PREFIX = "smtp.";

    /** Parameter suffix for the mail host */
    private static final String OPT_SMTP_HOST = "host";

    /** Parameter suffix for the mail port */
    private static final String OPT_SMTP_PORT = "port";

    /** Parameter suffix for the start tls status */
    private static final String OPT_SMTP_TLS = "starttls";

    /** Parameter suffix for the authentication setting */
    private static final String OPT_SMTP_AUTH = "auth";

    /** Parameter name for the username */
    private static final String OPT_SMTP_USER = "user";

    /** Parameter name for the password */
    private static final String OPT_SMTP_PASSWORD = "password";

    /** Parameter name for the recipient */
    private static final String OPT_SMTP_FROM = "from";

    /** Parameter name for the debugging setting */
    private static final String OPT_SMTP_DEBUG = "debug";

    /** Parameter name for the test setting */
    private static final String OPT_SMTP_TEST = "test";

    /** Default value for the mail server */
    private static final String DEFAULT_SMTP_HOST = "localhost";

    /** Default value for the mail port */
    private static final String DEFAULT_SMTP_PORT = "25";

    /** The mail properties */
    private final Properties mailProperties = new Properties();

    /** The mail host */
    private String mailHost = null;

    /** The mail user */
    private String mailUser = null;

    /** The mail password */
    private String mailPassword = null;

    /** The default mail session */
    private Session defaultMailSession = null;

    /** The mail transport protocol */
    private static final String MAIL_TRANSPORT = "smtp";

    /**
     * Callback from the OSGi <code>ConfigurationAdmin</code> on configuration
     * changes.
     * 
     * @param properties
     *          the configuration properties
     * @throws ConfigurationException
     *           if configuration fails
     */
    @Override
    public void updated(Dictionary properties) throws ConfigurationException {

        // Read the mail server properties
        mailProperties.clear();

        // The mail host is mandatory
        String propName = getConfigurationKey(OPT_SMTP_HOST);
        mailHost = StringUtils.trimToNull((String) properties.get(propName));
        if (mailHost == null) {
            mailHost = DEFAULT_SMTP_HOST;
            logger.debug("Mail server defaults to '{}'", mailHost);
        } else {
            logger.debug("Mail host is {}", mailHost);
        }
        mailProperties.put(getJavaMailSmtpKey(OPT_SMTP_HOST), mailHost);

        // Mail port
        propName = getConfigurationKey(OPT_SMTP_PORT);
        String mailPort = StringUtils.trimToNull((String) properties.get(propName));
        if (mailPort == null) {
            mailPort = DEFAULT_SMTP_PORT;
            logger.debug("Mail server port defaults to '{}'", mailPort);
        } else {
            logger.debug("Mail server port is '{}'", mailPort);
        }
        mailProperties.put(getJavaMailSmtpKey(OPT_SMTP_PORT), mailPort);

        // TSL over SMTP support
        propName = getConfigurationKey(OPT_SMTP_TLS);
        String smtpStartTLSStr = StringUtils.trimToNull((String) properties.get(propName));
        boolean smtpStartTLS = Boolean.parseBoolean(smtpStartTLSStr);
        if (smtpStartTLS) {
            mailProperties.put(getJavaMailSmtpKey(OPT_SMTP_TLS) + ".enable", "true");
            logger.debug("TLS over SMTP is enabled");
        } else {
            logger.debug("TLS over SMTP is disabled");
        }

        // Mail user
        propName = getConfigurationKey(OPT_SMTP_USER);
        mailUser = StringUtils.trimToNull((String) properties.get(propName));
        if (mailUser != null) {
            mailProperties.put(getJavaMailKey(OPT_SMTP_USER), mailUser);
            logger.debug("Mail user is '{}'", mailUser);
        } else {
            logger.debug("Sending mails to {} without authentication", mailHost);
        }

        // Mail password
        propName = getConfigurationKey(OPT_SMTP_PASSWORD);
        mailPassword = StringUtils.trimToNull((String) properties.get(propName));
        if (mailPassword != null) {
            mailProperties.put(getJavaMailKey(OPT_SMTP_PASSWORD), mailPassword);
            logger.debug("Mail password set");
        }

        // Mail sender
        propName = getConfigurationKey(OPT_SMTP_FROM);
        String mailFrom = StringUtils.trimToNull((String) properties.get(propName));
        if (mailFrom == null) {
            try {
                mailFrom = "weblounge@" + InetAddress.getLocalHost().getCanonicalHostName();
                logger.info("Mail sender defaults to '{}'", mailFrom);
            } catch (UnknownHostException e) {
                logger.error("Error retreiving localhost hostname used to create default sender address: {}",
                        e.getMessage());
                throw new ConfigurationException(OPT_SMTP_FROM,
                        "Error retreiving localhost hostname used to create default sender address");
            }
        } else {
            logger.debug("Mail sender is '{}'", mailFrom);
        }
        mailProperties.put(getJavaMailKey(OPT_SMTP_FROM), mailFrom);

        // Authentication
        propName = getConfigurationKey(OPT_SMTP_AUTH);
        mailProperties.put(getJavaMailSmtpKey(OPT_SMTP_AUTH), Boolean.toString(mailUser != null));

        // Mail debugging
        propName = getConfigurationKey(OPT_SMTP_DEBUG);
        String mailDebug = StringUtils.trimToNull((String) properties.get(propName));
        if (mailDebug != null) {
            boolean mailDebugEnabled = Boolean.parseBoolean(mailDebug);
            mailProperties.put(getJavaMailKey(OPT_SMTP_DEBUG), Boolean.toString(mailDebugEnabled));
            logger.info("Mail debugging is {}", mailDebugEnabled ? "enabled" : "disabled");
        }

        defaultMailSession = null;
        logger.info("Mail service configured with {}", mailHost);

        // Test
        propName = getConfigurationKey(OPT_SMTP_TEST);
        String mailTest = StringUtils.trimToNull((String) properties.get(propName));
        if (mailTest != null) {
            try {
                sendTestMessage(mailTest);
            } catch (MessagingException e) {
                logger.error("Error sending test message to " + mailTest + ": " + e.getMessage());
                throw new ConfigurationException(OPT_SMTP_PREFIX + MAIL_TRANSPORT + OPT_SMTP_HOST,
                        "Failed to send test message to " + mailTest);
            }
        }
    }

    /**
     * Returns the default mail session that can be used to create a new message.
     * 
     * @return the default mail session
     */
    public Session getSession() {
        if (defaultMailSession == null) {
            defaultMailSession = Session.getInstance(mailProperties);
        }
        return defaultMailSession;
    }

    /**
     * Creates a new message.
     * 
     * @return the new message
     */
    public MimeMessage createMessage() {
        return new MimeMessage(getSession());
    }

    /**
     * Sends <code>message</code> using the configured transport.
     * 
     * @param message
     *          the message
     * @throws MessagingException
     *           if sending the message failed
     */
    public void send(MimeMessage message) throws MessagingException {
        Transport t = getSession().getTransport(MAIL_TRANSPORT);
        try {
            if (mailUser != null)
                t.connect(mailUser, mailPassword);
            else
                t.connect();
            t.sendMessage(message, message.getAllRecipients());
        } finally {
            t.close();
        }
    }

    /**
     * Method to send a test message.
     * 
     * @throws MessagingException
     *           if sending the message failed
     */
    private void sendTestMessage(String recipient) throws MessagingException {
        MimeMessage message = createMessage();
        message.addRecipient(RecipientType.TO, new InternetAddress(recipient));
        message.setSubject("Test from Weblounge");
        message.setText("Hello world");
        message.saveChanges();
        send(message);
    }

    /**
     * Returns the key as expected in the service configuration.
     * 
     * @param option
     *          the option name
     * @return the full configuration key
     */
    private String getConfigurationKey(String option) {
        return OPT_SMTP_PREFIX + option;
    }

    /**
     * Returns the key as expected by the JavaMail library.
     * 
     * @param option
     *          the option name
     * @return the full configuration key
     */
    private String getJavaMailKey(String option) {
        return "mail." + option;
    }

    /**
     * Returns the key as expected by the JavaMail library configured for the smtp
     * transport.
     * 
     * @param option
     *          the option name
     * @return the full configuration key
     */
    private String getJavaMailSmtpKey(String option) {
        return "mail." + MAIL_TRANSPORT + "." + option;
    }

}