hornet.framework.mail.MailServiceImpl.java Source code

Java tutorial

Introduction

Here is the source code for hornet.framework.mail.MailServiceImpl.java

Source

/**
 * Copyright ou  ou Copr. Ministre de l'Europe et des Affaires trangres (2017)
 * <p/>
 * pole-architecture.dga-dsi-psi@diplomatie.gouv.fr
 * <p/>
 * Ce logiciel est un programme informatique servant  faciliter la cration
 * d'applications Web conformment aux rfrentiels gnraux franais : RGI, RGS et RGAA
 * <p/>
 * Ce logiciel est rgi par la licence CeCILL soumise au droit franais et
 * respectant les principes de diffusion des logiciels libres. Vous pouvez
 * utiliser, modifier et/ou redistribuer ce programme sous les conditions
 * de la licence CeCILL telle que diffuse par le CEA, le CNRS et l'INRIA
 * sur le site "http://www.cecill.info".
 * <p/>
 * En contrepartie de l'accessibilit au code source et des droits de copie,
 * de modification et de redistribution accords par cette licence, il n'est
 * offert aux utilisateurs qu'une garantie limite.  Pour les mmes raisons,
 * seule une responsabilit restreinte pse sur l'auteur du programme,  le
 * titulaire des droits patrimoniaux et les concdants successifs.
 * <p/>
 * A cet gard  l'attention de l'utilisateur est attire sur les risques
 * associs au chargement,   l'utilisation,   la modification et/ou au
 * dveloppement et  la reproduction du logiciel par l'utilisateur tant
 * donn sa spcificit de logiciel libre, qui peut le rendre complexe 
 * manipuler et qui le rserve donc  des dveloppeurs et des professionnels
 * avertis possdant  des  connaissances  informatiques approfondies.  Les
 * utilisateurs sont donc invits  charger  et  tester  l'adquation  du
 * logiciel  leurs besoins dans des conditions permettant d'assurer la
 * scurit de leurs systmes et ou de leurs donnes et, plus gnralement,
 *  l'utiliser et l'exploiter dans les mmes conditions de scurit.
 * <p/>
 * Le fait que vous puissiez accder  cet en-tte signifie que vous avez
 * pris connaissance de la licence CeCILL, et que vous en avez accept les
 * termes.
 * <p/>
 * <p/>
 * Copyright or  or Copr. Ministry for Europe and Foreign Affairs (2017)
 * <p/>
 * pole-architecture.dga-dsi-psi@diplomatie.gouv.fr
 * <p/>
 * This software is a computer program whose purpose is to facilitate creation of
 * web application in accordance with french general repositories : RGI, RGS and RGAA.
 * <p/>
 * This software is governed by the CeCILL license under French law and
 * abiding by the rules of distribution of free software.  You can  use,
 * modify and/ or redistribute the software under the terms of the CeCILL
 * license as circulated by CEA, CNRS and INRIA at the following URL
 * "http://www.cecill.info".
 * <p/>
 * As a counterpart to the access to the source code and  rights to copy,
 * modify and redistribute granted by the license, users are provided only
 * with a limited warranty  and the software's author,  the holder of the
 * economic rights,  and the successive licensors  have only  limited
 * liability.
 * <p/>
 * In this respect, the user's attention is drawn to the risks associated
 * with loading,  using,  modifying and/or developing or reproducing the
 * software by the user in light of its specific status of free software,
 * that may mean  that it is complicated to manipulate,  and  that  also
 * therefore means  that it is reserved for developers  and  experienced
 * professionals having in-depth computer knowledge. Users are therefore
 * encouraged to load and test the software's suitability as regards their
 * requirements in conditions enabling the security of their systems and/or
 * data to be ensured and,  more generally, to use and operate it in the
 * same conditions as regards security.
 * <p/>
 * The fact that you are presently reading this means that you have had
 * knowledge of the CeCILL license and that you accept its terms.
 *
 */
package hornet.framework.mail;

import java.io.IOException;
import java.io.InputStream;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import javax.mail.Address;
import javax.mail.AuthenticationFailedException;
import javax.mail.MessagingException;
import javax.mail.SendFailedException;
import javax.mail.Session;

import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.CharEncoding;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.io.InputStreamSource;
import org.springframework.mail.MailSendException;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.JavaMailSenderImpl;
import org.springframework.mail.javamail.MimeMessageHelper;

import com.sun.mail.smtp.SMTPMessage;

import hornet.framework.exception.BusinessException;
import hornet.framework.template.VelocityHelper;

/**
 * The Class MailServiceImpl.
 *
 * @author MAE - S. LEDUBY
 */
public class MailServiceImpl implements MailService {

    /** champ d'entete smtp "Reply-to". */
    public static final String SMTP_HEADER_REPLYTO = "smtp.header.replyto";

    /** champ d'entete smtp "Bcc". */
    public static final String SMTP_HEADER_BCC = "smtp.header.bcc";

    /** champ d'entete smtp "Cc". */
    public static final String SMTP_HEADER_CC = "smtp.header.cc";

    /** champ d'entete smtp "Priority". */
    public static final String SMTP_HEADER_PRIORITY = "smtp.header.priority";

    /** champ d'entete smtp "Return-Path". */
    public static final String SMTP_HEADER_RETURNPATH = "smtp.header.returnpath";

    /** contenu pice jointe. */
    public static final String SMTP_ATTACHMENT_CONTENU = "smtp.attachment.contenu";

    /** nom pice jointe. */
    public static final String SMTP_ATTACHMENT_NOM = "smtp.attachment.nom";

    /** Logger. */
    private static final Logger LOG = LoggerFactory.getLogger(MailServiceImpl.class);

    /** The Constant DEFAULT_MESSAGE_TEMPLATE. */
    private static final MessageFormat DEFAULT_MESSAGE_TEMPLATE = new MessageFormat("<HTML>" //
            + "<HEAD><META http-equiv=\"Content-Type\"" //
            + " content=\"text/html; charset=utf-8\"></HEAD>" //
            + "<BODY>{0}</BODY>" //
            + "</HTML>");

    /** JavaMailSender. */
    protected final transient JavaMailSender mailSender;

    /** Nom de l'application envoyant les mails. */
    protected final transient String nomApplication;

    /** Nom de domaine  utiliser pour le MessageID de l'entete SMTP. */
    protected final transient String messageIdDomainName;

    /**
     * Constructeur.
     *
     * @param mailSender
     *            JavaMailSender Spring
     * @param nomApplication
     *            Nom de l'application  l'origine de l'envoi du mail
     * @param messageIdDomainName
     *            Nom de domaine  utiliser pour le MessageID de l'entete SMTP
     */
    public MailServiceImpl(final JavaMailSender mailSender, final String nomApplication,
            final String messageIdDomainName) {

        this.mailSender = mailSender;
        this.nomApplication = nomApplication;
        this.messageIdDomainName = messageIdDomainName;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void envoyer(final String expediteur, final String sujet, final String message,
            final Map<String, Object> paramMap, final String... destinataires) {

        try {
            final Session session = ((JavaMailSenderImpl) mailSender).getSession();
            HornetMimeMessage mMessage = null;
            if (messageIdDomainName == null || messageIdDomainName.length() == 0) {
                mMessage = new HornetMimeMessage(nomApplication, session);
            } else {
                mMessage = new HornetMimeMessage(nomApplication, messageIdDomainName, session);
            }

            mMessage.setHeader("Content-Type", "text/html");
            final MimeMessageHelper helper = new MimeMessageHelper(mMessage, true, CharEncoding.UTF_8);

            addExtraSmtpField(paramMap, helper);

            helper.setFrom(expediteur);

            ajouterDestinataires(helper, destinataires);

            helper.setSubject(sujet);
            // message aux formats texte et html
            helper.setText(preparerMessageTexte(message), preparerMessageHTML(message));

            mailSender.send(mMessage);
        } catch (final MailSendException mse) {
            throw toBusinessException(mse);
        } catch (final Exception e) {
            throw new BusinessException("erreur.envoi.courriel", e);
        }
    }

    /**
     * Adds the extra smtp field.
     *
     * @param paramMap
     *            the param map
     * @param helper
     *            the helper
     * @throws MessagingException
     *             the messaging exception
     */
    protected void addExtraSmtpField(final Map<String, Object> paramMap, final MimeMessageHelper helper)
            throws MessagingException {

        if (paramMap != null) {
            if (paramMap.containsKey(SMTP_HEADER_REPLYTO)) {
                helper.setReplyTo((String) paramMap.get(SMTP_HEADER_REPLYTO));
            }
            if (paramMap.containsKey(SMTP_HEADER_BCC)) {
                helper.setBcc((String) paramMap.get(SMTP_HEADER_BCC));
            }
            if (paramMap.containsKey(SMTP_HEADER_CC)) {
                helper.setCc((String) paramMap.get(SMTP_HEADER_CC));
            }
            if (paramMap.containsKey(SMTP_HEADER_PRIORITY)) {
                helper.setPriority((Integer) paramMap.get(SMTP_HEADER_PRIORITY));
            }
            if (paramMap.containsKey(SMTP_HEADER_RETURNPATH)) {
                ((SMTPMessage) helper.getMimeMessage())
                        .setEnvelopeFrom((String) paramMap.get(SMTP_HEADER_RETURNPATH));
            }
            if (paramMap.containsKey(SMTP_ATTACHMENT_CONTENU)) {
                helper.addAttachment((String) paramMap.get(SMTP_ATTACHMENT_NOM),
                        (InputStreamSource) paramMap.get(SMTP_ATTACHMENT_CONTENU));
            }
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void envoyerDepuisModele(final String expediteur, final String sujet, final String messageTemplate,
            final Map<String, Object> paramMap, final String... destinataires) {

        String corpsMail = messageTemplate;
        String message;
        try {
            if (messageTemplate.endsWith(".vm")) {
                final InputStream is = this.getClass().getResourceAsStream("/" + messageTemplate);
                corpsMail = IOUtils.toString(is, "UTF-8");
            }

            message = VelocityHelper.renderVelocityFragment(corpsMail, paramMap);
        } catch (final IOException e) {
            throw new BusinessException("erreur.envoi.courriel", e);
        }
        envoyer(expediteur, sujet, message, paramMap, destinataires);
    }

    /**
     * Converti l'exception fourni en {@link BusinessException}.
     *
     * @param mse
     *            MailSendException
     * @return Une {@link BusinessException}
     */
    protected BusinessException toBusinessException(final MailSendException mse) {

        MailServiceImpl.LOG.debug("Conversion d'une erreur d'envoi de courriel");

        final List<String> adressesInvalides = new ArrayList<String>();
        for (final Exception exception : mse.getMessageExceptions()) {
            if (exception instanceof SendFailedException) {
                final SendFailedException sendFailedEx = (SendFailedException) exception;
                for (final Address adresseInvalide : sendFailedEx.getInvalidAddresses()) {
                    adressesInvalides.add(adresseInvalide.toString());
                    MailServiceImpl.LOG.debug(String.format("adresse invalide : %s", adresseInvalide));
                }
            } else if (exception instanceof AuthenticationFailedException) {
                final AuthenticationFailedException authenticationFailedEx = (AuthenticationFailedException) exception;
                return new BusinessException("erreur.envoi.courriel.authentification", authenticationFailedEx);
            }
        }

        if (adressesInvalides.isEmpty()) {
            return new BusinessException("erreur.envoi.courriel", mse);
        } else {
            return new BusinessException("erreur.envoi.courriel.addressesInvalides",
                    new String[] { StringUtils.join(adressesInvalides, ", ") }, mse);
        }
    }

    /**
     * Ajouter destinataires.
     *
     * @param helper
     *            Composant de prparation de message
     * @param destinataires
     *            Les destinataires
     * @throws MessagingException
     *             En cas d'invalidit d'adresse de courriel
     */
    protected void ajouterDestinataires(final MimeMessageHelper helper, final String... destinataires)
            throws MessagingException {

        helper.setTo(destinataires);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public String preparerMessageTexte(final String message) {

        String msg = message;
        if (StringUtils.isNotBlank(msg)) {
            // suppression des balises HTML
            msg = msg.replaceAll("<br\\s*/?>", "\n"); // <br>, <br/>, <br /> -> \n
            msg = msg.replaceAll("</?p[^>]*>", "\n"); // <p>, <p/>, <p />, </p> -> \n
            // <a href="url">texte</a> -> texte (url)
            msg = msg.replaceAll("<a\\s[^>]*href=['\"]([^'\"]*)['\"][^>]*>(.*)</a[^>]*>", "$2 ($1)");
            msg = msg.replaceAll("<[^>]+>", ""); // balise ouvrante ou fermante <ppp> ou </ppp>
            msg = msg.replaceAll("&nbsp;", " ");
            msg = msg.replaceAll("^\n+", ""); // \n au dbut
            msg = msg.replaceAll("\n+$", ""); // \n  la fin
        }

        return msg;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public String preparerMessageHTML(final String message) {

        String msg = message;
        if (StringUtils.isNotBlank(msg)) {
            // Encapsulation du message dans le code HTML
            msg = MailServiceImpl.DEFAULT_MESSAGE_TEMPLATE.format(new Object[] { msg });
        }

        return msg;
    }

}