File Source: MailUtil.java

         /* 
    P/P   *  Method: org.apache.roller.weblogger.util.MailUtil$MailingException__static_init
          */
     1  /*
     2   * Licensed to the Apache Software Foundation (ASF) under one or more
     3   *  contributor license agreements.  The ASF licenses this file to You
     4   * under the Apache License, Version 2.0 (the "License"); you may not
     5   * use this file except in compliance with the License.
     6   * You may obtain a copy of the License at
     7   *
     8   *     http://www.apache.org/licenses/LICENSE-2.0
     9   *
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS,
    12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   * See the License for the specific language governing permissions and
    14   * limitations under the License.  For additional information regarding
    15   * copyright in this work, please see the NOTICE file in the top level
    16   * directory of this distribution.
    17   */
    18  
    19  package org.apache.roller.weblogger.util;
    20  
    21  import java.text.MessageFormat;
    22  import java.util.ArrayList;
    23  import java.util.HashMap;
    24  import java.util.Iterator;
    25  import java.util.List;
    26  import java.util.Map;
    27  import java.util.ResourceBundle;
    28  import java.util.Set;
    29  import java.util.TreeSet;
    30  import javax.mail.Message;
    31  import javax.mail.MessagingException;
    32  import javax.mail.SendFailedException;
    33  import javax.mail.Session;
    34  import javax.mail.Transport;
    35  import javax.mail.Address;
    36  import javax.mail.internet.InternetAddress;
    37  import javax.mail.internet.MimeMessage;
    38  import org.apache.commons.lang.StringUtils;
    39  import org.apache.commons.logging.Log;
    40  import org.apache.commons.logging.LogFactory;
    41  import org.apache.roller.weblogger.WebloggerException;
    42  import org.apache.roller.weblogger.business.MailProvider;
    43  import org.apache.roller.weblogger.business.WebloggerFactory;
    44  import org.apache.roller.weblogger.business.UserManager;
    45  import org.apache.roller.weblogger.business.startup.WebloggerStartup;
    46  import org.apache.roller.weblogger.config.WebloggerConfig;
    47  import org.apache.roller.weblogger.config.WebloggerRuntimeConfig;
    48  import org.apache.roller.weblogger.pojos.WeblogPermission;
    49  import org.apache.roller.weblogger.pojos.User;
    50  import org.apache.roller.weblogger.pojos.WeblogEntry;
    51  import org.apache.roller.weblogger.pojos.Weblog;
    52  import org.apache.roller.weblogger.pojos.WeblogEntryComment;
    53  import org.apache.roller.weblogger.util.RollerMessages.RollerMessage;
    54  
    55  
    56  /**
    57   * A utility class for helping with sending emails.
    58   */
         /* 
    P/P   *  Method: void org.apache.roller.weblogger.util.MailUtil()
          */
    59  public class MailUtil {
    60      
             /* 
    P/P       *  Method: org.apache.roller.weblogger.util.MailUtil__static_init
              * 
              *  Postconditions:
              *    init'ed(log)
              */
    61      private static Log log = LogFactory.getLog(MailUtil.class);
    62      
    63      private static final String EMAIL_ADDR_REGEXP = "^.*@.*[.].{2,}$";
    64      
    65      
    66      /**
    67       * Ideally mail senders should call this first to avoid errors that occur 
    68       * when mail is not properly configured. We'll complain about that at 
    69       * startup, no need to complain on every attempt to send.
    70       */
    71      public static boolean isMailConfigured() {
                 /* 
    P/P           *  Method: bool isMailConfigured()
                  * 
                  *  Postconditions:
                  *    init'ed(return_value)
                  */
    72          return WebloggerStartup.getMailProvider() != null; 
    73      }
    74      
    75      /**
    76       * Send an email notice that a new pending entry has been submitted.
    77       */
    78      public static void sendPendingEntryNotice(WeblogEntry entry) 
    79              throws WebloggerException {
    80          
                 /* 
    P/P           *  Method: void sendPendingEntryNotice(WeblogEntry)
                  * 
                  *  Preconditions:
                  *    (soft) entry != null
                  *    (soft) log != null
                  * 
                  *  Presumptions:
                  *    init'ed(java.lang.Boolean.TRUE)
                  *    java.util.ArrayList:size(...)@113 >= 0
                  *    java.util.Iterator:next(...)@105 != null
                  *    java.util.ResourceBundle:getBundle(...)@118 != null
                  *    org.apache.roller.weblogger.business.MailProvider:getSession(...)@81 != null
                  *    ...
                  * 
                  *  Test Vectors:
                  *    java.util.Iterator:hasNext(...)@104: {0}, {1}
                  *    org.apache.roller.weblogger.pojos.User:getEmailAddress(...)@106: Addr_Set{null}, Inverse{null}
                  *    org.apache.roller.weblogger.pojos.Weblog:hasUserPermissions(...)@106: {0}, {1}
                  */
    81          Session mailSession = WebloggerStartup.getMailProvider().getSession();
    82          if(mailSession == null) {
    83              throw new WebloggerException("Couldn't get mail Session");
    84          }
    85          
    86          try {
    87              UserManager umgr = WebloggerFactory.getWeblogger().getUserManager();
    88              
    89              String userName = entry.getCreator().getUserName();
    90              String from = entry.getCreator().getEmailAddress();
    91              String cc[] = new String[] {from};
    92              String bcc[] = new String[0];
    93              String to[];
    94              String subject;
    95              String content;
    96              
    97              // list of enabled website authors and admins
    98              ArrayList reviewers = new ArrayList();
    99              List websiteUsers = umgr.getUsers(
   100                      entry.getWebsite(), Boolean.TRUE, null, null, 0, -1);
   101              
   102              // build list of reviewers (website users with author permission)
   103              Iterator websiteUserIter = websiteUsers.iterator();
   104              while (websiteUserIter.hasNext()) {
   105                  User websiteUser = (User)websiteUserIter.next();
   106                  if (entry.getWebsite().hasUserPermissions(
   107                          
   108                          websiteUser,WeblogPermission.AUTHOR)
   109                          && websiteUser.getEmailAddress() != null) {
   110                      reviewers.add(websiteUser.getEmailAddress());
   111                  }
   112              }
   113              to = (String[])reviewers.toArray(new String[reviewers.size()]);
   114              
   115              // Figure URL to entry edit page
   116              String editURL = WebloggerFactory.getWeblogger().getUrlStrategy().getEntryEditURL(entry.getWebsite().getHandle(), entry.getId(), true);
   117              
   118              ResourceBundle resources = ResourceBundle.getBundle(
   119                      "ApplicationResources", entry.getWebsite().getLocaleInstance());
   120              StringBuffer sb = new StringBuffer();
   121              sb.append(
   122                      MessageFormat.format(
   123                      resources.getString("weblogEntry.pendingEntrySubject"),
   124                      new Object[] {
   125                  entry.getWebsite().getName(),
   126                  entry.getWebsite().getHandle()
   127              }));
   128              subject = sb.toString();
   129              sb = new StringBuffer();
   130              sb.append(
   131                      MessageFormat.format(
   132                      resources.getString("weblogEntry.pendingEntryContent"),
   133                      new Object[] { userName, userName, editURL })
   134                      );
   135              content = sb.toString();
   136              MailUtil.sendTextMessage(
   137                      from, to, cc, bcc, subject, content);
   138          } catch (MessagingException e) {
   139              log.error("ERROR: Problem sending pending entry notification email.");
   140          }
   141      }
   142      
   143      
   144      /**
   145       * Send a weblog invitation email.
   146       */
   147      public static void sendWeblogInvitation(Weblog website, 
   148                                              User user)
   149              throws WebloggerException {
   150          
                 /* 
    P/P           *  Method: void sendWeblogInvitation(Weblog, User)
                  * 
                  *  Preconditions:
                  *    user != null
                  *    website != null
                  *    (soft) log != null
                  * 
                  *  Presumptions:
                  *    java.util.ResourceBundle:getBundle(...)@172 != null
                  *    org.apache.roller.weblogger.business.MailProvider:getSession(...)@151 != null
                  *    org.apache.roller.weblogger.business.WebloggerFactory:getWeblogger(...)@158 != null
                  *    org.apache.roller.weblogger.business.startup.WebloggerStartup:getMailProvider(...)@151 != null
                  */
   151          Session mailSession = WebloggerStartup.getMailProvider().getSession();
   152          if(mailSession == null) {
   153              throw new WebloggerException("ERROR: Notification email(s) not sent, "
   154                      + "Roller's mail session not properly configured");
   155          }
   156          
   157          try {
+  158              UserManager umgr = WebloggerFactory.getWeblogger().getUserManager();
   159              
+  160              String userName = user.getUserName();
   161              String from = website.getEmailAddress();
   162              String cc[] = new String[] {from};
   163              String bcc[] = new String[0];
   164              String to[] = new String[] {user.getEmailAddress()};
   165              String subject;
   166              String content;
   167              
   168              // Figure URL to entry edit page
   169              String rootURL = WebloggerRuntimeConfig.getAbsoluteContextURL();
   170              String url = rootURL + "/roller-ui/menu.rol";
   171              
   172              ResourceBundle resources = ResourceBundle.getBundle(
   173                      "ApplicationResources",
   174                      website.getLocaleInstance());
   175              StringBuffer sb = new StringBuffer();
   176              sb.append(MessageFormat.format(
   177                      resources.getString("inviteMember.notificationSubject"),
   178                      new Object[] {
   179                  website.getName(),
   180                  website.getHandle()})
   181                  );
   182              subject = sb.toString();
   183              sb = new StringBuffer();
   184              sb.append(MessageFormat.format(
   185                      resources.getString("inviteMember.notificationContent"),
   186                      new Object[] {
   187                  website.getName(),
   188                  website.getHandle(),
   189                  user.getUserName(),
   190                  url
   191              }));
   192              content = sb.toString();
   193              MailUtil.sendTextMessage(
   194                      from, to, cc, bcc, subject, content);
   195          } catch (MessagingException e) {
   196              throw new WebloggerException("ERROR: Notification email(s) not sent, "
   197                      + "due to Roller configuration or mail server problem.", e);
   198          }
   199      }
   200      
   201      
   202      /**
   203       * Send a weblog invitation email.
   204       */
   205      public static void sendUserActivationEmail(User user)
   206              throws WebloggerException {
   207          
                 /* 
    P/P           *  Method: void sendUserActivationEmail(User)
                  * 
                  *  Preconditions:
                  *    user != null
                  *    (soft) log != null
                  * 
                  *  Presumptions:
                  *    java.util.ResourceBundle:getBundle(...)@215 != null
                  *    org.apache.roller.weblogger.business.MailProvider:getSession(...)@208 != null
                  *    org.apache.roller.weblogger.business.startup.WebloggerStartup:getMailProvider(...)@208 != null
                  */
   208          Session mailSession = WebloggerStartup.getMailProvider().getSession();
   209          if(mailSession == null) {
   210              throw new WebloggerException("ERROR: Notification email(s) not sent, "
   211                      + "Roller's mail session not properly configured");
   212          }
   213          
   214          try {
   215              ResourceBundle resources = ResourceBundle.getBundle(
   216                      "ApplicationResources", I18nUtils.toLocale(user.getLocale()));
   217              
   218              String from = WebloggerRuntimeConfig.getProperty(
   219                      "user.account.activation.mail.from");
   220              
   221              String cc[] = new String[0];
   222              String bcc[] = new String[0];
   223              String to[] = new String[] { user.getEmailAddress() };
   224              String subject = resources.getString(
   225                      "user.account.activation.mail.subject");
   226              String content;
   227              
   228              String rootURL = WebloggerRuntimeConfig.getAbsoluteContextURL();
   229              
   230              StringBuffer sb = new StringBuffer();
   231              
   232              // activationURL=
   233              String activationURL = rootURL
   234                      + "/roller-ui/register!activate.rol?activationCode="
   235                      + user.getActivationCode();
   236              sb.append(MessageFormat.format(
   237                      resources.getString("user.account.activation.mail.content"),
   238                      new Object[] { user.getFullName(), user.getUserName(),
   239                      activationURL }));
   240              content = sb.toString();
   241              
   242              sendHTMLMessage(from, to, cc, bcc, subject, content);
   243          } catch (MessagingException e) {
   244              throw new WebloggerException("ERROR: Problem sending activation email.", e);
   245          }
   246      }
   247      
   248      
   249      /**
   250       * Send email notification of new or newly approved comment.
   251       * TODO: Make the addressing options configurable on a per-website basis.
   252       * 
   253       * @param commentObject      The new comment
   254       * @param messages           Messages to be included in e-mail (or null). 
   255       *                           Errors will be assumed to be "validation errors" 
   256       *                           and messages will be assumed to be "from the system"
   257       */
   258      public static void sendEmailNotification(WeblogEntryComment commentObject,
   259                                               RollerMessages messages, 
   260                                               I18nMessages resources,
   261                                               boolean notifySubscribers) 
   262              throws MailingException {
   263          
                 /* 
    P/P           *  Method: void sendEmailNotification(WeblogEntryComment, RollerMessages, I18nMessages, bool)
                  * 
                  *  Preconditions:
                  *    commentObject != null
                  *    (soft) log != null
                  *    (soft) messages != null
                  *    (soft) messages.mErrors != null
                  *    (soft) messages.mMessages != null
                  *    (soft) resources != null
                  *    (soft) resources.bundle != null
                  * 
                  *  Presumptions:
                  *    bcc.length@318 <= 232-1
                  *    java.util.Iterator:next(...)@298 != null
                  *    java.util.Iterator:next(...)@372 != null
                  *    java.util.Iterator:next(...)@389 != null
                  *    java.util.Set:toArray(...)@318 != null
                  *    ...
                  * 
                  *  Test Vectors:
                  *    notifySubscribers: {0}, {1}
                  *    commenterAddrs.length@318: {0}, {1..+Inf}
                  *    java.lang.Boolean:booleanValue(...)@270: {1}, {0}
                  *    java.lang.Boolean:booleanValue(...)@302: {0}, {1}
                  *    java.lang.String:matches(...)@304: {0}, {1}
                  *    java.util.Iterator:hasNext(...)@371: {0}, {1}
                  *    java.util.Iterator:hasNext(...)@388: {0}, {1}
                  *    java.util.List:size(...)@70: {-231..0}, {1..232-1}
                  *    java.util.List:size(...)@74: {-231..0}, {1..232-1}
                  *    java.util.Set:size(...)@421: {2..232-1}, {-231..1}
                  *    ...
                  */
   264          WeblogEntry entry = commentObject.getWeblogEntry();
   265          Weblog weblog = entry.getWebsite();
   266          User user = entry.getCreator();
   267          
   268          // Only send email if email notificaiton is enabled
   269          boolean notify = WebloggerRuntimeConfig.getBooleanProperty("users.comments.emailnotify");
   270          if (!notify || !weblog.getEmailComments().booleanValue()) {
   271              // notifications disabled, just bail
   272              return;
   273          }
   274          
   275          log.debug("Comment notification enabled ... preparing email");
   276          
   277          // Determine message and addressing options from init parameters
   278          boolean hideCommenterAddrs = WebloggerConfig.getBooleanProperty(
   279                  "comment.notification.hideCommenterAddresses");
   280          
   281          // use either the weblog configured from address or the site configured from address
   282          String from = weblog.getEmailFromAddress();
   283          if(StringUtils.isEmpty(from)) {
   284              // TODO: this should not be the users email address
   285              from = user.getEmailAddress();
   286          }
   287          
   288          // build list of email addresses to send notification to
   289          Set subscribers = new TreeSet();
   290          
   291          // If we are to notify subscribers, then...
   292          if (notifySubscribers) {
   293              log.debug("Sending notification email to all subscribers");
   294              
   295              // Get all the subscribers to this comment thread
   296              List comments = entry.getComments(true, true);
   297              for (Iterator it = comments.iterator(); it.hasNext();) {
   298                  WeblogEntryComment comment = (WeblogEntryComment) it.next();
   299                  if (!StringUtils.isEmpty(comment.getEmail())) {
   300                      // If user has commented twice,
   301                      // count the most recent notify setting
   302                      if (comment.getNotify().booleanValue()) {
   303                          // only add those with valid email
   304                          if (comment.getEmail().matches(EMAIL_ADDR_REGEXP)) {
   305                              subscribers.add(comment.getEmail());
   306                          }
   307                      } else {
   308                          // remove user who doesn't want to be notified
   309                          subscribers.remove(comment.getEmail());
   310                      }
   311                  }
   312              }
   313          } else {
   314              log.debug("Sending notification email only to weblog owner");
   315          }
   316          
   317          // Form array of commenter addrs
   318          String[] commenterAddrs = (String[])subscribers.toArray(new String[0]);
   319          
   320          //------------------------------------------
   321          // --- Form the messages to be sent -
   322          // Build separate owner and commenter (aka subscriber) messages
   323          
   324          // Determine with mime type to use for e-mail
   325          StringBuffer msg = new StringBuffer();
   326          StringBuffer ownermsg = new StringBuffer();
   327          boolean escapeHtml = !WebloggerRuntimeConfig.getBooleanProperty("users.comments.htmlenabled");
   328          
   329          // first the commenter message
   330          
   331          if (!escapeHtml) {
   332              msg.append("<html><body style=\"background: white; ");
   333              msg.append(" color: black; font-size: 12px\">");
   334          }
   335          
   336          if (!StringUtils.isEmpty(commentObject.getName())) {
   337              msg.append(commentObject.getName() + " "
   338                      + resources.getString("email.comment.wrote")+": ");
   339          } else {
   340              msg.append(resources.getString("email.comment.anonymous")+": ");
   341          }
   342          
   343          msg.append((escapeHtml) ? "\n\n" : "<br /><br />");
   344          
   345          msg.append((escapeHtml) ? Utilities.escapeHTML(commentObject.getContent())
   346          : Utilities.transformToHTMLSubset(Utilities.escapeHTML(commentObject.getContent())));
   347          
   348          msg.append((escapeHtml) ? "\n\n----\n"
   349                  : "<br /><br /><hr /><span style=\"font-size: 11px\">");
   350          msg.append(resources.getString("email.comment.respond") + ": ");
   351          msg.append((escapeHtml) ? "\n" : "<br />");
   352          
   353          // Build link back to comment
   354          String commentURL = WebloggerFactory.getWeblogger().getUrlStrategy().getWeblogCommentsURL(weblog, null, entry.getAnchor(), true);
   355          
   356          if (escapeHtml) {
   357              msg.append(commentURL);
   358          } else {
   359              msg.append("<a href=\""+commentURL+"\">"+commentURL+"</a></span>");
   360          }
   361          
   362          // next the owner message
   363          
   364          // First, list any messages from the system that were passed in:
   365          if (messages.getMessageCount() > 0) {
   366              ownermsg.append((escapeHtml) ? "" : "<p>");
   367              ownermsg.append(resources.getString("commentServlet.email.thereAreSystemMessages"));
   368              ownermsg.append((escapeHtml) ? "\n\n" : "</p>");
   369              ownermsg.append((escapeHtml) ? "" : "<ul>");
   370          }
   371          for (Iterator it = messages.getMessages(); it.hasNext();) {
   372              RollerMessage rollerMessage = (RollerMessage)it.next();
   373              ownermsg.append((escapeHtml) ? "" : "<li>");
   374              ownermsg.append(MessageFormat.format(resources.getString(rollerMessage.getKey()), (Object[])rollerMessage.getArgs()) );
   375              ownermsg.append((escapeHtml) ? "\n\n" : "</li>");
   376          }
   377          if (messages.getMessageCount() > 0) {
   378              ownermsg.append((escapeHtml) ? "\n\n" : "</ul>");
   379          }
   380          
   381          // Next, list any validation error messages that were passed in:
   382          if (messages.getErrorCount() > 0) {
   383              ownermsg.append((escapeHtml) ? "" : "<p>");
   384              ownermsg.append(resources.getString("commentServlet.email.thereAreErrorMessages"));
   385              ownermsg.append((escapeHtml) ? "\n\n" : "</p>");
   386              ownermsg.append((escapeHtml) ? "" : "<ul>");
   387          }
   388          for (Iterator it = messages.getErrors(); it.hasNext();) {
   389              RollerMessage rollerMessage = (RollerMessage)it.next();
   390              ownermsg.append((escapeHtml) ? "" : "<li>");
   391              ownermsg.append(MessageFormat.format(resources.getString(rollerMessage.getKey()), (Object[])rollerMessage.getArgs()) );
   392              ownermsg.append((escapeHtml) ? "\n\n" : "</li>");
   393          }
   394          if (messages.getErrorCount() > 0) {
   395              ownermsg.append((escapeHtml) ? "\n\n" : "</ul>");
   396          }
   397          
   398          ownermsg.append(msg);
   399          
   400          // add link to weblog edit page so user can login to manage comments
   401          ownermsg.append((escapeHtml) ? "\n\n----\n" :
   402              "<br /><br /><hr /><span style=\"font-size: 11px\">");
   403          ownermsg.append("Link to comment management page:");
   404          ownermsg.append((escapeHtml) ? "\n" : "<br />");
   405          
   406          Map<String, String> parameters = new HashMap();
   407          parameters.put("bean.entryId", entry.getId());
   408          String deleteURL = WebloggerFactory.getWeblogger().getUrlStrategy().getActionURL(
   409                  "comments", "/roller-ui/authoring", weblog.getHandle(), parameters, true);
   410          
   411          if (escapeHtml) {
   412              ownermsg.append(deleteURL);
   413          } else {
   414              ownermsg.append(
   415                      "<a href=\"" + deleteURL + "\">" + deleteURL + "</a></span>");
   416              msg.append("</Body></html>");
   417              ownermsg.append("</Body></html>");
   418          }
   419          
   420          String subject = null;
   421          if ((subscribers.size() > 1) ||
   422                  (StringUtils.equals(commentObject.getEmail(), user.getEmailAddress()))) {
   423              subject= "RE: "+resources.getString("email.comment.title")+": ";
   424          } else {
   425              subject = resources.getString("email.comment.title") + ": ";
   426          }
   427          subject += entry.getTitle();
   428          
   429          // send message to email recipients
   430          try {
   431              boolean isHtml = !escapeHtml;
   432              
   433              // Send separate messages to owner and commenters
   434              if(isHtml) {
   435                  sendHTMLMessage(
   436                          from,
   437                          new String[]{user.getEmailAddress()},
   438                          null,
   439                          null,
   440                          subject,
   441                          ownermsg.toString());
   442              } else {
   443                  sendTextMessage(
   444                          from,
   445                          new String[]{user.getEmailAddress()},
   446                          null,
   447                          null,
   448                          subject,
   449                          ownermsg.toString());
   450              }
   451              
   452              // now send to subscribers
   453              if (notifySubscribers && commenterAddrs.length > 0) {
   454                  // If hiding commenter addrs, they go in Bcc: otherwise in the To: of the second message
   455                  String[] to = hideCommenterAddrs ? null : commenterAddrs;
   456                  String[] bcc = hideCommenterAddrs ? commenterAddrs : null;
   457                  
   458                  if(isHtml) {
   459                      sendHTMLMessage(
   460                              from, 
   461                              to, 
   462                              null, 
   463                              bcc, 
   464                              subject, 
   465                              msg.toString());
   466                  } else {
   467                      sendTextMessage(
   468                              from, 
   469                              to, 
   470                              null, 
   471                              bcc, 
   472                              subject, 
   473                              msg.toString());
   474                  }
   475              }
   476          } catch (Exception e) {
   477              log.warn("Exception sending comment notification mail", e);
   478              // This will log the stack trace if debug is enabled
   479              if (log.isDebugEnabled()) {
   480                  log.debug(e);
   481              }
   482          }
   483          
   484          log.debug("Done sending email message");
   485      }
   486      
   487  
   488      public static void sendEmailApprovalNotifications(List<WeblogEntryComment> comments,
   489                                                 I18nMessages resources) 
   490              throws MailingException {
   491          
                 /* 
    P/P           *  Method: void sendEmailApprovalNotifications(List, I18nMessages)
                  * 
                  *  Preconditions:
                  *    comments != null
                  *    (soft) log != null
                  *    (soft) resources != null
                  *    (soft) resources.bundle != null
                  * 
                  *  Presumptions:
                  *    java.util.Iterator:next(...)@493 != null
                  * 
                  *  Test Vectors:
                  *    java.util.Iterator:hasNext(...)@493: {0}, {1}
                  */
   492          RollerMessages messages = new RollerMessages();
   493          for (WeblogEntryComment comment : comments) {            
   494              
   495              // Send email notifications because a new comment has been approved
   496              sendEmailNotification(comment, messages, resources, true);
   497  
   498              // Send approval notification to author of approved comment
   499              sendEmailApprovalNotification(comment, resources);
   500          }
   501      }
   502      
   503      
   504      /**
   505       * Send message to author of approved comment
   506       *
   507       * TODO: Make the addressing options configurable on a per-website basis.
   508       */
   509      public static void sendEmailApprovalNotification(WeblogEntryComment cd, 
   510                                                       I18nMessages resources) 
   511              throws MailingException {
   512          
                 /* 
    P/P           *  Method: void sendEmailApprovalNotification(WeblogEntryComment, I18nMessages)
                  * 
                  *  Preconditions:
                  *    cd != null
                  *    (soft) log != null
                  *    (soft) resources != null
                  *    (soft) resources.bundle != null
                  * 
                  *  Presumptions:
                  *    org.apache.roller.weblogger.business.Weblogger:getUrlStrategy(...)@539 != null
                  *    org.apache.roller.weblogger.business.WebloggerFactory:getWeblogger(...)@539 != null
                  *    org.apache.roller.weblogger.pojos.Weblog:getEmailComments(...)@519 != null
                  *    org.apache.roller.weblogger.pojos.WeblogEntry:getCreator(...)@515 != null
                  *    org.apache.roller.weblogger.pojos.WeblogEntry:getWebsite(...)@514 != null
                  *    ...
                  * 
                  *  Test Vectors:
                  *    java.lang.Boolean:booleanValue(...)@519: {1}, {0}
                  *    org.apache.commons.lang.StringUtils:isEmpty(...)@528: {0}, {1}
                  *    org.apache.roller.weblogger.config.WebloggerRuntimeConfig:getBooleanProperty(...)@518: {0}, {1}
                  */
   513          WeblogEntry entry = cd.getWeblogEntry();
   514          Weblog weblog = entry.getWebsite();
   515          User user = entry.getCreator();
   516          
   517          // Only send email if email notificaiton is enabled
   518          boolean notify = WebloggerRuntimeConfig.getBooleanProperty("users.comments.emailnotify");
   519          if (!notify || !weblog.getEmailComments().booleanValue()) {
   520              // notifications disabled, just bail
   521              return;
   522          }
   523          
   524          log.debug("Comment notification enabled ... preparing email");
   525          
   526          // use either the weblog configured from address or the site configured from address
   527          String from = weblog.getEmailFromAddress();
   528          if(StringUtils.isEmpty(from)) {
   529              // TODO: this should not be the users email address
   530              from = user.getEmailAddress();
   531          }
   532          
   533          // form the message to be sent
   534          String subject = resources.getString("email.comment.commentApproved");
   535          
   536          StringBuffer msg = new StringBuffer();
   537          msg.append(resources.getString("email.comment.commentApproved"));
   538          msg.append("\n\n");
   539          msg.append(WebloggerFactory.getWeblogger().getUrlStrategy().getWeblogCommentsURL(weblog, null, entry.getAnchor(), true));
   540          
   541          // send message to author of approved comment
   542          try {
   543              sendTextMessage(
   544                      from, // from
   545                      new String[] {cd.getEmail()}, // to
   546                      null, // cc
   547                      null, // bcc
   548                      subject, // subject
   549                      msg.toString()); // message
   550          } catch (Exception e) {
   551              log.warn("Exception sending comment mail: " + e.getMessage());
   552              // This will log the stack trace if debug is enabled
   553              if (log.isDebugEnabled()) {
   554                  log.debug(e);
   555              }
   556          }
   557          
   558          log.debug("Done sending email message");
   559      }
   560      
   561      
   562      // agangolli: Incorporated suggested changes from Ken Blackler.
   563      
   564      /**
   565       * This method is used to send a Message with a pre-defined
   566       * mime-type.
   567       *
   568       * @param from e-mail address of sender
   569       * @param to e-mail address(es) of recipients
   570       * @param subject subject of e-mail
   571       * @param content the body of the e-mail
   572       * @param mimeType type of message, i.e. text/plain or text/html
   573       * @throws MessagingException the exception to indicate failure
   574       */
   575      public static void sendMessage
   576              (
   577              String from,
   578              String[] to,
   579              String[] cc,
   580              String[] bcc,
   581              String subject,
   582              String content,
   583              String mimeType
   584              )
   585              throws MessagingException {
   586          
                 /* 
    P/P           *  Method: void sendMessage(String, String[], String[], String[], String, String, String)
                  * 
                  *  Preconditions:
                  *    (soft) bcc.length <= 232-1
                  *    (soft) init'ed(bcc[...])
                  *    (soft) cc.length <= 232-1
                  *    (soft) init'ed(cc[...])
                  *    (soft) log != null
                  *    (soft) to.length <= 232-1
                  *    (soft) init'ed(to[...])
                  * 
                  *  Presumptions:
                  *    init'ed(javax.mail.Message$RecipientType.BCC)
                  *    init'ed(javax.mail.Message$RecipientType.CC)
                  *    init'ed(javax.mail.Message$RecipientType.TO)
                  *    javax.mail.Message:getAllRecipients(...)@636 != null
                  *    org.apache.roller.weblogger.business.MailProvider:getTransport(...)@642 != null
                  *    ...
                  * 
                  *  Test Vectors:
                  *    bcc: Addr_Set{null}, Inverse{null}
                  *    cc: Addr_Set{null}, Inverse{null}
                  *    to: Addr_Set{null}, Inverse{null}
                  *    org.apache.commons.lang.StringUtils:isEmpty(...)@596: {1}, {0}
                  *    org.apache.commons.logging.Log:isDebugEnabled(...)@599: {0}, {1}
                  *    org.apache.commons.logging.Log:isDebugEnabled(...)@607: {0}, {1}
                  *    org.apache.commons.logging.Log:isDebugEnabled(...)@617: {0}, {1}
                  *    org.apache.commons.logging.Log:isDebugEnabled(...)@627: {0}, {1}
                  *    org.apache.roller.weblogger.business.startup.WebloggerStartup:getMailProvider(...)@587: Inverse{null}, Addr_Set{null}
                  */
   587          MailProvider mailProvider = WebloggerStartup.getMailProvider();
   588          if(mailProvider == null) {
   589              return;
   590          }
   591          
   592          Session session = mailProvider.getSession();
   593          Message message = new MimeMessage(session);
   594          
   595          // n.b. any default from address is expected to be determined by caller.
   596          if (! StringUtils.isEmpty(from)) {
   597              InternetAddress sentFrom = new InternetAddress(from);
   598              message.setFrom(sentFrom);
   599              if (log.isDebugEnabled()) log.debug("e-mail from: " + sentFrom);
   600          }
   601          
   602          if (to!=null) {
   603              InternetAddress[] sendTo = new InternetAddress[to.length];
   604              
   605              for (int i = 0; i < to.length; i++) {
   606                  sendTo[i] = new InternetAddress(to[i]);
   607                  if (log.isDebugEnabled()) log.debug("sending e-mail to: " + to[i]);
   608              }
   609              message.setRecipients(Message.RecipientType.TO, sendTo);
   610          }
   611          
   612          if (cc != null) {
   613              InternetAddress[] copyTo = new InternetAddress[cc.length];
   614              
   615              for (int i = 0; i < cc.length; i++) {
   616                  copyTo[i] = new InternetAddress(cc[i]);
   617                  if (log.isDebugEnabled()) log.debug("copying e-mail to: " + cc[i]);
   618              }
   619              message.setRecipients(Message.RecipientType.CC, copyTo);
   620          }
   621          
   622          if (bcc != null) {
   623              InternetAddress[] copyTo = new InternetAddress[bcc.length];
   624              
   625              for (int i = 0; i < bcc.length; i++) {
   626                  copyTo[i] = new InternetAddress(bcc[i]);
   627                  if (log.isDebugEnabled()) log.debug("blind copying e-mail to: " + bcc[i]);
   628              }
   629              message.setRecipients(Message.RecipientType.BCC, copyTo);
   630          }
   631          message.setSubject((subject == null) ? "(no subject)" : subject);
   632          message.setContent(content, mimeType);
   633          message.setSentDate(new java.util.Date());
   634          
   635          // First collect all the addresses together.
   636          Address[] remainingAddresses = message.getAllRecipients();
+  637          int nAddresses = remainingAddresses.length;
   638          boolean bFailedToSome = false;
   639          
   640          SendFailedException sendex = new SendFailedException("Unable to send message to some recipients");
   641          
   642          Transport transport = mailProvider.getTransport();
   643          
   644          // Try to send while there remain some potentially good addresses
   645          try { 
   646              do {
   647                  // Avoid a loop if we are stuck
   648                  nAddresses = remainingAddresses.length;
   649  
   650                  try {
   651                      // Send to the list of remaining addresses, ignoring the addresses attached to the message
   652                      transport.send(message, remainingAddresses);
   653                  } catch(SendFailedException ex) {
   654                      bFailedToSome=true;
   655                      sendex.setNextException(ex);
   656  
   657                      // Extract the remaining potentially good addresses
   658                      remainingAddresses=ex.getValidUnsentAddresses();
   659                  }
   660              } while (remainingAddresses!=null && remainingAddresses.length>0 && remainingAddresses.length!=nAddresses);
   661              
   662          } finally {
   663              transport.close();
   664          }
   665          
+  666          if (bFailedToSome) throw sendex;
   667      }
   668      
   669      
   670      /**
   671       * This method is used to send a Text Message.
   672       *
   673       * @param from e-mail address of sender
   674       * @param to e-mail addresses of recipients
   675       * @param subject subject of e-mail
   676       * @param content the body of the e-mail
   677       * @throws MessagingException the exception to indicate failure
   678       */
   679      public static void sendTextMessage
   680              (
   681              String from,
   682              String[] to,
   683              String[] cc,
   684              String[] bcc,
   685              String subject,
   686              String content
   687              )
   688              throws MessagingException {
                 /* 
    P/P           *  Method: void sendTextMessage(String, String[], String[], String[], String, String)
                  * 
                  *  Preconditions:
                  *    (soft) bcc.length <= 232-1
                  *    (soft) init'ed(bcc[...])
                  *    (soft) cc.length <= 232-1
                  *    (soft) init'ed(cc[...])
                  *    (soft) log != null
                  *    (soft) to.length <= 232-1
                  *    (soft) init'ed(to[...])
                  */
   689          sendMessage(from, to, cc, bcc, subject, content, "text/plain; charset=utf-8");
   690      }
   691      
   692      
   693      /**
   694       * This method overrides the sendTextMessage to specify
   695       * one receiver and mulitple cc recipients.
   696       *
   697       * @param from e-mail address of sender
   698       * @param to e-mail addresses of recipients
   699       * @param subject subject of e-mail
   700       * @param content the body of the e-mail
   701       * @throws MessagingException the exception to indicate failure
   702       */
   703      public static void sendTextMessage
   704              (
   705              String from,
   706              String to,
   707              String[] cc,
   708              String[] bcc,
   709              String subject,
   710              String content
   711              )
   712              throws MessagingException {
                 /* 
    P/P           *  Method: void sendTextMessage(String, String, String[], String[], String, String)
                  * 
                  *  Preconditions:
                  *    (soft) bcc.length <= 232-1
                  *    (soft) init'ed(bcc[...])
                  *    (soft) cc.length <= 232-1
                  *    (soft) init'ed(cc[...])
                  *    (soft) log != null
                  * 
                  *  Test Vectors:
                  *    to: Addr_Set{null}, Inverse{null}
                  */
   713          String[] recipient = null;
   714          if (to!=null) recipient = new String[] {to};
   715          
   716          sendMessage(from, recipient, cc, bcc, subject, content, "text/plain; charset=utf-8");
   717      }
   718      
   719      
   720      /**
   721       * This method overrides the sendTextMessage to specify
   722       * only one receiver and cc recipients, rather than
   723       * an array of recipients.
   724       *
   725       * @param from e-mail address of sender
   726       * @param to e-mail address of recipient
   727       * @param cc e-mail address of cc recipient
   728       * @param subject subject of e-mail
   729       * @param content the body of the e-mail
   730       * @throws MessagingException the exception to indicate failure
   731       */
   732      public static void sendTextMessage
   733              (
   734              String from,
   735              String to,
   736              String cc,
   737              String bcc,
   738              String subject,
   739              String content
   740              )
   741              throws MessagingException {
                 /* 
    P/P           *  Method: void sendTextMessage(String, String, String, String, String, String)
                  * 
                  *  Preconditions:
                  *    (soft) log != null
                  * 
                  *  Test Vectors:
                  *    bcc: Addr_Set{null}, Inverse{null}
                  *    cc: Addr_Set{null}, Inverse{null}
                  *    to: Addr_Set{null}, Inverse{null}
                  */
   742          String[] recipient = null;
   743          String[] copy = null;
   744          String[] bcopy = null;
   745          
   746          if (to!=null) recipient = new String[] {to};
   747          if (cc!=null) copy = new String[] {cc};
   748          if (bcc!=null) bcopy = new String[] {bcc};
   749          
   750          sendMessage(from, recipient, copy, bcopy, subject, content, "text/plain; charset=utf-8");
   751      }
   752      
   753      
   754      /**
   755       * This method is used to send a HTML Message
   756       *
   757       * @param from e-mail address of sender
   758       * @param to e-mail address(es) of recipients
   759       * @param subject subject of e-mail
   760       * @param content the body of the e-mail
   761       * @throws MessagingException the exception to indicate failure
   762       */
   763      public static void sendHTMLMessage
   764              (
   765              String from,
   766              String[] to,
   767              String[] cc,
   768              String[] bcc,
   769              String subject,
   770              String content
   771              )
   772              throws MessagingException {
                 /* 
    P/P           *  Method: void sendHTMLMessage(String, String[], String[], String[], String, String)
                  * 
                  *  Preconditions:
                  *    (soft) bcc.length <= 232-1
                  *    (soft) init'ed(bcc[...])
                  *    (soft) cc.length <= 232-1
                  *    (soft) init'ed(cc[...])
                  *    (soft) log != null
                  *    (soft) to.length <= 232-1
                  *    (soft) init'ed(to[...])
                  */
   773          sendMessage(from, to, cc, bcc, subject, content, "text/html; charset=utf-8");
   774      }
   775      
   776      
   777      /**
   778       * This method overrides the sendHTMLMessage to specify
   779       * only one sender, rather than an array of senders.
   780       *
   781       * @param from e-mail address of sender
   782       * @param to e-mail address of recipients
   783       * @param subject subject of e-mail
   784       * @param content the body of the e-mail
   785       * @throws MessagingException the exception to indicate failure
   786       */
   787      public static void sendHTMLMessage
   788              (
   789              String from,
   790              String to,
   791              String cc,
   792              String bcc,
   793              String subject,
   794              String content
   795              )
   796              throws MessagingException {
                 /* 
    P/P           *  Method: void sendHTMLMessage(String, String, String, String, String, String)
                  * 
                  *  Preconditions:
                  *    (soft) log != null
                  * 
                  *  Test Vectors:
                  *    bcc: Addr_Set{null}, Inverse{null}
                  *    cc: Addr_Set{null}, Inverse{null}
                  *    to: Addr_Set{null}, Inverse{null}
                  */
   797          String[] recipient = null;
   798          String[] copy = null;
   799          String[] bcopy = null;
   800          
   801          if (to!=null) recipient = new String[] {to};
   802          if (cc!=null) copy = new String[] {cc};
   803          if (bcc!=null) bcopy = new String[] {bcc};
   804          
   805          sendMessage(from, recipient, copy, bcopy, subject, content, "text/html; charset=utf-8");
   806      }
   807      
   808      
   809      /**
   810       * This method overrides the sendHTMLMessage to specify
   811       * one receiver and mulitple cc recipients.
   812       *
   813       * @param from e-mail address of sender
   814       * @param to e-mail address of recipient
   815       * @param cc e-mail addresses of recipients
   816       * @param subject subject of e-mail
   817       * @param content the body of the e-mail
   818       * @throws MessagingException the exception to indicate failure
   819       */
   820      public static void sendHTMLMessage
   821              (
   822              String from,
   823              String to,
   824              String[] cc,
   825              String[] bcc,
   826              String subject,
   827              String content
   828              )
   829              throws MessagingException {
                 /* 
    P/P           *  Method: void sendHTMLMessage(String, String, String[], String[], String, String)
                  * 
                  *  Preconditions:
                  *    (soft) bcc.length <= 232-1
                  *    (soft) init'ed(bcc[...])
                  *    (soft) cc.length <= 232-1
                  *    (soft) init'ed(cc[...])
                  *    (soft) log != null
                  * 
                  *  Test Vectors:
                  *    to: Addr_Set{null}, Inverse{null}
                  */
   830          String[] recipient = null;
   831          if (to!=null) recipient = new String[] {to};
   832          
   833          sendMessage(from, recipient, cc, bcc, subject, content, "text/html; charset=utf-8");
   834      }
   835      
   836      
   837      /**
   838       * An exception thrown if there is a problem sending an email.
   839       */
   840      public class MailingException extends WebloggerException {
                 /* 
    P/P           *  Method: void org.apache.roller.weblogger.util.MailUtil$MailingException(MailUtil, Throwable)
                  */
   841          public MailingException(Throwable t) {
   842              super(t);
   843          }
   844      }
   845  }








SofCheck Inspector Build Version : 2.18479
MailUtil.java 2009-Jan-02 14:25:34
MailUtil.class 2009-Sep-04 03:12:32
MailUtil$MailingException.class 2009-Sep-04 03:12:32