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