001    /**
002     * Copyright (c) 2000-2011 Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portlet.messageboards.messaging;
016    
017    import com.liferay.mail.service.MailServiceUtil;
018    import com.liferay.portal.NoSuchUserException;
019    import com.liferay.portal.kernel.log.Log;
020    import com.liferay.portal.kernel.log.LogFactoryUtil;
021    import com.liferay.portal.kernel.mail.Account;
022    import com.liferay.portal.kernel.mail.MailMessage;
023    import com.liferay.portal.kernel.mail.SMTPAccount;
024    import com.liferay.portal.kernel.messaging.MessageListener;
025    import com.liferay.portal.kernel.util.StringPool;
026    import com.liferay.portal.kernel.util.StringUtil;
027    import com.liferay.portal.model.Subscription;
028    import com.liferay.portal.model.User;
029    import com.liferay.portal.service.GroupLocalServiceUtil;
030    import com.liferay.portal.service.SubscriptionLocalServiceUtil;
031    import com.liferay.portal.service.UserLocalServiceUtil;
032    import com.liferay.portlet.messageboards.NoSuchMailingListException;
033    import com.liferay.portlet.messageboards.model.MBCategory;
034    import com.liferay.portlet.messageboards.model.MBMailingList;
035    import com.liferay.portlet.messageboards.model.MBThread;
036    import com.liferay.portlet.messageboards.service.MBMailingListLocalServiceUtil;
037    import com.liferay.portlet.messageboards.util.BBCodeUtil;
038    
039    import java.util.ArrayList;
040    import java.util.HashSet;
041    import java.util.List;
042    import java.util.Set;
043    
044    import javax.mail.internet.InternetAddress;
045    
046    /**
047     * @author Brian Wing Shun Chan
048     * @author Thiago Moreira
049     */
050    public class MBMessageListener implements MessageListener {
051    
052            public void receive(com.liferay.portal.kernel.messaging.Message message) {
053                    try {
054                            doReceive(message);
055                    }
056                    catch (Exception e) {
057                            _log.error("Unable to process message " + message, e);
058                    }
059            }
060    
061            protected void doReceive(
062                            com.liferay.portal.kernel.messaging.Message message)
063                    throws Exception {
064    
065                    long companyId = message.getLong("companyId");
066                    long userId = message.getLong("userId");
067                    long groupId = message.getLong("groupId");
068                    String categoryIds = message.getString("categoryIds");
069                    long threadId = message.getLong("threadId");
070                    String fromName = message.getString("fromName");
071                    String fromAddress = message.getString("fromAddress");
072                    String subject = message.getString("subject");
073                    String body = message.getString("body");
074                    String replyToAddress = message.getString("replyToAddress");
075                    String mailId = message.getString("mailId");
076                    String inReplyTo = message.getString("inReplyTo");
077                    boolean htmlFormat = message.getBoolean("htmlFormat");
078                    boolean sourceMailingList = message.getBoolean("sourceMailingList");
079    
080                    if (sourceMailingList) {
081                            subject = getMailingListSubject(subject, mailId);
082                    }
083    
084                    Set<Long> sent = new HashSet<Long>();
085    
086                    if (_log.isInfoEnabled()) {
087                            _log.info(
088                                    "Sending notifications for {mailId=" + mailId + ", threadId=" +
089                                            threadId + ", categoryIds=" + categoryIds + "}");
090                    }
091    
092                    // Threads
093    
094                    List<Subscription> subscriptions =
095                            SubscriptionLocalServiceUtil.getSubscriptions(
096                                    companyId, MBThread.class.getName(), threadId);
097    
098                    sendEmail(
099                            userId, groupId, fromName, fromAddress, subject, body,
100                            subscriptions, sent, replyToAddress, mailId, inReplyTo, htmlFormat);
101    
102                    // Categories
103    
104                    long[] categoryIdsArray = StringUtil.split(categoryIds, 0L);
105    
106                    for (long categoryId : categoryIdsArray) {
107                            subscriptions = SubscriptionLocalServiceUtil.getSubscriptions(
108                                    companyId, MBCategory.class.getName(), categoryId);
109    
110                            sendEmail(
111                                    userId, groupId, fromName, fromAddress, subject, body,
112                                    subscriptions, sent, replyToAddress, mailId, inReplyTo,
113                                    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, long groupId, String fromName, String fromAddress,
184                            String subject, String body, List<Subscription> subscriptions,
185                            Set<Long> sent, String replyToAddress, String mailId,
186                            String inReplyTo, 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                            if (!GroupLocalServiceUtil.hasUserGroup(
236                                            subscribedUserId, groupId)) {
237    
238                                    if (_log.isInfoEnabled()) {
239                                            _log.info(
240                                                    "Subscription " + subscription.getSubscriptionId() +
241                                                            " is stale and will be deleted");
242                                    }
243    
244                                    SubscriptionLocalServiceUtil.deleteSubscription(
245                                            subscription.getSubscriptionId());
246    
247                                    continue;
248                            }
249    
250                            InternetAddress userAddress = new InternetAddress(
251                                    user.getEmailAddress(), user.getFullName());
252    
253                            addresses.add(userAddress);
254                    }
255    
256                    InternetAddress[] bulkAddresses = addresses.toArray(
257                            new InternetAddress[addresses.size()]);
258    
259                    sendMail(
260                            fromAddress, fromName, bulkAddresses, subject, body, replyToAddress,
261                            mailId, inReplyTo, htmlFormat, null);
262            }
263    
264            protected void sendMail(
265                    String fromAddress, String fromName, InternetAddress[] bulkAddresses,
266                    String subject, String body, String replyToAddress, String mailId,
267                    String inReplyTo, boolean htmlFormat, SMTPAccount account) {
268    
269                    try {
270                            if (bulkAddresses.length == 0) {
271                                    return;
272                            }
273    
274                            InternetAddress from = new InternetAddress(fromAddress, fromName);
275    
276                            InternetAddress to = new InternetAddress(
277                                    replyToAddress, replyToAddress);
278    
279                            String curSubject = StringUtil.replace(
280                                    subject,
281                                    new String[] {
282                                            "[$TO_ADDRESS$]",
283                                            "[$TO_NAME$]"
284                                    },
285                                    new String[] {
286                                            replyToAddress,
287                                            replyToAddress
288                                    });
289    
290                            String curBody = StringUtil.replace(
291                                    body,
292                                    new String[] {
293                                            "[$TO_ADDRESS$]",
294                                            "[$TO_NAME$]"
295                                    },
296                                    new String[] {
297                                            replyToAddress,
298                                            replyToAddress
299                                    });
300    
301                            InternetAddress replyTo = new InternetAddress(
302                                    replyToAddress, replyToAddress);
303    
304                            if (htmlFormat) {
305                                    try {
306                                            curBody = BBCodeUtil.getHTML(curBody);
307                                    }
308                                    catch (Exception e) {
309                                            _log.error(
310                                                    "Could not parse message " + mailId + " " +
311                                                            e.getMessage());
312                                    }
313                            }
314    
315                            MailMessage message = new MailMessage(
316                                    from, to, curSubject, curBody, htmlFormat);
317    
318                            message.setBulkAddresses(bulkAddresses);
319                            message.setMessageId(mailId);
320                            message.setInReplyTo(inReplyTo);
321                            message.setReplyTo(new InternetAddress[] {replyTo});
322                            message.setSMTPAccount(account);
323    
324                            MailServiceUtil.sendEmail(message);
325                    }
326                    catch (Exception e) {
327                            _log.error(e);
328                    }
329            }
330    
331            private static Log _log = LogFactoryUtil.getLog(MBMessageListener.class);
332    
333    }