1   /**
2    * Copyright (c) 2000-2010 Liferay, Inc. All rights reserved.
3    *
4    * The contents of this file are subject to the terms of the Liferay Enterprise
5    * Subscription License ("License"). You may not use this file except in
6    * compliance with the License. You can obtain a copy of the License by
7    * contacting Liferay, Inc. See the License for the specific language governing
8    * permissions and limitations under the License, including but not limited to
9    * distribution rights of the Software.
10   *
11   *
12   * 
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.GetterUtil;
26  import com.liferay.portal.kernel.util.StringPool;
27  import com.liferay.portal.kernel.util.StringUtil;
28  import com.liferay.portal.model.Subscription;
29  import com.liferay.portal.model.User;
30  import com.liferay.portal.service.SubscriptionLocalServiceUtil;
31  import com.liferay.portal.service.UserLocalServiceUtil;
32  import com.liferay.portlet.messageboards.NoSuchMailingListException;
33  import com.liferay.portlet.messageboards.model.MBCategory;
34  import com.liferay.portlet.messageboards.model.MBMailingList;
35  import com.liferay.portlet.messageboards.model.MBThread;
36  import com.liferay.portlet.messageboards.service.MBMailingListLocalServiceUtil;
37  import com.liferay.portlet.messageboards.util.BBCodeUtil;
38  
39  import java.util.ArrayList;
40  import java.util.HashSet;
41  import java.util.List;
42  import java.util.Set;
43  
44  import javax.mail.internet.InternetAddress;
45  
46  /**
47   * <a href="MBMessageListener.java.html"><b><i>View Source</i></b></a>
48   *
49   * @author Brian Wing Shun Chan
50   * @author Thiago Moreira
51   */
52  public class MBMessageListener implements MessageListener {
53  
54      public void receive(com.liferay.portal.kernel.messaging.Message message) {
55          try {
56              doReceive(message);
57          }
58          catch (Exception e) {
59              _log.error("Unable to process message " + message, e);
60          }
61      }
62  
63      protected void doReceive(
64              com.liferay.portal.kernel.messaging.Message message)
65          throws Exception {
66  
67          long companyId = message.getLong("companyId");
68          long userId = message.getLong("userId");
69          String categoryIds = message.getString("categoryIds");
70          String threadId = message.getString("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(),
98                  GetterUtil.getLong(threadId));
99  
100         sendEmail(
101             userId, fromName, fromAddress, subject, body, subscriptions, sent,
102             replyToAddress, mailId, inReplyTo, htmlFormat);
103 
104         // Categories
105 
106         long[] categoryIdsArray = StringUtil.split(categoryIds, 0L);
107 
108         for (long categoryId : categoryIdsArray) {
109             subscriptions = SubscriptionLocalServiceUtil.getSubscriptions(
110                 companyId, MBCategory.class.getName(), categoryId);
111 
112             sendEmail(
113                 userId, fromName, fromAddress, subject, body, subscriptions,
114                 sent, replyToAddress, mailId, inReplyTo, htmlFormat);
115         }
116 
117         // Mailing list
118 
119         if (!sourceMailingList) {
120             for (long categoryId : categoryIdsArray) {
121                 try {
122                     notifyMailingList(
123                         subject, body, replyToAddress, mailId, inReplyTo,
124                         htmlFormat, categoryId);
125                 }
126                 catch (NoSuchMailingListException nsmle) {
127                 }
128             }
129         }
130 
131         if (_log.isInfoEnabled()) {
132             _log.info("Finished sending notifications");
133         }
134     }
135 
136     protected String getMailingListSubject(String subject, String mailId) {
137         return subject + StringPool.SPACE + mailId;
138     }
139 
140     protected void notifyMailingList(
141             String subject, String body, String replyToAddress, String mailId,
142             String inReplyTo, boolean htmlFormat, long categoryId)
143         throws Exception {
144 
145         MBMailingList mailingList =
146             MBMailingListLocalServiceUtil.getCategoryMailingList(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(
217                     subscription.getUserId());
218             }
219             catch (NoSuchUserException nsue) {
220                 if (_log.isInfoEnabled()) {
221                     _log.info(
222                         "Subscription " + subscription.getSubscriptionId() +
223                             " is stale and will be deleted");
224                 }
225 
226                 SubscriptionLocalServiceUtil.deleteSubscription(
227                     subscription.getSubscriptionId());
228 
229                 continue;
230             }
231 
232             if (!user.isActive()) {
233                 continue;
234             }
235 
236             InternetAddress userAddress = new InternetAddress(
237                 user.getEmailAddress(), user.getFullName());
238 
239             addresses.add(userAddress);
240         }
241 
242         InternetAddress[] bulkAddresses = addresses.toArray(
243             new InternetAddress[addresses.size()]);
244 
245         sendMail(
246             fromAddress, fromName, bulkAddresses, subject, body, replyToAddress,
247             mailId, inReplyTo, htmlFormat, null);
248     }
249 
250     protected void sendMail(
251         String fromAddress, String fromName, InternetAddress[] bulkAddresses,
252         String subject, String body, String replyToAddress, String mailId,
253         String inReplyTo, boolean htmlFormat, SMTPAccount account) {
254 
255         try {
256             if (bulkAddresses.length == 0) {
257                 return;
258             }
259 
260             InternetAddress from = new InternetAddress(fromAddress, fromName);
261 
262             InternetAddress to = new InternetAddress(
263                 replyToAddress, replyToAddress);
264 
265             String curSubject = StringUtil.replace(
266                 subject,
267                 new String[] {
268                     "[$TO_ADDRESS$]",
269                     "[$TO_NAME$]"
270                 },
271                 new String[] {
272                     replyToAddress,
273                     replyToAddress
274                 });
275 
276             String curBody = StringUtil.replace(
277                 body,
278                 new String[] {
279                     "[$TO_ADDRESS$]",
280                     "[$TO_NAME$]"
281                 },
282                 new String[] {
283                     replyToAddress,
284                     replyToAddress
285                 });
286 
287             InternetAddress replyTo = new InternetAddress(
288                 replyToAddress, replyToAddress);
289 
290             if (htmlFormat) {
291                 try {
292                     curBody = BBCodeUtil.getHTML(curBody);
293                 }
294                 catch (Exception e) {
295                     _log.error(
296                         "Could not parse message " + mailId + " " +
297                             e.getMessage());
298                 }
299             }
300 
301             MailMessage message = new MailMessage(
302                 from, to, curSubject, curBody, htmlFormat);
303 
304             message.setBulkAddresses(bulkAddresses);
305             message.setMessageId(mailId);
306             message.setInReplyTo(inReplyTo);
307             message.setReplyTo(new InternetAddress[] {replyTo});
308             message.setSMTPAccount(account);
309 
310             MailServiceUtil.sendEmail(message);
311         }
312         catch (Exception e) {
313             _log.error(e);
314         }
315     }
316 
317     private static Log _log = LogFactoryUtil.getLog(MBMessageListener.class);
318 
319 }