001    /**
002     * Copyright (c) 2000-2010 Liferay, Inc. All rights reserved.
003     *
004     * The contents of this file are subject to the terms of the Liferay Enterprise
005     * Subscription License ("License"). You may not use this file except in
006     * compliance with the License. You can obtain a copy of the License by
007     * contacting Liferay, Inc. See the License for the specific language governing
008     * permissions and limitations under the License, including but not limited to
009     * distribution rights of the Software.
010     *
011     *
012     *
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.SubscriptionLocalServiceUtil;
030    import com.liferay.portal.service.UserLocalServiceUtil;
031    import com.liferay.portlet.messageboards.NoSuchMailingListException;
032    import com.liferay.portlet.messageboards.model.MBCategory;
033    import com.liferay.portlet.messageboards.model.MBCategoryConstants;
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, fromName, fromAddress, subject, body, subscriptions, sent,
100                            replyToAddress, mailId, inReplyTo, htmlFormat);
101    
102                    // Categories
103    
104                    long[] categoryIdsArray = StringUtil.split(categoryIds, 0L);
105    
106                    for (long categoryId : categoryIdsArray) {
107                            if (categoryId == MBCategoryConstants.DEFAULT_PARENT_CATEGORY_ID) {
108                                    categoryId = groupId;
109                            }
110    
111                            subscriptions = SubscriptionLocalServiceUtil.getSubscriptions(
112                                    companyId, MBCategory.class.getName(), categoryId);
113    
114                            sendEmail(
115                                    userId, fromName, fromAddress, subject, body, subscriptions,
116                                    sent, replyToAddress, mailId, inReplyTo, htmlFormat);
117                    }
118    
119                    // Mailing list
120    
121                    if (!sourceMailingList) {
122                            for (long categoryId : categoryIdsArray) {
123                                    try {
124                                            notifyMailingList(
125                                                    subject, body, replyToAddress, mailId, inReplyTo,
126                                                    htmlFormat, groupId, categoryId);
127                                    }
128                                    catch (NoSuchMailingListException nsmle) {
129                                    }
130                            }
131                    }
132    
133                    if (_log.isInfoEnabled()) {
134                            _log.info("Finished sending notifications");
135                    }
136            }
137    
138            protected String getMailingListSubject(String subject, String mailId) {
139                    return subject + StringPool.SPACE + mailId;
140            }
141    
142            protected void notifyMailingList(
143                            String subject, String body, String replyToAddress, String mailId,
144                            String inReplyTo, boolean htmlFormat, long groupId, long categoryId)
145                    throws Exception {
146    
147                    MBMailingList mailingList =
148                            MBMailingListLocalServiceUtil.getCategoryMailingList(
149                                    groupId, categoryId);
150    
151                    if (!mailingList.isActive()) {
152                            return;
153                    }
154    
155                    subject = getMailingListSubject(subject, mailId);
156    
157                    String fromAddress = mailingList.getOutEmailAddress();
158    
159                    InternetAddress[] bulkAddresses = new InternetAddress[] {
160                            new InternetAddress(mailingList.getEmailAddress())
161                    };
162    
163                    SMTPAccount account = null;
164    
165                    if (mailingList.isOutCustom()) {
166                            String protocol = Account.PROTOCOL_SMTP;
167    
168                            if (mailingList.isOutUseSSL()) {
169                                    protocol = Account.PROTOCOL_SMTPS;
170                            }
171    
172                            account = (SMTPAccount)Account.getInstance(
173                                    protocol, mailingList.getOutServerPort());
174    
175                            account.setHost(mailingList.getOutServerName());
176                            account.setUser(mailingList.getOutUserName());
177                            account.setPassword(mailingList.getOutPassword());
178                    }
179    
180                    sendMail(
181                            fromAddress, null, bulkAddresses, subject, body, replyToAddress,
182                            mailId, inReplyTo, htmlFormat, account);
183            }
184    
185            protected void sendEmail(
186                            long userId, String fromName, String fromAddress, String subject,
187                            String body, List<Subscription> subscriptions, Set<Long> sent,
188                            String replyToAddress, String mailId, String inReplyTo,
189                            boolean htmlFormat)
190                    throws Exception {
191    
192                    List<InternetAddress> addresses = new ArrayList<InternetAddress>();
193    
194                    for (Subscription subscription : subscriptions) {
195                            long subscribedUserId = subscription.getUserId();
196    
197                            if (sent.contains(subscribedUserId)) {
198                                    if (_log.isDebugEnabled()) {
199                                            _log.debug(
200                                                    "Do not send a duplicate email to user " +
201                                                            subscribedUserId);
202                                    }
203    
204                                    continue;
205                            }
206                            else {
207                                    if (_log.isDebugEnabled()) {
208                                            _log.debug(
209                                                    "Add user " + subscribedUserId +
210                                                            " to the list of users who have received an email");
211                                    }
212    
213                                    sent.add(subscribedUserId);
214                            }
215    
216                            User user = null;
217    
218                            try {
219                                    user = UserLocalServiceUtil.getUserById(subscribedUserId);
220                            }
221                            catch (NoSuchUserException nsue) {
222                                    if (_log.isInfoEnabled()) {
223                                            _log.info(
224                                                    "Subscription " + subscription.getSubscriptionId() +
225                                                            " is stale and will be deleted");
226                                    }
227    
228                                    SubscriptionLocalServiceUtil.deleteSubscription(
229                                            subscription.getSubscriptionId());
230    
231                                    continue;
232                            }
233    
234                            if (!user.isActive()) {
235                                    continue;
236                            }
237    
238                            InternetAddress userAddress = new InternetAddress(
239                                    user.getEmailAddress(), user.getFullName());
240    
241                            addresses.add(userAddress);
242                    }
243    
244                    InternetAddress[] bulkAddresses = addresses.toArray(
245                            new InternetAddress[addresses.size()]);
246    
247                    sendMail(
248                            fromAddress, fromName, bulkAddresses, subject, body, replyToAddress,
249                            mailId, inReplyTo, htmlFormat, null);
250            }
251    
252            protected void sendMail(
253                    String fromAddress, String fromName, InternetAddress[] bulkAddresses,
254                    String subject, String body, String replyToAddress, String mailId,
255                    String inReplyTo, boolean htmlFormat, SMTPAccount account) {
256    
257                    try {
258                            if (bulkAddresses.length == 0) {
259                                    return;
260                            }
261    
262                            InternetAddress from = new InternetAddress(fromAddress, fromName);
263    
264                            InternetAddress to = new InternetAddress(
265                                    replyToAddress, replyToAddress);
266    
267                            String curSubject = StringUtil.replace(
268                                    subject,
269                                    new String[] {
270                                            "[$TO_ADDRESS$]",
271                                            "[$TO_NAME$]"
272                                    },
273                                    new String[] {
274                                            replyToAddress,
275                                            replyToAddress
276                                    });
277    
278                            String curBody = StringUtil.replace(
279                                    body,
280                                    new String[] {
281                                            "[$TO_ADDRESS$]",
282                                            "[$TO_NAME$]"
283                                    },
284                                    new String[] {
285                                            replyToAddress,
286                                            replyToAddress
287                                    });
288    
289                            InternetAddress replyTo = new InternetAddress(
290                                    replyToAddress, replyToAddress);
291    
292                            if (htmlFormat) {
293                                    try {
294                                            curBody = BBCodeUtil.getHTML(curBody);
295                                    }
296                                    catch (Exception e) {
297                                            _log.error(
298                                                    "Could not parse message " + mailId + " " +
299                                                            e.getMessage());
300                                    }
301                            }
302    
303                            MailMessage message = new MailMessage(
304                                    from, to, curSubject, curBody, htmlFormat);
305    
306                            message.setBulkAddresses(bulkAddresses);
307                            message.setMessageId(mailId);
308                            message.setInReplyTo(inReplyTo);
309                            message.setReplyTo(new InternetAddress[] {replyTo});
310                            message.setSMTPAccount(account);
311    
312                            MailServiceUtil.sendEmail(message);
313                    }
314                    catch (Exception e) {
315                            _log.error(e);
316                    }
317            }
318    
319            private static Log _log = LogFactoryUtil.getLog(MBMessageListener.class);
320    
321    }