001    /**
002     * Copyright (c) 2000-present 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.portal.util;
016    
017    import com.liferay.mail.model.FileAttachment;
018    import com.liferay.mail.service.MailServiceUtil;
019    import com.liferay.portal.kernel.exception.PortalException;
020    import com.liferay.portal.kernel.json.JSONFactoryUtil;
021    import com.liferay.portal.kernel.json.JSONObject;
022    import com.liferay.portal.kernel.log.Log;
023    import com.liferay.portal.kernel.log.LogFactoryUtil;
024    import com.liferay.portal.kernel.mail.MailMessage;
025    import com.liferay.portal.kernel.mail.SMTPAccount;
026    import com.liferay.portal.kernel.messaging.DestinationNames;
027    import com.liferay.portal.kernel.messaging.MessageBusUtil;
028    import com.liferay.portal.kernel.notifications.UserNotificationManagerUtil;
029    import com.liferay.portal.kernel.transaction.TransactionCommitCallbackRegistryUtil;
030    import com.liferay.portal.kernel.util.ArrayUtil;
031    import com.liferay.portal.kernel.util.ClassLoaderPool;
032    import com.liferay.portal.kernel.util.EscapableObject;
033    import com.liferay.portal.kernel.util.GetterUtil;
034    import com.liferay.portal.kernel.util.HtmlEscapableObject;
035    import com.liferay.portal.kernel.util.HtmlUtil;
036    import com.liferay.portal.kernel.util.LocaleUtil;
037    import com.liferay.portal.kernel.util.ObjectValuePair;
038    import com.liferay.portal.kernel.util.StringPool;
039    import com.liferay.portal.kernel.util.StringUtil;
040    import com.liferay.portal.kernel.util.Validator;
041    import com.liferay.portal.kernel.uuid.PortalUUIDUtil;
042    import com.liferay.portal.model.Company;
043    import com.liferay.portal.model.Group;
044    import com.liferay.portal.model.ResourceAction;
045    import com.liferay.portal.model.Subscription;
046    import com.liferay.portal.model.User;
047    import com.liferay.portal.model.UserNotificationDeliveryConstants;
048    import com.liferay.portal.security.permission.ActionKeys;
049    import com.liferay.portal.security.permission.BaseModelPermissionCheckerUtil;
050    import com.liferay.portal.security.permission.PermissionChecker;
051    import com.liferay.portal.security.permission.PermissionCheckerFactoryUtil;
052    import com.liferay.portal.service.CompanyLocalServiceUtil;
053    import com.liferay.portal.service.GroupLocalServiceUtil;
054    import com.liferay.portal.service.ResourceActionLocalServiceUtil;
055    import com.liferay.portal.service.ServiceContext;
056    import com.liferay.portal.service.SubscriptionLocalServiceUtil;
057    import com.liferay.portal.service.UserLocalServiceUtil;
058    import com.liferay.portal.service.UserNotificationEventLocalServiceUtil;
059    
060    import java.io.File;
061    import java.io.IOException;
062    import java.io.ObjectInputStream;
063    import java.io.ObjectOutputStream;
064    import java.io.Serializable;
065    
066    import java.util.ArrayList;
067    import java.util.HashMap;
068    import java.util.HashSet;
069    import java.util.List;
070    import java.util.Locale;
071    import java.util.Map;
072    import java.util.Set;
073    import java.util.concurrent.Callable;
074    
075    import javax.mail.internet.InternetAddress;
076    
077    /**
078     * @author Brian Wing Shun Chan
079     * @author Mate Thurzo
080     * @author Raymond Aug??
081     * @author Sergio Gonz??lez
082     * @author Roberto D??az
083     */
084    public class SubscriptionSender implements Serializable {
085    
086            public void addFileAttachment(File file) {
087                    addFileAttachment(file, null);
088            }
089    
090            public void addFileAttachment(File file, String fileName) {
091                    if (file == null) {
092                            return;
093                    }
094    
095                    if (fileAttachments == null) {
096                            fileAttachments = new ArrayList<FileAttachment>();
097                    }
098    
099                    FileAttachment attachment = new FileAttachment(file, fileName);
100    
101                    fileAttachments.add(attachment);
102            }
103    
104            public void addPersistedSubscribers(String className, long classPK) {
105                    ObjectValuePair<String, Long> ovp = new ObjectValuePair<String, Long>(
106                            className, classPK);
107    
108                    _persistestedSubscribersOVPs.add(ovp);
109            }
110    
111            public void addRuntimeSubscribers(String toAddress, String toName) {
112                    ObjectValuePair<String, String> ovp =
113                            new ObjectValuePair<String, String>(toAddress, toName);
114    
115                    _runtimeSubscribersOVPs.add(ovp);
116            }
117    
118            public void flushNotifications() throws Exception {
119                    initialize();
120    
121                    Thread currentThread = Thread.currentThread();
122    
123                    ClassLoader contextClassLoader = currentThread.getContextClassLoader();
124    
125                    try {
126                            if ((_classLoader != null) &&
127                                    (contextClassLoader != _classLoader)) {
128    
129                                    currentThread.setContextClassLoader(_classLoader);
130                            }
131    
132                            for (ObjectValuePair<String, Long> ovp :
133                                            _persistestedSubscribersOVPs) {
134    
135                                    String className = ovp.getKey();
136                                    long classPK = ovp.getValue();
137    
138                                    List<Subscription> subscriptions =
139                                            SubscriptionLocalServiceUtil.getSubscriptions(
140                                                    companyId, className, classPK);
141    
142                                    for (Subscription subscription : subscriptions) {
143                                            try {
144                                                    notifyPersistedSubscriber(subscription);
145                                            }
146                                            catch (Exception e) {
147                                                    _log.error(
148                                                            "Unable to process subscription: " + subscription);
149                                            }
150                                    }
151    
152                                    if (bulk) {
153                                            Locale locale = LocaleUtil.getDefault();
154    
155                                            InternetAddress to = new InternetAddress(
156                                                    replaceContent(replyToAddress, locale),
157                                                    replaceContent(replyToAddress, locale));
158    
159                                            sendEmail(to, locale);
160                                    }
161                            }
162    
163                            _persistestedSubscribersOVPs.clear();
164    
165                            for (ObjectValuePair<String, String> ovp :
166                                            _runtimeSubscribersOVPs) {
167    
168                                    String toAddress = ovp.getKey();
169    
170                                    if (Validator.isNull(toAddress)) {
171                                            continue;
172                                    }
173    
174                                    if (_sentEmailAddresses.contains(toAddress)) {
175                                            if (_log.isDebugEnabled()) {
176                                                    _log.debug(
177                                                            "Do not send a duplicate email to " + toAddress);
178                                            }
179    
180                                            continue;
181                                    }
182    
183                                    if (_log.isDebugEnabled()) {
184                                            _log.debug(
185                                                    "Add " + toAddress + " to the list of users who " +
186                                                            "have received an email");
187                                    }
188    
189                                    _sentEmailAddresses.add(toAddress);
190    
191                                    String toName = ovp.getValue();
192    
193                                    InternetAddress to = new InternetAddress(toAddress, toName);
194    
195                                    notifyRuntimeSubscriber(to, LocaleUtil.getDefault());
196                            }
197    
198                            _runtimeSubscribersOVPs.clear();
199                    }
200                    finally {
201                            if ((_classLoader != null) &&
202                                    (contextClassLoader != _classLoader)) {
203    
204                                    currentThread.setContextClassLoader(contextClassLoader);
205                            }
206                    }
207            }
208    
209            public void flushNotificationsAsync() {
210                    TransactionCommitCallbackRegistryUtil.registerCallback(
211                            new Callable<Void>() {
212    
213                                    @Override
214                                    public Void call() throws Exception {
215                                            Thread currentThread = Thread.currentThread();
216    
217                                            _classLoader = currentThread.getContextClassLoader();
218    
219                                            MessageBusUtil.sendMessage(
220                                                    DestinationNames.SUBSCRIPTION_SENDER,
221                                                    SubscriptionSender.this);
222    
223                                            return null;
224                                    }
225                            }
226                    );
227            }
228    
229            public Object getContextAttribute(String key) {
230                    return _context.get(key);
231            }
232    
233            public String getMailId() {
234                    return this.mailId;
235            }
236    
237            public void initialize() throws Exception {
238                    if (_initialized) {
239                            return;
240                    }
241    
242                    _initialized = true;
243    
244                    if ((groupId == 0) && (serviceContext != null)) {
245                            setScopeGroupId(serviceContext.getScopeGroupId());
246                    }
247    
248                    Company company = CompanyLocalServiceUtil.getCompany(companyId);
249    
250                    setContextAttribute("[$COMPANY_ID$]", company.getCompanyId());
251                    setContextAttribute("[$COMPANY_MX$]", company.getMx());
252                    setContextAttribute("[$COMPANY_NAME$]", company.getName());
253                    setContextAttribute("[$PORTAL_URL$]", company.getPortalURL(groupId));
254    
255                    if (groupId > 0) {
256                            Group group = GroupLocalServiceUtil.getGroup(groupId);
257    
258                            setContextAttribute("[$SITE_NAME$]", group.getDescriptiveName());
259                    }
260    
261                    if ((userId > 0) && Validator.isNotNull(_contextUserPrefix)) {
262                            setContextAttribute(
263                                    "[$" + _contextUserPrefix + "_USER_ADDRESS$]",
264                                    PortalUtil.getUserEmailAddress(userId));
265                            setContextAttribute(
266                                    "[$" + _contextUserPrefix + "_USER_NAME$]",
267                                    PortalUtil.getUserName(userId, StringPool.BLANK));
268                    }
269    
270                    if (uniqueMailId) {
271                            _mailIdIds = ArrayUtil.append(
272                                    _mailIdIds, PortalUUIDUtil.generate());
273                    }
274    
275                    mailId = PortalUtil.getMailId(
276                            company.getMx(), _mailIdPopPortletPrefix, _mailIdIds);
277            }
278    
279            public void setBody(String body) {
280                    this.body = body;
281            }
282    
283            public void setBulk(boolean bulk) {
284                    this.bulk = bulk;
285            }
286    
287            public void setClassName(String className) {
288                    _className = className;
289            }
290    
291            public void setClassPK(long classPK) {
292                    _classPK = classPK;
293            }
294    
295            public void setCompanyId(long companyId) {
296                    this.companyId = companyId;
297            }
298    
299            public void setContextAttribute(String key, EscapableObject<String> value) {
300                    _context.put(key, value);
301            }
302    
303            public void setContextAttribute(String key, Object value) {
304                    setContextAttribute(key, value, true);
305            }
306    
307            public void setContextAttribute(String key, Object value, boolean escape) {
308                    setContextAttribute(
309                            key,
310                            new HtmlEscapableObject<String>(String.valueOf(value), escape));
311            }
312    
313            public void setContextAttributes(Object... values) {
314                    for (int i = 0; i < values.length; i += 2) {
315                            setContextAttribute(String.valueOf(values[i]), values[i + 1]);
316                    }
317            }
318    
319            public void setContextUserPrefix(String contextUserPrefix) {
320                    _contextUserPrefix = contextUserPrefix;
321            }
322    
323            public void setEntryTitle(String entryTitle) {
324                    this._entryTitle = entryTitle;
325            }
326    
327            public void setEntryURL(String entryURL) {
328                    _entryURL = entryURL;
329            }
330    
331            public void setFrom(String fromAddress, String fromName) {
332                    this.fromAddress = fromAddress;
333                    this.fromName = fromName;
334            }
335    
336            public void setGroupId(long groupId) {
337                    this.groupId = groupId;
338            }
339    
340            public void setHtmlFormat(boolean htmlFormat) {
341                    this.htmlFormat = htmlFormat;
342            }
343    
344            public void setInReplyTo(String inReplyTo) {
345                    this.inReplyTo = inReplyTo;
346            }
347    
348            public void setLocalizedBodyMap(Map<Locale, String> localizedBodyMap) {
349                    this.localizedBodyMap = localizedBodyMap;
350            }
351    
352            public void setLocalizedSubjectMap(
353                    Map<Locale, String> localizedSubjectMap) {
354    
355                    this.localizedSubjectMap = localizedSubjectMap;
356            }
357    
358            public void setMailId(String popPortletPrefix, Object... ids) {
359                    _mailIdPopPortletPrefix = popPortletPrefix;
360                    _mailIdIds = ids;
361            }
362    
363            public void setNotificationClassNameId(long notificationClassNameId) {
364                    _notificationClassNameId = notificationClassNameId;
365            }
366    
367            /**
368             * @see com.liferay.portal.kernel.notifications.UserNotificationDefinition
369             */
370            public void setNotificationType(int notificationType) {
371                    _notificationType = notificationType;
372            }
373    
374            public void setPortletId(String portletId) {
375                    this.portletId = portletId;
376            }
377    
378            public void setReplyToAddress(String replyToAddress) {
379                    this.replyToAddress = replyToAddress;
380            }
381    
382            /**
383             * @see com.liferay.portal.kernel.search.BaseIndexer#getSiteGroupId(long)
384             */
385            public void setScopeGroupId(long scopeGroupId) {
386                    try {
387                            Group group = GroupLocalServiceUtil.getGroup(scopeGroupId);
388    
389                            if (group.isLayout()) {
390                                    groupId = group.getParentGroupId();
391                            }
392                            else {
393                                    groupId = scopeGroupId;
394                            }
395                    }
396                    catch (Exception e) {
397                    }
398    
399                    this.scopeGroupId = scopeGroupId;
400            }
401    
402            public void setServiceContext(ServiceContext serviceContext) {
403                    this.serviceContext = serviceContext;
404            }
405    
406            public void setSMTPAccount(SMTPAccount smtpAccount) {
407                    this.smtpAccount = smtpAccount;
408            }
409    
410            public void setSubject(String subject) {
411                    this.subject = subject;
412            }
413    
414            public void setUniqueMailId(boolean uniqueMailId) {
415                    this.uniqueMailId = uniqueMailId;
416            }
417    
418            public void setUserId(long userId) {
419                    this.userId = userId;
420            }
421    
422            protected void deleteSubscription(Subscription subscription)
423                    throws Exception {
424    
425                    SubscriptionLocalServiceUtil.deleteSubscription(
426                            subscription.getSubscriptionId());
427            }
428    
429            protected boolean hasPermission(
430                            Subscription subscription, String className, long classPK,
431                            User user)
432                    throws Exception {
433    
434                    if (subscription.getClassName() == null) {
435                            return false;
436                    }
437    
438                    PermissionChecker permissionChecker =
439                            PermissionCheckerFactoryUtil.create(user);
440    
441                    Boolean hasPermission = null;
442    
443                    if (Validator.isNotNull(className)) {
444                            hasPermission =
445                                    BaseModelPermissionCheckerUtil.containsBaseModelPermission(
446                                            permissionChecker, groupId, className, classPK,
447                                            ActionKeys.VIEW);
448    
449                            if ((hasPermission == null) || !hasPermission) {
450                                    return false;
451                            }
452                    }
453    
454                    hasPermission = hasSubscribePermission(permissionChecker, subscription);
455    
456                    if ((hasPermission == null) || !hasPermission) {
457                            return false;
458                    }
459    
460                    return true;
461            }
462    
463            protected boolean hasPermission(Subscription subscription, User user)
464                    throws Exception {
465    
466                    return hasPermission(subscription, _className, _classPK, user);
467            }
468    
469            /**
470             * @throws PortalException
471             */
472            protected Boolean hasSubscribePermission(
473                            PermissionChecker permissionChecker, Subscription subscription)
474                    throws PortalException {
475    
476                    ResourceAction resourceAction =
477                            ResourceActionLocalServiceUtil.fetchResourceAction(
478                                    subscription.getClassName(), ActionKeys.SUBSCRIBE);
479    
480                    if (resourceAction != null) {
481                            return BaseModelPermissionCheckerUtil.containsBaseModelPermission(
482                                    permissionChecker, groupId, subscription.getClassName(),
483                                    subscription.getClassPK(), ActionKeys.SUBSCRIBE);
484                    }
485    
486                    return Boolean.TRUE;
487            }
488    
489            protected void notifyPersistedSubscriber(Subscription subscription)
490                    throws Exception {
491    
492                    notifyPersistedSubscriber(subscription, _className, _classPK);
493            }
494    
495            protected void notifyPersistedSubscriber(
496                            Subscription subscription, String className, long classPK)
497                    throws Exception {
498    
499                    User user = UserLocalServiceUtil.fetchUserById(
500                            subscription.getUserId());
501    
502                    if (user == null) {
503                            if (_log.isInfoEnabled()) {
504                                    _log.info(
505                                            "Subscription " + subscription.getSubscriptionId() +
506                                                    " is stale and will be deleted");
507                            }
508    
509                            deleteSubscription(subscription);
510    
511                            return;
512                    }
513    
514                    String emailAddress = user.getEmailAddress();
515    
516                    if (_sentEmailAddresses.contains(emailAddress)) {
517                            if (_log.isDebugEnabled()) {
518                                    _log.debug("Do not send a duplicate email to " + emailAddress);
519                            }
520    
521                            return;
522                    }
523                    else {
524                            if (_log.isDebugEnabled()) {
525                                    _log.debug(
526                                            "Add " + emailAddress +
527                                                    " to the list of users who have received an email");
528                            }
529    
530                            _sentEmailAddresses.add(emailAddress);
531                    }
532    
533                    if (!user.isActive()) {
534                            if (_log.isDebugEnabled()) {
535                                    _log.debug("Skip inactive user " + user.getUserId());
536                            }
537    
538                            return;
539                    }
540    
541                    try {
542                            if (!hasPermission(subscription, className, classPK, user)) {
543                                    if (_log.isDebugEnabled()) {
544                                            _log.debug("Skip unauthorized user " + user.getUserId());
545                                    }
546    
547                                    return;
548                            }
549                    }
550                    catch (Exception e) {
551                            _log.error(e, e);
552    
553                            return;
554                    }
555    
556                    if (bulk) {
557                            if (UserNotificationManagerUtil.isDeliver(
558                                            user.getUserId(), portletId, _notificationClassNameId,
559                                            _notificationType,
560                                            UserNotificationDeliveryConstants.TYPE_EMAIL)) {
561    
562                                    InternetAddress bulkAddress = new InternetAddress(
563                                            user.getEmailAddress(), user.getFullName());
564    
565                                    if (_bulkAddresses == null) {
566                                            _bulkAddresses = new ArrayList<InternetAddress>();
567                                    }
568    
569                                    _bulkAddresses.add(bulkAddress);
570                            }
571    
572                            sendUserNotification(user);
573                    }
574                    else {
575                            sendNotification(user);
576                    }
577            }
578    
579            protected void notifyRuntimeSubscriber(InternetAddress to, Locale locale)
580                    throws Exception {
581    
582                    String emailAddress = to.getAddress();
583    
584                    User user = UserLocalServiceUtil.fetchUserByEmailAddress(
585                            companyId, emailAddress);
586    
587                    if (user == null) {
588                            if (_log.isInfoEnabled()) {
589                                    _log.info(
590                                            "User with email address " + emailAddress +
591                                                    " does not exist for company " + companyId);
592                            }
593    
594                            sendEmail(to, locale);
595                    }
596                    else {
597                            sendNotification(user);
598                    }
599            }
600    
601            /**
602             * @deprecated As of 6.2.0, replaced by {@link
603             *             #notifyPersistedSubscriber(Subscription)}
604             */
605            @Deprecated
606            protected void notifySubscriber(Subscription subscription)
607                    throws Exception {
608    
609                    notifyPersistedSubscriber(subscription, null, 0);
610            }
611    
612            /**
613             * @deprecated As of 7.0.0, replaced by {@link
614             *             #notifyPersistedSubscriber(Subscription)}
615             */
616            @Deprecated
617            protected void notifySubscriber(
618                            Subscription subscription, String inferredClassName,
619                            long inferredClassPK)
620                    throws Exception {
621    
622                    notifyPersistedSubscriber(
623                            subscription, inferredClassName, inferredClassPK);
624            }
625    
626            protected void processMailMessage(MailMessage mailMessage, Locale locale)
627                    throws Exception {
628    
629                    InternetAddress from = mailMessage.getFrom();
630                    InternetAddress to = mailMessage.getTo()[0];
631    
632                    String processedSubject = StringUtil.replace(
633                            mailMessage.getSubject(),
634                            new String[] {
635                                    "[$FROM_ADDRESS$]", "[$FROM_NAME$]", "[$TO_ADDRESS$]",
636                                    "[$TO_NAME$]"
637                            },
638                            new String[] {
639                                    from.getAddress(),
640                                    GetterUtil.getString(from.getPersonal(), from.getAddress()),
641                                    HtmlUtil.escape(to.getAddress()),
642                                    HtmlUtil.escape(
643                                            GetterUtil.getString(to.getPersonal(), to.getAddress()))
644                            });
645    
646                    processedSubject = replaceContent(processedSubject, locale, false);
647    
648                    mailMessage.setSubject(processedSubject);
649    
650                    String processedBody = StringUtil.replace(
651                            mailMessage.getBody(),
652                            new String[] {
653                                    "[$FROM_ADDRESS$]", "[$FROM_NAME$]", "[$TO_ADDRESS$]",
654                                    "[$TO_NAME$]"
655                            },
656                            new String[] {
657                                    from.getAddress(),
658                                    GetterUtil.getString(from.getPersonal(), from.getAddress()),
659                                    HtmlUtil.escape(to.getAddress()),
660                                    HtmlUtil.escape(
661                                            GetterUtil.getString(to.getPersonal(), to.getAddress()))
662                            });
663    
664                    processedBody = replaceContent(processedBody, locale, htmlFormat);
665    
666                    mailMessage.setBody(processedBody);
667            }
668    
669            protected String replaceContent(String content, Locale locale)
670                    throws Exception {
671    
672                    return replaceContent(content, locale, true);
673            }
674    
675            protected String replaceContent(
676                            String content, Locale locale, boolean escape)
677                    throws Exception {
678    
679                    for (Map.Entry<String, EscapableObject<String>> entry :
680                                    _context.entrySet()) {
681    
682                            String key = entry.getKey();
683                            EscapableObject<String> value = entry.getValue();
684    
685                            String valueString = null;
686    
687                            if (escape) {
688                                    valueString = value.getEscapedValue();
689                            }
690                            else {
691                                    valueString = value.getOriginalValue();
692                            }
693    
694                            content = StringUtil.replace(content, key, valueString);
695                    }
696    
697                    if (Validator.isNotNull(portletId)) {
698                            String portletName = PortalUtil.getPortletTitle(portletId, locale);
699    
700                            content = StringUtil.replace(
701                                    content, "[$PORTLET_NAME$]", portletName);
702                    }
703    
704                    Company company = CompanyLocalServiceUtil.getCompany(companyId);
705    
706                    content = StringUtil.replace(
707                            content,
708                            new String[] {
709                                    "href=\"/", "src=\"/"
710                            },
711                            new String[] {
712                                    "href=\"" + company.getPortalURL(groupId) + "/",
713                                    "src=\"" + company.getPortalURL(groupId) + "/"
714                            });
715    
716                    return content;
717            }
718    
719            protected void sendEmail(InternetAddress to, Locale locale)
720                    throws Exception {
721    
722                    InternetAddress from = new InternetAddress(
723                            replaceContent(fromAddress, locale),
724                            replaceContent(fromName, locale));
725    
726                    String processedSubject = null;
727    
728                    if (localizedSubjectMap != null) {
729                            String localizedSubject = localizedSubjectMap.get(locale);
730    
731                            if (Validator.isNull(localizedSubject)) {
732                                    Locale defaultLocale = LocaleUtil.getDefault();
733    
734                                    processedSubject = localizedSubjectMap.get(defaultLocale);
735                            }
736                            else {
737                                    processedSubject = localizedSubject;
738                            }
739                    }
740                    else {
741                            processedSubject = this.subject;
742                    }
743    
744                    String processedBody = null;
745    
746                    if (localizedBodyMap != null) {
747                            String localizedBody = localizedBodyMap.get(locale);
748    
749                            if (Validator.isNull(localizedBody)) {
750                                    Locale defaultLocale = LocaleUtil.getDefault();
751    
752                                    processedBody = localizedBodyMap.get(defaultLocale);
753                            }
754                            else {
755                                    processedBody = localizedBody;
756                            }
757                    }
758                    else {
759                            processedBody = this.body;
760                    }
761    
762                    MailMessage mailMessage = new MailMessage(
763                            from, to, processedSubject, processedBody, htmlFormat);
764    
765                    if (fileAttachments != null) {
766                            for (FileAttachment fileAttachment : fileAttachments) {
767                                    mailMessage.addFileAttachment(
768                                            fileAttachment.getFile(), fileAttachment.getFileName());
769                            }
770                    }
771    
772                    if (bulk && (_bulkAddresses != null)) {
773                            mailMessage.setBulkAddresses(
774                                    _bulkAddresses.toArray(
775                                            new InternetAddress[_bulkAddresses.size()]));
776    
777                            _bulkAddresses.clear();
778                    }
779    
780                    if (inReplyTo != null) {
781                            mailMessage.setInReplyTo(inReplyTo);
782                    }
783    
784                    mailMessage.setMessageId(mailId);
785    
786                    if (replyToAddress != null) {
787                            InternetAddress replyTo = new InternetAddress(
788                                    replaceContent(replyToAddress, locale),
789                                    replaceContent(replyToAddress, locale));
790    
791                            mailMessage.setReplyTo(new InternetAddress[] {replyTo});
792                    }
793    
794                    if (smtpAccount != null) {
795                            mailMessage.setSMTPAccount(smtpAccount);
796                    }
797    
798                    processMailMessage(mailMessage, locale);
799    
800                    MailServiceUtil.sendEmail(mailMessage);
801            }
802    
803            protected void sendEmailNotification(User user) throws Exception {
804                    if (UserNotificationManagerUtil.isDeliver(
805                                    user.getUserId(), portletId, _notificationClassNameId,
806                                    _notificationType,
807                                    UserNotificationDeliveryConstants.TYPE_EMAIL)) {
808    
809                            InternetAddress to = new InternetAddress(
810                                    user.getEmailAddress(), user.getFullName());
811    
812                            sendEmail(to, user.getLocale());
813                    }
814            }
815    
816            protected void sendNotification(User user) throws Exception {
817                    sendEmailNotification(user);
818                    sendUserNotification(user);
819            }
820    
821            protected void sendUserNotification(User user) throws Exception {
822                    JSONObject notificationEventJSONObject =
823                            JSONFactoryUtil.createJSONObject();
824    
825                    notificationEventJSONObject.put("className", _className);
826                    notificationEventJSONObject.put("classPK", _classPK);
827                    notificationEventJSONObject.put("entryTitle", _entryTitle);
828                    notificationEventJSONObject.put("entryURL", _entryURL);
829                    notificationEventJSONObject.put("notificationType", _notificationType);
830                    notificationEventJSONObject.put("userId", user.getUserId());
831    
832                    if (UserNotificationManagerUtil.isDeliver(
833                                    user.getUserId(), portletId, _notificationClassNameId,
834                                    _notificationType,
835                                    UserNotificationDeliveryConstants.TYPE_PUSH)) {
836    
837                            UserNotificationEventLocalServiceUtil.sendUserNotificationEvents(
838                                    user.getUserId(), portletId,
839                                    UserNotificationDeliveryConstants.TYPE_PUSH,
840                                    notificationEventJSONObject);
841                    }
842    
843                    if (UserNotificationManagerUtil.isDeliver(
844                                    user.getUserId(), portletId, _notificationClassNameId,
845                                    _notificationType,
846                                    UserNotificationDeliveryConstants.TYPE_WEBSITE)) {
847    
848                            UserNotificationEventLocalServiceUtil.sendUserNotificationEvents(
849                                    user.getUserId(), portletId,
850                                    UserNotificationDeliveryConstants.TYPE_WEBSITE,
851                                    notificationEventJSONObject);
852                    }
853            }
854    
855            protected String body;
856            protected boolean bulk;
857            protected long companyId;
858            protected List<FileAttachment> fileAttachments =
859                    new ArrayList<FileAttachment>();
860            protected String fromAddress;
861            protected String fromName;
862            protected long groupId;
863            protected boolean htmlFormat;
864            protected String inReplyTo;
865            protected Map<Locale, String> localizedBodyMap;
866            protected Map<Locale, String> localizedSubjectMap;
867            protected String mailId;
868            protected String portletId;
869            protected String replyToAddress;
870            protected long scopeGroupId;
871            protected ServiceContext serviceContext;
872            protected SMTPAccount smtpAccount;
873            protected String subject;
874            protected boolean uniqueMailId = true;
875            protected long userId;
876    
877            private void readObject(ObjectInputStream objectInputStream)
878                    throws ClassNotFoundException, IOException {
879    
880                    objectInputStream.defaultReadObject();
881    
882                    String servletContextName = objectInputStream.readUTF();
883    
884                    if (!servletContextName.isEmpty()) {
885                            _classLoader = ClassLoaderPool.getClassLoader(servletContextName);
886                    }
887            }
888    
889            private void writeObject(ObjectOutputStream objectOutputStream)
890                    throws IOException {
891    
892                    objectOutputStream.defaultWriteObject();
893    
894                    String servletContextName = StringPool.BLANK;
895    
896                    if (_classLoader != null) {
897                            servletContextName = ClassLoaderPool.getContextName(_classLoader);
898                    }
899    
900                    objectOutputStream.writeUTF(servletContextName);
901            }
902    
903            private static Log _log = LogFactoryUtil.getLog(SubscriptionSender.class);
904    
905            private List<InternetAddress> _bulkAddresses;
906            private transient ClassLoader _classLoader;
907            private String _className;
908            private long _classPK;
909            private Map<String, EscapableObject<String>> _context =
910                    new HashMap<String, EscapableObject<String>>();
911            private String _contextUserPrefix;
912            private String _entryTitle;
913            private String _entryURL;
914            private boolean _initialized;
915            private Object[] _mailIdIds;
916            private String _mailIdPopPortletPrefix;
917            private long _notificationClassNameId;
918            private int _notificationType;
919            private List<ObjectValuePair<String, Long>> _persistestedSubscribersOVPs =
920                    new ArrayList<ObjectValuePair<String, Long>>();
921            private List<ObjectValuePair<String, String>> _runtimeSubscribersOVPs =
922                    new ArrayList<ObjectValuePair<String, String>>();
923            private Set<String> _sentEmailAddresses = new HashSet<String>();
924    
925    }