Coverage Report - org.apache.commons.mail.HtmlEmail
 
Classes in this File Line Coverage Branch Coverage Complexity
HtmlEmail
82%
112/135
88%
46/52
4.765
HtmlEmail$InlineImage
53%
8/15
0%
0/4
4.765
 
 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.io.UnsupportedEncodingException;
 23  
 import java.net.MalformedURLException;
 24  
 import java.net.URL;
 25  
 import java.util.HashMap;
 26  
 import java.util.Iterator;
 27  
 import java.util.List;
 28  
 import java.util.Locale;
 29  
 import java.util.Map;
 30  
 
 31  
 import javax.activation.DataHandler;
 32  
 import javax.activation.DataSource;
 33  
 import javax.activation.FileDataSource;
 34  
 import javax.activation.URLDataSource;
 35  
 import javax.mail.BodyPart;
 36  
 import javax.mail.MessagingException;
 37  
 import javax.mail.internet.MimeBodyPart;
 38  
 import javax.mail.internet.MimeMultipart;
 39  
 
 40  
 /**
 41  
  * An HTML multipart email.
 42  
  *
 43  
  * <p>This class is used to send HTML formatted email.  A text message
 44  
  * can also be set for HTML unaware email clients, such as text-based
 45  
  * email clients.
 46  
  *
 47  
  * <p>This class also inherits from {@link MultiPartEmail}, so it is easy to
 48  
  * add attachments to the email.
 49  
  *
 50  
  * <p>To send an email in HTML, one should create a <code>HtmlEmail</code>, then
 51  
  * use the {@link #setFrom(String)}, {@link #addTo(String)} etc. methods.
 52  
  * The HTML content can be set with the {@link #setHtmlMsg(String)} method. The
 53  
  * alternative text content can be set with {@link #setTextMsg(String)}.
 54  
  *
 55  
  * <p>Either the text or HTML can be omitted, in which case the "main"
 56  
  * part of the multipart becomes whichever is supplied rather than a
 57  
  * <code>multipart/alternative</code>.
 58  
  *
 59  
  * <h3>Embedding Images and Media</h3>
 60  
  *
 61  
  * <p>It is also possible to embed URLs, files, or arbitrary
 62  
  * <code>DataSource</code>s directly into the body of the mail:
 63  
  * <pre><code>
 64  
  * HtmlEmail he = new HtmlEmail();
 65  
  * File img = new File("my/image.gif");
 66  
  * PNGDataSource png = new PNGDataSource(decodedPNGOutputStream); // a custom class
 67  
  * StringBuffer msg = new StringBuffer();
 68  
  * msg.append("&lt;html&gt;&lt;body&gt;");
 69  
  * msg.append("&lt;img src=cid:").append(he.embed(img)).append("&gt;");
 70  
  * msg.append("&lt;img src=cid:").append(he.embed(png)).append("&gt;");
 71  
  * msg.append("&lt;/body&gt;&lt;/html&gt;");
 72  
  * he.setHtmlMsg(msg.toString());
 73  
  * // code to set the other email fields (not shown)
 74  
  * </pre></code>
 75  
  *
 76  
  * <p>Embedded entities are tracked by their name, which for <code>File</code>s is
 77  
  * the filename itself and for <code>URL</code>s is the canonical path. It is
 78  
  * an error to bind the same name to more than one entity, and this class will
 79  
  * attempt to validate that for <code>File</code>s and <code>URL</code>s. When
 80  
  * embedding a <code>DataSource</code>, the code uses the <code>equals()</code>
 81  
  * method defined on the <code>DataSource</code>s to make the determination.
 82  
  *
 83  
  * @since 1.0
 84  
  * @author <a href="mailto:unknown">Regis Koenig</a>
 85  
  * @author <a href="mailto:sean@informage.net">Sean Legassick</a>
 86  
  * @version $Id: HtmlEmail.java 1421492 2012-12-13 20:25:53Z tn $
 87  
  */
 88  97
 public class HtmlEmail extends MultiPartEmail
 89  
 {
 90  
     /** Definition of the length of generated CID's. */
 91  
     public static final int CID_LENGTH = 10;
 92  
 
 93  
     /** prefix for default HTML mail. */
 94  
     private static final String HTML_MESSAGE_START = "<html><body><pre>";
 95  
     /** suffix for default HTML mail. */
 96  
     private static final String HTML_MESSAGE_END = "</pre></body></html>";
 97  
 
 98  
 
 99  
     /**
 100  
      * Text part of the message. This will be used as alternative text if
 101  
      * the email client does not support HTML messages.
 102  
      */
 103  
     protected String text;
 104  
 
 105  
     /** Html part of the message. */
 106  
     protected String html;
 107  
 
 108  
     /**
 109  
      * @deprecated As of commons-email 1.1, no longer used. Inline embedded
 110  
      * objects are now stored in {@link #inlineEmbeds}.
 111  
      */
 112  
     @Deprecated
 113  
     protected List<InlineImage> inlineImages;
 114  
 
 115  
     /**
 116  
      * Embedded images Map<String, InlineImage> where the key is the
 117  
      * user-defined image name.
 118  
      */
 119  97
     protected Map<String, InlineImage> inlineEmbeds = new HashMap<String, InlineImage>();
 120  
 
 121  
     /**
 122  
      * Set the text content.
 123  
      *
 124  
      * @param aText A String.
 125  
      * @return An HtmlEmail.
 126  
      * @throws EmailException see javax.mail.internet.MimeBodyPart
 127  
      *  for definitions
 128  
      * @since 1.0
 129  
      */
 130  
     public HtmlEmail setTextMsg(String aText) throws EmailException
 131  
     {
 132  52
         if (EmailUtils.isEmpty(aText))
 133  
         {
 134  4
             throw new EmailException("Invalid message supplied");
 135  
         }
 136  
 
 137  48
         this.text = aText;
 138  48
         return this;
 139  
     }
 140  
 
 141  
     /**
 142  
      * Set the HTML content.
 143  
      *
 144  
      * @param aHtml A String.
 145  
      * @return An HtmlEmail.
 146  
      * @throws EmailException see javax.mail.internet.MimeBodyPart
 147  
      *  for definitions
 148  
      * @since 1.0
 149  
      */
 150  
     public HtmlEmail setHtmlMsg(String aHtml) throws EmailException
 151  
     {
 152  72
         if (EmailUtils.isEmpty(aHtml))
 153  
         {
 154  6
             throw new EmailException("Invalid message supplied");
 155  
         }
 156  
 
 157  66
         this.html = aHtml;
 158  66
         return this;
 159  
     }
 160  
 
 161  
     /**
 162  
      * Set the message.
 163  
      *
 164  
      * <p>This method overrides {@link MultiPartEmail#setMsg(String)} in
 165  
      * order to send an HTML message instead of a plain text message in
 166  
      * the mail body. The message is formatted in HTML for the HTML
 167  
      * part of the message; it is left as is in the alternate text
 168  
      * part.
 169  
      *
 170  
      * @param msg the message text to use
 171  
      * @return this <code>HtmlEmail</code>
 172  
      * @throws EmailException if msg is null or empty;
 173  
      * see javax.mail.internet.MimeBodyPart for definitions
 174  
      * @since 1.0
 175  
      */
 176  
     @Override
 177  
     public Email setMsg(String msg) throws EmailException
 178  
     {
 179  24
         if (EmailUtils.isEmpty(msg))
 180  
         {
 181  4
             throw new EmailException("Invalid message supplied");
 182  
         }
 183  
 
 184  20
         setTextMsg(msg);
 185  
 
 186  20
         StringBuffer htmlMsgBuf = new StringBuffer(
 187  
             msg.length()
 188  
             + HTML_MESSAGE_START.length()
 189  
             + HTML_MESSAGE_END.length()
 190  
         );
 191  
 
 192  20
         htmlMsgBuf.append(HTML_MESSAGE_START)
 193  
             .append(msg)
 194  
             .append(HTML_MESSAGE_END);
 195  
 
 196  20
         setHtmlMsg(htmlMsgBuf.toString());
 197  
 
 198  20
         return this;
 199  
     }
 200  
 
 201  
     /**
 202  
      * Attempts to parse the specified <code>String</code> as a URL that will
 203  
      * then be embedded in the message.
 204  
      *
 205  
      * @param urlString String representation of the URL.
 206  
      * @param name The name that will be set in the filename header field.
 207  
      * @return A String with the Content-ID of the URL.
 208  
      * @throws EmailException when URL supplied is invalid or if {@code name} is null
 209  
      * or empty; also see {@link javax.mail.internet.MimeBodyPart} for definitions
 210  
      *
 211  
      * @see #embed(URL, String)
 212  
      * @since 1.1
 213  
      */
 214  
     public String embed(String urlString, String name) throws EmailException
 215  
     {
 216  
         try
 217  
         {
 218  0
             return embed(new URL(urlString), name);
 219  
         }
 220  0
         catch (MalformedURLException e)
 221  
         {
 222  0
             throw new EmailException("Invalid URL", e);
 223  
         }
 224  
     }
 225  
 
 226  
     /**
 227  
      * Embeds an URL in the HTML.
 228  
      *
 229  
      * <p>This method embeds a file located by an URL into
 230  
      * the mail body. It allows, for instance, to add inline images
 231  
      * to the email.  Inline files may be referenced with a
 232  
      * <code>cid:xxxxxx</code> URL, where xxxxxx is the Content-ID
 233  
      * returned by the embed function. It is an error to bind the same name
 234  
      * to more than one URL; if the same URL is embedded multiple times, the
 235  
      * same Content-ID is guaranteed to be returned.
 236  
      *
 237  
      * <p>While functionally the same as passing <code>URLDataSource</code> to
 238  
      * {@link #embed(DataSource, String, String)}, this method attempts
 239  
      * to validate the URL before embedding it in the message and will throw
 240  
      * <code>EmailException</code> if the validation fails. In this case, the
 241  
      * <code>HtmlEmail</code> object will not be changed.
 242  
      *
 243  
      * <p>
 244  
      * NOTE: Clients should take care to ensure that different URLs are bound to
 245  
      * different names. This implementation tries to detect this and throw
 246  
      * <code>EmailException</code>. However, it is not guaranteed to catch
 247  
      * all cases, especially when the URL refers to a remote HTTP host that
 248  
      * may be part of a virtual host cluster.
 249  
      *
 250  
      * @param url The URL of the file.
 251  
      * @param name The name that will be set in the filename header
 252  
      * field.
 253  
      * @return A String with the Content-ID of the file.
 254  
      * @throws EmailException when URL supplied is invalid or if {@code name} is null
 255  
      * or empty; also see {@link javax.mail.internet.MimeBodyPart} for definitions
 256  
      * @since 1.0
 257  
      */
 258  
     public String embed(URL url, String name) throws EmailException
 259  
     {
 260  16
         if (EmailUtils.isEmpty(name))
 261  
         {
 262  0
             throw new EmailException("name cannot be null or empty");
 263  
         }
 264  
 
 265  
         // check if a URLDataSource for this name has already been attached;
 266  
         // if so, return the cached CID value.
 267  16
         if (inlineEmbeds.containsKey(name))
 268  
         {
 269  4
             InlineImage ii = inlineEmbeds.get(name);
 270  4
             URLDataSource urlDataSource = (URLDataSource) ii.getDataSource();
 271  
             // make sure the supplied URL points to the same thing
 272  
             // as the one already associated with this name.
 273  
             // NOTE: Comparing URLs with URL.equals() is a blocking operation
 274  
             // in the case of a network failure therefore we use
 275  
             // url.toExternalForm().equals() here.
 276  4
             if (url.toExternalForm().equals(urlDataSource.getURL().toExternalForm()))
 277  
             {
 278  2
                 return ii.getCid();
 279  
             }
 280  
             else
 281  
             {
 282  2
                 throw new EmailException("embedded name '" + name
 283  
                     + "' is already bound to URL " + urlDataSource.getURL()
 284  
                     + "; existing names cannot be rebound");
 285  
             }
 286  
         }
 287  
 
 288  
         // verify that the URL is valid
 289  12
         InputStream is = null;
 290  
         try
 291  
         {
 292  12
             is = url.openStream();
 293  
         }
 294  2
         catch (IOException e)
 295  
         {
 296  2
             throw new EmailException("Invalid URL", e);
 297  
         }
 298  
         finally
 299  
         {
 300  2
             try
 301  
             {
 302  12
                 if (is != null)
 303  
                 {
 304  10
                     is.close();
 305  
                 }
 306  
             }
 307  0
             catch (IOException ioe) // NOPMD
 308  14
             { /* sigh */ }
 309  0
         }
 310  
 
 311  10
         return embed(new URLDataSource(url), name);
 312  
     }
 313  
 
 314  
     /**
 315  
      * Embeds a file in the HTML. This implementation delegates to
 316  
      * {@link #embed(File, String)}.
 317  
      *
 318  
      * @param file The <code>File</code> object to embed
 319  
      * @return A String with the Content-ID of the file.
 320  
      * @throws EmailException when the supplied <code>File</code> cannot be
 321  
      * used; also see {@link javax.mail.internet.MimeBodyPart} for definitions
 322  
      *
 323  
      * @see #embed(File, String)
 324  
      * @since 1.1
 325  
      */
 326  
     public String embed(File file) throws EmailException
 327  
     {
 328  10
         String cid = EmailUtils.randomAlphabetic(HtmlEmail.CID_LENGTH).toLowerCase(Locale.ENGLISH);
 329  10
         return embed(file, cid);
 330  
     }
 331  
 
 332  
     /**
 333  
      * Embeds a file in the HTML.
 334  
      *
 335  
      * <p>This method embeds a file located by an URL into
 336  
      * the mail body. It allows, for instance, to add inline images
 337  
      * to the email.  Inline files may be referenced with a
 338  
      * <code>cid:xxxxxx</code> URL, where xxxxxx is the Content-ID
 339  
      * returned by the embed function. Files are bound to their names, which is
 340  
      * the value returned by {@link java.io.File#getName()}. If the same file
 341  
      * is embedded multiple times, the same CID is guaranteed to be returned.
 342  
      *
 343  
      * <p>While functionally the same as passing <code>FileDataSource</code> to
 344  
      * {@link #embed(DataSource, String, String)}, this method attempts
 345  
      * to validate the file before embedding it in the message and will throw
 346  
      * <code>EmailException</code> if the validation fails. In this case, the
 347  
      * <code>HtmlEmail</code> object will not be changed.
 348  
      *
 349  
      * @param file The <code>File</code> to embed
 350  
      * @param cid the Content-ID to use for the embedded <code>File</code>
 351  
      * @return A String with the Content-ID of the file.
 352  
      * @throws EmailException when the supplied <code>File</code> cannot be used
 353  
      *  or if the file has already been embedded;
 354  
      *  also see {@link javax.mail.internet.MimeBodyPart} for definitions
 355  
      * @since 1.1
 356  
      */
 357  
     public String embed(File file, String cid) throws EmailException
 358  
     {
 359  20
         if (EmailUtils.isEmpty(file.getName()))
 360  
         {
 361  0
             throw new EmailException("file name cannot be null or empty");
 362  
         }
 363  
 
 364  
         // verify that the File can provide a canonical path
 365  20
         String filePath = null;
 366  
         try
 367  
         {
 368  20
             filePath = file.getCanonicalPath();
 369  
         }
 370  0
         catch (IOException ioe)
 371  
         {
 372  0
             throw new EmailException("couldn't get canonical path for "
 373  
                     + file.getName(), ioe);
 374  20
         }
 375  
 
 376  
         // check if a FileDataSource for this name has already been attached;
 377  
         // if so, return the cached CID value.
 378  20
         if (inlineEmbeds.containsKey(file.getName()))
 379  
         {
 380  4
             InlineImage ii = inlineEmbeds.get(file.getName());
 381  4
             FileDataSource fileDataSource = (FileDataSource) ii.getDataSource();
 382  
             // make sure the supplied file has the same canonical path
 383  
             // as the one already associated with this name.
 384  4
             String existingFilePath = null;
 385  
             try
 386  
             {
 387  4
                 existingFilePath = fileDataSource.getFile().getCanonicalPath();
 388  
             }
 389  0
             catch (IOException ioe)
 390  
             {
 391  0
                 throw new EmailException("couldn't get canonical path for file "
 392  
                         + fileDataSource.getFile().getName()
 393  
                         + "which has already been embedded", ioe);
 394  4
             }
 395  4
             if (filePath.equals(existingFilePath))
 396  
             {
 397  4
                 return ii.getCid();
 398  
             }
 399  
             else
 400  
             {
 401  0
                 throw new EmailException("embedded name '" + file.getName()
 402  
                     + "' is already bound to file " + existingFilePath
 403  
                     + "; existing names cannot be rebound");
 404  
             }
 405  
         }
 406  
 
 407  
         // verify that the file is valid
 408  16
         if (!file.exists())
 409  
         {
 410  0
             throw new EmailException("file " + filePath + " doesn't exist");
 411  
         }
 412  16
         if (!file.isFile())
 413  
         {
 414  0
             throw new EmailException("file " + filePath + " isn't a normal file");
 415  
         }
 416  16
         if (!file.canRead())
 417  
         {
 418  0
             throw new EmailException("file " + filePath + " isn't readable");
 419  
         }
 420  
 
 421  16
         return embed(new FileDataSource(file), file.getName(), cid);
 422  
     }
 423  
 
 424  
     /**
 425  
      * Embeds the specified <code>DataSource</code> in the HTML using a
 426  
      * randomly generated Content-ID. Returns the generated Content-ID string.
 427  
      *
 428  
      * @param dataSource the <code>DataSource</code> to embed
 429  
      * @param name the name that will be set in the filename header field
 430  
      * @return the generated Content-ID for this <code>DataSource</code>
 431  
      * @throws EmailException if the embedding fails or if <code>name</code> is
 432  
      * null or empty
 433  
      * @see #embed(DataSource, String, String)
 434  
      * @since 1.1
 435  
      */
 436  
     public String embed(DataSource dataSource, String name) throws EmailException
 437  
     {
 438  
         // check if the DataSource has already been attached;
 439  
         // if so, return the cached CID value.
 440  29
         if (inlineEmbeds.containsKey(name))
 441  
         {
 442  4
             InlineImage ii = inlineEmbeds.get(name);
 443  
             // make sure the supplied URL points to the same thing
 444  
             // as the one already associated with this name.
 445  4
             if (dataSource.equals(ii.getDataSource()))
 446  
             {
 447  2
                 return ii.getCid();
 448  
             }
 449  
             else
 450  
             {
 451  2
                 throw new EmailException("embedded DataSource '" + name
 452  
                     + "' is already bound to name " + ii.getDataSource().toString()
 453  
                     + "; existing names cannot be rebound");
 454  
             }
 455  
         }
 456  
 
 457  25
         String cid = EmailUtils.randomAlphabetic(HtmlEmail.CID_LENGTH).toLowerCase();
 458  25
         return embed(dataSource, name, cid);
 459  
     }
 460  
 
 461  
     /**
 462  
      * Embeds the specified <code>DataSource</code> in the HTML using the
 463  
      * specified Content-ID. Returns the specified Content-ID string.
 464  
      *
 465  
      * @param dataSource the <code>DataSource</code> to embed
 466  
      * @param name the name that will be set in the filename header field
 467  
      * @param cid the Content-ID to use for this <code>DataSource</code>
 468  
      * @return the URL encoded Content-ID for this <code>DataSource</code>
 469  
      * @throws EmailException if the embedding fails or if <code>name</code> is
 470  
      * null or empty
 471  
      * @since 1.1
 472  
      */
 473  
     public String embed(DataSource dataSource, String name, String cid)
 474  
         throws EmailException
 475  
     {
 476  41
         if (EmailUtils.isEmpty(name))
 477  
         {
 478  2
             throw new EmailException("name cannot be null or empty");
 479  
         }
 480  
 
 481  39
         MimeBodyPart mbp = new MimeBodyPart();
 482  
 
 483  
         try
 484  
         {
 485  
             // url encode the cid according to rfc 2392
 486  39
             cid = EmailUtils.encodeUrl(cid);
 487  
 
 488  39
             mbp.setDataHandler(new DataHandler(dataSource));
 489  39
             mbp.setFileName(name);
 490  39
             mbp.setDisposition(EmailAttachment.INLINE);
 491  39
             mbp.setContentID("<" + cid + ">");
 492  
 
 493  39
             InlineImage ii = new InlineImage(cid, dataSource, mbp);
 494  39
             this.inlineEmbeds.put(name, ii);
 495  
 
 496  39
             return cid;
 497  
         }
 498  0
         catch (MessagingException me)
 499  
         {
 500  0
             throw new EmailException(me);
 501  
         }
 502  0
         catch (UnsupportedEncodingException uee)
 503  
         {
 504  0
             throw new EmailException(uee);
 505  
         }
 506  
     }
 507  
 
 508  
     /**
 509  
      * Does the work of actually building the MimeMessage. Please note that
 510  
      * a user rarely calls this method directly and only if he/she is
 511  
      * interested in the sending the underlying MimeMessage without
 512  
      * commons-email.
 513  
      *
 514  
      * @exception EmailException if there was an error.
 515  
      * @since 1.0
 516  
      */
 517  
     @Override
 518  
     public void buildMimeMessage() throws EmailException
 519  
     {
 520  
         try
 521  
         {
 522  35
             build();
 523  
         }
 524  0
         catch (MessagingException me)
 525  
         {
 526  0
             throw new EmailException(me);
 527  35
         }
 528  35
         super.buildMimeMessage();
 529  33
     }
 530  
 
 531  
     /**
 532  
      * @throws EmailException EmailException
 533  
      * @throws MessagingException MessagingException
 534  
      */
 535  
     private void build() throws MessagingException, EmailException
 536  
     {
 537  35
         MimeMultipart rootContainer = this.getContainer();
 538  35
         MimeMultipart bodyEmbedsContainer = rootContainer;
 539  35
         MimeMultipart bodyContainer = rootContainer;
 540  35
         BodyPart msgHtml = null;
 541  35
         BodyPart msgText = null;
 542  
 
 543  35
         rootContainer.setSubType("mixed");
 544  
 
 545  
         // determine how to form multiparts of email
 546  
 
 547  35
         if (EmailUtils.isNotEmpty(this.html) && this.inlineEmbeds.size() > 0)
 548  
         {
 549  
             //If HTML body and embeds are used, create a related container and add it to the root container
 550  19
             bodyEmbedsContainer = new MimeMultipart("related");
 551  19
             bodyContainer = bodyEmbedsContainer;
 552  19
             this.addPart(bodyEmbedsContainer, 0);
 553  
 
 554  
             //If TEXT body was specified, create a alternative container and add it to the embeds container
 555  19
             if (EmailUtils.isNotEmpty(this.text))
 556  
             {
 557  10
                 bodyContainer = new MimeMultipart("alternative");
 558  10
                 BodyPart bodyPart = createBodyPart();
 559  
                 try
 560  
                 {
 561  10
                     bodyPart.setContent(bodyContainer);
 562  10
                     bodyEmbedsContainer.addBodyPart(bodyPart, 0);
 563  
                 }
 564  0
                 catch (MessagingException me)
 565  
                 {
 566  0
                     throw new EmailException(me);
 567  10
                 }
 568  10
             }
 569  
         }
 570  16
         else if (EmailUtils.isNotEmpty(this.text) && EmailUtils.isNotEmpty(this.html))
 571  
         {
 572  
             //If both HTML and TEXT bodies are provided, create a alternative container and add it to the root container
 573  8
             bodyContainer = new MimeMultipart("alternative");
 574  8
             this.addPart(bodyContainer, 0);
 575  
         }
 576  
 
 577  35
         if (EmailUtils.isNotEmpty(this.html))
 578  
         {
 579  33
             msgHtml = new MimeBodyPart();
 580  33
             bodyContainer.addBodyPart(msgHtml, 0);
 581  
 
 582  
             // apply default charset if one has been set
 583  33
             if (EmailUtils.isNotEmpty(this.charset))
 584  
             {
 585  19
                 msgHtml.setContent(
 586  
                     this.html,
 587  
                     EmailConstants.TEXT_HTML + "; charset=" + this.charset);
 588  
             }
 589  
             else
 590  
             {
 591  14
                 msgHtml.setContent(this.html, EmailConstants.TEXT_HTML);
 592  
             }
 593  
 
 594  33
             Iterator<InlineImage> iter = this.inlineEmbeds.values().iterator();
 595  56
             while (iter.hasNext())
 596  
             {
 597  23
                 InlineImage ii = iter.next();
 598  23
                 bodyEmbedsContainer.addBodyPart(ii.getMbp());
 599  23
             }
 600  
         }
 601  
 
 602  35
         if (EmailUtils.isNotEmpty(this.text))
 603  
         {
 604  20
             msgText = new MimeBodyPart();
 605  20
             bodyContainer.addBodyPart(msgText, 0);
 606  
 
 607  
             // apply default charset if one has been set
 608  20
             if (EmailUtils.isNotEmpty(this.charset))
 609  
             {
 610  12
                 msgText.setContent(
 611  
                     this.text,
 612  
                     EmailConstants.TEXT_PLAIN + "; charset=" + this.charset);
 613  
             }
 614  
             else
 615  
             {
 616  8
                 msgText.setContent(this.text, EmailConstants.TEXT_PLAIN);
 617  
             }
 618  
         }
 619  35
     }
 620  
 
 621  
     /**
 622  
      * Private bean class that encapsulates data about URL contents
 623  
      * that are embedded in the final email.
 624  
      * @since 1.1
 625  
      */
 626  97
     private static class InlineImage
 627  
     {
 628  
         /** content id. */
 629  
         private String cid;
 630  
         /** <code>DataSource</code> for the content. */
 631  
         private DataSource dataSource;
 632  
         /** the <code>MimeBodyPart</code> that contains the encoded data. */
 633  
         private MimeBodyPart mbp;
 634  
 
 635  
         /**
 636  
          * Creates an InlineImage object to represent the
 637  
          * specified content ID and <code>MimeBodyPart</code>.
 638  
          * @param cid the generated content ID
 639  
          * @param dataSource the <code>DataSource</code> that represents the content
 640  
          * @param mbp the <code>MimeBodyPart</code> that contains the encoded
 641  
          * data
 642  
          */
 643  
         public InlineImage(String cid, DataSource dataSource, MimeBodyPart mbp)
 644  39
         {
 645  39
             this.cid = cid;
 646  39
             this.dataSource = dataSource;
 647  39
             this.mbp = mbp;
 648  39
         }
 649  
 
 650  
         /**
 651  
          * Returns the unique content ID of this InlineImage.
 652  
          * @return the unique content ID of this InlineImage
 653  
          */
 654  
         public String getCid()
 655  
         {
 656  8
             return cid;
 657  
         }
 658  
 
 659  
         /**
 660  
          * Returns the <code>DataSource</code> that represents the encoded content.
 661  
          * @return the <code>DataSource</code> representing the encoded content
 662  
          */
 663  
         public DataSource getDataSource()
 664  
         {
 665  14
             return dataSource;
 666  
         }
 667  
 
 668  
         /**
 669  
          * Returns the <code>MimeBodyPart</code> that contains the
 670  
          * encoded InlineImage data.
 671  
          * @return the <code>MimeBodyPart</code> containing the encoded
 672  
          * InlineImage data
 673  
          */
 674  
         public MimeBodyPart getMbp()
 675  
         {
 676  23
             return mbp;
 677  
         }
 678  
 
 679  
         // equals()/hashCode() implementations, since this class
 680  
         // is stored as a entry in a Map.
 681  
         /**
 682  
          * {@inheritDoc}
 683  
          * @return true if the other object is also an InlineImage with the same cid.
 684  
          */
 685  
         @Override
 686  
         public boolean equals(Object obj)
 687  
         {
 688  0
             if (this == obj)
 689  
             {
 690  0
                 return true;
 691  
             }
 692  0
             if (!(obj instanceof InlineImage))
 693  
             {
 694  0
                 return false;
 695  
             }
 696  
 
 697  0
             InlineImage that = (InlineImage) obj;
 698  
 
 699  0
             return this.cid.equals(that.cid);
 700  
         }
 701  
 
 702  
         /**
 703  
          * {@inheritDoc}
 704  
          * @return the cid hashCode.
 705  
          */
 706  
         @Override
 707  
         public int hashCode()
 708  
         {
 709  0
             return cid.hashCode();
 710  
         }
 711  
     }
 712  
 }