Coverage Report - net.sourceforge.pebble.util.MailUtils
 
Classes in this File Line Coverage Branch Coverage Complexity
MailUtils
44%
19/43
50%
4/8
1.667
MailUtils$SendMailRunnable
0%
0/37
0%
0/6
1.667
 
 1  
 /*
 2  
  * Copyright (c) 2003-2011, Simon Brown
 3  
  * All rights reserved.
 4  
  *
 5  
  * Redistribution and use in source and binary forms, with or without
 6  
  * modification, are permitted provided that the following conditions are met:
 7  
  *
 8  
  *   - Redistributions of source code must retain the above copyright
 9  
  *     notice, this list of conditions and the following disclaimer.
 10  
  *
 11  
  *   - Redistributions in binary form must reproduce the above copyright
 12  
  *     notice, this list of conditions and the following disclaimer in
 13  
  *     the documentation and/or other materials provided with the
 14  
  *     distribution.
 15  
  *
 16  
  *   - Neither the name of Pebble nor the names of its contributors may
 17  
  *     be used to endorse or promote products derived from this software
 18  
  *     without specific prior written permission.
 19  
  *
 20  
  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 21  
  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 22  
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 23  
  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 24  
  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 25  
  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 26  
  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 27  
  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 28  
  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 29  
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 30  
  * POSSIBILITY OF SUCH DAMAGE.
 31  
  */
 32  
 package net.sourceforge.pebble.util;
 33  
 
 34  
 import net.sourceforge.pebble.domain.Blog;
 35  
 import net.sourceforge.pebble.domain.State;
 36  
 import org.apache.commons.logging.Log;
 37  
 import org.apache.commons.logging.LogFactory;
 38  
 import net.sourceforge.pebble.web.validation.ValidationContext;
 39  
 import net.sourceforge.pebble.PebbleContext;
 40  
 
 41  
 import javax.mail.Message;
 42  
 import javax.mail.Session;
 43  
 import javax.mail.Transport;
 44  
 import javax.mail.internet.AddressException;
 45  
 import javax.mail.internet.InternetAddress;
 46  
 import javax.mail.internet.MimeMessage;
 47  
 import javax.mail.internet.MimeUtility;
 48  
 import javax.naming.Context;
 49  
 import javax.naming.InitialContext;
 50  
 import java.util.*;
 51  
 import java.util.concurrent.ExecutorService;
 52  
 import java.util.concurrent.Executors;
 53  
 
 54  
 /**
 55  
  * Utilities for e-mail related functions.
 56  
  *
 57  
  * @author    Simon Brown
 58  
  */
 59  0
 public class MailUtils {
 60  
 
 61  
   /** the log used by this class */
 62  4
   private static Log log = LogFactory.getLog(MailUtils.class);
 63  4
   private static String ENCODING = "UTF-8";
 64  
 
 65  
   /** thread pool used to send e-mail */
 66  4
   private static ExecutorService pool = Executors.newFixedThreadPool(1);
 67  
 
 68  
   /**
 69  
    * Get the prefix to be used for blog entry emails
 70  
    *
 71  
    * @param blog The blog to get the prefix for
 72  
    * @return The prefix
 73  
    */
 74  
   public static String getBlogEntryPrefix(Blog blog) {
 75  28
     return getPrefix(blog, "notification.prefix.blog.entry", "blogentry.blogentry");
 76  
   }
 77  
 
 78  
   /**
 79  
    * Get the prefix to be used for blog entry emails in the given state
 80  
    *
 81  
    * @param blog The blog to get the prefix for
 82  
    * @param state The state the blog entry is in
 83  
    * @return The prefix
 84  
    */
 85  
   public static String getBlogEntryPrefix(Blog blog, State state) {
 86  0
     return getPrefix(blog, "notification.prefix.blog.entry", "blogentry.blogentry", state);
 87  
   }
 88  
 
 89  
   /**
 90  
    * Get the prefix to be used for comment emails
 91  
    *
 92  
    * @param blog The blog to get the prefix for
 93  
    * @return The prefix
 94  
    */
 95  
   public static String getCommentPrefix(Blog blog) {
 96  0
     return getPrefix(blog, "notification.prefix.comment", "blogentry.comment");
 97  
   }
 98  
 
 99  
   /**
 100  
    * Get the prefix to be used for comment emails
 101  
    *
 102  
    * @param blog The blog to get the prefix for
 103  
    * @param state The state the comment is in
 104  
    * @return The prefix
 105  
    */
 106  
   public static String getCommentPrefix(Blog blog, State state) {
 107  0
     return getPrefix(blog, "notification.prefix.comment", "blogentry.comment", state);
 108  
   }
 109  
 
 110  
   /**
 111  
    * Get the prefix to be used for trackback emails
 112  
    *
 113  
    * @param blog The blog to get the prefix for
 114  
    * @param state The state the trackback is in
 115  
    * @return The prefix
 116  
    */
 117  
   public static String getTrackbackPrefix(Blog blog, State state) {
 118  0
     return getPrefix(blog, "notification.prefix.trackback", "blogentry.trackback", state);
 119  
   }
 120  
 
 121  
   private static String getPrefix(Blog blog, String key, String defaultValue, State state) {
 122  0
     String value = blog.getProperty(key);
 123  0
     if (value == null) {
 124  0
       value = I18n.getMessage(blog, defaultValue);
 125  
     }
 126  0
     return "[" + value + " - " + I18n.getMessage(blog, "admin." + state.getName()) + "]";
 127  
   }
 128  
 
 129  
   private static String getPrefix(Blog blog, String key, String defaultValue) {
 130  28
     String value = blog.getProperty(key);
 131  28
     if (value == null) {
 132  28
       value = I18n.getMessage(blog, defaultValue);
 133  
     }
 134  28
     return "[" + value + "]";
 135  
   }
 136  
 
 137  
   /**
 138  
    * Sends an e-mail.
 139  
    *
 140  
    * @param blog    the notifying blog
 141  
    * @param to     the e-mail addresses of the recipients in the TO field
 142  
    * @param subject       the subject of the e-mail
 143  
    * @param message       the body of the e-mail
 144  
    */
 145  
   public static void sendMail(Session session, Blog blog, String to, String subject, String message) {
 146  0
     Collection set = new HashSet();
 147  0
     set.add(to);
 148  0
     sendMail(session, blog, set, new HashSet(), new HashSet(), subject, message);
 149  0
   }
 150  
 
 151  
   /**
 152  
    * Sends an e-mail.
 153  
    *
 154  
    * @param blog    the notifying blog
 155  
    * @param to     the e-mail addresses of the recipients in the TO field
 156  
    * @param subject       the subject of the e-mail
 157  
    * @param message       the body of the e-mail
 158  
    */
 159  
   public static void sendMail(Session session, Blog blog, Collection to, String subject, String message) {
 160  0
     sendMail(session, blog, to, new HashSet(), new HashSet(), subject, message);
 161  0
   }
 162  
 
 163  
   /**
 164  
    * Sends an e-mail.
 165  
    *
 166  
    * @param blog    the notifying blog
 167  
    * @param to     the e-mail addresses of the recipients in the TO field
 168  
    * @param cc     the e-mail addresses of the recipients in the CC field
 169  
    * @param subject       the subject of the e-mail
 170  
    * @param message       the body of the e-mail
 171  
    */
 172  
   public static void sendMail(Session session, Blog blog, Collection to, Collection cc, String subject, String message) {
 173  0
     sendMail(session, blog, to, cc, new HashSet(), subject, message);
 174  0
   }
 175  
 
 176  
   /**
 177  
    * Sends an e-mail.
 178  
    *
 179  
    * @param blog    the notifying blog
 180  
    * @param to     the e-mail addresses of the recipients in the TO field
 181  
    * @param cc     the e-mail addresses of the recipients in the CC field
 182  
    * @param bcc     the e-mail addresses of the recipients in the BCC field
 183  
    * @param subject       the subject of the e-mail
 184  
    * @param message       the body of the e-mail
 185  
    */
 186  
   public static void sendMail(Session session, Blog blog, Collection to, Collection cc, Collection bcc, String subject, String message) {
 187  0
     Runnable r = new SendMailRunnable(session, blog, to, cc, bcc, subject, message);
 188  0
     pool.execute(r);
 189  0
   }
 190  
 
 191  
   /**
 192  
    * A thread allowing the e-mail to be sent asynchronously, so the requesting
 193  
    * thread (and therefore the user) isn't held up.
 194  
    */
 195  0
   static class SendMailRunnable implements Runnable {
 196  
 
 197  
     /** the JavaMail session */
 198  
     private Session session;
 199  
 
 200  
     /** the notifying blog */
 201  
     private Blog blog;
 202  
 
 203  
     /** the e-mail addresses of the recipients in the TO field */
 204  
     private Collection to;
 205  
 
 206  
     /** the e-mail addresses of the recipients in the CC field */
 207  
     private Collection cc;
 208  
 
 209  
     /** the e-mail addresses of the recipients in the BCC field */
 210  
     private Collection bcc;
 211  
 
 212  
     /** the subject of the e-mail */
 213  
     private String subject;
 214  
 
 215  
     /** the body of the e-mail */
 216  
     private String message;
 217  
 
 218  
     /**
 219  
      * Creates a new thread to send a new e-mail.
 220  
      *
 221  
      * @param session   a JavaMail Session instance
 222  
      * @param blog    the notifying blog
 223  
      * @param to     the e-mail addresses of the recipients in the TO field
 224  
      * @param cc     the e-mail addresses of the recipients in the CC field
 225  
      * @param bcc     the e-mail addresses of the recipients in the BCC field
 226  
      * @param subject       the subject of the e-mail
 227  
      * @param message       the body of the e-mail
 228  
      */
 229  0
     public SendMailRunnable(Session session, Blog blog, Collection to, Collection cc, Collection bcc, String subject, String message) {
 230  0
       this.session = session;
 231  0
       this.blog = blog;
 232  0
       this.to = to;
 233  0
       this.cc = cc;
 234  0
       this.bcc = bcc;
 235  0
       this.subject = subject;
 236  0
       this.message = message;
 237  0
     }
 238  
 
 239  
     /**
 240  
      * Performs the processing associated with this thread.
 241  
      */
 242  
     public void run() {
 243  
       try {
 244  
         // create a message and try to send it
 245  0
         Message msg = new MimeMessage(session);
 246  0
         msg.setFrom(new InternetAddress(blog.getFirstEmailAddress(), MimeUtility.encodeText(blog.getName(), ENCODING, "B")));
 247  0
         Collection internetAddresses = new HashSet();
 248  0
         Iterator it = to.iterator();
 249  0
         while (it.hasNext()) {
 250  0
           internetAddresses.add(new InternetAddress(it.next().toString()));
 251  
         }
 252  0
         msg.addRecipients(Message.RecipientType.TO, (InternetAddress[])internetAddresses.toArray(new InternetAddress[]{}));
 253  
 
 254  0
         internetAddresses = new HashSet();
 255  0
         it = cc.iterator();
 256  0
         while (it.hasNext()) {
 257  0
           internetAddresses.add(new InternetAddress(it.next().toString()));
 258  
         }
 259  0
         msg.addRecipients(Message.RecipientType.CC, (InternetAddress[])internetAddresses.toArray(new InternetAddress[]{}));
 260  
 
 261  0
         internetAddresses = new HashSet();
 262  0
         it = bcc.iterator();
 263  0
         while (it.hasNext()) {
 264  0
           internetAddresses.add(new InternetAddress(it.next().toString()));
 265  
         }
 266  0
         msg.addRecipients(Message.RecipientType.BCC, (InternetAddress[])internetAddresses.toArray(new InternetAddress[]{}));
 267  
 
 268  0
         msg.setSubject(MimeUtility.encodeText(subject, ENCODING, "B"));
 269  0
         msg.setSentDate(new Date());
 270  0
         msg.setContent(message, "text/html; charset=" + ENCODING);
 271  
 
 272  0
         log.debug("From : " + blog.getName() + " (" + blog.getFirstEmailAddress() + ")");
 273  0
         log.debug("Subject : " + subject);
 274  0
         log.debug("Message : " + message);
 275  
 
 276  0
         Transport.send(msg);
 277  0
       } catch (Exception e) {
 278  0
         log.error("Notification e-mail could not be sent", e);
 279  0
       }
 280  0
     }
 281  
 
 282  
   }
 283  
 
 284  
   /**
 285  
    * Creates a reference to a JavaMail Session.
 286  
    *
 287  
    * @return  a Session instance
 288  
    * @throws Exception    if something goes wrong creating a session
 289  
    */
 290  
   public static Session createSession() throws Exception {
 291  28
     String ref = PebbleContext.getInstance().getConfiguration().getSmtpHost();
 292  28
     if (ref.startsWith("java:comp/env")) {
 293  
       // this is a JNDI based mail session
 294  28
       Context ctx = new InitialContext();
 295  28
       return (Session)ctx.lookup(ref);
 296  
     } else {
 297  
       // this is a simple SMTP hostname based session
 298  0
       Properties props = new Properties();
 299  0
       props.put("mail.smtp.host", ref);
 300  0
       return Session.getDefaultInstance(props, null);
 301  
     }
 302  
   }
 303  
 
 304  
   /**
 305  
    * Validates the given comment.
 306  
    *
 307  
    * @param email   the Comment instance to validate
 308  
    * @param context   the context in which to perform validation
 309  
    */
 310  
   public static void validate(String email, ValidationContext context) {
 311  80
     if (email != null) {
 312  
       try {
 313  64
         InternetAddress ia = new InternetAddress(email, true);
 314  44
         ia.validate();
 315  20
       } catch (AddressException aex) {
 316  20
         context.addError(aex.getMessage() + ": " + email);
 317  44
       }
 318  
     }
 319  80
   }
 320  
 
 321  
 }