1   /**
2    * Copyright (c) 2000-2007 Liferay, Inc. All rights reserved.
3    *
4    * Permission is hereby granted, free of charge, to any person obtaining a copy
5    * of this software and associated documentation files (the "Software"), to deal
6    * in the Software without restriction, including without limitation the rights
7    * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8    * copies of the Software, and to permit persons to whom the Software is
9    * furnished to do so, subject to the following conditions:
10   *
11   * The above copyright notice and this permission notice shall be included in
12   * all copies or substantial portions of the Software.
13   *
14   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20   * SOFTWARE.
21   */
22  
23  package com.liferay.portlet.mail.action;
24  
25  import com.liferay.portal.kernel.util.Constants;
26  import com.liferay.portal.kernel.util.ParamUtil;
27  import com.liferay.portal.kernel.util.StringMaker;
28  import com.liferay.portal.kernel.util.StringPool;
29  import com.liferay.portal.kernel.util.StringUtil;
30  import com.liferay.portal.kernel.util.Validator;
31  import com.liferay.portal.model.User;
32  import com.liferay.portal.struts.PortletAction;
33  import com.liferay.portal.theme.ThemeDisplay;
34  import com.liferay.portal.util.ContentTypeUtil;
35  import com.liferay.portal.util.DateFormats;
36  import com.liferay.portal.util.PortalUtil;
37  import com.liferay.portal.util.WebKeys;
38  import com.liferay.portlet.mail.RecipientException;
39  import com.liferay.portlet.mail.model.MailAttachment;
40  import com.liferay.portlet.mail.model.MailMessage;
41  import com.liferay.portlet.mail.model.RemoteMailAttachment;
42  import com.liferay.portlet.mail.util.MailUtil;
43  import com.liferay.portlet.mail.util.multiaccount.MailAccount;
44  import com.liferay.portlet.mail.util.multiaccount.MailAccounts;
45  import com.liferay.util.FileUtil;
46  import com.liferay.util.Html;
47  import com.liferay.util.mail.InternetAddressUtil;
48  import com.liferay.util.servlet.SessionErrors;
49  import com.liferay.util.servlet.UploadPortletRequest;
50  
51  import java.io.File;
52  
53  import java.text.DateFormat;
54  
55  import java.util.ArrayList;
56  import java.util.Enumeration;
57  import java.util.HashMap;
58  import java.util.Iterator;
59  import java.util.List;
60  import java.util.Map;
61  
62  import javax.mail.internet.InternetAddress;
63  
64  import javax.portlet.ActionRequest;
65  import javax.portlet.ActionResponse;
66  import javax.portlet.PortletConfig;
67  import javax.portlet.PortletPreferences;
68  import javax.portlet.PortletRequest;
69  import javax.portlet.RenderRequest;
70  import javax.portlet.RenderResponse;
71  
72  import javax.servlet.http.HttpServletRequest;
73  
74  import org.apache.struts.action.ActionForm;
75  import org.apache.struts.action.ActionForward;
76  import org.apache.struts.action.ActionMapping;
77  
78  /**
79   * <a href="EditMessageAction.java.html"><b><i>View Source</i></b></a>
80   *
81   * @author Ming-Gih Lam
82   * @author  Alexander Chow
83   *
84   */
85  public class EditMessageAction extends PortletAction {
86  
87      public void processAction(
88              ActionMapping mapping, ActionForm form, PortletConfig config,
89              ActionRequest req, ActionResponse res)
90          throws Exception {
91  
92          try {
93              completeMessage(req);
94  
95              sendRedirect(req, res);
96          }
97          catch (Exception e) {
98              if (e instanceof RecipientException) {
99                  SessionErrors.add(req, e.getClass().getName());
100             }
101             else {
102                 throw e;
103             }
104         }
105     }
106 
107     public ActionForward render(
108             ActionMapping mapping, ActionForm form, PortletConfig config,
109             RenderRequest req, RenderResponse res)
110         throws Exception {
111 
112         HttpServletRequest httpReq = PortalUtil.getHttpServletRequest(req);
113 
114         String cmd = ParamUtil.getString(req, Constants.CMD);
115 
116         PortletPreferences prefs = req.getPreferences();
117 
118         String folderId = ParamUtil.getString(req, "folderId");
119         long messageId = ParamUtil.getLong(req, "messageId");
120 
121         String signature = prefs.getValue("signature", StringPool.BLANK);
122 
123         if (Validator.isNotNull(signature)) {
124             signature = "<br />--<br />" + signature;
125         }
126 
127         if (cmd.equals("forward") || cmd.startsWith("reply")) {
128             MailUtil.setFolder(httpReq, folderId);
129 
130             MailMessage mailMessage = MailUtil.getMessage(httpReq, messageId);
131 
132             if (cmd.equals("forward")) {
133                 req.setAttribute(
134                     WebKeys.MAIL_MESSAGE_SUBJECT,
135                     "Fw: " + getSubject(mailMessage.getSubject(), "fw"));
136                 req.setAttribute(
137                     WebKeys.MAIL_MESSAGE_ATTACHMENTS,
138                     mailMessage.getRemoteAttachments());
139             }
140             else {
141                 String to = StringPool.BLANK;
142                 String cc = StringPool.BLANK;
143 
144                 if (cmd.equals("replyAll")) {
145                     User user = PortalUtil.getUser(req);
146 
147                     String emailAddress = user.getEmailAddress();
148 
149                     to = InternetAddressUtil.toString(
150                         InternetAddressUtil.removeEntry(
151                             mailMessage.getTo(), emailAddress));
152 
153                     cc = InternetAddressUtil.toString(
154                         InternetAddressUtil.removeEntry(
155                             mailMessage.getCc(), emailAddress));
156 
157                     String replyTo = InternetAddressUtil.toString(
158                         mailMessage.getReplyTo());
159 
160                     if (Validator.isNull(replyTo)) {
161                         InternetAddress from =
162                             (InternetAddress)mailMessage.getFrom();
163 
164                         replyTo = from.toUnicodeString();
165                     }
166 
167                     to = replyTo + StringPool.COMMA + StringPool.SPACE + to;
168                 }
169                 else {
170                     to = InternetAddressUtil.toString(
171                         mailMessage.getReplyTo());
172 
173                     if (Validator.isNull(to)) {
174                         InternetAddress from =
175                             (InternetAddress)mailMessage.getFrom();
176 
177                         to = from.toUnicodeString();
178                     }
179                 }
180 
181                 String[] recipients = new String[] {
182                     Html.escape(to),
183                     Html.escape(cc),
184                     StringPool.BLANK
185                 };
186 
187                 req.setAttribute(WebKeys.MAIL_MESSAGE_ORIGINAL_ID,
188                     String.valueOf(mailMessage.getMessageId()));
189                 req.setAttribute(WebKeys.MAIL_MESSAGE_RECIPIENTS, recipients);
190                 req.setAttribute(
191                     WebKeys.MAIL_MESSAGE_IN_REPLY_TO,
192                     String.valueOf(mailMessage.getInReplyTo()));
193                 req.setAttribute(
194                     WebKeys.MAIL_MESSAGE_REFERENCES,
195                     String.valueOf(mailMessage.getReferences()));
196                 req.setAttribute(
197                     WebKeys.MAIL_MESSAGE_SUBJECT,
198                     "Re: " + getSubject(mailMessage.getSubject(), "re"));
199             }
200 
201             req.setAttribute(
202                 WebKeys.MAIL_MESSAGE_BODY,
203                 signature + getBody(req, mailMessage));
204         }
205         else if (cmd.equals(Constants.EDIT)) {
206             MailUtil.setFolder(httpReq, folderId);
207 
208             MailMessage mailMessage = MailUtil.getMessage(httpReq, messageId);
209 
210             String to = Html.escape(
211                 InternetAddressUtil.toString(mailMessage.getTo()));
212             String cc = Html.escape(
213                 InternetAddressUtil.toString(mailMessage.getCc()));
214             String bcc = Html.escape(
215                 InternetAddressUtil.toString(mailMessage.getBcc()));
216 
217             String[] recipients = new String[] {to, cc, bcc};
218 
219             req.setAttribute(
220                 WebKeys.MAIL_MESSAGE_ORIGINAL_ID,
221                 new String(_DRAFT_ID_PREFIX + messageId));
222             req.setAttribute(WebKeys.MAIL_MESSAGE_RECIPIENTS, recipients);
223             req.setAttribute(
224                 WebKeys.MAIL_MESSAGE_SUBJECT, mailMessage.getSubject());
225             req.setAttribute(
226                 WebKeys.MAIL_MESSAGE_BODY, mailMessage.getBody());
227             req.setAttribute(
228                 WebKeys.MAIL_MESSAGE_ATTACHMENTS,
229                 mailMessage.getRemoteAttachments());
230         }
231         else if (cmd.equals(Constants.SEND)) {
232             String originalId = ParamUtil.getString(req, "originalId");
233 
234             String to = ParamUtil.getString(req, "to");
235             String cc = ParamUtil.getString(req, "cc");
236             String bcc = ParamUtil.getString(req, "bcc");
237 
238             String[] recipients = new String[] {to, cc, bcc};
239 
240             String subject = ParamUtil.getString(req, "subject");
241             String body = ParamUtil.getString(req, "body");
242 
243             req.setAttribute(WebKeys.MAIL_MESSAGE_ORIGINAL_ID, originalId);
244             req.setAttribute(WebKeys.MAIL_MESSAGE_RECIPIENTS, recipients);
245             req.setAttribute(WebKeys.MAIL_MESSAGE_SUBJECT, subject);
246             req.setAttribute(WebKeys.MAIL_MESSAGE_BODY, body);
247             req.setAttribute(
248                 WebKeys.MAIL_MESSAGE_ATTACHMENTS, getRemoteAttachments(req));
249         }
250         else {
251             String to = ParamUtil.getString(req, "to");
252 
253             String[] recipients =
254                 new String[] {to, StringPool.BLANK, StringPool.BLANK};
255 
256             req.setAttribute(WebKeys.MAIL_MESSAGE_RECIPIENTS, recipients);
257             req.setAttribute(WebKeys.MAIL_MESSAGE_BODY, signature);
258         }
259 
260         return mapping.findForward("portlet.mail.edit_message");
261     }
262 
263     protected void completeMessage(ActionRequest req)
264         throws Exception {
265 
266         String cmd = ParamUtil.getString(req, Constants.CMD);
267 
268         User user = PortalUtil.getUser(req);
269 
270         String originalId = ParamUtil.getString(req, "originalId");
271 
272         boolean wasDraft = false;
273 
274         if (originalId.startsWith(_DRAFT_ID_PREFIX)) {
275             wasDraft = true;
276 
277             originalId = originalId.substring(_DRAFT_ID_PREFIX.length());
278         }
279 
280         String to = ParamUtil.getString(req, "to");
281         String cc = ParamUtil.getString(req, "cc");
282         String bcc = ParamUtil.getString(req, "bcc");
283         String inReplyTo = ParamUtil.getString(req, "inReplyTo");
284         String references = ParamUtil.getString(req, "references");
285         String subject = ParamUtil.getString(req, "subject");
286         String body = ParamUtil.getString(req, "body");
287 
288         MailMessage mailMessage = new MailMessage();
289 
290         try {
291             MailAccount account = MailAccounts.getCurrentAccount(req);
292 
293             mailMessage.setFrom(new InternetAddress(
294                 account.getEmailAddress(), user.getFullName()));
295             mailMessage.setTo(to);
296             mailMessage.setCc(cc);
297             mailMessage.setBcc(bcc);
298             mailMessage.setInReplyTo(inReplyTo);
299             mailMessage.setReferences(references);
300         }
301         catch (Exception ex) {
302             throw new RecipientException(ex);
303         }
304 
305         mailMessage.setSubject(subject);
306         mailMessage.setBody(body);
307 
308         Iterator itr = getAttachments(req).entrySet().iterator();
309 
310         while (itr.hasNext()) {
311             Map.Entry entry = (Map.Entry)itr.next();
312 
313             String fileName = (String)entry.getKey();
314             byte[] attachment = (byte[])entry.getValue();
315 
316             MailAttachment mailAttachment = new MailAttachment();
317 
318             mailAttachment.setFilename(fileName);
319             mailAttachment.setContent(attachment);
320             mailAttachment.setContentType(
321                 ContentTypeUtil.getContentType(fileName));
322 
323             mailMessage.appendAttachment(mailAttachment);
324         }
325 
326         mailMessage.setRemoteAttachments(getRemoteAttachments(req));
327 
328         boolean send = cmd.equals(Constants.SEND);
329 
330         HttpServletRequest httpReq = PortalUtil.getHttpServletRequest(req);
331 
332         MailUtil.completeMessage(
333             httpReq, mailMessage, send, originalId, wasDraft);
334     }
335 
336     protected Map getAttachments(ActionRequest req) throws Exception {
337         UploadPortletRequest uploadReq =
338             PortalUtil.getUploadPortletRequest(req);
339 
340         Map attachments = new HashMap();
341 
342         Enumeration enu = uploadReq.getParameterNames();
343 
344         while (enu.hasMoreElements()) {
345             String name = (String)enu.nextElement();
346 
347             if (name.startsWith("attachment")) {
348                 File file = uploadReq.getFile(name);
349                 String fileName = uploadReq.getFileName(name);
350                 byte[] bytes = FileUtil.getBytes(file);
351 
352                 if ((bytes != null) && (bytes.length > 0)) {
353                     attachments.put(fileName, bytes);
354                 }
355             }
356         }
357 
358         return attachments;
359     }
360 
361     protected String getBody(RenderRequest req, MailMessage mailMessage)
362         throws Exception {
363 
364         StringMaker sm = new StringMaker();
365 
366         InternetAddress from = (InternetAddress)mailMessage.getFrom();
367 
368         ThemeDisplay themeDisplay = (ThemeDisplay)req.getAttribute(
369             WebKeys.THEME_DISPLAY);
370 
371         DateFormat dateFormatDateTime = DateFormats.getDateTime(
372             themeDisplay.getLocale(), themeDisplay.getTimeZone());
373 
374         sm.append("<br /><br />");
375         sm.append("On " + dateFormatDateTime.format(mailMessage.getSentDate()));
376         sm.append(StringPool.COMMA + StringPool.NBSP + from.getPersonal());
377         sm.append(" &lt;<a href=\"mailto: " + from.getAddress() + "\">");
378         sm.append(from.getAddress() + "</a>&gt; wrote:<br />");
379         sm.append("<div style=\"");
380         sm.append("border-left: 1px solid rgb(204, 204, 204); ");
381         sm.append("margin: 0pt 0pt 0pt 1ex; ");
382         sm.append("padding-left: 1ex; \">");
383         sm.append(mailMessage.getBody());
384         sm.append("</div>");
385 
386         return sm.toString();
387     }
388 
389     protected List getRemoteAttachments(PortletRequest req)
390         throws Exception {
391 
392         List list = new ArrayList();
393 
394         String prefix = "remoteAttachment";
395 
396         Enumeration enu = req.getParameterNames();
397 
398         while (enu.hasMoreElements()) {
399             String name = (String)enu.nextElement();
400 
401             if (name.startsWith(prefix)) {
402                 String fileName = name.substring(prefix.length());
403                 String contentPath = ParamUtil.getString(req, name);
404 
405                 RemoteMailAttachment remoteMailAttachment =
406                     new RemoteMailAttachment();
407 
408                 remoteMailAttachment.setFilename(fileName);
409                 remoteMailAttachment.setContentPath(contentPath);
410 
411                 list.add(remoteMailAttachment);
412             }
413         }
414 
415         return list;
416     }
417 
418     protected String getSubject(String subject, String prefix)
419         throws Exception {
420 
421         if (Validator.isNotNull(subject)) {
422             while (StringUtil.startsWith(subject, prefix + ":") ||
423                    StringUtil.startsWith(subject, prefix + ">")) {
424 
425                 subject = subject.substring(3).trim();
426             }
427         }
428 
429         return subject;
430     }
431 
432     private String _DRAFT_ID_PREFIX = "draft.";
433 
434 }