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