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             InternetAddress userAddress = new InternetAddress(
241                 user.getEmailAddress(), user.getFullName());
242 
243             addresses.add(userAddress);
244         }
245 
246         InternetAddress[] bulkAddresses = addresses.toArray(
247             new InternetAddress[addresses.size()]);
248 
249         sendMail(
250             fromAddress, fromName, bulkAddresses, subject, body, replyToAddress,
251             mailId, inReplyTo, htmlFormat, null);
252     }
253 
254     protected void sendMail(
255         String fromAddress, String fromName, InternetAddress[] bulkAddresses,
256         String subject, String body, String replyToAddress, String mailId,
257         String inReplyTo, boolean htmlFormat, SMTPAccount account) {
258 
259         try {
260             if (bulkAddresses.length == 0) {
261                 return;
262             }
263 
264             InternetAddress from = new InternetAddress(fromAddress, fromName);
265 
266             InternetAddress to = new InternetAddress(
267                 replyToAddress, replyToAddress);
268 
269             String curSubject = StringUtil.replace(
270                 subject,
271                 new String[] {
272                     "[$TO_ADDRESS$]",
273                     "[$TO_NAME$]"
274                 },
275                 new String[] {
276                     replyToAddress,
277                     replyToAddress
278                 });
279 
280             String curBody = StringUtil.replace(
281                 body,
282                 new String[] {
283                     "[$TO_ADDRESS$]",
284                     "[$TO_NAME$]"
285                 },
286                 new String[] {
287                     replyToAddress,
288                     replyToAddress
289                 });
290 
291             InternetAddress replyTo = new InternetAddress(
292                 replyToAddress, replyToAddress);
293 
294             if (htmlFormat) {
295                 try {
296                     curBody = BBCodeUtil.getHTML(curBody);
297                 }
298                 catch (Exception e) {
299                     _log.error(
300                         "Could not parse message " + mailId + " " +
301                             e.getMessage());
302                 }
303             }
304 
305             MailMessage message = new MailMessage(
306                 from, to, curSubject, curBody, htmlFormat);
307 
308             message.setBulkAddresses(bulkAddresses);
309             message.setMessageId(mailId);
310             message.setInReplyTo(inReplyTo);
311             message.setReplyTo(new InternetAddress[] {replyTo});
312             message.setSMTPAccount(account);
313 
314             MailServiceUtil.sendEmail(message);
315         }
316         catch (Exception e) {
317             _log.error(e);
318         }
319     }
320 
321     private static Log _log = LogFactoryUtil.getLog(MBMessageListener.class);
322 
323 }