Coverage Report - org.apache.commons.mail.Email
 
Classes in this File Line Coverage Branch Coverage Complexity
Email
81%
261/319
74%
118/158
2.455
 
 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.UnsupportedEncodingException;
 20  
 import java.nio.charset.Charset;
 21  
 import java.util.ArrayList;
 22  
 import java.util.Collection;
 23  
 import java.util.Date;
 24  
 import java.util.HashMap;
 25  
 import java.util.Iterator;
 26  
 import java.util.List;
 27  
 import java.util.Map;
 28  
 import java.util.Properties;
 29  
 
 30  
 import javax.mail.Authenticator;
 31  
 import javax.mail.Message;
 32  
 import javax.mail.MessagingException;
 33  
 import javax.mail.Session;
 34  
 import javax.mail.Store;
 35  
 import javax.mail.Transport;
 36  
 import javax.mail.internet.AddressException;
 37  
 import javax.mail.internet.InternetAddress;
 38  
 import javax.mail.internet.MimeMessage;
 39  
 import javax.mail.internet.MimeMultipart;
 40  
 import javax.mail.internet.MimeUtility;
 41  
 import javax.naming.Context;
 42  
 import javax.naming.InitialContext;
 43  
 import javax.naming.NamingException;
 44  
 
 45  
 /**
 46  
  * The base class for all email messages.  This class sets the
 47  
  * sender's email & name, receiver's email & name, subject, and the
 48  
  * sent date.  Subclasses are responsible for setting the message
 49  
  * body.
 50  
  *
 51  
  * @since 1.0
 52  
  * @author <a href="mailto:quintonm@bellsouth.net">Quinton McCombs</a>
 53  
  * @author <a href="mailto:jon@latchkey.com">Jon S. Stevens</a>
 54  
  * @author <a href="mailto:frank.kim@clearink.com">Frank Y. Kim</a>
 55  
  * @author <a href="mailto:bmclaugh@algx.net">Brett McLaughlin</a>
 56  
  * @author <a href="mailto:greg@shwoop.com">Greg Ritter</a>
 57  
  * @author <a href="mailto:unknown">Regis Koenig</a>
 58  
  * @author <a href="mailto:colin.chalmers@maxware.nl">Colin Chalmers</a>
 59  
  * @author <a href="mailto:matthias@wessendorf.net">Matthias Wessendorf</a>
 60  
  * @author <a href="mailto:corey.scott@gmail.com">Corey Scott</a>
 61  
  * @version $Id: Email.java 1448626 2013-02-21 12:57:29Z tn $
 62  
  */
 63  181
 public abstract class Email
 64  
 {
 65  
     /** @deprecated since 1.3, use {@link EmailConstants#SENDER_EMAIL} instead */
 66  
     @Deprecated
 67  
     public static final String SENDER_EMAIL = EmailConstants.SENDER_EMAIL;
 68  
 
 69  
     /** @deprecated since 1.3, use {@link EmailConstants#SENDER_NAME} instead */
 70  
     @Deprecated
 71  
     public static final String SENDER_NAME = EmailConstants.SENDER_NAME;
 72  
 
 73  
     /** @deprecated since 1.3, use {@link EmailConstants#RECEIVER_EMAIL} instead */
 74  
     @Deprecated
 75  
     public static final String RECEIVER_EMAIL = EmailConstants.RECEIVER_EMAIL;
 76  
 
 77  
     /** @deprecated since 1.3, use {@link EmailConstants#RECEIVER_NAME} instead */
 78  
     @Deprecated
 79  
     public static final String RECEIVER_NAME = EmailConstants.RECEIVER_NAME;
 80  
 
 81  
     /** @deprecated since 1.3, use {@link EmailConstants#EMAIL_SUBJECT} instead */
 82  
     @Deprecated
 83  
     public static final String EMAIL_SUBJECT = EmailConstants.EMAIL_SUBJECT;
 84  
 
 85  
     /** @deprecated since 1.3, use {@link EmailConstants#EMAIL_BODY} instead */
 86  
     @Deprecated
 87  
     public static final String EMAIL_BODY = EmailConstants.EMAIL_BODY;
 88  
 
 89  
     /** @deprecated since 1.3, use {@link EmailConstants#CONTENT_TYPE} instead */
 90  
     @Deprecated
 91  
     public static final String CONTENT_TYPE = EmailConstants.CONTENT_TYPE;
 92  
 
 93  
     /** @deprecated since 1.3, use {@link EmailConstants#ATTACHMENTS} instead */
 94  
     @Deprecated
 95  
     public static final String ATTACHMENTS = EmailConstants.ATTACHMENTS;
 96  
 
 97  
     /** @deprecated since 1.3, use {@link EmailConstants#FILE_SERVER} instead */
 98  
     @Deprecated
 99  
     public static final String FILE_SERVER = EmailConstants.FILE_SERVER;
 100  
 
 101  
     /** @deprecated since 1.3, use {@link EmailConstants#KOI8_R} instead */
 102  
     @Deprecated
 103  
     public static final String KOI8_R = EmailConstants.KOI8_R;
 104  
 
 105  
     /** @deprecated since 1.3, use {@link EmailConstants#ISO_8859_1} instead */
 106  
     @Deprecated
 107  
     public static final String ISO_8859_1 = EmailConstants.ISO_8859_1;
 108  
 
 109  
     /** @deprecated since 1.3, use {@link EmailConstants#US_ASCII} instead */
 110  
     @Deprecated
 111  
     public static final String US_ASCII = EmailConstants.US_ASCII;
 112  
 
 113  
     /** @deprecated since 1.3, use {@link EmailConstants#MAIL_DEBUG} instead */
 114  
     @Deprecated
 115  
     public static final String MAIL_DEBUG = EmailConstants.MAIL_DEBUG;
 116  
 
 117  
     /** @deprecated since 1.3, use {@link EmailConstants#MAIL_HOST} instead */
 118  
     @Deprecated
 119  
     public static final String MAIL_HOST = EmailConstants.MAIL_HOST;
 120  
 
 121  
     /** @deprecated since 1.3, use {@link EmailConstants#MAIL_PORT} instead */
 122  
     @Deprecated
 123  
     public static final String MAIL_PORT = EmailConstants.MAIL_PORT;
 124  
 
 125  
     /** @deprecated since 1.3, use {@link EmailConstants#MAIL_SMTP_FROM} instead */
 126  
     @Deprecated
 127  
     public static final String MAIL_SMTP_FROM = EmailConstants.MAIL_SMTP_FROM;
 128  
 
 129  
     /** @deprecated since 1.3, use {@link EmailConstants#MAIL_SMTP_AUTH} instead */
 130  
     @Deprecated
 131  
     public static final String MAIL_SMTP_AUTH = EmailConstants.MAIL_SMTP_AUTH;
 132  
 
 133  
     /** @deprecated since 1.3, use {@link EmailConstants#MAIL_SMTP_USER} instead */
 134  
     @Deprecated
 135  
     public static final String MAIL_SMTP_USER = EmailConstants.MAIL_SMTP_USER;
 136  
 
 137  
     /** @deprecated since 1.3, use {@link EmailConstants#MAIL_SMTP_PASSWORD} instead */
 138  
     @Deprecated
 139  
     public static final String MAIL_SMTP_PASSWORD = EmailConstants.MAIL_SMTP_PASSWORD;
 140  
 
 141  
     /** @deprecated since 1.3, use {@link EmailConstants#MAIL_TRANSPORT_PROTOCOL} instead */
 142  
     @Deprecated
 143  
     public static final String MAIL_TRANSPORT_PROTOCOL = EmailConstants.MAIL_TRANSPORT_PROTOCOL;
 144  
 
 145  
     /** @deprecated since 1.3, use {@link EmailConstants#SMTP} instead */
 146  
     @Deprecated
 147  
     public static final String SMTP = EmailConstants.SMTP;
 148  
 
 149  
     /** @deprecated since 1.3, use {@link EmailConstants#TEXT_HTML} instead */
 150  
     @Deprecated
 151  
     public static final String TEXT_HTML = EmailConstants.TEXT_HTML;
 152  
 
 153  
     /** @deprecated since 1.3, use {@link EmailConstants#TEXT_PLAIN} instead */
 154  
     @Deprecated
 155  
     public static final String TEXT_PLAIN = EmailConstants.TEXT_PLAIN;
 156  
 
 157  
     /** @deprecated since 1.3, use {@link EmailConstants#MAIL_TRANSPORT_TLS} instead */
 158  
     @Deprecated
 159  
     public static final String MAIL_TRANSPORT_TLS = EmailConstants.MAIL_TRANSPORT_TLS;
 160  
 
 161  
     /** @deprecated since 1.3, use {@link EmailConstants#MAIL_SMTP_SOCKET_FACTORY_FALLBACK} instead */
 162  
     @Deprecated
 163  
     public static final String MAIL_SMTP_SOCKET_FACTORY_FALLBACK = EmailConstants.MAIL_SMTP_SOCKET_FACTORY_FALLBACK;
 164  
 
 165  
     /** @deprecated since 1.3, use {@link EmailConstants#MAIL_SMTP_SOCKET_FACTORY_CLASS} instead */
 166  
     @Deprecated
 167  
     public static final String MAIL_SMTP_SOCKET_FACTORY_CLASS = EmailConstants.MAIL_SMTP_SOCKET_FACTORY_CLASS;
 168  
 
 169  
     /** @deprecated since 1.3, use {@link EmailConstants#MAIL_SMTP_SOCKET_FACTORY_PORT} instead */
 170  
     @Deprecated
 171  
     public static final String MAIL_SMTP_SOCKET_FACTORY_PORT = EmailConstants.MAIL_SMTP_SOCKET_FACTORY_PORT;
 172  
 
 173  
     /** @deprecated since 1.3, use {@link EmailConstants#MAIL_SMTP_CONNECTIONTIMEOUT} instead */
 174  
     @Deprecated
 175  
     public static final String MAIL_SMTP_CONNECTIONTIMEOUT = EmailConstants.MAIL_SMTP_CONNECTIONTIMEOUT;
 176  
 
 177  
     /** @deprecated since 1.3, use {@link EmailConstants#MAIL_SMTP_TIMEOUT} instead */
 178  
     @Deprecated
 179  
     public static final String MAIL_SMTP_TIMEOUT = EmailConstants.MAIL_SMTP_TIMEOUT;
 180  
 
 181  
     /** The email message to send. */
 182  
     protected MimeMessage message;
 183  
 
 184  
     /** The charset to use for this message. */
 185  
     protected String charset;
 186  
 
 187  
     /** The Address of the sending party, mandatory. */
 188  
     protected InternetAddress fromAddress;
 189  
 
 190  
     /** The Subject. */
 191  
     protected String subject;
 192  
 
 193  
     /** An attachment. */
 194  
     protected MimeMultipart emailBody;
 195  
 
 196  
     /** The content. */
 197  
     protected Object content;
 198  
 
 199  
     /** The content type. */
 200  
     protected String contentType;
 201  
 
 202  
     /** Set session debugging on or off. */
 203  
     protected boolean debug;
 204  
 
 205  
     /** Sent date. */
 206  
     protected Date sentDate;
 207  
 
 208  
     /**
 209  
      * Instance of an <code>Authenticator</code> object that will be used
 210  
      * when authentication is requested from the mail server.
 211  
      */
 212  
     protected Authenticator authenticator;
 213  
 
 214  
     /**
 215  
      * The hostname of the mail server with which to connect. If null will try
 216  
      * to get property from system.properties. If still null, quit.
 217  
      */
 218  
     protected String hostName;
 219  
 
 220  
     /**
 221  
      * The port number of the mail server to connect to.
 222  
      * Defaults to the standard port ( 25 ).
 223  
      */
 224  181
     protected String smtpPort = "25";
 225  
 
 226  
     /**
 227  
      * The port number of the SSL enabled SMTP server;
 228  
      * defaults to the standard port, 465.
 229  
      */
 230  181
     protected String sslSmtpPort = "465";
 231  
 
 232  
     /** List of "to" email addresses. */
 233  181
     protected List<InternetAddress> toList = new ArrayList<InternetAddress>();
 234  
 
 235  
     /** List of "cc" email addresses. */
 236  181
     protected List<InternetAddress> ccList = new ArrayList<InternetAddress>();
 237  
 
 238  
     /** List of "bcc" email addresses. */
 239  181
     protected List<InternetAddress> bccList = new ArrayList<InternetAddress>();
 240  
 
 241  
     /** List of "replyTo" email addresses. */
 242  181
     protected List<InternetAddress> replyList = new ArrayList<InternetAddress>();
 243  
 
 244  
     /**
 245  
      * Address to which undeliverable mail should be sent.
 246  
      * Because this is handled by JavaMail as a String property
 247  
      * in the mail session, this property is of type <code>String</code>
 248  
      * rather than <code>InternetAddress</code>.
 249  
      */
 250  
     protected String bounceAddress;
 251  
 
 252  
     /**
 253  
      * Used to specify the mail headers.  Example:
 254  
      *
 255  
      * X-Mailer: Sendmail, X-Priority: 1( highest )
 256  
      * or  2( high ) 3( normal ) 4( low ) and 5( lowest )
 257  
      * Disposition-Notification-To: user@domain.net
 258  
      */
 259  181
     protected Map<String, String> headers = new HashMap<String, String>();
 260  
 
 261  
     /**
 262  
      * Used to determine whether to use pop3 before smtp, and if so the settings.
 263  
      */
 264  
     protected boolean popBeforeSmtp;
 265  
 
 266  
     /** the host name of the pop3 server. */
 267  
     protected String popHost;
 268  
 
 269  
     /** the user name to log into the pop3 server. */
 270  
     protected String popUsername;
 271  
 
 272  
     /** the password to log into the pop3 server. */
 273  
     protected String popPassword;
 274  
 
 275  
     /**
 276  
      * Does server require TLS encryption for authentication?
 277  
      * @deprecated  since 1.3, use setStartTLSEnabled() instead
 278  
      */
 279  
     @Deprecated
 280  
     protected boolean tls;
 281  
 
 282  
     /**
 283  
      * Does the current transport use SSL/TLS encryption upon connection?
 284  
      * @deprecated since 1.3, use setSSLOnConnect() instead
 285  
      */
 286  
     @Deprecated
 287  
     protected boolean ssl;
 288  
 
 289  
     /** socket I/O timeout value in milliseconds. */
 290  181
     protected int socketTimeout = EmailConstants.SOCKET_TIMEOUT_MS;
 291  
 
 292  
     /** socket connection timeout value in milliseconds. */
 293  181
     protected int socketConnectionTimeout = EmailConstants.SOCKET_TIMEOUT_MS;
 294  
 
 295  
     /**
 296  
      * If true, enables the use of the STARTTLS command (if supported by
 297  
      * the server) to switch the connection to a TLS-protected connection
 298  
      * before issuing any login commands. Note that an appropriate trust
 299  
      * store must configured so that the client will trust the server's
 300  
      * certificate.
 301  
      * Defaults to false.
 302  
      */
 303  
     private boolean startTlsEnabled;
 304  
 
 305  
     /**
 306  
      * If true, requires the use of the STARTTLS command. If the server doesn't
 307  
      * support the STARTTLS command, or the command fails, the connect method
 308  
      * will fail.
 309  
      * Defaults to false.
 310  
      */
 311  
     private boolean startTlsRequired;
 312  
 
 313  
     /** does the current transport use SSL/TLS encryption upon connection? */
 314  
     private boolean sslOnConnect;
 315  
 
 316  
     /**
 317  
      * If set to true, check the server identity as specified by RFC 2595. These
 318  
      * additional checks based on the content of the server's certificate are
 319  
      * intended to prevent man-in-the-middle attacks.
 320  
      * Defaults to false.
 321  
      */
 322  
     private boolean sslCheckServerIdentity;
 323  
 
 324  
     /** The Session to mail with. */
 325  
     private Session session;
 326  
 
 327  
     /**
 328  
      * Setting to true will enable the display of debug information.
 329  
      *
 330  
      * @param d A boolean.
 331  
      * @since 1.0
 332  
      */
 333  
     public void setDebug(boolean d)
 334  
     {
 335  15
         this.debug = d;
 336  15
     }
 337  
 
 338  
     /**
 339  
      * Sets the userName and password if authentication is needed.  If this
 340  
      * method is not used, no authentication will be performed.
 341  
      * <p>
 342  
      * This method will create a new instance of
 343  
      * <code>DefaultAuthenticator</code> using the supplied parameters.
 344  
      *
 345  
      * @param userName User name for the SMTP server
 346  
      * @param password password for the SMTP server
 347  
      * @see DefaultAuthenticator
 348  
      * @see #setAuthenticator
 349  
      * @since 1.0
 350  
      */
 351  
     public void setAuthentication(String userName, String password)
 352  
     {
 353  21
         this.setAuthenticator(new DefaultAuthenticator(userName, password));
 354  21
     }
 355  
 
 356  
     /**
 357  
      * Sets the <code>Authenticator</code> to be used when authentication
 358  
      * is requested from the mail server.
 359  
      * <p>
 360  
      * This method should be used when your outgoing mail server requires
 361  
      * authentication.  Your mail server must also support RFC2554.
 362  
      *
 363  
      * @param newAuthenticator the <code>Authenticator</code> object.
 364  
      * @see Authenticator
 365  
      * @since 1.0
 366  
      */
 367  
     public void setAuthenticator(Authenticator newAuthenticator)
 368  
     {
 369  35
         this.authenticator = newAuthenticator;
 370  35
     }
 371  
 
 372  
     /**
 373  
      * Set the charset of the message. Please note that you should set the charset before
 374  
      * adding the message content.
 375  
      *
 376  
      * @param newCharset A String.
 377  
      * @throws java.nio.charset.IllegalCharsetNameException if the charset name is invalid
 378  
      * @throws java.nio.charset.UnsupportedCharsetException if no support for the named charset
 379  
      * exists in the current JVM
 380  
      * @since 1.0
 381  
      */
 382  
     public void setCharset(String newCharset)
 383  
     {
 384  33
         Charset set = Charset.forName(newCharset);
 385  33
         this.charset = set.name();
 386  33
     }
 387  
 
 388  
     /**
 389  
      * Set the emailBody to a MimeMultiPart
 390  
      *
 391  
      * @param aMimeMultipart aMimeMultipart
 392  
      * @since 1.0
 393  
      */
 394  
     public void setContent(MimeMultipart aMimeMultipart)
 395  
     {
 396  47
         this.emailBody = aMimeMultipart;
 397  47
     }
 398  
 
 399  
     /**
 400  
      * Set the content & contentType
 401  
      *
 402  
      * @param   aObject aObject
 403  
      * @param   aContentType aContentType
 404  
      * @since 1.0
 405  
      */
 406  
     public void setContent(Object aObject, String aContentType)
 407  
     {
 408  22
         this.content = aObject;
 409  22
         this.updateContentType(aContentType);
 410  22
     }
 411  
 
 412  
     /**
 413  
      * Update the contentType.
 414  
      *
 415  
      * @param   aContentType aContentType
 416  
      * @since 1.2
 417  
      */
 418  
     public void updateContentType(final String aContentType)
 419  
     {
 420  74
         if (EmailUtils.isEmpty(aContentType))
 421  
         {
 422  42
             this.contentType = null;
 423  
         }
 424  
         else
 425  
         {
 426  
             // set the content type
 427  32
             this.contentType = aContentType;
 428  
 
 429  
             // set the charset if the input was properly formed
 430  32
             String strMarker = "; charset=";
 431  32
             int charsetPos = aContentType.toLowerCase().indexOf(strMarker);
 432  
 
 433  32
             if (charsetPos != -1)
 434  
             {
 435  
                 // find the next space (after the marker)
 436  13
                 charsetPos += strMarker.length();
 437  13
                 int intCharsetEnd =
 438  
                     aContentType.toLowerCase().indexOf(" ", charsetPos);
 439  
 
 440  13
                 if (intCharsetEnd != -1)
 441  
                 {
 442  1
                     this.charset =
 443  
                         aContentType.substring(charsetPos, intCharsetEnd);
 444  
                 }
 445  
                 else
 446  
                 {
 447  12
                     this.charset = aContentType.substring(charsetPos);
 448  
                 }
 449  13
             }
 450  
             else
 451  
             {
 452  
                 // use the default charset, if one exists, for messages
 453  
                 // whose content-type is some form of text.
 454  19
                 if (this.contentType.startsWith("text/") && EmailUtils.isNotEmpty(this.charset))
 455  
                 {
 456  7
                     StringBuffer contentTypeBuf = new StringBuffer(this.contentType);
 457  7
                     contentTypeBuf.append(strMarker);
 458  7
                     contentTypeBuf.append(this.charset);
 459  7
                     this.contentType = contentTypeBuf.toString();
 460  
                 }
 461  
             }
 462  
         }
 463  74
     }
 464  
 
 465  
     /**
 466  
      * Set the hostname of the outgoing mail server.
 467  
      *
 468  
      * @param   aHostName aHostName
 469  
      * @since 1.0
 470  
      */
 471  
     public void setHostName(String aHostName)
 472  
     {
 473  60
         checkSessionAlreadyInitialized();
 474  60
         this.hostName = aHostName;
 475  60
     }
 476  
 
 477  
     /**
 478  
      * Set or disable the STARTTLS encryption. Please see EMAIL-105
 479  
      * for the reasons of deprecation.
 480  
      *
 481  
      * @deprecated since 1.3, use setStartTLSEnabled() instead
 482  
      * @param withTLS true if STARTTLS requested, false otherwise
 483  
      * @since 1.1
 484  
      */
 485  
     @Deprecated
 486  
     public void setTLS(boolean withTLS)
 487  
     {
 488  0
         setStartTLSEnabled(withTLS);
 489  0
     }
 490  
 
 491  
     /**
 492  
      * Set or disable the STARTTLS encryption.
 493  
      *
 494  
      * @param startTlsEnabled true if STARTTLS requested, false otherwise
 495  
      * @return An Email.
 496  
      * @since 1.3
 497  
      */
 498  
     public Email setStartTLSEnabled(boolean startTlsEnabled)
 499  
     {
 500  13
         checkSessionAlreadyInitialized();
 501  13
         this.startTlsEnabled = startTlsEnabled;
 502  13
         this.tls = startTlsEnabled;
 503  13
         return this;
 504  
     }
 505  
 
 506  
     /**
 507  
      * Set or disable the required STARTTLS encryption.
 508  
      *
 509  
      * @param startTlsRequired true if STARTTLS requested, false otherwise
 510  
      * @return An Email.
 511  
      * @since 1.3
 512  
      */
 513  
     public Email setStartTLSRequired(boolean startTlsRequired)
 514  
     {
 515  13
         checkSessionAlreadyInitialized();
 516  13
         this.startTlsRequired = startTlsRequired;
 517  13
         return this;
 518  
     }
 519  
 
 520  
     /**
 521  
      * Set the port number of the outgoing mail server.
 522  
      *
 523  
      * @param  aPortNumber aPortNumber
 524  
      * @throws IllegalArgumentException if the port number is &lt; 1
 525  
      * @since 1.0
 526  
      */
 527  
     public void setSmtpPort(int aPortNumber)
 528  
     {
 529  56
         checkSessionAlreadyInitialized();
 530  
 
 531  56
         if (aPortNumber < 1)
 532  
         {
 533  3
             throw new IllegalArgumentException(
 534  
                 "Cannot connect to a port number that is less than 1 ( "
 535  
                     + aPortNumber
 536  
                     + " )");
 537  
         }
 538  
 
 539  53
         this.smtpPort = Integer.toString(aPortNumber);
 540  53
     }
 541  
 
 542  
     /**
 543  
      * Supply a mail Session object to use. Please note that passing
 544  
      * a user name and password (in the case of mail authentication) will
 545  
      * create a new mail session with a DefaultAuthenticator. This is a
 546  
      * convenience but might come unexpected.
 547  
      *
 548  
      * If mail authentication is used but NO username and password
 549  
      * is supplied the implementation assumes that you have set a
 550  
      * authenticator and will use the existing mail session (as expected).
 551  
      *
 552  
      * @param aSession mail session to be used
 553  
      * @throws IllegalArgumentException if the session is {@code null}
 554  
      * @since 1.0
 555  
      */
 556  
     public void setMailSession(Session aSession)
 557  
     {
 558  4
         EmailUtils.notNull(aSession, "no mail session supplied");
 559  
 
 560  4
         Properties sessionProperties = aSession.getProperties();
 561  4
         String auth = sessionProperties.getProperty(MAIL_SMTP_AUTH);
 562  
 
 563  4
         if ("true".equalsIgnoreCase(auth))
 564  
         {
 565  3
             String userName = sessionProperties.getProperty(MAIL_SMTP_USER);
 566  3
             String password = sessionProperties.getProperty(MAIL_SMTP_PASSWORD);
 567  
 
 568  3
             if (EmailUtils.isNotEmpty(userName) && EmailUtils.isNotEmpty(password))
 569  
             {
 570  
                 // only create a new mail session with an authenticator if
 571  
                 // authentication is required and no user name is given
 572  0
                 this.authenticator = new DefaultAuthenticator(userName, password);
 573  0
                 this.session = Session.getInstance(sessionProperties, this.authenticator);
 574  
             }
 575  
             else
 576  
             {
 577  
                 // assume that the given mail session contains a working authenticator
 578  3
                 this.session = aSession;
 579  
             }
 580  3
         }
 581  
         else
 582  
         {
 583  1
             this.session = aSession;
 584  
         }
 585  4
     }
 586  
 
 587  
     /**
 588  
      * Supply a mail Session object from a JNDI directory.
 589  
      *
 590  
      * @param jndiName name of JNDI resource (javax.mail.Session type), resource
 591  
      * if searched in java:comp/env if name does not start with "java:"
 592  
      * @throws IllegalArgumentException if the JNDI name is null or empty
 593  
      * @throws NamingException if the resource cannot be retrieved from JNDI directory
 594  
      * @since 1.1
 595  
      */
 596  
     public void setMailSessionFromJNDI(String jndiName) throws NamingException
 597  
     {
 598  0
         if (EmailUtils.isEmpty(jndiName))
 599  
         {
 600  0
             throw new IllegalArgumentException("JNDI name missing");
 601  
         }
 602  0
         Context ctx = null;
 603  0
         if (jndiName.startsWith("java:"))
 604  
         {
 605  0
             ctx = new InitialContext();
 606  
         }
 607  
         else
 608  
         {
 609  0
             ctx = (Context) new InitialContext().lookup("java:comp/env");
 610  
 
 611  
         }
 612  0
         this.setMailSession((Session) ctx.lookup(jndiName));
 613  0
     }
 614  
 
 615  
     /**
 616  
      * Determines the mail session used when sending this Email, creating
 617  
      * the Session if necessary. When a mail session is already
 618  
      * initialized setting the session related properties will cause
 619  
      * an IllegalStateException.
 620  
      *
 621  
      * @return A Session.
 622  
      * @throws EmailException if the host name was not set
 623  
      * @since 1.0
 624  
      */
 625  
     public Session getMailSession() throws EmailException
 626  
     {
 627  56
         if (this.session == null)
 628  
         {
 629  52
             Properties properties = new Properties(System.getProperties());
 630  52
             properties.setProperty(MAIL_TRANSPORT_PROTOCOL, SMTP);
 631  
 
 632  52
             if (EmailUtils.isEmpty(this.hostName))
 633  
             {
 634  2
                 this.hostName = properties.getProperty(MAIL_HOST);
 635  
             }
 636  
 
 637  52
             if (EmailUtils.isEmpty(this.hostName))
 638  
             {
 639  2
                 throw new EmailException("Cannot find valid hostname for mail session");
 640  
             }
 641  
 
 642  50
             properties.setProperty(MAIL_PORT, this.smtpPort);
 643  50
             properties.setProperty(MAIL_HOST, this.hostName);
 644  50
             properties.setProperty(MAIL_DEBUG, String.valueOf(this.debug));
 645  
 
 646  50
             properties.setProperty(EmailConstants.MAIL_TRANSPORT_STARTTLS_ENABLE,
 647  
                     isStartTLSEnabled() ? "true" : "false");
 648  50
             properties.setProperty(EmailConstants.MAIL_TRANSPORT_STARTTLS_REQUIRED,
 649  
                     isStartTLSRequired() ? "true" : "false");
 650  
 
 651  50
             if (this.authenticator != null)
 652  
             {
 653  30
                 properties.setProperty(MAIL_SMTP_AUTH, "true");
 654  
             }
 655  
 
 656  50
             if (isSSLOnConnect())
 657  
             {
 658  1
                 properties.setProperty(MAIL_PORT, this.sslSmtpPort);
 659  1
                 properties.setProperty(MAIL_SMTP_SOCKET_FACTORY_PORT, this.sslSmtpPort);
 660  1
                 properties.setProperty(MAIL_SMTP_SOCKET_FACTORY_CLASS, "javax.net.ssl.SSLSocketFactory");
 661  1
                 properties.setProperty(MAIL_SMTP_SOCKET_FACTORY_FALLBACK, "false");
 662  
             }
 663  
 
 664  50
             if ((isSSLOnConnect() || isStartTLSEnabled()) && isSSLCheckServerIdentity())
 665  
             {
 666  0
                 properties.setProperty(EmailConstants.MAIL_SMTP_SSL_CHECKSERVERIDENTITY, "true");
 667  
             }
 668  
 
 669  50
             if (this.bounceAddress != null)
 670  
             {
 671  10
                 properties.setProperty(MAIL_SMTP_FROM, this.bounceAddress);
 672  
             }
 673  
 
 674  50
             if (this.socketTimeout > 0)
 675  
             {
 676  50
                 properties.setProperty(MAIL_SMTP_TIMEOUT, Integer.toString(this.socketTimeout));
 677  
             }
 678  
 
 679  50
             if (this.socketConnectionTimeout > 0)
 680  
             {
 681  50
                 properties.setProperty(MAIL_SMTP_CONNECTIONTIMEOUT, Integer.toString(this.socketConnectionTimeout));
 682  
             }
 683  
 
 684  
             // changed this (back) to getInstance due to security exceptions
 685  
             // caused when testing using maven
 686  50
             this.session = Session.getInstance(properties, this.authenticator);
 687  
         }
 688  54
         return this.session;
 689  
     }
 690  
 
 691  
     /**
 692  
      * Set the FROM field of the email to use the specified address. The email
 693  
      * address will also be used as the personal name.
 694  
      * The name will be encoded by the charset of {@link #setCharset(java.lang.String) setCharset()}.
 695  
      * If it is not set, it will be encoded using
 696  
      * the Java platform's default charset (UTF-16) if it contains
 697  
      * non-ASCII characters; otherwise, it is used as is.
 698  
      *
 699  
      * @param email A String.
 700  
      * @return An Email.
 701  
      * @throws EmailException Indicates an invalid email address.
 702  
      * @since 1.0
 703  
      */
 704  
     public Email setFrom(String email)
 705  
         throws EmailException
 706  
     {
 707  84
         return setFrom(email, null);
 708  
     }
 709  
 
 710  
     /**
 711  
      * Set the FROM field of the email to use the specified address and the
 712  
      * specified personal name.
 713  
      * The name will be encoded by the charset of {@link #setCharset(java.lang.String) setCharset()}.
 714  
      * If it is not set, it will be encoded using
 715  
      * the Java platform's default charset (UTF-16) if it contains
 716  
      * non-ASCII characters; otherwise, it is used as is.
 717  
      *
 718  
      * @param email A String.
 719  
      * @param name A String.
 720  
      * @return An Email.
 721  
      * @throws EmailException Indicates an invalid email address.
 722  
      * @since 1.0
 723  
      */
 724  
     public Email setFrom(String email, String name)
 725  
         throws EmailException
 726  
     {
 727  87
         return setFrom(email, name, this.charset);
 728  
     }
 729  
 
 730  
     /**
 731  
      * Set the FROM field of the email to use the specified address, personal
 732  
      * name, and charset encoding for the name.
 733  
      *
 734  
      * @param email A String.
 735  
      * @param name A String.
 736  
      * @param charset The charset to encode the name with.
 737  
      * @return An Email.
 738  
      * @throws EmailException Indicates an invalid email address or charset.
 739  
      * @since 1.1
 740  
      */
 741  
     public Email setFrom(String email, String name, String charset)
 742  
         throws EmailException
 743  
     {
 744  89
         this.fromAddress = createInternetAddress(email, name, charset);
 745  59
         return this;
 746  
     }
 747  
 
 748  
     /**
 749  
      * Add a recipient TO to the email. The email
 750  
      * address will also be used as the personal name.
 751  
      * The name will be encoded by the charset of
 752  
      * {@link #setCharset(java.lang.String) setCharset()}.
 753  
      * If it is not set, it will be encoded using
 754  
      * the Java platform's default charset (UTF-16) if it contains
 755  
      * non-ASCII characters; otherwise, it is used as is.
 756  
      *
 757  
      * @param email A String.
 758  
      * @return An Email.
 759  
      * @throws EmailException Indicates an invalid email address.
 760  
      * @since 1.0
 761  
      */
 762  
     public Email addTo(String email)
 763  
         throws EmailException
 764  
     {
 765  54
         return addTo(email, null);
 766  
     }
 767  
 
 768  
     /**
 769  
      * Add a list of TO recipients to the email. The email
 770  
      * addresses will also be used as the personal names.
 771  
      * The names will be encoded by the charset of
 772  
      * {@link #setCharset(java.lang.String) setCharset()}.
 773  
      * If it is not set, it will be encoded using
 774  
      * the Java platform's default charset (UTF-16) if it contains
 775  
      * non-ASCII characters; otherwise, it is used as is.
 776  
      *
 777  
      * @param emails A String array.
 778  
      * @return An Email.
 779  
      * @throws EmailException Indicates an invalid email address.
 780  
      * @since 1.3
 781  
      */
 782  
     public Email addTo(String... emails)
 783  
         throws EmailException
 784  
     {
 785  1
         if (emails == null || emails.length == 0)
 786  
         {
 787  0
             throw new EmailException("Address List provided was invalid");
 788  
         }
 789  
 
 790  4
         for (String email : emails)
 791  
         {
 792  3
             addTo(email, null);
 793  
         }
 794  
 
 795  1
         return this;
 796  
     }
 797  
 
 798  
     /**
 799  
      * Add a recipient TO to the email using the specified address and the
 800  
      * specified personal name.
 801  
      * The name will be encoded by the charset of
 802  
      * {@link #setCharset(java.lang.String) setCharset()}.
 803  
      * If it is not set, it will be encoded using
 804  
      * the Java platform's default charset (UTF-16) if it contains
 805  
      * non-ASCII characters; otherwise, it is used as is.
 806  
      *
 807  
      * @param email A String.
 808  
      * @param name A String.
 809  
      * @return An Email.
 810  
      * @throws EmailException Indicates an invalid email address.
 811  
      * @since 1.0
 812  
      */
 813  
     public Email addTo(String email, String name)
 814  
         throws EmailException
 815  
     {
 816  89
         return addTo(email, name, this.charset);
 817  
     }
 818  
 
 819  
     /**
 820  
      * Add a recipient TO to the email using the specified address, personal
 821  
      * name, and charset encoding for the name.
 822  
      *
 823  
      * @param email A String.
 824  
      * @param name A String.
 825  
      * @param charset The charset to encode the name with.
 826  
      * @return An Email.
 827  
      * @throws EmailException Indicates an invalid email address or charset.
 828  
      * @since 1.1
 829  
      */
 830  
     public Email addTo(String email, String name, String charset)
 831  
         throws EmailException
 832  
     {
 833  93
         this.toList.add(createInternetAddress(email, name, charset));
 834  63
         return this;
 835  
     }
 836  
 
 837  
     /**
 838  
      * Set a list of "TO" addresses. All elements in the specified
 839  
      * <code>Collection</code> are expected to be of type
 840  
      * <code>java.mail.internet.InternetAddress</code>.
 841  
      *
 842  
      * @param  aCollection collection of <code>InternetAddress</code> objects.
 843  
      * @return An Email.
 844  
      * @throws EmailException Indicates an invalid email address.
 845  
      * @see javax.mail.internet.InternetAddress
 846  
      * @since 1.0
 847  
      */
 848  
     public Email setTo(Collection<InternetAddress> aCollection) throws EmailException
 849  
     {
 850  3
         if (aCollection == null || aCollection.isEmpty())
 851  
         {
 852  2
             throw new EmailException("Address List provided was invalid");
 853  
         }
 854  
 
 855  1
         this.toList = new ArrayList<InternetAddress>(aCollection);
 856  1
         return this;
 857  
     }
 858  
 
 859  
     /**
 860  
      * Add a recipient CC to the email. The email
 861  
      * address will also be used as the personal name.
 862  
      * The name will be encoded by the charset of {@link #setCharset(java.lang.String) setCharset()}.
 863  
      * If it is not set, it will be encoded using
 864  
      * the Java platform's default charset (UTF-16) if it contains
 865  
      * non-ASCII characters; otherwise, it is used as is.
 866  
      *
 867  
      * @param email A String.
 868  
      * @return An Email.
 869  
      * @throws EmailException Indicates an invalid email address.
 870  
      * @since 1.0
 871  
      */
 872  
     public Email addCc(String email)
 873  
         throws EmailException
 874  
     {
 875  4
         return this.addCc(email, null);
 876  
     }
 877  
 
 878  
     /**
 879  
      * Add an array of CC recipients to the email. The email
 880  
      * addresses will also be used as the personal name.
 881  
      * The names will be encoded by the charset of
 882  
      * {@link #setCharset(java.lang.String) setCharset()}.
 883  
      * If it is not set, it will be encoded using
 884  
      * the Java platform's default charset (UTF-16) if it contains
 885  
      * non-ASCII characters; otherwise, it is used as is.
 886  
      *
 887  
      * @param emails A String array.
 888  
      * @return An Email.
 889  
      * @throws EmailException Indicates an invalid email address.
 890  
      * @since 1.3
 891  
      */
 892  
     public Email addCc(String... emails)
 893  
         throws EmailException
 894  
     {
 895  1
         if (emails == null || emails.length == 0)
 896  
         {
 897  0
             throw new EmailException("Address List provided was invalid");
 898  
         }
 899  
 
 900  4
         for (String email : emails)
 901  
         {
 902  3
             addCc(email, null);
 903  
         }
 904  
 
 905  1
         return this;
 906  
     }
 907  
 
 908  
     /**
 909  
      * Add a recipient CC to the email using the specified address and the
 910  
      * specified personal name.
 911  
      * The name will be encoded by the charset of {@link #setCharset(java.lang.String) setCharset()}.
 912  
      * If it is not set, it will be encoded using
 913  
      * the Java platform's default charset (UTF-16) if it contains
 914  
      * non-ASCII characters; otherwise, it is used as is.
 915  
      *
 916  
      * @param email A String.
 917  
      * @param name A String.
 918  
      * @return An Email.
 919  
      * @throws EmailException Indicates an invalid email address.
 920  
      * @since 1.0
 921  
      */
 922  
     public Email addCc(String email, String name)
 923  
         throws EmailException
 924  
     {
 925  39
         return addCc(email, name, this.charset);
 926  
     }
 927  
 
 928  
     /**
 929  
      * Add a recipient CC to the email using the specified address, personal
 930  
      * name, and charset encoding for the name.
 931  
      *
 932  
      * @param email A String.
 933  
      * @param name A String.
 934  
      * @param charset The charset to encode the name with.
 935  
      * @return An Email.
 936  
      * @throws EmailException Indicates an invalid email address or charset.
 937  
      * @since 1.1
 938  
      */
 939  
     public Email addCc(String email, String name, String charset)
 940  
         throws EmailException
 941  
     {
 942  43
         this.ccList.add(createInternetAddress(email, name, charset));
 943  13
         return this;
 944  
     }
 945  
 
 946  
     /**
 947  
      * Set a list of "CC" addresses. All elements in the specified
 948  
      * <code>Collection</code> are expected to be of type
 949  
      * <code>java.mail.internet.InternetAddress</code>.
 950  
      *
 951  
      * @param aCollection collection of <code>InternetAddress</code> objects.
 952  
      * @return An Email.
 953  
      * @throws EmailException Indicates an invalid email address.
 954  
      * @see javax.mail.internet.InternetAddress
 955  
      * @since 1.0
 956  
      */
 957  
     public Email setCc(Collection<InternetAddress> aCollection) throws EmailException
 958  
     {
 959  3
         if (aCollection == null || aCollection.isEmpty())
 960  
         {
 961  2
             throw new EmailException("Address List provided was invalid");
 962  
         }
 963  
 
 964  1
         this.ccList = new ArrayList<InternetAddress>(aCollection);
 965  1
         return this;
 966  
     }
 967  
 
 968  
     /**
 969  
      * Add a blind BCC recipient to the email. The email
 970  
      * address will also be used as the personal name.
 971  
      * The name will be encoded by the charset of {@link #setCharset(java.lang.String) setCharset()}.
 972  
      * If it is not set, it will be encoded using
 973  
      * the Java platform's default charset (UTF-16) if it contains
 974  
      * non-ASCII characters; otherwise, it is used as is.
 975  
      *
 976  
      * @param email A String.
 977  
      * @return An Email.
 978  
      * @throws EmailException Indicates an invalid email address
 979  
      * @since 1.0
 980  
      */
 981  
     public Email addBcc(String email)
 982  
         throws EmailException
 983  
     {
 984  4
         return this.addBcc(email, null);
 985  
     }
 986  
 
 987  
     /**
 988  
      * Add an array of blind BCC recipients to the email. The email
 989  
      * addresses will also be used as the personal name.
 990  
      * The names will be encoded by the charset of
 991  
      * {@link #setCharset(java.lang.String) setCharset()}.
 992  
      * If it is not set, it will be encoded using
 993  
      * the Java platform's default charset (UTF-16) if it contains
 994  
      * non-ASCII characters; otherwise, it is used as is.
 995  
      *
 996  
      * @param emails A String array.
 997  
      * @return An Email.
 998  
      * @throws EmailException Indicates an invalid email address
 999  
      * @since 1.3
 1000  
      */
 1001  
     public Email addBcc(String... emails)
 1002  
         throws EmailException
 1003  
     {
 1004  1
         if (emails == null || emails.length == 0)
 1005  
         {
 1006  0
             throw new EmailException("Address List provided was invalid");
 1007  
         }
 1008  
 
 1009  4
         for (String email : emails)
 1010  
         {
 1011  3
             addBcc(email, null);
 1012  
         }
 1013  
 
 1014  1
         return this;
 1015  
     }
 1016  
 
 1017  
     /**
 1018  
      * Add a blind BCC recipient to the email using the specified address and
 1019  
      * the specified personal name.
 1020  
      * The name will be encoded by the charset of {@link #setCharset(java.lang.String) setCharset()}.
 1021  
      * If it is not set, it will be encoded using
 1022  
      * the Java platform's default charset (UTF-16) if it contains
 1023  
      * non-ASCII characters; otherwise, it is used as is.
 1024  
      *
 1025  
      * @param email A String.
 1026  
      * @param name A String.
 1027  
      * @return An Email.
 1028  
      * @throws EmailException Indicates an invalid email address
 1029  
      * @since 1.0
 1030  
      */
 1031  
     public Email addBcc(String email, String name)
 1032  
         throws EmailException
 1033  
     {
 1034  39
         return addBcc(email, name, this.charset);
 1035  
     }
 1036  
 
 1037  
     /**
 1038  
      * Add a blind BCC recipient to the email using the specified address,
 1039  
      * personal name, and charset encoding for the name.
 1040  
      *
 1041  
      * @param email A String.
 1042  
      * @param name A String.
 1043  
      * @param charset The charset to encode the name with.
 1044  
      * @return An Email.
 1045  
      * @throws EmailException Indicates an invalid email address
 1046  
      * @since 1.1
 1047  
      */
 1048  
     public Email addBcc(String email, String name, String charset)
 1049  
         throws EmailException
 1050  
     {
 1051  43
         this.bccList.add(createInternetAddress(email, name, charset));
 1052  13
         return this;
 1053  
     }
 1054  
 
 1055  
     /**
 1056  
      * Set a list of "BCC" addresses. All elements in the specified
 1057  
      * <code>Collection</code> are expected to be of type
 1058  
      * <code>java.mail.internet.InternetAddress</code>.
 1059  
      *
 1060  
      * @param  aCollection collection of <code>InternetAddress</code> objects
 1061  
      * @return An Email.
 1062  
      * @throws EmailException Indicates an invalid email address
 1063  
      * @see javax.mail.internet.InternetAddress
 1064  
      * @since 1.0
 1065  
      */
 1066  
     public Email setBcc(Collection<InternetAddress> aCollection) throws EmailException
 1067  
     {
 1068  4
         if (aCollection == null || aCollection.isEmpty())
 1069  
         {
 1070  2
             throw new EmailException("Address List provided was invalid");
 1071  
         }
 1072  
 
 1073  2
         this.bccList = new ArrayList<InternetAddress>(aCollection);
 1074  2
         return this;
 1075  
     }
 1076  
 
 1077  
     /**
 1078  
      * Add a reply to address to the email. The email
 1079  
      * address will also be used as the personal name.
 1080  
      * The name will be encoded by the charset of {@link #setCharset(java.lang.String) setCharset()}.
 1081  
      * If it is not set, it will be encoded using
 1082  
      * the Java platform's default charset (UTF-16) if it contains
 1083  
      * non-ASCII characters; otherwise, it is used as is.
 1084  
      *
 1085  
      * @param email A String.
 1086  
      * @return An Email.
 1087  
      * @throws EmailException Indicates an invalid email address
 1088  
      * @since 1.0
 1089  
      */
 1090  
     public Email addReplyTo(String email)
 1091  
         throws EmailException
 1092  
     {
 1093  4
         return this.addReplyTo(email, null);
 1094  
     }
 1095  
 
 1096  
     /**
 1097  
      * Add a reply to address to the email using the specified address and
 1098  
      * the specified personal name.
 1099  
      * The name will be encoded by the charset of {@link #setCharset(java.lang.String) setCharset()}.
 1100  
      * If it is not set, it will be encoded using
 1101  
      * the Java platform's default charset (UTF-16) if it contains
 1102  
      * non-ASCII characters; otherwise, it is used as is.
 1103  
      *
 1104  
      * @param email A String.
 1105  
      * @param name A String.
 1106  
      * @return An Email.
 1107  
      * @throws EmailException Indicates an invalid email address
 1108  
      * @since 1.0
 1109  
      */
 1110  
     public Email addReplyTo(String email, String name)
 1111  
         throws EmailException
 1112  
     {
 1113  7
         return addReplyTo(email, name, this.charset);
 1114  
     }
 1115  
 
 1116  
     /**
 1117  
      * Add a reply to address to the email using the specified address,
 1118  
      * personal name, and charset encoding for the name.
 1119  
      *
 1120  
      * @param email A String.
 1121  
      * @param name A String.
 1122  
      * @param charset The charset to encode the name with.
 1123  
      * @return An Email.
 1124  
      * @throws EmailException Indicates an invalid email address or charset.
 1125  
      * @since 1.1
 1126  
      */
 1127  
     public Email addReplyTo(String email, String name, String charset)
 1128  
         throws EmailException
 1129  
     {
 1130  11
         this.replyList.add(createInternetAddress(email, name, charset));
 1131  10
         return this;
 1132  
     }
 1133  
 
 1134  
     /**
 1135  
      * Set a list of reply to addresses. All elements in the specified
 1136  
      * <code>Collection</code> are expected to be of type
 1137  
      * <code>java.mail.internet.InternetAddress</code>.
 1138  
      *
 1139  
      * @param   aCollection collection of <code>InternetAddress</code> objects
 1140  
      * @return  An Email.
 1141  
      * @throws EmailException Indicates an invalid email address
 1142  
      * @see javax.mail.internet.InternetAddress
 1143  
      * @since 1.1
 1144  
      */
 1145  
     public Email setReplyTo(Collection<InternetAddress> aCollection) throws EmailException
 1146  
     {
 1147  0
         if (aCollection == null || aCollection.isEmpty())
 1148  
         {
 1149  0
             throw new EmailException("Address List provided was invalid");
 1150  
         }
 1151  
 
 1152  0
         this.replyList = new ArrayList<InternetAddress>(aCollection);
 1153  0
         return this;
 1154  
     }
 1155  
 
 1156  
     /**
 1157  
      * Used to specify the mail headers.  Example:
 1158  
      *
 1159  
      * X-Mailer: Sendmail, X-Priority: 1( highest )
 1160  
      * or  2( high ) 3( normal ) 4( low ) and 5( lowest )
 1161  
      * Disposition-Notification-To: user@domain.net
 1162  
      *
 1163  
      * @param map A Map.
 1164  
      * @throws IllegalArgumentException if either of the provided header / value is null or empty
 1165  
      * @since 1.0
 1166  
      */
 1167  
     public void setHeaders(Map<String, String> map)
 1168  
     {
 1169  4
         this.headers.clear();
 1170  
 
 1171  4
         Iterator<Map.Entry<String, String>> iterKeyBad = map.entrySet().iterator();
 1172  
 
 1173  10
         while (iterKeyBad.hasNext())
 1174  
         {
 1175  8
             Map.Entry<String, String> entry = iterKeyBad.next();
 1176  8
             addHeader(entry.getKey(), entry.getValue());
 1177  6
         }
 1178  2
     }
 1179  
 
 1180  
     /**
 1181  
      * Adds a header ( name, value ) to the headers Map.
 1182  
      *
 1183  
      * @param name A String with the name.
 1184  
      * @param value A String with the value.
 1185  
      * @since 1.0
 1186  
      * @throws IllegalArgumentException if either {@code name} or {@code value} is null or empty
 1187  
      */
 1188  
     public void addHeader(String name, String value)
 1189  
     {
 1190  16
         if (EmailUtils.isEmpty(name))
 1191  
         {
 1192  2
             throw new IllegalArgumentException("name can not be null or empty");
 1193  
         }
 1194  14
         if (EmailUtils.isEmpty(value))
 1195  
         {
 1196  3
             throw new IllegalArgumentException("value can not be null or empty");
 1197  
         }
 1198  
 
 1199  11
         this.headers.put(name, value);
 1200  11
     }
 1201  
 
 1202  
     /**
 1203  
      * Set the email subject.
 1204  
      *
 1205  
      * @param aSubject A String.
 1206  
      * @return An Email.
 1207  
      * @since 1.0
 1208  
      */
 1209  
     public Email setSubject(String aSubject)
 1210  
     {
 1211  49
         this.subject = aSubject;
 1212  49
         return this;
 1213  
     }
 1214  
 
 1215  
     /**
 1216  
      * Set the "bounce address" - the address to which undeliverable messages
 1217  
      * will be returned.  If this value is never set, then the message will be
 1218  
      * sent to the address specified with the System property "mail.smtp.from",
 1219  
      * or if that value is not set, then to the "from" address.
 1220  
      *
 1221  
      * @param email A String.
 1222  
      * @return An Email.
 1223  
      * @throws IllegalStateException when the mail session is already initialized
 1224  
      * @since 1.0
 1225  
      */
 1226  
     public Email setBounceAddress(String email)
 1227  
     {
 1228  13
         checkSessionAlreadyInitialized();
 1229  13
         this.bounceAddress = email;
 1230  13
         return this;
 1231  
     }
 1232  
 
 1233  
 
 1234  
     /**
 1235  
      * Define the content of the mail. It should be overridden by the
 1236  
      * subclasses.
 1237  
      *
 1238  
      * @param msg A String.
 1239  
      * @return An Email.
 1240  
      * @throws EmailException generic exception.
 1241  
      * @since 1.0
 1242  
      */
 1243  
     public abstract Email setMsg(String msg) throws EmailException;
 1244  
 
 1245  
     /**
 1246  
      * Does the work of actually building the MimeMessage. Please note that
 1247  
      * a user rarely calls this method directly and only if he/she is
 1248  
      * interested in the sending the underlying MimeMessage without
 1249  
      * commons-email.
 1250  
      *
 1251  
      * @throws IllegalStateException if the MimeMessage was already built
 1252  
      * @throws EmailException if there was an error.
 1253  
      * @since 1.0
 1254  
      */
 1255  
     public void buildMimeMessage() throws EmailException
 1256  
     {
 1257  56
         if (this.message != null)
 1258  
         {
 1259  
             // [EMAIL-95] we assume that an email is not reused therefore invoking
 1260  
             // buildMimeMessage() more than once is illegal.
 1261  2
             throw new IllegalStateException("The MimeMessage is already built.");
 1262  
         }
 1263  
 
 1264  
         try
 1265  
         {
 1266  54
             this.message = this.createMimeMessage(this.getMailSession());
 1267  
 
 1268  52
             if (EmailUtils.isNotEmpty(this.subject))
 1269  
             {
 1270  42
                 if (EmailUtils.isNotEmpty(this.charset))
 1271  
                 {
 1272  30
                     this.message.setSubject(this.subject, this.charset);
 1273  
                 }
 1274  
                 else
 1275  
                 {
 1276  12
                     this.message.setSubject(this.subject);
 1277  
                 }
 1278  
             }
 1279  
 
 1280  
             // update content type (and encoding)
 1281  52
             this.updateContentType(this.contentType);
 1282  
 
 1283  52
             if (this.content != null)
 1284  
             {
 1285  11
                 this.message.setContent(this.content, this.contentType);
 1286  
             }
 1287  41
             else if (this.emailBody != null)
 1288  
             {
 1289  36
                 if (this.contentType == null)
 1290  
                 {
 1291  36
                     this.message.setContent(this.emailBody);
 1292  
                 }
 1293  
                 else
 1294  
                 {
 1295  0
                     this.message.setContent(this.emailBody, this.contentType);
 1296  
                 }
 1297  
             }
 1298  
             else
 1299  
             {
 1300  5
                 this.message.setContent("", Email.TEXT_PLAIN);
 1301  
             }
 1302  
 
 1303  52
             if (this.fromAddress != null)
 1304  
             {
 1305  51
                 this.message.setFrom(this.fromAddress);
 1306  
             }
 1307  
             else
 1308  
             {
 1309  1
                 if (session.getProperty(MAIL_SMTP_FROM) == null)
 1310  
                 {
 1311  1
                     throw new EmailException("From address required");
 1312  
                 }
 1313  
             }
 1314  
 
 1315  51
             if (this.toList.size() + this.ccList.size() + this.bccList.size() == 0)
 1316  
             {
 1317  1
                 throw new EmailException("At least one receiver address required");
 1318  
             }
 1319  
 
 1320  50
             if (this.toList.size() > 0)
 1321  
             {
 1322  50
                 this.message.setRecipients(
 1323  
                     Message.RecipientType.TO,
 1324  
                     this.toInternetAddressArray(this.toList));
 1325  
             }
 1326  
 
 1327  50
             if (this.ccList.size() > 0)
 1328  
             {
 1329  1
                 this.message.setRecipients(
 1330  
                     Message.RecipientType.CC,
 1331  
                     this.toInternetAddressArray(this.ccList));
 1332  
             }
 1333  
 
 1334  50
             if (this.bccList.size() > 0)
 1335  
             {
 1336  1
                 this.message.setRecipients(
 1337  
                     Message.RecipientType.BCC,
 1338  
                     this.toInternetAddressArray(this.bccList));
 1339  
             }
 1340  
 
 1341  50
             if (this.replyList.size() > 0)
 1342  
             {
 1343  1
                 this.message.setReplyTo(
 1344  
                     this.toInternetAddressArray(this.replyList));
 1345  
             }
 1346  
 
 1347  
 
 1348  50
             if (this.headers.size() > 0)
 1349  
             {
 1350  3
                 Iterator<String> iterHeaderKeys = this.headers.keySet().iterator();
 1351  8
                 while (iterHeaderKeys.hasNext())
 1352  
                 {
 1353  5
                     String name = iterHeaderKeys.next();
 1354  5
                     String value = headers.get(name);
 1355  5
                     String foldedValue = createFoldedHeaderValue(name, value);
 1356  5
                     this.message.addHeader(name, foldedValue);
 1357  5
                 }
 1358  
             }
 1359  
 
 1360  50
             if (this.message.getSentDate() == null)
 1361  
             {
 1362  50
                 this.message.setSentDate(getSentDate());
 1363  
             }
 1364  
 
 1365  50
             if (this.popBeforeSmtp)
 1366  
             {
 1367  0
                 Store store = session.getStore("pop3");
 1368  0
                 store.connect(this.popHost, this.popUsername, this.popPassword);
 1369  
             }
 1370  
         }
 1371  0
         catch (MessagingException me)
 1372  
         {
 1373  0
             throw new EmailException(me);
 1374  50
         }
 1375  50
     }
 1376  
 
 1377  
     /**
 1378  
      * Sends the previously created MimeMessage to the SMTP server.
 1379  
      *
 1380  
      * @return the message id of the underlying MimeMessage
 1381  
      * @throws IllegalArgumentException if the MimeMessage has not been created
 1382  
      * @throws EmailException the sending failed
 1383  
      */
 1384  
     public String sendMimeMessage()
 1385  
        throws EmailException
 1386  
     {
 1387  25
         EmailUtils.notNull(this.message, "MimeMessage has not been created yet");
 1388  
 
 1389  
         try
 1390  
         {
 1391  25
             Transport.send(this.message);
 1392  22
             return this.message.getMessageID();
 1393  
         }
 1394  3
         catch (Throwable t)
 1395  
         {
 1396  3
             String msg = "Sending the email to the following server failed : "
 1397  
                 + this.getHostName()
 1398  
                 + ":"
 1399  
                 + this.getSmtpPort();
 1400  
 
 1401  3
             throw new EmailException(msg, t);
 1402  
         }
 1403  
     }
 1404  
 
 1405  
     /**
 1406  
      * Returns the internal MimeMessage. Please not that the
 1407  
      * MimeMessage is build by the buildMimeMessage() method.
 1408  
      *
 1409  
      * @return the MimeMessage
 1410  
      */
 1411  
     public MimeMessage getMimeMessage()
 1412  
     {
 1413  20
         return this.message;
 1414  
     }
 1415  
 
 1416  
     /**
 1417  
      * Sends the email. Internally we build a MimeMessage
 1418  
      * which is afterwards sent to the SMTP server.
 1419  
      *
 1420  
      * @return the message id of the underlying MimeMessage
 1421  
      * @throws IllegalStateException if the MimeMessage was already built, ie {@link #buildMimeMessage()}
 1422  
      *   was already called
 1423  
      * @throws EmailException the sending failed
 1424  
      */
 1425  
     public String send() throws EmailException
 1426  
     {
 1427  31
         this.buildMimeMessage();
 1428  25
         return this.sendMimeMessage();
 1429  
     }
 1430  
 
 1431  
     /**
 1432  
      * Sets the sent date for the email.  The sent date will default to the
 1433  
      * current date if not explicitly set.
 1434  
      *
 1435  
      * @param date Date to use as the sent date on the email
 1436  
      * @since 1.0
 1437  
      */
 1438  
     public void setSentDate(Date date)
 1439  
     {
 1440  2
         if (date != null)
 1441  
         {
 1442  
             // create a separate instance to keep findbugs happy
 1443  1
             this.sentDate = new Date(date.getTime());
 1444  
         }
 1445  2
     }
 1446  
 
 1447  
     /**
 1448  
      * Gets the sent date for the email.
 1449  
      *
 1450  
      * @return date to be used as the sent date for the email
 1451  
      * @since 1.0
 1452  
      */
 1453  
     public Date getSentDate()
 1454  
     {
 1455  52
         if (this.sentDate == null)
 1456  
         {
 1457  50
             return new Date();
 1458  
         }
 1459  2
         return new Date(this.sentDate.getTime());
 1460  
     }
 1461  
 
 1462  
     /**
 1463  
      * Gets the subject of the email.
 1464  
      *
 1465  
      * @return email subject
 1466  
      */
 1467  
     public String getSubject()
 1468  
     {
 1469  7
         return this.subject;
 1470  
     }
 1471  
 
 1472  
     /**
 1473  
      * Gets the sender of the email.
 1474  
      *
 1475  
      * @return from address
 1476  
      */
 1477  
     public InternetAddress getFromAddress()
 1478  
     {
 1479  2
         return this.fromAddress;
 1480  
     }
 1481  
 
 1482  
     /**
 1483  
      * Gets the host name of the SMTP server,
 1484  
      *
 1485  
      * @return host name
 1486  
      */
 1487  
     public String getHostName()
 1488  
     {
 1489  0
         if (this.session != null)
 1490  
         {
 1491  0
             return this.session.getProperty(MAIL_HOST);
 1492  
         }
 1493  0
         else if (EmailUtils.isNotEmpty(this.hostName))
 1494  
         {
 1495  0
             return this.hostName;
 1496  
         }
 1497  0
         return null;
 1498  
     }
 1499  
 
 1500  
     /**
 1501  
      * Gets the listening port of the SMTP server.
 1502  
      *
 1503  
      * @return smtp port
 1504  
      */
 1505  
     public String getSmtpPort()
 1506  
     {
 1507  5
         if (this.session != null)
 1508  
         {
 1509  3
             return this.session.getProperty(MAIL_PORT);
 1510  
         }
 1511  2
         else if (EmailUtils.isNotEmpty(this.smtpPort))
 1512  
         {
 1513  2
             return this.smtpPort;
 1514  
         }
 1515  0
         return null;
 1516  
     }
 1517  
 
 1518  
     /**
 1519  
      * Gets whether the client is configured to require STARTTLS.
 1520  
      *
 1521  
      * @return true if using STARTTLS for authentication, false otherwise
 1522  
      * @since 1.3
 1523  
      */
 1524  
     public boolean isStartTLSRequired()
 1525  
     {
 1526  50
         return this.startTlsRequired;
 1527  
     }
 1528  
 
 1529  
     /**
 1530  
      * Gets whether the client is configured to try to enable STARTTLS.
 1531  
      *
 1532  
      * @return true if using STARTTLS for authentication, false otherwise
 1533  
      * @since 1.3
 1534  
      */
 1535  
     public boolean isStartTLSEnabled()
 1536  
     {
 1537  99
         return this.startTlsEnabled || tls;
 1538  
     }
 1539  
 
 1540  
     /**
 1541  
      * Gets whether the client is configured to try to enable STARTTLS.
 1542  
      * See EMAIL-105 for reason of deprecation.
 1543  
      *
 1544  
      * @deprecated since 1.3, use isStartTLSEnabled() instead
 1545  
      * @return true if using STARTTLS for authentication, false otherwise
 1546  
      * @since 1.1
 1547  
      */
 1548  
     @Deprecated
 1549  
     public boolean isTLS()
 1550  
     {
 1551  0
         return isStartTLSEnabled();
 1552  
     }
 1553  
 
 1554  
     /**
 1555  
      * Utility to copy List of known InternetAddress objects into an
 1556  
      * array.
 1557  
      *
 1558  
      * @param list A List.
 1559  
      * @return An InternetAddress[].
 1560  
      * @since 1.0
 1561  
      */
 1562  
     protected InternetAddress[] toInternetAddressArray(List<InternetAddress> list)
 1563  
     {
 1564  53
         InternetAddress[] ia = list.toArray(new InternetAddress[list.size()]);
 1565  
 
 1566  53
         return ia;
 1567  
     }
 1568  
 
 1569  
     /**
 1570  
      * Set details regarding "pop3 before smtp" authentication.
 1571  
      *
 1572  
      * @param newPopBeforeSmtp Whether or not to log into pop3 server before sending mail.
 1573  
      * @param newPopHost The pop3 host to use.
 1574  
      * @param newPopUsername The pop3 username.
 1575  
      * @param newPopPassword The pop3 password.
 1576  
      * @since 1.0
 1577  
      */
 1578  
     public void setPopBeforeSmtp(
 1579  
         boolean newPopBeforeSmtp,
 1580  
         String newPopHost,
 1581  
         String newPopUsername,
 1582  
         String newPopPassword)
 1583  
     {
 1584  1
         this.popBeforeSmtp = newPopBeforeSmtp;
 1585  1
         this.popHost = newPopHost;
 1586  1
         this.popUsername = newPopUsername;
 1587  1
         this.popPassword = newPopPassword;
 1588  1
     }
 1589  
 
 1590  
     /**
 1591  
      * Returns whether SSL/TLS encryption for the transport is currently enabled (SMTPS/POPS).
 1592  
      * See EMAIL-105 for reason of deprecation.
 1593  
      *
 1594  
      * @deprecated since 1.3, use isSSLOnConnect() instead
 1595  
      * @return true if SSL enabled for the transport
 1596  
      */
 1597  
     @Deprecated
 1598  
     public boolean isSSL()
 1599  
     {
 1600  0
         return isSSLOnConnect();
 1601  
     }
 1602  
 
 1603  
     /**
 1604  
      * Returns whether SSL/TLS encryption for the transport is currently enabled (SMTPS/POPS).
 1605  
      *
 1606  
      * @return true if SSL enabled for the transport
 1607  
      * @since 1.3
 1608  
      */
 1609  
     public boolean isSSLOnConnect()
 1610  
     {
 1611  100
         return sslOnConnect || ssl;
 1612  
     }
 1613  
 
 1614  
     /**
 1615  
      * Sets whether SSL/TLS encryption should be enabled for the SMTP transport upon connection (SMTPS/POPS).
 1616  
      * See EMAIL-105 for reason of deprecation.
 1617  
      *
 1618  
      * @deprecated since 1.3, use setSSLOnConnect() instead
 1619  
      * @param ssl whether to enable the SSL transport
 1620  
      */
 1621  
     @Deprecated
 1622  
     public void setSSL(boolean ssl)
 1623  
     {
 1624  0
         setSSLOnConnect(ssl);
 1625  0
     }
 1626  
 
 1627  
     /**
 1628  
      * Sets whether SSL/TLS encryption should be enabled for the SMTP transport upon connection (SMTPS/POPS).
 1629  
      *
 1630  
      * @param ssl whether to enable the SSL transport
 1631  
      * @return An Email.
 1632  
      * @since 1.3
 1633  
      */
 1634  
     public Email setSSLOnConnect(boolean ssl)
 1635  
     {
 1636  14
         checkSessionAlreadyInitialized();
 1637  14
         this.sslOnConnect = ssl;
 1638  14
         this.ssl = ssl;
 1639  14
         return this;
 1640  
     }
 1641  
 
 1642  
     /**
 1643  
     * Is the server identity checked as specified by RFC 2595
 1644  
     *
 1645  
     * @return true if the server identity is checked
 1646  
     * @since 1.3
 1647  
     */
 1648  
     public boolean isSSLCheckServerIdentity()
 1649  
     {
 1650  11
         return sslCheckServerIdentity;
 1651  
     }
 1652  
 
 1653  
     /**
 1654  
      * Sets whether the server identity is checked as specified by RFC 2595
 1655  
      *
 1656  
      * @param sslCheckServerIdentity whether to enable server identity check
 1657  
      * @return An Email.
 1658  
      * @since 1.3
 1659  
      */
 1660  
     public Email setSSLCheckServerIdentity(boolean sslCheckServerIdentity)
 1661  
     {
 1662  13
         this.sslCheckServerIdentity = sslCheckServerIdentity;
 1663  13
         return this;
 1664  
     }
 1665  
 
 1666  
     /**
 1667  
      * Returns the current SSL port used by the SMTP transport.
 1668  
      *
 1669  
      * @return the current SSL port used by the SMTP transport
 1670  
      */
 1671  
     public String getSslSmtpPort()
 1672  
     {
 1673  0
         if (this.session != null)
 1674  
         {
 1675  0
             return this.session.getProperty(MAIL_SMTP_SOCKET_FACTORY_PORT);
 1676  
         }
 1677  0
         else if (EmailUtils.isNotEmpty(this.sslSmtpPort))
 1678  
         {
 1679  0
             return this.sslSmtpPort;
 1680  
         }
 1681  0
         return null;
 1682  
     }
 1683  
 
 1684  
     /**
 1685  
      * Sets the SSL port to use for the SMTP transport. Defaults to the standard
 1686  
      * port, 465.
 1687  
      *
 1688  
      * @param sslSmtpPort the SSL port to use for the SMTP transport
 1689  
      */
 1690  
     public void setSslSmtpPort(String sslSmtpPort)
 1691  
     {
 1692  0
         checkSessionAlreadyInitialized();
 1693  0
         this.sslSmtpPort = sslSmtpPort;
 1694  0
     }
 1695  
 
 1696  
     /**
 1697  
      * Get the list of "To" addresses.
 1698  
      *
 1699  
      * @return List addresses
 1700  
      */
 1701  
     public List<InternetAddress> getToAddresses()
 1702  
     {
 1703  40
         return this.toList;
 1704  
     }
 1705  
 
 1706  
     /**
 1707  
      * Get the list of "CC" addresses.
 1708  
      *
 1709  
      * @return List addresses
 1710  
      */
 1711  
     public List<InternetAddress> getCcAddresses()
 1712  
     {
 1713  39
         return this.ccList;
 1714  
     }
 1715  
 
 1716  
     /**
 1717  
      * Get the list of "Bcc" addresses.
 1718  
      *
 1719  
      * @return List addresses
 1720  
      */
 1721  
     public List<InternetAddress> getBccAddresses()
 1722  
     {
 1723  40
         return this.bccList;
 1724  
     }
 1725  
 
 1726  
     /**
 1727  
      * Get the list of "Reply-To" addresses.
 1728  
      *
 1729  
      * @return List addresses
 1730  
      */
 1731  
     public List<InternetAddress> getReplyToAddresses()
 1732  
     {
 1733  6
         return this.replyList;
 1734  
     }
 1735  
 
 1736  
     /**
 1737  
      * Get the socket connection timeout value in milliseconds.
 1738  
      *
 1739  
      * @return the timeout in milliseconds.
 1740  
      * @since 1.2
 1741  
      */
 1742  
     public int getSocketConnectionTimeout()
 1743  
     {
 1744  0
         return this.socketConnectionTimeout;
 1745  
     }
 1746  
 
 1747  
     /**
 1748  
      * Set the socket connection timeout value in milliseconds.
 1749  
      * Default is a 60 second timeout.
 1750  
      *
 1751  
      * @param socketConnectionTimeout the connection timeout
 1752  
      * @since 1.2
 1753  
      */
 1754  
     public void setSocketConnectionTimeout(int socketConnectionTimeout)
 1755  
     {
 1756  0
         checkSessionAlreadyInitialized();
 1757  0
         this.socketConnectionTimeout = socketConnectionTimeout;
 1758  0
     }
 1759  
 
 1760  
     /**
 1761  
      * Get the socket I/O timeout value in milliseconds.
 1762  
      *
 1763  
      * @return the socket I/O timeout
 1764  
      * @since 1.2
 1765  
      */
 1766  
     public int getSocketTimeout()
 1767  
     {
 1768  0
         return this.socketTimeout;
 1769  
     }
 1770  
 
 1771  
     /**
 1772  
      * Set the socket I/O timeout value in milliseconds.
 1773  
      * Default is 60 second timeout.
 1774  
      *
 1775  
      * @param socketTimeout the socket I/O timeout
 1776  
      * @since 1.2
 1777  
      */
 1778  
     public void setSocketTimeout(int socketTimeout)
 1779  
     {
 1780  0
         checkSessionAlreadyInitialized();
 1781  0
         this.socketTimeout = socketTimeout;
 1782  0
     }
 1783  
 
 1784  
     /**
 1785  
      * Factory method to create a customized MimeMessage which can be
 1786  
      * implemented by a derived class, e.g. to set the message id.
 1787  
      *
 1788  
      * @param aSession mail session to be used
 1789  
      * @return the newly created message
 1790  
      */
 1791  
     protected MimeMessage createMimeMessage(Session aSession)
 1792  
     {
 1793  52
         return new MimeMessage(aSession);
 1794  
     }
 1795  
 
 1796  
     /**
 1797  
      * Create a folded header value containing 76 character chunks.
 1798  
      *
 1799  
      * @param name the name of the header
 1800  
      * @param value the value of the header
 1801  
      * @return the folded header value
 1802  
      * @throws IllegalArgumentException if either the name or value is null or empty
 1803  
      */
 1804  
     private String createFoldedHeaderValue(String name, Object value)
 1805  
     {
 1806  
         String result;
 1807  
 
 1808  5
         if (EmailUtils.isEmpty(name))
 1809  
         {
 1810  0
             throw new IllegalArgumentException("name can not be null or empty");
 1811  
         }
 1812  5
         if (value == null || EmailUtils.isEmpty(value.toString()))
 1813  
         {
 1814  0
             throw new IllegalArgumentException("value can not be null or empty");
 1815  
         }
 1816  
 
 1817  
         try
 1818  
         {
 1819  5
             result = MimeUtility.fold(name.length() + 2, MimeUtility.encodeText(value.toString(), this.charset, null));
 1820  
         }
 1821  0
         catch (UnsupportedEncodingException e)
 1822  
         {
 1823  0
             result = value.toString();
 1824  5
         }
 1825  
 
 1826  5
         return result;
 1827  
     }
 1828  
 
 1829  
     /**
 1830  
      * Creates a InternetAddress.
 1831  
      *
 1832  
      * @param email An email address.
 1833  
      * @param name A name.
 1834  
      * @param charsetName The name of the charset to encode the name with.
 1835  
      * @return An internet address.
 1836  
      * @throws EmailException Thrown when the supplied address, name or charset were invalid.
 1837  
      */
 1838  
     private InternetAddress createInternetAddress(String email, String name, String charsetName)
 1839  
         throws EmailException
 1840  
     {
 1841  279
         InternetAddress address = null;
 1842  
 
 1843  
         try
 1844  
         {
 1845  279
             address = new InternetAddress(email);
 1846  
 
 1847  
             // check name input
 1848  163
             if (EmailUtils.isNotEmpty(name))
 1849  
             {
 1850  
                 // check charset input.
 1851  15
                 if (EmailUtils.isEmpty(charsetName))
 1852  
                 {
 1853  5
                     address.setPersonal(name);
 1854  
                 }
 1855  
                 else
 1856  
                 {
 1857  
                     // canonicalize the charset name and make sure
 1858  
                     // the current platform supports it.
 1859  10
                     Charset set = Charset.forName(charsetName);
 1860  5
                     address.setPersonal(name, set.name());
 1861  
                 }
 1862  
             }
 1863  
 
 1864  
             // run sanity check on new InternetAddress object; if this fails
 1865  
             // it will throw AddressException.
 1866  158
             address.validate();
 1867  
         }
 1868  116
         catch (AddressException e)
 1869  
         {
 1870  116
             throw new EmailException(e);
 1871  
         }
 1872  0
         catch (UnsupportedEncodingException e)
 1873  
         {
 1874  0
             throw new EmailException(e);
 1875  158
         }
 1876  158
         return address;
 1877  
     }
 1878  
 
 1879  
     /**
 1880  
      * When a mail session is already initialized setting the
 1881  
      * session properties has no effect. In order to flag the
 1882  
      * problem throw an IllegalStateException.
 1883  
      *
 1884  
      * @throws IllegalStateException when the mail session is already initialized
 1885  
      */
 1886  
     private void checkSessionAlreadyInitialized()
 1887  
     {
 1888  169
         if (this.session != null)
 1889  
         {
 1890  0
             throw new IllegalStateException("The mail session is already initialized");
 1891  
         }
 1892  169
     }
 1893  
 }