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}