001/*
002 *  Copyright 2014 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.socialnetworking;
017
018import java.io.IOException;
019import java.util.ArrayList;
020import java.util.HashMap;
021import java.util.List;
022import java.util.Map;
023import java.util.regex.Pattern;
024
025import org.apache.avalon.framework.parameters.Parameters;
026import org.apache.avalon.framework.service.ServiceException;
027import org.apache.avalon.framework.service.ServiceManager;
028import org.apache.cocoon.acting.ServiceableAction;
029import org.apache.cocoon.environment.ObjectModelHelper;
030import org.apache.cocoon.environment.Redirector;
031import org.apache.cocoon.environment.Request;
032import org.apache.cocoon.environment.SourceResolver;
033import org.apache.commons.lang.StringUtils;
034
035import org.ametys.core.captcha.CaptchaHelper;
036import org.ametys.core.cocoon.ActionResultGenerator;
037import org.ametys.core.ui.mail.StandardMailBodyHelper;
038import org.ametys.core.ui.mail.StandardMailBodyHelper.MailBodyBuilder;
039import org.ametys.core.util.I18nUtils;
040import org.ametys.core.util.mail.SendMailHelper;
041import org.ametys.plugins.repository.AmetysObjectResolver;
042import org.ametys.runtime.i18n.I18nizableText;
043import org.ametys.web.cache.PageHelper;
044import org.ametys.web.repository.page.Page;
045
046import jakarta.mail.MessagingException;
047
048/**
049 * Check if the form is well formed
050 * Send the mail to all the receiver
051 */
052public class SendMailAction extends ServiceableAction
053{
054    /** The pattern to check emails */
055    protected static final Pattern EMAIL_VALIDATOR = Pattern.compile("^([a-z0-9._-]+@[a-z0-9.-]{2,}[.][a-zA-Z0-9]{2,})?$");
056    
057    /** The pattern to check a list of emails */
058    protected static final Pattern EMAIL_LIST_VALIDATOR = Pattern.compile("^([a-z0-9._-]+@[a-z0-9.-]{2,}[.][a-z]{2,})?(\\s*,\\s*([a-z0-9._-]+@[a-z0-9.-]{2,}[.][a-z]{2,})?)*$");
059    
060    /** The pattern to check text input */
061    protected static final Pattern TEXT_VALIDATOR = Pattern.compile("^\\s*$");
062    
063    /** Repository content */
064    protected AmetysObjectResolver _resolver;
065    
066    /** The i18n utils of runtime */
067    protected I18nUtils _i18nUtils;
068
069    /** The page helper */
070    protected PageHelper _pageHelper;
071    
072    @Override
073    public void service(ServiceManager smanager) throws ServiceException
074    {
075        super.service(smanager);
076        _resolver = (AmetysObjectResolver) smanager.lookup(AmetysObjectResolver.ROLE);
077        _i18nUtils = (I18nUtils) smanager.lookup(I18nUtils.ROLE);
078        _pageHelper = (PageHelper) smanager.lookup(PageHelper.ROLE);
079    }
080    
081    @SuppressWarnings("unchecked")
082    @Override
083    public Map act(Redirector redirector, SourceResolver resolver, Map objectModel, String source, Parameters parameters) throws Exception
084    {
085        Map<String, Object> result = new HashMap<>();
086        List<I18nizableText> errors = new ArrayList<>();
087        Request request = ObjectModelHelper.getRequest(objectModel);
088        
089        String pageId = _getPageId(request);
090        Page page = _resolver.resolveById(pageId);
091        
092        if (_pageHelper.isCaptchaRequired(page))
093        { 
094            String captchaKey = request.getParameter("captcha-key");
095            String captchaValue = request.getParameter("captcha-value");
096            if (!CaptchaHelper.checkAndInvalidate(captchaKey, captchaValue)) 
097            {
098                errors.add(new I18nizableText("plugin.socialnetworking", "PLUGINS_SOCIAL_NETWORKING_SEND_MAIL_ERROR_CAPTCHA"));
099            }
100        }
101        
102        String emailBy = request.getParameter("email");
103        if (emailBy == null || !EMAIL_VALIDATOR.matcher(StringUtils.trimToEmpty(emailBy)).matches() || TEXT_VALIDATOR.matcher(StringUtils.trimToEmpty(emailBy)).matches())
104        {
105            errors.add(new I18nizableText("plugin.socialnetworking", "PLUGINS_SOCIAL_NETWORKING_SEND_MAIL_ERROR_MAILBY"));
106        }
107        else
108        {
109            result.put("emailBy", emailBy);
110        }
111        
112        String emailTo = request.getParameter("emailTo");
113        if (emailTo == null || !EMAIL_LIST_VALIDATOR.matcher(StringUtils.trimToEmpty(emailTo)).matches() || TEXT_VALIDATOR.matcher(StringUtils.trimToEmpty(emailTo)).matches())
114        {
115            errors.add(new I18nizableText("plugin.socialnetworking", "PLUGINS_SOCIAL_NETWORKING_SEND_MAIL_ERROR_MAILTO"));
116        }
117        else
118        {
119            result.put("emailTo", emailTo);
120        }
121        
122        String userName = request.getParameter("name");
123        if (userName == null || TEXT_VALIDATOR.matcher(StringUtils.trimToEmpty(userName)).matches())
124        {
125            errors.add(new I18nizableText("plugin.socialnetworking", "PLUGINS_SOCIAL_NETWORKING_SEND_MAIL_ERROR_NAME"));
126        }
127        else
128        {
129            result.put("name", userName);
130        }
131        
132        String text = request.getParameter("text");
133        if (text == null)
134        {
135            errors.add(new I18nizableText("plugin.socialnetworking", "PLUGINS_SOCIAL_NETWORKING_SEND_MAIL_ERROR_CONTENT"));
136        }
137        else
138        {
139            result.put("text", text);
140        }
141        
142        if (errors.isEmpty())
143        {            
144            String pagePath = request.getHeader("Referer");
145            String lang = page.getSitemapName();
146            
147            List<String> i18nparam = new ArrayList<>();
148            i18nparam.add(page.getTitle());
149            i18nparam.add(page.getSite().getTitle());
150            
151            I18nizableText i18nTextSubject = new I18nizableText("plugin.socialnetworking", "PLUGINS_SOCIAL_NETWORKING_SEND_MAIL_SUBJECT", i18nparam);
152            String subject = _i18nUtils.translate(i18nTextSubject, lang);
153            
154            i18nparam = new ArrayList<>();
155            i18nparam.add(userName);
156            i18nparam.add(pagePath); // Page path
157            i18nparam.add(text);
158            i18nparam.add(page.getSite().getUrl()); // Site url
159            
160            I18nizableText i18nTextBody = new I18nizableText("plugin.socialnetworking", "PLUGINS_SOCIAL_NETWORKING_SEND_MAIL_TEXT_BODY", i18nparam);
161            String textBody = _i18nUtils.translate(i18nTextBody, lang);
162            
163            MailBodyBuilder bodyBuilder = StandardMailBodyHelper.newHTMLBody()
164                .withMessage(new I18nizableText("plugin.socialnetworking", "PLUGINS_SOCIAL_NETWORKING_SEND_MAIL_HTML_BODY", i18nparam))
165                .withLanguage(lang)
166                .withTitle(subject)
167                
168                .withLink(page.getSite().getUrl(), new I18nizableText("plugin.socialnetworking", "PLUGINS_SOCIAL_NETWORKING_SEND_MAIL_HTML_BODY_SITE_LINK"));
169            
170            if (StringUtils.isNotEmpty(text))
171            {
172                bodyBuilder.withDetails(new I18nizableText("plugin.socialnetworking", "PLUGINS_SOCIAL_NETWORKING_SEND_MAIL_HTML_BODY_MESSAGE"), text, false);
173            }
174                        
175            String htmlBody = bodyBuilder.build();
176            
177            String[] tabMail = StringUtils.split(emailTo, ",");
178            for (int i = 0; i < tabMail.length; i++)
179            {
180                try
181                {
182                    SendMailHelper.newMail()
183                                  .withSubject(subject)
184                                  .withHTMLBody(htmlBody)
185                                  .withTextBody(textBody)
186                                  .withSender(emailBy)
187                                  .withRecipient(StringUtils.trimToEmpty(tabMail[i]))
188                                  .sendMail();
189                }
190                catch (MessagingException | IOException e)
191                {
192                    if (!result.containsKey("mailError"))
193                    {
194                        result.put("mailError", new ArrayList<>());
195                    }
196                    
197                    ((List<String>) result.get("mailError")).add(tabMail[i]);
198                    
199                    getLogger().error("Failed to send mail to '" + tabMail[i] + "'", e);
200                }
201            }     
202        }
203        
204        result.put("error", errors);
205        
206        request.setAttribute(ActionResultGenerator.MAP_REQUEST_ATTR, result);
207        
208        return EMPTY_MAP;
209    }
210
211    private String _getPageId(Request request)
212    {
213        String pageId = request.getParameter("page-id");
214        if (pageId == null) 
215        {
216            throw new IllegalStateException("Unable to send page by mail: cannot determine the current page");
217        }
218        else
219        {
220            Page page = _resolver.resolveById(pageId);
221            if (page == null)
222            {
223                throw new IllegalStateException("Unable to send page by mail: the page of id " + pageId + " is unknown");
224            }
225        }
226        return pageId;
227    }
228
229}