1   /**
2    * Copyright (c) 2000-2010 Liferay, Inc. All rights reserved.
3    *
4    * This library is free software; you can redistribute it and/or modify it under
5    * the terms of the GNU Lesser General Public License as published by the Free
6    * Software Foundation; either version 2.1 of the License, or (at your option)
7    * any later version.
8    *
9    * This library is distributed in the hope that it will be useful, but WITHOUT
10   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11   * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
12   * details.
13   */
14  
15  package com.liferay.portlet.messageboards.messaging;
16  
17  import com.liferay.mail.service.MailServiceUtil;
18  import com.liferay.portal.NoSuchUserException;
19  import com.liferay.portal.kernel.log.Log;
20  import com.liferay.portal.kernel.log.LogFactoryUtil;
21  import com.liferay.portal.kernel.mail.Account;
22  import com.liferay.portal.kernel.mail.MailMessage;
23  import com.liferay.portal.kernel.mail.SMTPAccount;
24  import com.liferay.portal.kernel.messaging.MessageListener;
25  import com.liferay.portal.kernel.util.StringPool;
26  import com.liferay.portal.kernel.util.StringUtil;
27  import com.liferay.portal.model.Subscription;
28  import com.liferay.portal.model.User;
29  import com.liferay.portal.service.SubscriptionLocalServiceUtil;
30  import com.liferay.portal.service.UserLocalServiceUtil;
31  import com.liferay.portlet.messageboards.NoSuchMailingListException;
32  import com.liferay.portlet.messageboards.model.MBCategory;
33  import com.liferay.portlet.messageboards.model.MBMailingList;
34  import com.liferay.portlet.messageboards.model.MBThread;
35  import com.liferay.portlet.messageboards.service.MBMailingListLocalServiceUtil;
36  import com.liferay.portlet.messageboards.util.BBCodeUtil;
37  
38  import java.util.ArrayList;
39  import java.util.HashSet;
40  import java.util.List;
41  import java.util.Set;
42  
43  import javax.mail.internet.InternetAddress;
44  
45  /**
46   * <a href="MBMessageListener.java.html"><b><i>View Source</i></b></a>
47   *
48   * @author Brian Wing Shun Chan
49   * @author Thiago Moreira
50   */
51  public class MBMessageListener implements MessageListener {
52  
53      public void receive(com.liferay.portal.kernel.messaging.Message message) {
54          try {
55              doReceive(message);
56          }
57          catch (Exception e) {
58              _log.error("Unable to process message " + message, e);
59          }
60      }
61  
62      protected void doReceive(
63              com.liferay.portal.kernel.messaging.Message message)
64          throws Exception {
65  
66          long companyId = message.getLong("companyId");
67          long userId = message.getLong("userId");
68          long groupId = message.getLong("groupId");
69          String categoryIds = message.getString("categoryIds");
70          long threadId = message.getLong("threadId");
71          String fromName = message.getString("fromName");
72          String fromAddress = message.getString("fromAddress");
73          String subject = message.getString("subject");
74          String body = message.getString("body");
75          String replyToAddress = message.getString("replyToAddress");
76          String mailId = message.getString("mailId");
77          String inReplyTo = message.getString("inReplyTo");
78          boolean htmlFormat = message.getBoolean("htmlFormat");
79          boolean sourceMailingList = message.getBoolean("sourceMailingList");
80  
81          if (sourceMailingList) {
82              subject = getMailingListSubject(subject, mailId);
83          }
84  
85          Set<Long> sent = new HashSet<Long>();
86  
87          if (_log.isInfoEnabled()) {
88              _log.info(
89                  "Sending notifications for {mailId=" + mailId + ", threadId=" +
90                      threadId + ", categoryIds=" + categoryIds + "}");
91          }
92  
93          // Threads
94  
95          List<Subscription> subscriptions =
96              SubscriptionLocalServiceUtil.getSubscriptions(
97                  companyId, MBThread.class.getName(), threadId);
98  
99          sendEmail(
100             userId, fromName, fromAddress, subject, body, subscriptions, sent,
101             replyToAddress, mailId, inReplyTo, htmlFormat);
102 
103         // Categories
104 
105         long[] categoryIdsArray = StringUtil.split(categoryIds, 0L);
106 
107         for (long categoryId : categoryIdsArray) {
108             subscriptions = SubscriptionLocalServiceUtil.getSubscriptions(
109                 companyId, MBCategory.class.getName(), categoryId);
110 
111             sendEmail(
112                 userId, fromName, fromAddress, subject, body, subscriptions,
113                 sent, replyToAddress, mailId, inReplyTo, htmlFormat);
114         }
115 
116         // Mailing list
117 
118         if (!sourceMailingList) {
119             for (long categoryId : categoryIdsArray) {
120                 try {
121                     notifyMailingList(
122                         subject, body, replyToAddress, mailId, inReplyTo,
123                         htmlFormat, groupId, categoryId);
124                 }
125                 catch (NoSuchMailingListException nsmle) {
126                 }
127             }
128         }
129 
130         if (_log.isInfoEnabled()) {
131             _log.info("Finished sending notifications");
132         }
133     }
134 
135     protected String getMailingListSubject(String subject, String mailId) {
136         return subject + StringPool.SPACE + mailId;
137     }
138 
139     protected void notifyMailingList(
140             String subject, String body, String replyToAddress, String mailId,
141             String inReplyTo, boolean htmlFormat, long groupId, long categoryId)
142         throws Exception {
143 
144         MBMailingList mailingList =
145             MBMailingListLocalServiceUtil.getCategoryMailingList(
146                 groupId, categoryId);
147 
148         if (!mailingList.isActive()) {
149             return;
150         }
151 
152         subject = getMailingListSubject(subject, mailId);
153 
154         String fromAddress = mailingList.getOutEmailAddress();
155 
156         InternetAddress[] bulkAddresses = new InternetAddress[] {
157             new InternetAddress(mailingList.getEmailAddress())
158         };
159 
160         SMTPAccount account = null;
161 
162         if (mailingList.isOutCustom()) {
163             String protocol = Account.PROTOCOL_SMTP;
164 
165             if (mailingList.isOutUseSSL()) {
166                 protocol = Account.PROTOCOL_SMTPS;
167             }
168 
169             account = (SMTPAccount)Account.getInstance(
170                 protocol, mailingList.getOutServerPort());
171 
172             account.setHost(mailingList.getOutServerName());
173             account.setUser(mailingList.getOutUserName());
174             account.setPassword(mailingList.getOutPassword());
175         }
176 
177         sendMail(
178             fromAddress, null, bulkAddresses, subject, body, replyToAddress,
179             mailId, inReplyTo, htmlFormat, account);
180     }
181 
182     protected void sendEmail(
183             long userId, String fromName, String fromAddress, String subject,
184             String body, List<Subscription> subscriptions, Set<Long> sent,
185             String replyToAddress, String mailId, String inReplyTo,
186             boolean htmlFormat)
187         throws Exception {
188 
189         List<InternetAddress> addresses = new ArrayList<InternetAddress>();
190 
191         for (Subscription subscription : subscriptions) {
192             long subscribedUserId = subscription.getUserId();
193 
194             if (sent.contains(subscribedUserId)) {
195                 if (_log.isDebugEnabled()) {
196                     _log.debug(
197                         "Do not send a duplicate email to user " +
198                             subscribedUserId);
199                 }
200 
201                 continue;
202             }
203             else {
204                 if (_log.isDebugEnabled()) {
205                     _log.debug(
206                         "Add user " + subscribedUserId +
207                             " to the list of users who have received an email");
208                 }
209 
210                 sent.add(subscribedUserId);
211             }
212 
213             User user = null;
214 
215             try {
216                 user = UserLocalServiceUtil.getUserById(subscribedUserId);
217             }
218             catch (NoSuchUserException nsue) {
219                 if (_log.isInfoEnabled()) {
220                     _log.info(
221                         "Subscription " + subscription.getSubscriptionId() +
222                             " is stale and will be deleted");
223                 }
224 
225                 SubscriptionLocalServiceUtil.deleteSubscription(
226                     subscription.getSubscriptionId());
227 
228                 continue;
229             }
230 
231             if (!user.isActive()) {
232                 continue;
233             }
234 
235             InternetAddress userAddress = new InternetAddress(
236                 user.getEmailAddress(), user.getFullName());
237 
238             addresses.add(userAddress);
239         }
240 
241         InternetAddress[] bulkAddresses = addresses.toArray(
242             new InternetAddress[addresses.size()]);
243 
244         sendMail(
245             fromAddress, fromName, bulkAddresses, subject, body, replyToAddress,
246             mailId, inReplyTo, htmlFormat, null);
247     }
248 
249     protected void sendMail(
250         String fromAddress, String fromName, InternetAddress[] bulkAddresses,
251         String subject, String body, String replyToAddress, String mailId,
252         String inReplyTo, boolean htmlFormat, SMTPAccount account) {
253 
254         try {
255             if (bulkAddresses.length == 0) {
256                 return;
257             }
258 
259             InternetAddress from = new InternetAddress(fromAddress, fromName);
260 
261             InternetAddress to = new InternetAddress(
262                 replyToAddress, replyToAddress);
263 
264             String curSubject = StringUtil.replace(
265                 subject,
266                 new String[] {
267                     "[$TO_ADDRESS$]",
268                     "[$TO_NAME$]"
269                 },
270                 new String[] {
271                     replyToAddress,
272                     replyToAddress
273                 });
274 
275             String curBody = StringUtil.replace(
276                 body,
277                 new String[] {
278                     "[$TO_ADDRESS$]",
279                     "[$TO_NAME$]"
280                 },
281                 new String[] {
282                     replyToAddress,
283                     replyToAddress
284                 });
285 
286             InternetAddress replyTo = new InternetAddress(
287                 replyToAddress, replyToAddress);
288 
289             if (htmlFormat) {
290                 try {
291                     curBody = BBCodeUtil.getHTML(curBody);
292                 }
293                 catch (Exception e) {
294                     _log.error(
295                         "Could not parse message " + mailId + " " +
296                             e.getMessage());
297                 }
298             }
299 
300             MailMessage message = new MailMessage(
301                 from, to, curSubject, curBody, htmlFormat);
302 
303             message.setBulkAddresses(bulkAddresses);
304             message.setMessageId(mailId);
305             message.setInReplyTo(inReplyTo);
306             message.setReplyTo(new InternetAddress[] {replyTo});
307             message.setSMTPAccount(account);
308 
309             MailServiceUtil.sendEmail(message);
310         }
311         catch (Exception e) {
312             _log.error(e);
313         }
314     }
315 
316     private static Log _log = LogFactoryUtil.getLog(MBMessageListener.class);
317 
318 }