001/*
002 * #%L
003 * Netarchivesuite - common
004 * %%
005 * Copyright (C) 2005 - 2014 The Royal Danish Library, the Danish State and University Library,
006 *             the National Library of France and the Austrian National Library.
007 * %%
008 * This program is free software: you can redistribute it and/or modify
009 * it under the terms of the GNU Lesser General Public License as
010 * published by the Free Software Foundation, either version 2.1 of the
011 * License, or (at your option) any later version.
012 * 
013 * This program is distributed in the hope that it will be useful,
014 * but WITHOUT ANY WARRANTY; without even the implied warranty of
015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
016 * GNU General Lesser Public License for more details.
017 * 
018 * You should have received a copy of the GNU General Lesser Public
019 * License along with this program.  If not, see
020 * <http://www.gnu.org/licenses/lgpl-2.1.html>.
021 * #L%
022 */
023
024package dk.netarkivet.common.utils;
025
026import java.util.Date;
027import java.util.Properties;
028
029import javax.mail.Message;
030import javax.mail.MessagingException;
031import javax.mail.Session;
032import javax.mail.Transport;
033import javax.mail.internet.AddressException;
034import javax.mail.internet.InternetAddress;
035import javax.mail.internet.MimeMessage;
036
037import org.slf4j.Logger;
038import org.slf4j.LoggerFactory;
039
040import dk.netarkivet.common.CommonSettings;
041import dk.netarkivet.common.exceptions.ArgumentNotValid;
042import dk.netarkivet.common.exceptions.IOFailure;
043
044/**
045 * Utilities for sending an email.
046 */
047public final class EMailUtils {
048
049    /** The class logger. */
050    private static final Logger log = LoggerFactory.getLogger(EMailUtils.class);
051
052    /** name of property defining the sender of the mail. */
053    private static final String MAIL_FROM_PROPERTY_KEY = "mail.from";
054    /** name of property defining the host sending the mail. */
055    private static final String MAIL_HOST_PROPERTY_KEY = "mail.host";
056    /** The mimetype used in the mail. */
057    private static final String MIMETYPE = "text/plain";
058
059    /** private constructor to avoid initialization. */
060    private EMailUtils() {
061    }
062
063    /**
064     * Send an email, throwing exceptions on errors.
065     *
066     * @param to The recipient of the email. Separate multiple recipients with commas.
067     * @param from The sender of the email.
068     * @param subject The subject of the email.
069     * @param body The body of the email.
070     * @throws ArgumentNotValid If either parameter is null, if to, from or subject is the empty string, if to or from
071     * does not contain valid email adresses.
072     * @throws IOFailure If the message cannot be sent for some reason.
073     */
074    public static void sendEmail(String to, String from, String subject, String body) {
075        sendEmail(to, from, subject, body, false);
076    }
077
078    /**
079     * Send an email, possibly forgiving errors.
080     *
081     * @param to The recipient of the email. Separate multiple recipients with commas. Supports only adresses of the
082     * type 'john@doe.dk', not 'John Doe <john@doe.dk>'
083     * @param from The sender of the email.
084     * @param subject The subject of the email.
085     * @param body The body of the email.
086     * @param forgive On true, will send the email even on invalid email addresses, if at least one recipient can be
087     * set, on false, will throw exceptions on any invalid email address.
088     * @throws ArgumentNotValid If either parameter is null, if to, from or subject is the empty string, or no recipient
089     * can be set. If "forgive" is false, also on any invalid to or from address.
090     * @throws IOFailure If the message cannot be sent for some reason.
091     */
092    public static void sendEmail(String to, String from, String subject, String body, boolean forgive) {
093        ArgumentNotValid.checkNotNullOrEmpty(to, "String to");
094        ArgumentNotValid.checkNotNullOrEmpty(from, "String from");
095        ArgumentNotValid.checkNotNullOrEmpty(subject, "String subject");
096        ArgumentNotValid.checkNotNull(body, "String body");
097
098        Properties props = new Properties();
099        props.put(MAIL_FROM_PROPERTY_KEY, from);
100        props.put(MAIL_HOST_PROPERTY_KEY, Settings.get(CommonSettings.MAIL_SERVER));
101
102        Session session = Session.getDefaultInstance(props);
103        Message msg = new MimeMessage(session);
104
105        // to might contain more than one e-mail address
106        for (String toAddressS : to.split(",")) {
107            try {
108                InternetAddress toAddress = new InternetAddress(toAddressS.trim());
109                msg.addRecipient(Message.RecipientType.TO, toAddress);
110            } catch (AddressException e) {
111                if (forgive) {
112                    log.warn("To address '{}' is not a valid email address", toAddressS, e);
113                } else {
114                    throw new ArgumentNotValid("To address '" + toAddressS + "' is not a valid email address", e);
115                }
116            } catch (MessagingException e) {
117                if (forgive) {
118                    log.warn("To address '{}' could not be set in email", toAddressS, e);
119                } else {
120                    throw new ArgumentNotValid("To address '" + toAddressS + "' could not be set in email", e);
121                }
122            }
123        }
124        try {
125            if (msg.getAllRecipients().length == 0) {
126                throw new ArgumentNotValid("No valid recipients in '" + to + "'");
127            }
128        } catch (MessagingException e) {
129            throw new ArgumentNotValid("Message invalid after setting recipients", e);
130        }
131
132        try {
133            InternetAddress fromAddress = null;
134            fromAddress = new InternetAddress(from);
135            msg.setFrom(fromAddress);
136        } catch (AddressException e) {
137            throw new ArgumentNotValid("From address '" + from + "' is not a valid email address", e);
138        } catch (MessagingException e) {
139            if (forgive) {
140                log.warn("From address '{}' could not be set in email", from, e);
141            } else {
142                throw new ArgumentNotValid("From address '" + from + "' could not be set in email", e);
143            }
144        }
145
146        try {
147            msg.setSubject(subject);
148            msg.setContent(body, MIMETYPE);
149            msg.setSentDate(new Date());
150            Transport.send(msg);
151        } catch (MessagingException e) {
152            throw new IOFailure("Could not send email with subject '" + subject + "' from '" + from + "' to '" + to
153                    + "'. Body:\n" + body, e);
154        }
155    }
156
157}