1   /**
2    * Copyright (c) 2000-2008 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), Html.escape(cc), StringPool.BLANK
183                 };
184 
185                 req.setAttribute(WebKeys.MAIL_MESSAGE_ORIGINAL_ID,
186                     String.valueOf(mailMessage.getMessageId()));
187                 req.setAttribute(WebKeys.MAIL_MESSAGE_RECIPIENTS, recipients);
188                 req.setAttribute(
189                     WebKeys.MAIL_MESSAGE_IN_REPLY_TO,
190                     String.valueOf(mailMessage.getInReplyTo()));
191                 req.setAttribute(
192                     WebKeys.MAIL_MESSAGE_REFERENCES,
193                     String.valueOf(mailMessage.getReferences()));
194                 req.setAttribute(
195                     WebKeys.MAIL_MESSAGE_SUBJECT,
196                     "Re: " + getSubject(mailMessage.getSubject(), "re"));
197             }
198 
199             req.setAttribute(
200                 WebKeys.MAIL_MESSAGE_BODY,
201                 signature + getBody(req, mailMessage));
202         }
203         else if (cmd.equals(Constants.EDIT)) {
204             MailUtil.setFolder(httpReq, folderId);
205 
206             MailMessage mailMessage = MailUtil.getMessage(httpReq, messageId);
207 
208             String to = Html.escape(
209                 InternetAddressUtil.toString(mailMessage.getTo()));
210             String cc = Html.escape(
211                 InternetAddressUtil.toString(mailMessage.getCc()));
212             String bcc = Html.escape(
213                 InternetAddressUtil.toString(mailMessage.getBcc()));
214 
215             String[] recipients = new String[] {to, cc, bcc};
216 
217             req.setAttribute(
218                 WebKeys.MAIL_MESSAGE_ORIGINAL_ID,
219                 new String(_DRAFT_ID_PREFIX + messageId));
220             req.setAttribute(WebKeys.MAIL_MESSAGE_RECIPIENTS, recipients);
221             req.setAttribute(
222                 WebKeys.MAIL_MESSAGE_SUBJECT, mailMessage.getSubject());
223             req.setAttribute(
224                 WebKeys.MAIL_MESSAGE_BODY, mailMessage.getBody());
225             req.setAttribute(
226                 WebKeys.MAIL_MESSAGE_ATTACHMENTS,
227                 mailMessage.getRemoteAttachments());
228         }
229         else if (cmd.equals(Constants.SEND)) {
230             String originalId = ParamUtil.getString(req, "originalId");
231 
232             String to = ParamUtil.getString(req, "to");
233             String cc = ParamUtil.getString(req, "cc");
234             String bcc = ParamUtil.getString(req, "bcc");
235 
236             String[] recipients = new String[] {to, cc, bcc};
237 
238             String subject = ParamUtil.getString(req, "subject");
239             String body = ParamUtil.getString(req, "body");
240 
241             req.setAttribute(WebKeys.MAIL_MESSAGE_ORIGINAL_ID, originalId);
242             req.setAttribute(WebKeys.MAIL_MESSAGE_RECIPIENTS, recipients);
243             req.setAttribute(WebKeys.MAIL_MESSAGE_SUBJECT, subject);
244             req.setAttribute(WebKeys.MAIL_MESSAGE_BODY, body);
245             req.setAttribute(
246                 WebKeys.MAIL_MESSAGE_ATTACHMENTS, getRemoteAttachments(req));
247         }
248         else {
249             String to = ParamUtil.getString(req, "to");
250 
251             String[] recipients =
252                 new String[] {to, StringPool.BLANK, StringPool.BLANK};
253 
254             req.setAttribute(WebKeys.MAIL_MESSAGE_RECIPIENTS, recipients);
255             req.setAttribute(WebKeys.MAIL_MESSAGE_BODY, signature);
256         }
257 
258         return mapping.findForward("portlet.mail.edit_message");
259     }
260 
261     protected void completeMessage(ActionRequest req)
262         throws Exception {
263 
264         String cmd = ParamUtil.getString(req, Constants.CMD);
265 
266         User user = PortalUtil.getUser(req);
267 
268         String originalId = ParamUtil.getString(req, "originalId");
269 
270         boolean wasDraft = false;
271 
272         if (originalId.startsWith(_DRAFT_ID_PREFIX)) {
273             wasDraft = true;
274 
275             originalId = originalId.substring(_DRAFT_ID_PREFIX.length());
276         }
277 
278         String to = ParamUtil.getString(req, "to");
279         String cc = ParamUtil.getString(req, "cc");
280         String bcc = ParamUtil.getString(req, "bcc");
281         String inReplyTo = ParamUtil.getString(req, "inReplyTo");
282         String references = ParamUtil.getString(req, "references");
283         String subject = ParamUtil.getString(req, "subject");
284         String body = ParamUtil.getString(req, "body");
285 
286         MailMessage mailMessage = new MailMessage();
287 
288         try {
289             MailAccount account = MailAccounts.getCurrentAccount(req);
290 
291             mailMessage.setFrom(new InternetAddress(
292                 account.getEmailAddress(), user.getFullName()));
293             mailMessage.setTo(to);
294             mailMessage.setCc(cc);
295             mailMessage.setBcc(bcc);
296             mailMessage.setInReplyTo(inReplyTo);
297             mailMessage.setReferences(references);
298         }
299         catch (Exception ex) {
300             throw new RecipientException(ex);
301         }
302 
303         mailMessage.setSubject(subject);
304         mailMessage.setBody(body);
305 
306         Iterator itr = getAttachments(req).entrySet().iterator();
307 
308         while (itr.hasNext()) {
309             Map.Entry entry = (Map.Entry)itr.next();
310 
311             String fileName = (String)entry.getKey();
312             byte[] attachment = (byte[])entry.getValue();
313 
314             MailAttachment mailAttachment = new MailAttachment();
315 
316             mailAttachment.setFilename(fileName);
317             mailAttachment.setContent(attachment);
318             mailAttachment.setContentType(
319                 ContentTypeUtil.getContentType(fileName));
320 
321             mailMessage.appendAttachment(mailAttachment);
322         }
323 
324         mailMessage.setRemoteAttachments(getRemoteAttachments(req));
325 
326         boolean send = cmd.equals(Constants.SEND);
327 
328         HttpServletRequest httpReq = PortalUtil.getHttpServletRequest(req);
329 
330         MailUtil.completeMessage(
331             httpReq, mailMessage, send, originalId, wasDraft);
332     }
333 
334     protected Map getAttachments(ActionRequest req) throws Exception {
335         UploadPortletRequest uploadReq =
336             PortalUtil.getUploadPortletRequest(req);
337 
338         Map attachments = new HashMap();
339 
340         Enumeration enu = uploadReq.getParameterNames();
341 
342         while (enu.hasMoreElements()) {
343             String name = (String)enu.nextElement();
344 
345             if (name.startsWith("attachment")) {
346                 File file = uploadReq.getFile(name);
347                 String fileName = uploadReq.getFileName(name);
348                 byte[] bytes = FileUtil.getBytes(file);
349 
350                 if ((bytes != null) && (bytes.length > 0)) {
351                     attachments.put(fileName, bytes);
352                 }
353             }
354         }
355 
356         return attachments;
357     }
358 
359     protected String getBody(RenderRequest req, MailMessage mailMessage)
360         throws Exception {
361 
362         StringMaker sm = new StringMaker();
363 
364         InternetAddress from = (InternetAddress)mailMessage.getFrom();
365 
366         ThemeDisplay themeDisplay = (ThemeDisplay)req.getAttribute(
367             WebKeys.THEME_DISPLAY);
368 
369         DateFormat dateFormatDateTime = DateFormats.getDateTime(
370             themeDisplay.getLocale(), themeDisplay.getTimeZone());
371 
372         sm.append("<br /><br />");
373         sm.append("On " + dateFormatDateTime.format(mailMessage.getSentDate()));
374         sm.append(StringPool.COMMA + StringPool.NBSP + from.getPersonal());
375         sm.append(" &lt;<a href=\"mailto: " + from.getAddress() + "\">");
376         sm.append(from.getAddress() + "</a>&gt; wrote:<br />");
377         sm.append("<div style=\"");
378         sm.append("border-left: 1px solid rgb(204, 204, 204); ");
379         sm.append("margin: 0pt 0pt 0pt 1ex; ");
380         sm.append("padding-left: 1ex; \">");
381         sm.append(mailMessage.getBody());
382         sm.append("</div>");
383 
384         return sm.toString();
385     }
386 
387     protected List getRemoteAttachments(PortletRequest req)
388         throws Exception {
389 
390         List list = new ArrayList();
391 
392         String prefix = "remoteAttachment";
393 
394         Enumeration enu = req.getParameterNames();
395 
396         while (enu.hasMoreElements()) {
397             String name = (String)enu.nextElement();
398 
399             if (name.startsWith(prefix)) {
400                 String fileName = name.substring(prefix.length());
401                 String contentPath = ParamUtil.getString(req, name);
402 
403                 RemoteMailAttachment remoteMailAttachment =
404                     new RemoteMailAttachment();
405 
406                 remoteMailAttachment.setFilename(fileName);
407                 remoteMailAttachment.setContentPath(contentPath);
408 
409                 list.add(remoteMailAttachment);
410             }
411         }
412 
413         return list;
414     }
415 
416     protected String getSubject(String subject, String prefix)
417         throws Exception {
418 
419         if (Validator.isNotNull(subject)) {
420             while (StringUtil.startsWith(subject, prefix + ":") ||
421                    StringUtil.startsWith(subject, prefix + ">")) {
422 
423                 subject = subject.substring(3).trim();
424             }
425         }
426 
427         return subject;
428     }
429 
430     private String _DRAFT_ID_PREFIX = "draft.";
431 
432 }