001/*
002 *  Copyright 2010 Anyware Services
003 *
004 *  Licensed under the Apache License, Version 2.0 (the "License");
005 *  you may not use this file except in compliance with the License.
006 *  You may obtain a copy of the License at
007 *
008 *      http://www.apache.org/licenses/LICENSE-2.0
009 *
010 *  Unless required by applicable law or agreed to in writing, software
011 *  distributed under the License is distributed on an "AS IS" BASIS,
012 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 *  See the License for the specific language governing permissions and
014 *  limitations under the License.
015 */
016package org.ametys.plugins.newsletter.workflow;
017
018import java.io.IOException;
019import java.util.Date;
020import java.util.Map;
021import java.util.Random;
022import java.util.regex.Matcher;
023import java.util.regex.Pattern;
024
025import org.slf4j.Logger;
026import org.slf4j.LoggerFactory;
027
028import org.ametys.core.util.mail.SendMailHelper;
029import org.ametys.web.analytics.AbstractWebAnalyticsProvider;
030
031import jakarta.mail.MessagingException;
032
033/**
034 * Sends mails in a thread
035 */
036public class SendMailEngine implements Runnable
037{
038    private static Logger _logger = LoggerFactory.getLogger(SendMailEngine.class);
039
040    private static final Random _RNG = new Random((long) Math.random() * System.nanoTime());
041    
042    private String _subject;
043    private String _htmlBody;
044    private String _textBody;
045    private Map<String, String> _recipients;
046    private String _sender;
047    
048    private boolean _parametrized;
049    
050    /**
051     * Parameterize engine
052     * @param subject The mail subject
053     * @param htmlBody The mail body in HTML format
054     * @param textBody The mail body in text format
055     * @param recipients The recipient addresses
056     * @param sender The sender address
057     */
058    public void parameterize (String subject, String htmlBody, String textBody, Map<String, String> recipients, String sender)
059    {
060        _subject = subject;
061        _htmlBody = SendMailHelper.inlineCSS(htmlBody);
062        _textBody = textBody;
063        _recipients = recipients;
064        _sender = sender;
065        
066        _parametrized = true;
067    }
068    
069    private void _checkParametrization()
070    {
071        if (!_parametrized)
072        {
073            String message = "The mail engine component has to be parameterized before it can be run.";
074            _logger.error(message);
075            throw new IllegalStateException(message);
076        }
077    }
078    
079    public void run()
080    {
081        _checkParametrization ();
082        
083        if (_logger.isInfoEnabled())
084        {
085            _logger.info("Try to send " + _recipients.size() + " mails at " + new Date());
086        }
087
088        for (String recipient : _recipients.keySet())
089        {
090            try
091            {
092                String htmlBody = _htmlBody.replaceAll("#token#", _recipients.get(recipient));
093                String textBody = _textBody.replaceAll("#token#", _recipients.get(recipient));
094                
095                Pattern pattern = Pattern.compile("\\" + AbstractWebAnalyticsProvider.RANDOM_NUMBER_TOKEN);
096                Matcher m = pattern.matcher(htmlBody);
097                StringBuffer sb = new StringBuffer();
098                while (m.find()) 
099                {
100                    m.appendReplacement(sb, Integer.toString(_RNG.nextInt(Integer.MAX_VALUE)));
101                }
102                m.appendTail(sb);
103
104                SendMailHelper.newMail()
105                              .withSubject(_subject)
106                              .withHTMLBody(sb.toString())
107                              .withInlineCSS(false) // We inline the CSS manually once and for all to avoid doing it multiple times
108                              .withTextBody(textBody)
109                              .withSender(_sender)
110                              .withRecipient(recipient)
111                              .sendMail();
112                
113                Thread.sleep(1000);
114            }
115            catch (MessagingException | IOException e)
116            {
117                _logger.error("Mail failed !", e);
118            }
119            catch (InterruptedException e)
120            {
121                _logger.error("Error while waiting for sending mails", e);
122            }
123        }
124        
125        if (_logger.isInfoEnabled())
126        {
127            _logger.info("All mails are sent at " + new Date());
128        }
129    }
130}