no.kantega.publishing.modules.mailsender.MailSender.java Source code

Java tutorial

Introduction

Here is the source code for no.kantega.publishing.modules.mailsender.MailSender.java

Source

/*
 * Copyright 2009 Kantega AS
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package no.kantega.publishing.modules.mailsender;

import no.kantega.commons.configuration.Configuration;
import no.kantega.commons.exception.ConfigurationException;
import no.kantega.commons.exception.SystemException;
import no.kantega.publishing.common.Aksess;
import no.kantega.publishing.eventlog.Event;
import no.kantega.publishing.eventlog.EventLog;
import no.kantega.publishing.spring.RootContext;
import org.apache.commons.io.IOUtils;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;
import org.apache.velocity.tools.generic.DateTool;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;

import javax.activation.DataHandler;
import javax.activation.FileDataSource;
import javax.mail.*;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
import javax.mail.util.ByteArrayDataSource;
import java.io.File;
import java.io.InputStream;
import java.io.StringWriter;
import java.io.UnsupportedEncodingException;
import java.util.Base64;
import java.util.Date;
import java.util.Map;
import java.util.Properties;

/**
 * Utility class for sending mail - with helper methods to create elements to use in a mail.
 *
 * @author Anders Skar, Vidar B. Tilrem
 */
public class MailSender {
    private static final Logger log = LoggerFactory.getLogger(MailSender.class);
    private static EventLog eventLog;

    /**
     * Sends a mail message. The message body is created by using a simple template mechanism. See MailTextReader.
     *
     * @param from           Sender's email address.
     * @param to             Recipient's email address.
     * @param subject        Subject text for the email.
     * @param contentFile    Template file.
     * @param replaceStrings Strings to insert into template.
     * @throws SystemException        if an unexpected error occurs.
     * @throws ConfigurationException if a configuration error occurs.
     */
    public static void send(String from, String to, String subject, String contentFile, String replaceStrings[])
            throws SystemException, ConfigurationException {
        // Fyll inn content
        String text = MailTextReader.getContent(contentFile, replaceStrings);
        send(from, to, subject, text);

    }

    /**
     * Sends a mail message. The message body is created by using a Velocity template.
     *
     * @param from        Sender's email address.
     * @param to          Recipient's email address.
     * @param subject     Subject text for the email.
     * @param contentFile Velocity template file.
     * @param parameters  Parameters used by Velocity to merge values into the template.
     * @throws SystemException        if an unexpected error occurs.
     * @throws ConfigurationException if a configuration error occurs.
     */
    public static void send(String from, String to, String subject, String contentFile,
            Map<String, Object> parameters) throws SystemException, ConfigurationException {
        String content = createStringFromVelocityTemplate(contentFile, parameters);
        if (log.isDebugEnabled()) {
            log.debug("Email parameters: " + parameters);
            log.debug("Email content: " + content);
            log.debug("Email content, encoded with default charset and then base64 encoded: "
                    + Base64.getEncoder().encodeToString(content.getBytes()));
            try {
                log.debug("Email content, encoded with iso-8859-1 and then base64 encoded: "
                        + Base64.getEncoder().encodeToString(content.getBytes("iso-8859-1")));
            } catch (UnsupportedEncodingException e) {
                log.error("Unable to encode email content as iso-8859-1");
            }
        }

        send(from, to, subject, content);
    }

    /**
     * Sends a mail message with a simple string as the message body.
     *
     * @param from    Sender's email address.
     * @param to      Recipient's email address.
     * @param subject Subject text for the email.
     * @param content The message body.
     * @throws SystemException        if an unexpected error occurs.
     * @throws ConfigurationException if a configuration error occurs.
     */
    public static void send(String from, String to, String subject, String content)
            throws ConfigurationException, SystemException {
        try {
            MimeBodyPart bp = createMimeBodyPartFromStringMessage(content);
            send(from, to, subject, new MimeBodyPart[] { bp });
        } catch (SystemException e) {
            throw new SystemException("Feil ved utsending av epost", e);
        }

    }

    /**
     * Sends a mail message. The content must be provided as MimeBodyPart objects.
     *
     * @param from      Sender's email address.
     * @param to        Recipient's email address.
     * @param subject   Subject text for the email.
     * @param bodyParts The body parts to insert into the message.
     * @throws SystemException        if an unexpected error occurs.
     * @throws ConfigurationException if a configuration error occurs.
     */
    public static void send(String from, String to, String subject, MimeBodyPart[] bodyParts)
            throws ConfigurationException, SystemException {
        send(from, to, null, null, subject, bodyParts);
    }

    /**
     * Sends a mail message. The content must be provided as MimeBodyPart objects.
     *
     * @param from      Sender's email address.
     * @param to        Recipient's email address.
     * @param cc        Email address for CC.
     * @param bcc       Email address for BCC.
     * @param subject   Subject text for the email.
     * @param bodyParts The body parts to insert into the message.
     * @throws SystemException        if an unexpected error occurs.
     * @throws ConfigurationException if a configuration error occurs.
     */
    public static void send(String from, String to, String cc, String bcc, String subject, MimeBodyPart[] bodyParts)
            throws ConfigurationException, SystemException {

        initEventLog();

        try {
            Properties props = new Properties();

            Configuration config = Aksess.getConfiguration();
            String host = config.getString("mail.host");
            if (host == null) {
                throw new ConfigurationException("mail.host");
            }

            // I noen tilfeller nsker vi at all epost skal g til en testadresse
            String catchAllTo = config.getString("mail.catchall.to");
            boolean catchallExists = catchAllTo != null && catchAllTo.contains("@");
            if (catchallExists) {
                StringBuilder prefix = new StringBuilder(" (original recipient: " + to);
                if (cc != null) {
                    prefix.append(", cc: ").append(cc);
                }
                if (bcc != null) {
                    prefix.append(", bcc: ").append(bcc);
                }
                prefix.append(") ");
                subject = prefix + subject;
                to = catchAllTo;
                cc = null;
                bcc = null;
            }

            props.setProperty("mail.smtp.host", host);

            Session session = Session.getDefaultInstance(props);

            boolean debug = config.getBoolean("mail.debug", false);
            if (debug) {
                session.setDebug(true);
            }

            // Opprett message, sett attributter
            MimeMessage message = new MimeMessage(session);
            InternetAddress fromAddress = new InternetAddress(from);
            InternetAddress toAddress[] = InternetAddress.parse(to);

            message.setFrom(fromAddress);

            if (toAddress.length > 1) {
                message.setRecipients(Message.RecipientType.BCC, toAddress);
            } else {
                message.setRecipients(Message.RecipientType.TO, toAddress);
            }
            if (cc != null) {
                message.addRecipients(Message.RecipientType.CC, cc);
            }
            if (bcc != null) {
                message.addRecipients(Message.RecipientType.BCC, bcc);
            }

            message.setSubject(subject, "ISO-8859-1");
            message.setSentDate(new Date());

            Multipart mp = new MimeMultipart();
            for (MimeBodyPart bodyPart : bodyParts) {
                mp.addBodyPart(bodyPart);
            }
            message.setContent(mp);

            // Send meldingen
            Transport.send(message);

            eventLog.log("System", null, Event.EMAIL_SENT, to + ":" + subject, null);

            // Logg sending
            log.info("Sending email to " + to + " with subject " + subject);
        } catch (MessagingException e) {
            String errormessage = "Subject: " + subject + " | Error: " + e.getMessage();
            eventLog.log("System", null, Event.FAILED_EMAIL_SUBMISSION, errormessage + " | to: " + to, null);
            log.error("Error sending mail", e);
            throw new SystemException("Error sending email to : " + to + " with subject " + subject, e);
        }
    }

    private static void initEventLog() {
        if (eventLog == null) {
            eventLog = RootContext.getInstance().getBean(EventLog.class);
        }
    }

    /**
     * Helper method to create a string from a Velocity template.
     *
     * @param templateFile The name of the template file to use.
     * @param parameters   The values to merge into the template.
     * @return The result of the merge.
     * @throws SystemException if template handling fails.
     */
    public static String createStringFromVelocityTemplate(String templateFile, Map<String, Object> parameters)
            throws SystemException {
        try {
            Velocity.init();

            ResourceLoader source = (ResourceLoader) RootContext.getInstance()
                    .getBean("emailTemplateResourceLoader");
            Resource resource = source.getResource(templateFile);

            parameters.put("dateFormatter", new DateTool());

            Configuration config = Aksess.getConfiguration();

            String encoding = config.getString("mail.templates.encoding", "ISO-8859-1");
            try (InputStream is = resource.getInputStream()) {
                String templateText = IOUtils.toString(is, encoding);

                VelocityContext context = new VelocityContext(parameters);
                StringWriter textWriter = new StringWriter();
                Velocity.evaluate(context, textWriter, "body", templateText);

                return textWriter.toString();
            }
        } catch (Exception e) {
            throw new SystemException(
                    "Feil ved generering av mailtekst basert p Velocity. TemplateFile: " + templateFile, e);
        }
    }

    /**
     * Helper method to create a string from a Velocity template.
     *
     * @param templateFile The name of the template file to use.
     * @return A VelocityTemplateRenderer you can configure to render the template to a string
     */
    public static VelocityTemplateRenderer createVelocityTemplateRenderer(String templateFile)
            throws SystemException {
        return new VelocityTemplateRenderer(templateFile);
    }

    /**
     * Helper method to create a MimeBodyPart from a string.
     *
     * @param content The string to insert into the MimeBodyPart.
     * @return The resulting MimeBodyPart.
     * @throws SystemException if the MimeBodyPart can't be created.
     */
    public static MimeBodyPart createMimeBodyPartFromStringMessage(String content) throws SystemException {
        try {
            MimeBodyPart bp = new MimeBodyPart();
            if (content.toLowerCase().contains("<html>")) {
                log.debug("Set content as text/html");
                bp.setContent(content, "text/html; charset=iso-8859-1");
            } else {
                log.debug("Set content as text/plain");
                bp.setText(content, "ISO-8859-1");
                bp.setHeader("Content-Transfer-Encoding", "quoted-printable");
            }
            return bp;
        } catch (MessagingException e) {
            throw new SystemException("Feil ved generering av MimeBodyPart fra string", e);
        }
    }

    /**
     * Helper method to create a MimeBodyPart from a binary file.
     *
     * @param pathToFile The complete path to the file - including file name.
     * @param contentType The Mime content type of the file.
     * @param fileName   The name of the file - as it will appear for the mail recipient.
     * @return The resulting MimeBodyPart.
     * @throws SystemException if the MimeBodyPart can't be created.
     */
    public static MimeBodyPart createMimeBodyPartFromBinaryFile(final String pathToFile, final String contentType,
            String fileName) throws SystemException {
        try {
            MimeBodyPart attachmentPart1 = new MimeBodyPart();
            FileDataSource fileDataSource1 = new FileDataSource(pathToFile) {
                @Override
                public String getContentType() {
                    return contentType;
                }
            };
            attachmentPart1.setDataHandler(new DataHandler(fileDataSource1));
            attachmentPart1.setFileName(fileName);
            return attachmentPart1;
        } catch (MessagingException e) {
            throw new SystemException("Feil ved generering av MimeBodyPart fra binrfil", e);
        }
    }

    /**
     * Helper method to create a MimeBodyPart from a binary file.
     *
     * @param data Data
     * @param contentType The Mime content type of the file.
     * @param fileName   The name of the file - as it will appear for the mail recipient.
     * @return The resulting MimeBodyPart.
     * @throws SystemException if the MimeBodyPart can't be created.
     */
    public static MimeBodyPart createMimeBodyPartFromData(byte[] data, final String contentType, String fileName)
            throws SystemException {
        try {
            MimeBodyPart attachmentPart1 = new MimeBodyPart();
            ByteArrayDataSource dataSource = new ByteArrayDataSource(data, contentType) {
                @Override
                public String getContentType() {
                    return contentType;
                }
            };
            attachmentPart1.setDataHandler(new DataHandler(dataSource));
            attachmentPart1.setFileName(fileName);
            return attachmentPart1;
        } catch (MessagingException e) {
            throw new SystemException("Feil ved generering av MimeBodyPart fra data[]", e);
        }
    }

    /**
     * Helper method to create a MimeBodyPart from a binary file.
     *
     * @param file     The file.
     * @param contentType The Mime content type of the file.
     * @param fileName The name of the file - as it will appear for the mail recipient.
     * @return The resulting MimeBodyPart.
     * @throws SystemException if the MimeBodyPart can't be created.
     */
    public static MimeBodyPart createMimeBodyPartFromBinaryFile(final File file, final String contentType,
            String fileName) throws SystemException {
        try {
            MimeBodyPart attachmentPart1 = new MimeBodyPart();
            FileDataSource fileDataSource1 = new FileDataSource(file) {
                @Override
                public String getContentType() {
                    return contentType;
                }
            };
            attachmentPart1.setDataHandler(new DataHandler(fileDataSource1));
            attachmentPart1.setFileName(fileName);
            return attachmentPart1;
        } catch (MessagingException e) {
            throw new SystemException("Feil ved generering av MimeBodyPart fra binrfil", e);
        }
    }
}