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