2 * Copyright (C) 2001, 2002 The Mir-coders group
4 * This file is part of Mir.
6 * Mir is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * Mir is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with Mir; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 * In addition, as a special exception, The Mir-coders gives permission to link
21 * the code of this program with any library licensed under the Apache Software License,
22 * The Sun (tm) Java Advanced Imaging library (JAI), The Sun JIMI library
23 * (or with modified versions of the above that use the same license as the above),
24 * and distribute linked combinations including the two. You must obey the
25 * GNU General Public License in all respects for all of the code used other than
26 * the above mentioned libraries. If you modify this file, you may extend this
27 * exception to your version of the file, but you are not obligated to do so.
28 * If you do not wish to do so, delete this exception statement from your version.
30 package mircoders.localizer.basic;
32 import java.io.IOException;
33 import java.io.PrintWriter;
34 import java.io.StringWriter;
35 import java.util.ArrayList;
36 import java.util.Collections;
37 import java.util.HashMap;
38 import java.util.List;
39 import java.util.Locale;
42 import mir.config.MirPropertiesConfiguration;
43 import mir.generator.Generator;
44 import mir.generator.GeneratorHelper;
45 import mir.log.LoggerWrapper;
46 import mir.session.Request;
47 import mir.session.Response;
48 import mir.session.Session;
49 import mir.session.SessionExc;
50 import mir.session.SessionFailure;
51 import mir.session.SessionHandler;
52 import mir.session.ValidationHelper;
53 import mir.session.HTTPAdapters.HTTPRequestAdapter;
54 import mir.util.StringRoutines;
55 import mircoders.entity.EntityContent;
56 import mircoders.global.CacheKey;
57 import mircoders.global.MirGlobal;
58 import mircoders.module.ModuleContent;
60 import org.apache.commons.net.smtp.SMTPClient;
61 import org.apache.commons.net.smtp.SMTPReply;
66 * <p>Title: Tenative session handler for emailing postings </p>
67 * <p>Description: </p>
68 * <p>Copyright: Copyright (c) 2003</p>
75 public class MirBasicEmailArticleHandler implements SessionHandler {
76 protected LoggerWrapper logger;
77 protected MirPropertiesConfiguration configuration;
79 public MirBasicEmailArticleHandler() {
80 logger = new LoggerWrapper("Localizer.EmailArticle");
82 configuration = MirPropertiesConfiguration.instance();
85 logger.fatal("Cannot load configuration: " + t.toString());
87 throw new RuntimeException("Cannot load configuration: " + t.toString());
91 public void processRequest(Request aRequest, Session aSession, Response aResponse) throws SessionExc, SessionFailure {
92 if (aSession.getAttribute("initialRequest") == null) {
93 aSession.setAttribute("initialRequest", "no");
94 initialRequest(aRequest, aSession, aResponse);
97 subsequentRequest(aRequest, aSession, aResponse);
101 protected void initialRequest(Request aRequest, Session aSession, Response aResponse) throws SessionExc, SessionFailure {
102 initializeSession(aRequest, aSession);
103 makeInitialResponse(aRequest, aSession, aResponse);
106 protected void initializeSession(Request aRequest, Session aSession) throws SessionExc, SessionFailure {
107 /* do nothing for now */
111 protected void makeInitialResponse(Request aRequest, Session aSession, Response aResponse) throws SessionExc, SessionFailure {
112 /* if you do not supply an aid to this handler, it should return an error page */
113 /* if you supply a non-functioning/non-published aid to this handler, it should return an error page, but at a
114 later stage, because we don't check the db until we are potentially populating the cache*/
115 /* otherwise you get to address an article and add some comments */
116 String articleID = aRequest.getParameter("mail_aid");
117 if (articleID == null){
118 throw new SessionExc("makeInitialResponse: article id not set!");
121 aSession.setAttribute("email.aid",articleID);
122 aResponse.setResponseValue("errors", null);
124 String mail_language = configuration.getString("Mir.Login.DefaultLanguage", "en");
125 aResponse.setResponseValue("mail_language",mail_language);
126 aResponse.setResponseValue("mail_to","");
127 aResponse.setResponseValue("mail_from","");
128 aResponse.setResponseValue("mail_from_name","");
129 aResponse.setResponseValue("mail_comment","");
131 aResponse.setResponseGenerator(configuration.getString("Localizer.OpenSession.email.PrepareTemplate"));
137 protected boolean shouldSendMail(Request aRequest, Session aSession, Response aResponse,List aValidationErrors) throws SessionExc, SessionFailure{
138 if (validate(aRequest,aSession,aResponse,aValidationErrors)){
139 String to=aRequest.getParameter("mail_to");
140 if (to.indexOf('@') == -1
141 || to.indexOf('\n') != -1
142 || to.indexOf('\r') != -1
143 || to.indexOf(',') != -1) {
144 throw new SessionExc("Invalid to address"); // we might want to see this in a log, so it is not a validation error
146 return true; // go for it
148 return false; //validation failed, but not in a potentially abusive way
156 protected boolean validate(Request aRequest, Session aSession, Response aResponse,List aValidationErrors) throws SessionExc, SessionFailure{
158 if (ValidationHelper.testFieldEntered(aRequest, "mail_to", "validationerror.missing", aValidationErrors))
159 aResponse.setResponseValue("mail_to",aRequest.getParameter("mail_to"));
160 if (ValidationHelper.testFieldEntered(aRequest, "mail_from", "validationerror.missing", aValidationErrors))
161 aResponse.setResponseValue("mail_from",aRequest.getParameter("mail_from"));
162 if (ValidationHelper.testFieldEntered(aRequest, "mail_from_name", "validationerror.missing", aValidationErrors))
163 aResponse.setResponseValue("mail_from_name",aRequest.getParameter("mail_from_name"));
164 if (ValidationHelper.testFieldEntered(aRequest, "mail_language", "validationerror.missing", aValidationErrors))
165 aResponse.setResponseValue("mail_language",aRequest.getParameter("mail_language"));
167 return (aValidationErrors==null || aValidationErrors.size() == 0);
170 protected String getEmailText(String aid,String language) throws SessionExc{
172 CacheKey theCacheKey=new CacheKey("email",aid+language);
174 if (MirGlobal.mruCache().hasObject(theCacheKey)){
175 logger.info("fetching email text for article "+aid+" from cache");
176 theText = (String) MirGlobal.mruCache().getObject(theCacheKey);
180 ModuleContent contentModule = new ModuleContent();
181 EntityContent contentEnt = (EntityContent) contentModule.getById(aid);
183 Map articleData = new HashMap();
184 articleData.put("article", MirGlobal.localizer().dataModel().adapterModel().makeEntityAdapter("content", contentEnt));
185 articleData.put("languagecode", language);
186 Map responseData = GeneratorHelper.makeBasicGenerationData(new Locale[] {new Locale(language,""),new Locale(configuration.getString("Mir.Admin.FallbackLanguage", "en"), "")},"bundles.open","bundles.open");
187 responseData.put("data",articleData);
189 String emailAnArticleTemplate = configuration.getString("Localizer.OpenSession.email.MailTemplate");
191 Generator generator = MirGlobal.localizer().generators().makeOpenPostingGeneratorLibrary().makeGenerator(emailAnArticleTemplate);
193 StringWriter theEmailStringWriter = new StringWriter();
194 PrintWriter theEmailPrintWriter = new PrintWriter(theEmailStringWriter);
195 generator.generate(theEmailPrintWriter, responseData, logger);
197 theEmailStringWriter.close();
199 theText = theEmailStringWriter.toString();
200 MirGlobal.mruCache().storeObject(theCacheKey, theText);
202 catch (Throwable e) {
203 throw new SessionExc("Couldn't get content for article " + aid + language + ": " + e.getMessage());
210 protected String getExtraEmailHeaders(Request aRequest,String to,String from) throws SessionExc {
212 String headers = "To: " + to + "\nReply-To: "+ from+"\n";
213 if (configuration.getString("Localizer.OpenSession.email.includeSenderIP","no").equals("yes"))
214 headers= headers+"X-Originating-IP: "+ ((HTTPRequestAdapter)aRequest).getRequest().getRemoteAddr() + "\n";
219 protected String interpolateComment(String emailText,String comment,String from_name,String language) throws SessionExc{
220 if (comment != null) {
221 String commentTextToInsert =
222 MirGlobal.getBundleFactory().getBundle("etc/bundles/open", new String[] { language }).
223 getValue("email.comment.intro" , Collections.singletonList(from_name)) + "\n";
226 emailText = StringRoutines.performRegularExpressionReplacement(emailText, "!COMMENT!", commentTextToInsert);
228 catch (Throwable e) {
229 throw new SessionExc("Problem doing regular expression replacement :" + e.toString());
234 emailText = StringRoutines.performRegularExpressionReplacement(emailText, "!COMMENT!", "");
236 catch (Throwable e) {
237 throw new SessionExc("Problem doing regular expression replacement " + e.toString());
243 protected boolean doTheSMTP(String aMessage,String aTo,String aFrom) throws SessionExc{
244 SMTPClient client=new SMTPClient();
247 client.connect(configuration.getString("ServletModule.OpenIndy.SMTPServer"));
248 reply = client.getReplyCode();
250 if (!SMTPReply.isPositiveCompletion(reply)) {
252 throw new SessionExc("SMTP server refused connection.");
254 boolean trueIfItWorked = client.sendSimpleMessage(configuration.getString("ServletModule.OpenIndy.EmailIsFrom"), aTo, aMessage);
256 // mission accomplished??
257 if (! trueIfItWorked)
258 throw new SessionExc(client.getReplyString());
259 return trueIfItWorked;
261 catch(IOException e) {
262 if(client.isConnected()) {
265 } catch(IOException f) {
269 throw new SessionExc(e.getMessage());
273 protected boolean sendMail(Request aRequest,Session aSession,Response aResponse) throws SessionExc,SessionFailure {
274 String to=aRequest.getParameter("mail_to");
275 String from=aRequest.getParameter("mail_from");
276 String from_name=aRequest.getParameter("mail_from_name");
277 String language=aRequest.getParameter("mail_language");
278 String comment=aRequest.getParameter("mail_comment");
280 String theEmailText=getEmailText((String) aSession.getAttribute("email.aid"),language);
281 String headers=getExtraEmailHeaders(aRequest,to,from);
282 theEmailText=interpolateComment(theEmailText,comment,from_name,language);
283 String message=headers+theEmailText; // the space between headers and content is in the template
285 return doTheSMTP(message,to,from);
290 protected void subsequentRequest(Request aRequest, Session aSession, Response aResponse) throws SessionExc, SessionFailure {
291 List validationErrors = new ArrayList();
292 if (shouldSendMail(aRequest,aSession,aResponse,validationErrors)){
294 sendMail(aRequest,aSession,aResponse);
295 aResponse.setResponseGenerator(configuration.getString("Localizer.OpenSession.email.DoneTemplate"));
298 aResponse.setResponseValue("mail_comment",aRequest.getParameter("mail_comment")); //everything else is required
299 aResponse.setResponseValue("errors",validationErrors);
300 aResponse.setResponseGenerator(configuration.getString("Localizer.OpenSession.email.PrepareTemplate"));
306 String mail_language = aRequest.getParameter("mail_language");
307 if (mail_language == null)
308 mail_language = configuration.getString("Mir.Login.DefaultLanguage", "en");
310 aResponse.setResponseValue("mail_language",mail_language);