edu.harvard.med.screensaver.service.SmtpEmailService.java Source code

Java tutorial

Introduction

Here is the source code for edu.harvard.med.screensaver.service.SmtpEmailService.java

Source

// $HeadURL$
// $Id$
//
// Copyright  2006, 2010, 2011, 2012 by the President and Fellows of Harvard College.
// 
// Screensaver is an open-source project developed by the ICCB-L and NSRB labs
// at Harvard Medical School. This software is distributed under the terms of
// the GNU General Public License.

package edu.harvard.med.screensaver.service;

import java.io.File;
import java.io.IOException;
import java.util.Properties;
import java.util.Set;

import javax.activation.DataHandler;
import javax.activation.FileDataSource;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Multipart;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.AddressException;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;

import com.google.common.collect.Sets;

import edu.harvard.med.screensaver.util.StringUtils;

import org.apache.commons.cli.OptionBuilder;
import org.apache.log4j.Logger;

/**
 * SMTP EmailService implementation
 * TODO: rework this class using a builder patter for creation of the message (to better handle multipart messages).
 */
public class SmtpEmailService implements EmailService {
    private static Logger log = Logger.getLogger(SmtpEmailService.class);

    // member variables used if instantiated as a service
    private String host;
    private String username;
    private String password;
    private boolean useSmtps;
    private InternetAddress[] replyTos;

    public SmtpEmailService(String host, String username, String replyTos) throws AddressException {
        this(host, username, replyTos, null, false);
    }

    /**
     * @motivation for Spring instantiation
     * @param host mail server host i.e. smtp.cl.med.harvard.edu
     * @param username mail account name
     * @param password password, can be blank if unnecessary
     * @throws AddressException 
     */
    public SmtpEmailService(String host, String username, String replyTos, String password)
            throws AddressException {
        this(host, username, replyTos, password, false);
    }

    /**
     * @param useSmtps in order to use smtp.gmail.com (for testing)
     * @throws AddressException 
     */
    public SmtpEmailService(String host, String username, String replyTos, String password, boolean useSmtps)
            throws AddressException {
        this.host = host;
        this.username = username;
        this.password = password;
        this.useSmtps = useSmtps;
        if (replyTos != null) {
            String[] sreplyTos = replyTos.split(",");
            Set<InternetAddress> set = Sets.newHashSet();
            for (String s : sreplyTos) {
                if (!StringUtils.isEmpty(s))
                    set.add(new InternetAddress(s));
            }
            this.replyTos = set.toArray(new InternetAddress[] {});
        }
    }

    public void send(String subject, String message, InternetAddress from, InternetAddress[] recipients,
            InternetAddress[] cclist) throws MessagingException {
        try {
            send(subject, message, from, recipients, cclist, null);
        } catch (IOException e) {
            throw new RuntimeException("should not happen as there is no file attachment", e);
        }
    }

    public void send(String subject, String message, InternetAddress from, InternetAddress[] recipients,
            InternetAddress[] cclist, File attachedFile) throws MessagingException, IOException {
        sendMessage(subject, message, from, recipients, cclist, attachedFile);
    }

    public void send(String subject, String message, String from, String[] recipients, String[] cclist)
            throws MessagingException {
        try {
            send(subject, message, from, recipients, cclist, null);
        } catch (IOException e) {
            throw new RuntimeException("should not happen as there is no file attachment", e);
        }
    }

    public void send(String subject, String message, String from, String[] recipients, String[] cclist,
            File attachedFile) throws MessagingException, IOException {
        sendMessage(subject, message, from, recipients, cclist, attachedFile);
    }

    /**
     * Convert string email addresses to proper InternetAddress
     * 
     * @throws IOException
     */
    private void sendMessage(String subject, String message, String from, String[] srecipients, String[] scclist,
            File attachedFile) throws MessagingException, IOException {
        InternetAddress[] recipients = new InternetAddress[srecipients.length];
        int i = 0;
        for (String r : srecipients) {
            recipients[i++] = new InternetAddress(r);

        }
        InternetAddress[] cclist = null;
        i = 0;
        if (scclist != null) {
            cclist = new InternetAddress[scclist.length];
            for (String r : scclist) {
                cclist[i++] = new InternetAddress(r);
            }
        }
        sendMessage(subject, message, new InternetAddress(from), recipients, cclist, attachedFile);
    }

    private void sendMessage(String subject, String message, InternetAddress from, InternetAddress[] recipients,
            InternetAddress[] cclist, File attachedFile) throws MessagingException, IOException {
        log.info("try to send: " + printEmail(subject, message, from, this.replyTos, recipients, cclist,
                (attachedFile == null ? "" : "" + attachedFile.getCanonicalFile())));
        log.info("host: " + host + ", useSMTPS: " + useSmtps);
        Properties props = new Properties();
        String protocol = "smtp";
        if (useSmtps) // need smtps to test with gmail
        {
            props.put("mail.smtps.auth", "true");
            protocol = "smtps";
        }
        Session session = Session.getDefaultInstance(props, null);
        Transport t = session.getTransport(protocol);

        try {
            MimeMessage msg = new MimeMessage(session);
            if (this.replyTos != null)
                msg.setReplyTo(replyTos);
            msg.setFrom(from);
            msg.setSubject(subject);

            if (attachedFile != null) {
                setFileAsAttachment(msg, message, attachedFile);
            } else {
                msg.setContent(message, "text/plain");
            }

            msg.addRecipients(Message.RecipientType.TO, recipients);
            if (cclist != null)
                msg.addRecipients(Message.RecipientType.CC, cclist);

            t.connect(host, username, password);
            t.sendMessage(msg, msg.getAllRecipients());
        } finally {
            t.close();
        }
        log.info("sent: " + printEmailHeader(subject, from, this.replyTos, recipients, cclist,
                (attachedFile == null ? "" : "" + attachedFile.getCanonicalFile())));
    }

    // Set a file as an attachment.  Uses JAF FileDataSource.
    // from http://en.wikipedia.org/wiki/Javamail
    private static void setFileAsAttachment(Message msg, String message, File file) throws MessagingException {
        MimeBodyPart p1 = new MimeBodyPart();
        p1.setText(message);

        // Create second part
        MimeBodyPart p2 = new MimeBodyPart();

        // Put a file in the second part
        FileDataSource fds = new FileDataSource(file);
        p2.setDataHandler(new DataHandler(fds));
        p2.setFileName(fds.getName());

        // Create the Multipart.  Add BodyParts to it.
        Multipart mp = new MimeMultipart();
        mp.addBodyPart(p1);
        mp.addBodyPart(p2);

        // Set Multipart as the message's content
        msg.setContent(mp);
    }

    //    // Set a single part html content.
    //    // Sending data of any type is similar.
    //    // from http://en.wikipedia.org/wiki/Javamail
    //  private static void setHTMLContent(Message msg) throws MessagingException
    //  {
    //
    //        String html = "<html><head><title>" +
    //                        msg.getSubject() +
    //                        "</title></head><body><h1>" +
    //                        msg.getSubject() +
    //                        "</h1><p>This is a test of sending an HTML e-mail" +
    //                        " through Java.</body></html>";
    //
    //        // HTMLDataSource is an inner class
    //        msg.setDataHandler(new DataHandler(new HTMLDataSource(html)));
    //    }
    //
    //    /*
    //     * Inner class to act as a JAF datasource to send HTML e-mail content
    //     */
    //    static class HTMLDataSource implements DataSource {
    //        private String html;
    //
    //        public HTMLDataSource(String htmlString) {
    //            html = htmlString;
    //        }
    //
    //        // Return html string in an InputStream.
    //        // A new stream must be returned each time.
    //        public InputStream getInputStream() throws IOException {
    //            if (html == null) throw new IOException("Null HTML");
    //            return new ByteArrayInputStream(html.getBytes());
    //        }
    //
    //        public OutputStream getOutputStream() throws IOException {
    //            throw new IOException("This DataHandler cannot write HTML");
    //        }
    //
    //        public String getContentType() {
    //            return "text/html";
    //        }
    //
    //        public String getName() {
    //            return "JAF text/html dataSource to send e-mail only";
    //        }
    //    }

    /**
     * For logging
     */
    public static String printEmail(String subject, String message, InternetAddress from,
            InternetAddress[] replyTos, InternetAddress[] recipients, InternetAddress[] cclist,
            String attachedFilePath) {
        return printEmailHeader(subject, from, replyTos, recipients, cclist, attachedFilePath)
                + "\n========message========\n" + message;
    }

    public static String printEmailHeader(String subject, InternetAddress from, InternetAddress[] replyTos,
            InternetAddress[] recipients, InternetAddress[] cclist, String attachedFilePath) {
        return "\nSubject: " + subject + "\nFrom: " + from + "\nReplyTo's: "
                + (replyTos == null ? "" : com.google.common.base.Joiner.on(',').join(replyTos)) + "\nTo: "
                + com.google.common.base.Joiner.on(',').join(recipients) + "\nCC: "
                + (cclist == null ? "" : com.google.common.base.Joiner.on(',').join(cclist)) + "\nAttached File: "
                + attachedFilePath;
    }
}