Coverage Report - org.apache.commons.mail.MultiPartEmail
 
Classes in this File Line Coverage Branch Coverage Complexity
MultiPartEmail
84%
102/121
94%
32/34
3.091
 
 1  
 /*
 2  
  * Licensed to the Apache Software Foundation (ASF) under one or more
 3  
  * contributor license agreements.  See the NOTICE file distributed with
 4  
  * this work for additional information regarding copyright ownership.
 5  
  * The ASF licenses this file to You under the Apache License, Version 2.0
 6  
  * (the "License"); you may not use this file except in compliance with
 7  
  * the License.  You may obtain a copy of the License at
 8  
  *
 9  
  *     http://www.apache.org/licenses/LICENSE-2.0
 10  
  *
 11  
  * Unless required by applicable law or agreed to in writing, software
 12  
  * distributed under the License is distributed on an "AS IS" BASIS,
 13  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 14  
  * See the License for the specific language governing permissions and
 15  
  * limitations under the License.
 16  
  */
 17  
 package org.apache.commons.mail;
 18  
 
 19  
 import java.io.File;
 20  
 import java.io.IOException;
 21  
 import java.io.InputStream;
 22  
 import java.net.URL;
 23  
 
 24  
 import javax.activation.DataHandler;
 25  
 import javax.activation.DataSource;
 26  
 import javax.activation.FileDataSource;
 27  
 import javax.activation.URLDataSource;
 28  
 import javax.mail.BodyPart;
 29  
 import javax.mail.MessagingException;
 30  
 import javax.mail.internet.MimeBodyPart;
 31  
 import javax.mail.internet.MimeMultipart;
 32  
 import javax.mail.internet.MimePart;
 33  
 
 34  
 /**
 35  
  * A multipart email.
 36  
  *
 37  
  * <p>This class is used to send multi-part internet email like
 38  
  * messages with attachments.
 39  
  *
 40  
  * <p>To create a multi-part email, call the default constructor and
 41  
  * then you can call setMsg() to set the message and call the
 42  
  * different attach() methods.
 43  
  *
 44  
  * @since 1.0
 45  
  * @author <a href="mailto:quintonm@bellsouth.net">Quinton McCombs</a>
 46  
  * @author <a href="mailto:jon@latchkey.com">Jon S. Stevens</a>
 47  
  * @author <a href="mailto:frank.kim@clearink.com">Frank Y. Kim</a>
 48  
  * @author <a href="mailto:bmclaugh@algx.net">Brett McLaughlin</a>
 49  
  * @author <a href="mailto:unknown">Regis Koenig</a>
 50  
  * @author <a href="mailto:corey.scott@gmail.com">Corey Scott</a>
 51  
  * @version $Id: MultiPartEmail.java 1420402 2012-12-11 20:59:15Z tn $
 52  
  */
 53  113
 public class MultiPartEmail extends Email
 54  
 {
 55  
     /** Body portion of the email. */
 56  
     private MimeMultipart container;
 57  
 
 58  
     /** The message container. */
 59  
     private BodyPart primaryBodyPart;
 60  
 
 61  
     /** The MIME subtype. */
 62  
     private String subType;
 63  
 
 64  
     /** Indicates if the message has been initialized. */
 65  
     private boolean initialized;
 66  
 
 67  
     /** Indicates if attachments have been added to the message. */
 68  
     private boolean boolHasAttachments;
 69  
 
 70  
     /**
 71  
      * Set the MIME subtype of the email.
 72  
      *
 73  
      * @param aSubType MIME subtype of the email
 74  
      * @since 1.0
 75  
      */
 76  
     public void setSubType(String aSubType)
 77  
     {
 78  8
         this.subType = aSubType;
 79  8
     }
 80  
 
 81  
     /**
 82  
      * Get the MIME subtype of the email.
 83  
      *
 84  
      * @return MIME subtype of the email
 85  
      * @since 1.0
 86  
      */
 87  
     public String getSubType()
 88  
     {
 89  7
         return subType;
 90  
     }
 91  
 
 92  
     /**
 93  
      * Add a new part to the email.
 94  
      *
 95  
      * @param partContent The content.
 96  
      * @param partContentType The content type.
 97  
      * @return An Email.
 98  
      * @throws EmailException see javax.mail.internet.MimeBodyPart
 99  
      *  for definitions
 100  
      * @since 1.0
 101  
      */
 102  
     public Email addPart(String partContent, String partContentType)
 103  
         throws EmailException
 104  
     {
 105  1
             BodyPart bodyPart = createBodyPart();
 106  
         try
 107  
         {
 108  1
             bodyPart.setContent(partContent, partContentType);
 109  1
             getContainer().addBodyPart(bodyPart);
 110  
         }
 111  0
         catch (MessagingException me)
 112  
         {
 113  0
             throw new EmailException(me);
 114  1
         }
 115  
 
 116  1
         return this;
 117  
     }
 118  
 
 119  
     /**
 120  
      * Add a new part to the email.
 121  
      *
 122  
      * @param multipart The MimeMultipart.
 123  
      * @return An Email.
 124  
      * @throws EmailException see javax.mail.internet.MimeBodyPart
 125  
      *  for definitions
 126  
      *  @since 1.0
 127  
      */
 128  
     public Email addPart(MimeMultipart multipart) throws EmailException
 129  
     {
 130  
         try
 131  
         {
 132  1
             return addPart(multipart, getContainer().getCount());
 133  
         }
 134  0
         catch (MessagingException me)
 135  
         {
 136  0
             throw new EmailException(me);
 137  
         }
 138  
     }
 139  
 
 140  
     /**
 141  
      * Add a new part to the email.
 142  
      *
 143  
      * @param multipart The part to add.
 144  
      * @param index The index to add at.
 145  
      * @return The email.
 146  
      * @throws EmailException An error occured while adding the part.
 147  
      * @since 1.0
 148  
      */
 149  
     public Email addPart(MimeMultipart multipart, int index) throws EmailException
 150  
     {
 151  28
             BodyPart bodyPart = createBodyPart();
 152  
         try
 153  
         {
 154  28
             bodyPart.setContent(multipart);
 155  28
             getContainer().addBodyPart(bodyPart, index);
 156  
         }
 157  0
         catch (MessagingException me)
 158  
         {
 159  0
             throw new EmailException(me);
 160  28
         }
 161  
 
 162  28
         return this;
 163  
     }
 164  
 
 165  
     /**
 166  
      * Initialize the multipart email.
 167  
      * @since 1.0
 168  
      */
 169  
     protected void init()
 170  
     {
 171  45
         if (initialized)
 172  
         {
 173  1
             throw new IllegalStateException("Already initialized");
 174  
         }
 175  
 
 176  44
         container = createMimeMultipart();
 177  44
         super.setContent(container);
 178  
 
 179  44
         initialized = true;
 180  44
     }
 181  
 
 182  
     /**
 183  
      * Set the message of the email.
 184  
      *
 185  
      * @param msg A String.
 186  
      * @return An Email.
 187  
      * @throws EmailException see javax.mail.internet.MimeBodyPart
 188  
      *  for definitions
 189  
      * @since 1.0
 190  
      */
 191  
     @Override
 192  
     public Email setMsg(String msg) throws EmailException
 193  
     {
 194  
         // throw exception on null message
 195  19
         if (EmailUtils.isEmpty(msg))
 196  
         {
 197  2
             throw new EmailException("Invalid message supplied");
 198  
         }
 199  
         try
 200  
         {
 201  17
             BodyPart primary = getPrimaryBodyPart();
 202  
 
 203  17
             if ((primary instanceof MimePart) && EmailUtils.isNotEmpty(charset))
 204  
             {
 205  9
                 ((MimePart) primary).setText(msg, charset);
 206  
             }
 207  
             else
 208  
             {
 209  8
                 primary.setText(msg);
 210  
             }
 211  
         }
 212  0
         catch (MessagingException me)
 213  
         {
 214  0
             throw new EmailException(me);
 215  17
         }
 216  17
         return this;
 217  
     }
 218  
 
 219  
     /**
 220  
      * Does the work of actually building the MimeMessage. Please note that
 221  
      * a user rarely calls this method directly and only if he/she is
 222  
      * interested in the sending the underlying MimeMessage without
 223  
      * commons-email.
 224  
      *
 225  
      * @exception EmailException if there was an error.
 226  
      * @since 1.0
 227  
      */
 228  
     @Override
 229  
     public void buildMimeMessage() throws EmailException
 230  
     {
 231  
         try
 232  
         {
 233  39
             if (primaryBodyPart != null)
 234  
             {
 235  
                 // before a multipart message can be sent, we must make sure that
 236  
                 // the content for the main body part was actually set.  If not,
 237  
                 // an IOException will be thrown during super.send().
 238  
 
 239  3
                 BodyPart body = this.getPrimaryBodyPart();
 240  
                 try
 241  
                 {
 242  3
                     body.getContent();
 243  
                 }
 244  0
                 catch (IOException e) // NOPMD
 245  
                 {
 246  
                     // do nothing here.
 247  
                     // content will be set to an empty string as a result.
 248  
                     // (Should this really be rethrown as an email exception?)
 249  
                     // throw new EmailException(e);
 250  3
                 }
 251  
             }
 252  
 
 253  39
             if (subType != null)
 254  
             {
 255  1
                 getContainer().setSubType(subType);
 256  
             }
 257  
 
 258  39
             super.buildMimeMessage();
 259  
         }
 260  0
         catch (MessagingException me)
 261  
         {
 262  0
             throw new EmailException(me);
 263  36
         }
 264  36
     }
 265  
 
 266  
     /**
 267  
      * Attach a file.
 268  
      *
 269  
      * @param file A file attachment
 270  
      * @return A MultiPartEmail.
 271  
      * @throws EmailException see javax.mail.internet.MimeBodyPart
 272  
      *  for definitions
 273  
      * @since 1.3
 274  
      */
 275  
     public MultiPartEmail attach(File file)
 276  
         throws EmailException
 277  
     {
 278  2
         String fileName = file.getAbsolutePath();
 279  
 
 280  
         try
 281  
         {
 282  2
             if (!file.exists())
 283  
             {
 284  0
                 throw new IOException("\"" + fileName + "\" does not exist");
 285  
             }
 286  
 
 287  2
             FileDataSource fds = new FileDataSource(file);
 288  
 
 289  2
             return attach(fds, file.getName(), null, EmailAttachment.ATTACHMENT);
 290  
         }
 291  0
         catch (IOException e)
 292  
         {
 293  0
             throw new EmailException("Cannot attach file \"" + fileName + "\"", e);
 294  
         }
 295  
     }
 296  
 
 297  
     /**
 298  
      * Attach an EmailAttachment.
 299  
      *
 300  
      * @param attachment An EmailAttachment.
 301  
      * @return A MultiPartEmail.
 302  
      * @throws EmailException see javax.mail.internet.MimeBodyPart
 303  
      *  for definitions
 304  
      * @since 1.0
 305  
      */
 306  
     public MultiPartEmail attach(EmailAttachment attachment)
 307  
         throws EmailException
 308  
     {
 309  10
         MultiPartEmail result = null;
 310  
 
 311  10
         if (attachment == null)
 312  
         {
 313  1
             throw new EmailException("Invalid attachment supplied");
 314  
         }
 315  
 
 316  9
         URL url = attachment.getURL();
 317  
 
 318  9
         if (url == null)
 319  
         {
 320  7
             String fileName = null;
 321  
             try
 322  
             {
 323  7
                 fileName = attachment.getPath();
 324  7
                 File file = new File(fileName);
 325  7
                 if (!file.exists())
 326  
                 {
 327  1
                     throw new IOException("\"" + fileName + "\" does not exist");
 328  
                 }
 329  6
                 result =
 330  
                     attach(
 331  
                         new FileDataSource(file),
 332  
                         attachment.getName(),
 333  
                         attachment.getDescription(),
 334  
                         attachment.getDisposition());
 335  
             }
 336  1
             catch (IOException e)
 337  
             {
 338  1
                 throw new EmailException("Cannot attach file \"" + fileName + "\"", e);
 339  6
             }
 340  6
         }
 341  
         else
 342  
         {
 343  2
             result =
 344  
                 attach(
 345  
                     url,
 346  
                     attachment.getName(),
 347  
                     attachment.getDescription(),
 348  
                     attachment.getDisposition());
 349  
         }
 350  
 
 351  7
         return result;
 352  
     }
 353  
 
 354  
     /**
 355  
      * Attach a file located by its URL.  The disposition of the file
 356  
      * is set to mixed.
 357  
      *
 358  
      * @param url The URL of the file (may be any valid URL).
 359  
      * @param name The name field for the attachment.
 360  
      * @param description A description for the attachment.
 361  
      * @return A MultiPartEmail.
 362  
      * @throws EmailException see javax.mail.internet.MimeBodyPart
 363  
      *  for definitions
 364  
      * @since 1.0
 365  
      */
 366  
     public MultiPartEmail attach(URL url, String name, String description)
 367  
         throws EmailException
 368  
     {
 369  3
         return attach(url, name, description, EmailAttachment.ATTACHMENT);
 370  
     }
 371  
 
 372  
     /**
 373  
      * Attach a file located by its URL.
 374  
      *
 375  
      * @param url The URL of the file (may be any valid URL).
 376  
      * @param name The name field for the attachment.
 377  
      * @param description A description for the attachment.
 378  
      * @param disposition Either mixed or inline.
 379  
      * @return A MultiPartEmail.
 380  
      * @throws EmailException see javax.mail.internet.MimeBodyPart
 381  
      *  for definitions
 382  
      * @since 1.0
 383  
      */
 384  
     public MultiPartEmail attach(
 385  
         URL url,
 386  
         String name,
 387  
         String description,
 388  
         String disposition)
 389  
         throws EmailException
 390  
     {
 391  
         // verify that the URL is valid
 392  
        try
 393  
        {
 394  5
            InputStream is = url.openStream();
 395  4
            is.close();
 396  
        }
 397  1
        catch (IOException e)
 398  
        {
 399  1
            throw new EmailException("Invalid URL set:" + url, e);
 400  4
        }
 401  
 
 402  4
        return attach(new URLDataSource(url), name, description, disposition);
 403  
     }
 404  
 
 405  
     /**
 406  
      * Attach a file specified as a DataSource interface.
 407  
      *
 408  
      * @param ds A DataSource interface for the file.
 409  
      * @param name The name field for the attachment.
 410  
      * @param description A description for the attachment.
 411  
      * @return A MultiPartEmail.
 412  
      * @throws EmailException see javax.mail.internet.MimeBodyPart
 413  
      *  for definitions
 414  
      * @since 1.0
 415  
      */
 416  
     public MultiPartEmail attach(
 417  
         DataSource ds,
 418  
         String name,
 419  
         String description)
 420  
         throws EmailException
 421  
     {
 422  
         // verify that the DataSource is valid
 423  
         try
 424  
         {
 425  5
             final InputStream is = (ds != null) ? ds.getInputStream() : null;
 426  4
             if (is != null)
 427  
             {
 428  
                 // close the input stream to prevent file locking on windows
 429  3
                 is.close();
 430  
             }
 431  
 
 432  4
             if (is == null)
 433  
             {
 434  1
                 throw new EmailException("Invalid Datasource");
 435  
             }
 436  
         }
 437  1
         catch (IOException e)
 438  
         {
 439  1
             throw new EmailException("Invalid Datasource", e);
 440  3
         }
 441  
 
 442  3
         return attach(ds, name, description, EmailAttachment.ATTACHMENT);
 443  
     }
 444  
 
 445  
     /**
 446  
      * Attach a file specified as a DataSource interface.
 447  
      *
 448  
      * @param ds A DataSource interface for the file.
 449  
      * @param name The name field for the attachment.
 450  
      * @param description A description for the attachment.
 451  
      * @param disposition Either mixed or inline.
 452  
      * @return A MultiPartEmail.
 453  
      * @throws EmailException see javax.mail.internet.MimeBodyPart
 454  
      *  for definitions
 455  
      * @since 1.0
 456  
      */
 457  
     public MultiPartEmail attach(
 458  
         DataSource ds,
 459  
         String name,
 460  
         String description,
 461  
         String disposition)
 462  
         throws EmailException
 463  
     {
 464  15
         if (EmailUtils.isEmpty(name))
 465  
         {
 466  1
             name = ds.getName();
 467  
         }
 468  15
         BodyPart bodyPart = createBodyPart();
 469  
         try
 470  
         {
 471  15
             getContainer().addBodyPart(bodyPart);
 472  
 
 473  15
             bodyPart.setDisposition(disposition);
 474  15
             bodyPart.setFileName(name);
 475  15
             bodyPart.setDescription(description);
 476  15
             bodyPart.setDataHandler(new DataHandler(ds));
 477  
         }
 478  0
         catch (MessagingException me)
 479  
         {
 480  0
             throw new EmailException(me);
 481  15
         }
 482  15
         setBoolHasAttachments(true);
 483  
 
 484  15
         return this;
 485  
     }
 486  
 
 487  
     /**
 488  
      * Gets first body part of the message.
 489  
      *
 490  
      * @return The primary body part.
 491  
      * @throws MessagingException An error occurred while getting the primary body part.
 492  
      * @since 1.0
 493  
      */
 494  
     protected BodyPart getPrimaryBodyPart() throws MessagingException
 495  
     {
 496  35
         if (!initialized)
 497  
         {
 498  3
             init();
 499  
         }
 500  
 
 501  
         // Add the first body part to the message.  The fist body part must be
 502  35
         if (this.primaryBodyPart == null)
 503  
         {
 504  4
             primaryBodyPart = createBodyPart();
 505  4
             getContainer().addBodyPart(primaryBodyPart, 0);
 506  
         }
 507  
 
 508  35
         return primaryBodyPart;
 509  
     }
 510  
 
 511  
     /**
 512  
      * Gets the message container.
 513  
      *
 514  
      * @return The message container.
 515  
      * @since 1.0
 516  
      */
 517  
     protected MimeMultipart getContainer()
 518  
     {
 519  88
         if (!initialized)
 520  
         {
 521  40
             init();
 522  
         }
 523  88
         return container;
 524  
     }
 525  
 
 526  
     /**
 527  
      * Creates a body part object.
 528  
      * Can be overridden if you don't want to create a BodyPart.
 529  
      *
 530  
      * @return the created body part
 531  
      */
 532  
     protected BodyPart createBodyPart()
 533  
     {
 534  58
         BodyPart bodyPart = new MimeBodyPart();
 535  58
         return bodyPart;
 536  
     }
 537  
 
 538  
     /**
 539  
      * Creates a mime multipart object.
 540  
      *
 541  
      * @return the created mime part
 542  
      */
 543  
     protected MimeMultipart createMimeMultipart()
 544  
     {
 545  44
         MimeMultipart mmp = new MimeMultipart();
 546  44
         return mmp;
 547  
     }
 548  
 
 549  
     /**
 550  
      * Checks whether there are attachments.
 551  
      *
 552  
      * @return true if there are attachments
 553  
      * @since 1.0
 554  
      */
 555  
     public boolean isBoolHasAttachments()
 556  
     {
 557  2
         return boolHasAttachments;
 558  
     }
 559  
 
 560  
     /**
 561  
      * Sets whether there are attachments.
 562  
      *
 563  
      * @param b  the attachments flag
 564  
      * @since 1.0
 565  
      */
 566  
     public void setBoolHasAttachments(boolean b)
 567  
     {
 568  15
         boolHasAttachments = b;
 569  15
     }
 570  
 
 571  
     /**
 572  
      * Checks if this object is initialized.
 573  
      *
 574  
      * @return true if initialized
 575  
      */
 576  
     protected boolean isInitialized()
 577  
     {
 578  0
         return initialized;
 579  
     }
 580  
 
 581  
     /**
 582  
      * Sets the initialized status of this object.
 583  
      *
 584  
      * @param b  the initialized status flag
 585  
      */
 586  
     protected void setInitialized(boolean b)
 587  
     {
 588  0
         initialized = b;
 589  0
     }
 590  
 
 591  
 }