| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package org.apache.commons.mail; |
| |
| import java.io.UnsupportedEncodingException; |
| import java.nio.charset.Charset; |
| import java.util.ArrayList; |
| import java.util.Collection; |
| import java.util.Date; |
| import java.util.HashMap; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Properties; |
| |
| import javax.mail.Authenticator; |
| import javax.mail.Message; |
| import javax.mail.MessagingException; |
| import javax.mail.Session; |
| import javax.mail.Store; |
| import javax.mail.Transport; |
| import javax.mail.internet.AddressException; |
| import javax.mail.internet.InternetAddress; |
| import javax.mail.internet.MimeMessage; |
| import javax.mail.internet.MimeMultipart; |
| import javax.mail.internet.MimeUtility; |
| import javax.naming.Context; |
| import javax.naming.InitialContext; |
| import javax.naming.NamingException; |
| |
| import org.apache.commons.mail.util.IDNEmailAddressConverter; |
| |
| /** |
| * The base class for all email messages. This class sets the |
| * sender's email & name, receiver's email & name, subject, and the |
| * sent date. |
| * <p> |
| * Subclasses are responsible for setting the message body. |
| * |
| * @since 1.0 |
| */ |
| public abstract class Email |
| { |
| /** @deprecated since 1.3, use {@link EmailConstants#SENDER_EMAIL} instead */ |
| @Deprecated |
| public static final String SENDER_EMAIL = EmailConstants.SENDER_EMAIL; |
| |
| /** @deprecated since 1.3, use {@link EmailConstants#SENDER_NAME} instead */ |
| @Deprecated |
| public static final String SENDER_NAME = EmailConstants.SENDER_NAME; |
| |
| /** @deprecated since 1.3, use {@link EmailConstants#RECEIVER_EMAIL} instead */ |
| @Deprecated |
| public static final String RECEIVER_EMAIL = EmailConstants.RECEIVER_EMAIL; |
| |
| /** @deprecated since 1.3, use {@link EmailConstants#RECEIVER_NAME} instead */ |
| @Deprecated |
| public static final String RECEIVER_NAME = EmailConstants.RECEIVER_NAME; |
| |
| /** @deprecated since 1.3, use {@link EmailConstants#EMAIL_SUBJECT} instead */ |
| @Deprecated |
| public static final String EMAIL_SUBJECT = EmailConstants.EMAIL_SUBJECT; |
| |
| /** @deprecated since 1.3, use {@link EmailConstants#EMAIL_BODY} instead */ |
| @Deprecated |
| public static final String EMAIL_BODY = EmailConstants.EMAIL_BODY; |
| |
| /** @deprecated since 1.3, use {@link EmailConstants#CONTENT_TYPE} instead */ |
| @Deprecated |
| public static final String CONTENT_TYPE = EmailConstants.CONTENT_TYPE; |
| |
| /** @deprecated since 1.3, use {@link EmailConstants#ATTACHMENTS} instead */ |
| @Deprecated |
| public static final String ATTACHMENTS = EmailConstants.ATTACHMENTS; |
| |
| /** @deprecated since 1.3, use {@link EmailConstants#FILE_SERVER} instead */ |
| @Deprecated |
| public static final String FILE_SERVER = EmailConstants.FILE_SERVER; |
| |
| /** @deprecated since 1.3, use {@link EmailConstants#KOI8_R} instead */ |
| @Deprecated |
| public static final String KOI8_R = EmailConstants.KOI8_R; |
| |
| /** @deprecated since 1.3, use {@link EmailConstants#ISO_8859_1} instead */ |
| @Deprecated |
| public static final String ISO_8859_1 = EmailConstants.ISO_8859_1; |
| |
| /** @deprecated since 1.3, use {@link EmailConstants#US_ASCII} instead */ |
| @Deprecated |
| public static final String US_ASCII = EmailConstants.US_ASCII; |
| |
| /** @deprecated since 1.3, use {@link EmailConstants#MAIL_DEBUG} instead */ |
| @Deprecated |
| public static final String MAIL_DEBUG = EmailConstants.MAIL_DEBUG; |
| |
| /** @deprecated since 1.3, use {@link EmailConstants#MAIL_HOST} instead */ |
| @Deprecated |
| public static final String MAIL_HOST = EmailConstants.MAIL_HOST; |
| |
| /** @deprecated since 1.3, use {@link EmailConstants#MAIL_PORT} instead */ |
| @Deprecated |
| public static final String MAIL_PORT = EmailConstants.MAIL_PORT; |
| |
| /** @deprecated since 1.3, use {@link EmailConstants#MAIL_SMTP_FROM} instead */ |
| @Deprecated |
| public static final String MAIL_SMTP_FROM = EmailConstants.MAIL_SMTP_FROM; |
| |
| /** @deprecated since 1.3, use {@link EmailConstants#MAIL_SMTP_AUTH} instead */ |
| @Deprecated |
| public static final String MAIL_SMTP_AUTH = EmailConstants.MAIL_SMTP_AUTH; |
| |
| /** @deprecated since 1.3, use {@link EmailConstants#MAIL_SMTP_USER} instead */ |
| @Deprecated |
| public static final String MAIL_SMTP_USER = EmailConstants.MAIL_SMTP_USER; |
| |
| /** @deprecated since 1.3, use {@link EmailConstants#MAIL_SMTP_PASSWORD} instead */ |
| @Deprecated |
| public static final String MAIL_SMTP_PASSWORD = EmailConstants.MAIL_SMTP_PASSWORD; |
| |
| /** @deprecated since 1.3, use {@link EmailConstants#MAIL_TRANSPORT_PROTOCOL} instead */ |
| @Deprecated |
| public static final String MAIL_TRANSPORT_PROTOCOL = EmailConstants.MAIL_TRANSPORT_PROTOCOL; |
| |
| /** @deprecated since 1.3, use {@link EmailConstants#SMTP} instead */ |
| @Deprecated |
| public static final String SMTP = EmailConstants.SMTP; |
| |
| /** @deprecated since 1.3, use {@link EmailConstants#TEXT_HTML} instead */ |
| @Deprecated |
| public static final String TEXT_HTML = EmailConstants.TEXT_HTML; |
| |
| /** @deprecated since 1.3, use {@link EmailConstants#TEXT_PLAIN} instead */ |
| @Deprecated |
| public static final String TEXT_PLAIN = EmailConstants.TEXT_PLAIN; |
| |
| /** @deprecated since 1.3, use {@link EmailConstants#MAIL_TRANSPORT_TLS} instead */ |
| @Deprecated |
| public static final String MAIL_TRANSPORT_TLS = EmailConstants.MAIL_TRANSPORT_TLS; |
| |
| /** @deprecated since 1.3, use {@link EmailConstants#MAIL_SMTP_SOCKET_FACTORY_FALLBACK} instead */ |
| @Deprecated |
| public static final String MAIL_SMTP_SOCKET_FACTORY_FALLBACK = EmailConstants.MAIL_SMTP_SOCKET_FACTORY_FALLBACK; |
| |
| /** @deprecated since 1.3, use {@link EmailConstants#MAIL_SMTP_SOCKET_FACTORY_CLASS} instead */ |
| @Deprecated |
| public static final String MAIL_SMTP_SOCKET_FACTORY_CLASS = EmailConstants.MAIL_SMTP_SOCKET_FACTORY_CLASS; |
| |
| /** @deprecated since 1.3, use {@link EmailConstants#MAIL_SMTP_SOCKET_FACTORY_PORT} instead */ |
| @Deprecated |
| public static final String MAIL_SMTP_SOCKET_FACTORY_PORT = EmailConstants.MAIL_SMTP_SOCKET_FACTORY_PORT; |
| |
| /** @deprecated since 1.3, use {@link EmailConstants#MAIL_SMTP_CONNECTIONTIMEOUT} instead */ |
| @Deprecated |
| public static final String MAIL_SMTP_CONNECTIONTIMEOUT = EmailConstants.MAIL_SMTP_CONNECTIONTIMEOUT; |
| |
| /** @deprecated since 1.3, use {@link EmailConstants#MAIL_SMTP_TIMEOUT} instead */ |
| @Deprecated |
| public static final String MAIL_SMTP_TIMEOUT = EmailConstants.MAIL_SMTP_TIMEOUT; |
| |
| /** The email message to send. */ |
| protected MimeMessage message; |
| |
| /** The charset to use for this message. */ |
| protected String charset; |
| |
| /** The Address of the sending party, mandatory. */ |
| protected InternetAddress fromAddress; |
| |
| /** The Subject. */ |
| protected String subject; |
| |
| /** An attachment. */ |
| protected MimeMultipart emailBody; |
| |
| /** The content. */ |
| protected Object content; |
| |
| /** The content type. */ |
| protected String contentType; |
| |
| /** Set session debugging on or off. */ |
| protected boolean debug; |
| |
| /** Sent date. */ |
| protected Date sentDate; |
| |
| /** |
| * Instance of an {@code Authenticator} object that will be used |
| * when authentication is requested from the mail server. |
| */ |
| protected Authenticator authenticator; |
| |
| /** |
| * The hostname of the mail server with which to connect. If null will try |
| * to get property from system.properties. If still null, quit. |
| */ |
| protected String hostName; |
| |
| /** |
| * The port number of the mail server to connect to. |
| * Defaults to the standard port ( 25 ). |
| */ |
| protected String smtpPort = "25"; |
| |
| /** |
| * The port number of the SSL enabled SMTP server; |
| * defaults to the standard port, 465. |
| */ |
| protected String sslSmtpPort = "465"; |
| |
| /** List of "to" email addresses. */ |
| protected List<InternetAddress> toList = new ArrayList<InternetAddress>(); |
| |
| /** List of "cc" email addresses. */ |
| protected List<InternetAddress> ccList = new ArrayList<InternetAddress>(); |
| |
| /** List of "bcc" email addresses. */ |
| protected List<InternetAddress> bccList = new ArrayList<InternetAddress>(); |
| |
| /** List of "replyTo" email addresses. */ |
| protected List<InternetAddress> replyList = new ArrayList<InternetAddress>(); |
| |
| /** |
| * Address to which undeliverable mail should be sent. |
| * Because this is handled by JavaMail as a String property |
| * in the mail session, this property is of type {@code String} |
| * rather than {@code InternetAddress}. |
| */ |
| protected String bounceAddress; |
| |
| /** |
| * Used to specify the mail headers. Example: |
| * |
| * X-Mailer: Sendmail, X-Priority: 1( highest ) |
| * or 2( high ) 3( normal ) 4( low ) and 5( lowest ) |
| * Disposition-Notification-To: user@domain.net |
| */ |
| protected Map<String, String> headers = new HashMap<String, String>(); |
| |
| /** |
| * Used to determine whether to use pop3 before smtp, and if so the settings. |
| */ |
| protected boolean popBeforeSmtp; |
| |
| /** the host name of the pop3 server. */ |
| protected String popHost; |
| |
| /** the user name to log into the pop3 server. */ |
| protected String popUsername; |
| |
| /** the password to log into the pop3 server. */ |
| protected String popPassword; |
| |
| /** |
| * Does server require TLS encryption for authentication? |
| * @deprecated since 1.3, use setStartTLSEnabled() instead |
| */ |
| @Deprecated |
| protected boolean tls; |
| |
| /** |
| * Does the current transport use SSL/TLS encryption upon connection? |
| * @deprecated since 1.3, use setSSLOnConnect() instead |
| */ |
| @Deprecated |
| protected boolean ssl; |
| |
| /** socket I/O timeout value in milliseconds. */ |
| protected int socketTimeout = EmailConstants.SOCKET_TIMEOUT_MS; |
| |
| /** socket connection timeout value in milliseconds. */ |
| protected int socketConnectionTimeout = EmailConstants.SOCKET_TIMEOUT_MS; |
| |
| /** |
| * If true, enables the use of the STARTTLS command (if supported by |
| * the server) to switch the connection to a TLS-protected connection |
| * before issuing any login commands. Note that an appropriate trust |
| * store must configured so that the client will trust the server's |
| * certificate. |
| * Defaults to false. |
| */ |
| private boolean startTlsEnabled; |
| |
| /** |
| * If true, requires the use of the STARTTLS command. If the server doesn't |
| * support the STARTTLS command, or the command fails, the connect method |
| * will fail. |
| * Defaults to false. |
| */ |
| private boolean startTlsRequired; |
| |
| /** does the current transport use SSL/TLS encryption upon connection? */ |
| private boolean sslOnConnect; |
| |
| /** |
| * If set to true, check the server identity as specified by RFC 2595. These |
| * additional checks based on the content of the server's certificate are |
| * intended to prevent man-in-the-middle attacks. |
| * Defaults to false. |
| */ |
| private boolean sslCheckServerIdentity; |
| |
| /** |
| * If set to true, and a message has some valid and some invalid addresses, send the message anyway, |
| * reporting the partial failure with a SendFailedException. |
| * If set to false (the default), the message is not sent to any of the recipients |
| * if there is an invalid recipient address. |
| * Defaults to false. |
| */ |
| private boolean sendPartial; |
| |
| /** The Session to mail with. */ |
| private Session session; |
| |
| /** |
| * Setting to true will enable the display of debug information. |
| * |
| * @param d A boolean. |
| * @since 1.0 |
| */ |
| public void setDebug(final boolean d) |
| { |
| this.debug = d; |
| } |
| |
| /** |
| * Sets the userName and password if authentication is needed. If this |
| * method is not used, no authentication will be performed. |
| * <p> |
| * This method will create a new instance of |
| * {@code DefaultAuthenticator} using the supplied parameters. |
| * |
| * @param userName User name for the SMTP server |
| * @param password password for the SMTP server |
| * @see DefaultAuthenticator |
| * @see #setAuthenticator |
| * @since 1.0 |
| */ |
| public void setAuthentication(final String userName, final String password) |
| { |
| this.setAuthenticator(new DefaultAuthenticator(userName, password)); |
| } |
| |
| /** |
| * Sets the {@code Authenticator} to be used when authentication |
| * is requested from the mail server. |
| * <p> |
| * This method should be used when your outgoing mail server requires |
| * authentication. Your mail server must also support RFC2554. |
| * |
| * @param newAuthenticator the {@code Authenticator} object. |
| * @see Authenticator |
| * @since 1.0 |
| */ |
| public void setAuthenticator(final Authenticator newAuthenticator) |
| { |
| this.authenticator = newAuthenticator; |
| } |
| |
| /** |
| * Set the charset of the message. Please note that you should set the charset before |
| * adding the message content. |
| * |
| * @param newCharset A String. |
| * @throws java.nio.charset.IllegalCharsetNameException if the charset name is invalid |
| * @throws java.nio.charset.UnsupportedCharsetException if no support for the named charset |
| * exists in the current JVM |
| * @since 1.0 |
| */ |
| public void setCharset(final String newCharset) |
| { |
| final Charset set = Charset.forName(newCharset); |
| this.charset = set.name(); |
| } |
| |
| /** |
| * Set the emailBody to a MimeMultiPart |
| * |
| * @param aMimeMultipart aMimeMultipart |
| * @since 1.0 |
| */ |
| public void setContent(final MimeMultipart aMimeMultipart) |
| { |
| this.emailBody = aMimeMultipart; |
| } |
| |
| /** |
| * Set the content and contentType. |
| * |
| * @param aObject aObject |
| * @param aContentType aContentType |
| * @since 1.0 |
| */ |
| public void setContent(final Object aObject, final String aContentType) |
| { |
| this.content = aObject; |
| this.updateContentType(aContentType); |
| } |
| |
| /** |
| * Update the contentType. |
| * |
| * @param aContentType aContentType |
| * @since 1.2 |
| */ |
| public void updateContentType(final String aContentType) |
| { |
| if (EmailUtils.isEmpty(aContentType)) |
| { |
| this.contentType = null; |
| } |
| else |
| { |
| // set the content type |
| this.contentType = aContentType; |
| |
| // set the charset if the input was properly formed |
| final String strMarker = "; charset="; |
| int charsetPos = aContentType.toLowerCase().indexOf(strMarker); |
| |
| if (charsetPos != -1) |
| { |
| // find the next space (after the marker) |
| charsetPos += strMarker.length(); |
| final int intCharsetEnd = |
| aContentType.toLowerCase().indexOf(" ", charsetPos); |
| |
| if (intCharsetEnd != -1) |
| { |
| this.charset = |
| aContentType.substring(charsetPos, intCharsetEnd); |
| } |
| else |
| { |
| this.charset = aContentType.substring(charsetPos); |
| } |
| } |
| else |
| { |
| // use the default charset, if one exists, for messages |
| // whose content-type is some form of text. |
| if (this.contentType.startsWith("text/") && EmailUtils.isNotEmpty(this.charset)) |
| { |
| final StringBuffer contentTypeBuf = new StringBuffer(this.contentType); |
| contentTypeBuf.append(strMarker); |
| contentTypeBuf.append(this.charset); |
| this.contentType = contentTypeBuf.toString(); |
| } |
| } |
| } |
| } |
| |
| /** |
| * Set the hostname of the outgoing mail server. |
| * |
| * @param aHostName aHostName |
| * @throws IllegalStateException if the mail session is already initialized |
| * @since 1.0 |
| */ |
| public void setHostName(final String aHostName) |
| { |
| checkSessionAlreadyInitialized(); |
| this.hostName = aHostName; |
| } |
| |
| /** |
| * Set or disable the STARTTLS encryption. Please see EMAIL-105 |
| * for the reasons of deprecation. |
| * |
| * @deprecated since 1.3, use setStartTLSEnabled() instead |
| * @param withTLS true if STARTTLS requested, false otherwise |
| * @since 1.1 |
| */ |
| @Deprecated |
| public void setTLS(final boolean withTLS) |
| { |
| setStartTLSEnabled(withTLS); |
| } |
| |
| /** |
| * Set or disable the STARTTLS encryption. |
| * |
| * @param startTlsEnabled true if STARTTLS requested, false otherwise |
| * @return An Email. |
| * @throws IllegalStateException if the mail session is already initialized |
| * @since 1.3 |
| */ |
| public Email setStartTLSEnabled(final boolean startTlsEnabled) |
| { |
| checkSessionAlreadyInitialized(); |
| this.startTlsEnabled = startTlsEnabled; |
| this.tls = startTlsEnabled; |
| return this; |
| } |
| |
| /** |
| * Set or disable the required STARTTLS encryption. |
| * <p> |
| * Defaults to {@link #smtpPort}; can be overridden by using {@link #setSmtpPort(int)} |
| * |
| * @param startTlsRequired true if STARTTLS requested, false otherwise |
| * @return An Email. |
| * @throws IllegalStateException if the mail session is already initialized |
| * @since 1.3 |
| */ |
| public Email setStartTLSRequired(final boolean startTlsRequired) |
| { |
| checkSessionAlreadyInitialized(); |
| this.startTlsRequired = startTlsRequired; |
| return this; |
| } |
| |
| /** |
| * Set the non-SSL port number of the outgoing mail server. |
| * |
| * @param aPortNumber aPortNumber |
| * @throws IllegalArgumentException if the port number is < 1 |
| * @throws IllegalStateException if the mail session is already initialized |
| * @since 1.0 |
| * @see #setSslSmtpPort(String) |
| */ |
| public void setSmtpPort(final int aPortNumber) |
| { |
| checkSessionAlreadyInitialized(); |
| |
| if (aPortNumber < 1) |
| { |
| throw new IllegalArgumentException( |
| "Cannot connect to a port number that is less than 1 ( " |
| + aPortNumber |
| + " )"); |
| } |
| |
| this.smtpPort = Integer.toString(aPortNumber); |
| } |
| |
| /** |
| * Supply a mail Session object to use. Please note that passing |
| * a user name and password (in the case of mail authentication) will |
| * create a new mail session with a DefaultAuthenticator. This is a |
| * convenience but might come unexpected. |
| * |
| * If mail authentication is used but NO username and password |
| * is supplied the implementation assumes that you have set a |
| * authenticator and will use the existing mail session (as expected). |
| * |
| * @param aSession mail session to be used |
| * @throws IllegalArgumentException if the session is {@code null} |
| * @since 1.0 |
| */ |
| public void setMailSession(final Session aSession) |
| { |
| EmailUtils.notNull(aSession, "no mail session supplied"); |
| |
| final Properties sessionProperties = aSession.getProperties(); |
| final String auth = sessionProperties.getProperty(EmailConstants.MAIL_SMTP_AUTH); |
| |
| if ("true".equalsIgnoreCase(auth)) |
| { |
| final String userName = sessionProperties.getProperty(EmailConstants.MAIL_SMTP_USER); |
| final String password = sessionProperties.getProperty(EmailConstants.MAIL_SMTP_PASSWORD); |
| |
| if (EmailUtils.isNotEmpty(userName) && EmailUtils.isNotEmpty(password)) |
| { |
| // only create a new mail session with an authenticator if |
| // authentication is required and no user name is given |
| this.authenticator = new DefaultAuthenticator(userName, password); |
| this.session = Session.getInstance(sessionProperties, this.authenticator); |
| } |
| else |
| { |
| // assume that the given mail session contains a working authenticator |
| this.session = aSession; |
| } |
| } |
| else |
| { |
| this.session = aSession; |
| } |
| } |
| |
| /** |
| * Supply a mail Session object from a JNDI directory. |
| * |
| * @param jndiName name of JNDI resource (javax.mail.Session type), resource |
| * if searched in java:comp/env if name does not start with "java:" |
| * @throws IllegalArgumentException if the JNDI name is null or empty |
| * @throws NamingException if the resource cannot be retrieved from JNDI directory |
| * @since 1.1 |
| */ |
| public void setMailSessionFromJNDI(final String jndiName) throws NamingException |
| { |
| if (EmailUtils.isEmpty(jndiName)) |
| { |
| throw new IllegalArgumentException("JNDI name missing"); |
| } |
| Context ctx = null; |
| if (jndiName.startsWith("java:")) |
| { |
| ctx = new InitialContext(); |
| } |
| else |
| { |
| ctx = (Context) new InitialContext().lookup("java:comp/env"); |
| |
| } |
| this.setMailSession((Session) ctx.lookup(jndiName)); |
| } |
| |
| /** |
| * Determines the mail session used when sending this Email, creating |
| * the Session if necessary. When a mail session is already |
| * initialized setting the session related properties will cause |
| * an IllegalStateException. |
| * |
| * @return A Session. |
| * @throws EmailException if the host name was not set |
| * @since 1.0 |
| */ |
| public Session getMailSession() throws EmailException |
| { |
| if (this.session == null) |
| { |
| final Properties properties = new Properties(System.getProperties()); |
| properties.setProperty(EmailConstants.MAIL_TRANSPORT_PROTOCOL, EmailConstants.SMTP); |
| |
| if (EmailUtils.isEmpty(this.hostName)) |
| { |
| this.hostName = properties.getProperty(EmailConstants.MAIL_HOST); |
| } |
| |
| if (EmailUtils.isEmpty(this.hostName)) |
| { |
| throw new EmailException("Cannot find valid hostname for mail session"); |
| } |
| |
| properties.setProperty(EmailConstants.MAIL_PORT, this.smtpPort); |
| properties.setProperty(EmailConstants.MAIL_HOST, this.hostName); |
| properties.setProperty(EmailConstants.MAIL_DEBUG, String.valueOf(this.debug)); |
| |
| properties.setProperty(EmailConstants.MAIL_TRANSPORT_STARTTLS_ENABLE, |
| isStartTLSEnabled() ? "true" : "false"); |
| properties.setProperty(EmailConstants.MAIL_TRANSPORT_STARTTLS_REQUIRED, |
| isStartTLSRequired() ? "true" : "false"); |
| |
| properties.setProperty(EmailConstants.MAIL_SMTP_SEND_PARTIAL, |
| isSendPartial() ? "true" : "false"); |
| properties.setProperty(EmailConstants.MAIL_SMTPS_SEND_PARTIAL, |
| isSendPartial() ? "true" : "false"); |
| |
| if (this.authenticator != null) |
| { |
| properties.setProperty(EmailConstants.MAIL_SMTP_AUTH, "true"); |
| } |
| |
| if (isSSLOnConnect()) |
| { |
| properties.setProperty(EmailConstants.MAIL_PORT, this.sslSmtpPort); |
| properties.setProperty(EmailConstants.MAIL_SMTP_SOCKET_FACTORY_PORT, this.sslSmtpPort); |
| properties.setProperty(EmailConstants.MAIL_SMTP_SOCKET_FACTORY_CLASS, "javax.net.ssl.SSLSocketFactory"); |
| properties.setProperty(EmailConstants.MAIL_SMTP_SOCKET_FACTORY_FALLBACK, "false"); |
| } |
| |
| if ((isSSLOnConnect() || isStartTLSEnabled()) && isSSLCheckServerIdentity()) |
| { |
| properties.setProperty(EmailConstants.MAIL_SMTP_SSL_CHECKSERVERIDENTITY, "true"); |
| } |
| |
| if (this.bounceAddress != null) |
| { |
| properties.setProperty(EmailConstants.MAIL_SMTP_FROM, this.bounceAddress); |
| } |
| |
| if (this.socketTimeout > 0) |
| { |
| properties.setProperty(EmailConstants.MAIL_SMTP_TIMEOUT, Integer.toString(this.socketTimeout)); |
| } |
| |
| if (this.socketConnectionTimeout > 0) |
| { |
| properties.setProperty(EmailConstants.MAIL_SMTP_CONNECTIONTIMEOUT, Integer.toString(this.socketConnectionTimeout)); |
| } |
| |
| // changed this (back) to getInstance due to security exceptions |
| // caused when testing using maven |
| this.session = Session.getInstance(properties, this.authenticator); |
| } |
| return this.session; |
| } |
| |
| /** |
| * Set the FROM field of the email to use the specified address. The email |
| * address will also be used as the personal name. |
| * The name will be encoded by the charset of {@link #setCharset(java.lang.String) setCharset()}. |
| * If it is not set, it will be encoded using |
| * the Java platform's default charset (UTF-16) if it contains |
| * non-ASCII characters; otherwise, it is used as is. |
| * |
| * @param email A String. |
| * @return An Email. |
| * @throws EmailException Indicates an invalid email address. |
| * @since 1.0 |
| */ |
| public Email setFrom(final String email) |
| throws EmailException |
| { |
| return setFrom(email, null); |
| } |
| |
| /** |
| * Set the FROM field of the email to use the specified address and the |
| * specified personal name. |
| * The name will be encoded by the charset of {@link #setCharset(java.lang.String) setCharset()}. |
| * If it is not set, it will be encoded using |
| * the Java platform's default charset (UTF-16) if it contains |
| * non-ASCII characters; otherwise, it is used as is. |
| * |
| * @param email A String. |
| * @param name A String. |
| * @return An Email. |
| * @throws EmailException Indicates an invalid email address. |
| * @since 1.0 |
| */ |
| public Email setFrom(final String email, final String name) |
| throws EmailException |
| { |
| return setFrom(email, name, this.charset); |
| } |
| |
| /** |
| * Set the FROM field of the email to use the specified address, personal |
| * name, and charset encoding for the name. |
| * |
| * @param email A String. |
| * @param name A String. |
| * @param charset The charset to encode the name with. |
| * @return An Email. |
| * @throws EmailException Indicates an invalid email address or charset. |
| * @since 1.1 |
| */ |
| public Email setFrom(final String email, final String name, final String charset) |
| throws EmailException |
| { |
| this.fromAddress = createInternetAddress(email, name, charset); |
| return this; |
| } |
| |
| /** |
| * Add a recipient TO to the email. The email |
| * address will also be used as the personal name. |
| * The name will be encoded by the charset of |
| * {@link #setCharset(java.lang.String) setCharset()}. |
| * If it is not set, it will be encoded using |
| * the Java platform's default charset (UTF-16) if it contains |
| * non-ASCII characters; otherwise, it is used as is. |
| * |
| * @param email A String. |
| * @return An Email. |
| * @throws EmailException Indicates an invalid email address. |
| * @since 1.0 |
| */ |
| public Email addTo(final String email) |
| throws EmailException |
| { |
| return addTo(email, null); |
| } |
| |
| /** |
| * Add a list of TO recipients to the email. The email |
| * addresses will also be used as the personal names. |
| * The names will be encoded by the charset of |
| * {@link #setCharset(java.lang.String) setCharset()}. |
| * If it is not set, it will be encoded using |
| * the Java platform's default charset (UTF-16) if it contains |
| * non-ASCII characters; otherwise, it is used as is. |
| * |
| * @param emails A String array. |
| * @return An Email. |
| * @throws EmailException Indicates an invalid email address. |
| * @since 1.3 |
| */ |
| public Email addTo(final String... emails) |
| throws EmailException |
| { |
| if (emails == null || emails.length == 0) |
| { |
| throw new EmailException("Address List provided was invalid"); |
| } |
| |
| for (final String email : emails) |
| { |
| addTo(email, null); |
| } |
| |
| return this; |
| } |
| |
| /** |
| * Add a recipient TO to the email using the specified address and the |
| * specified personal name. |
| * The name will be encoded by the charset of |
| * {@link #setCharset(java.lang.String) setCharset()}. |
| * If it is not set, it will be encoded using |
| * the Java platform's default charset (UTF-16) if it contains |
| * non-ASCII characters; otherwise, it is used as is. |
| * |
| * @param email A String. |
| * @param name A String. |
| * @return An Email. |
| * @throws EmailException Indicates an invalid email address. |
| * @since 1.0 |
| */ |
| public Email addTo(final String email, final String name) |
| throws EmailException |
| { |
| return addTo(email, name, this.charset); |
| } |
| |
| /** |
| * Add a recipient TO to the email using the specified address, personal |
| * name, and charset encoding for the name. |
| * |
| * @param email A String. |
| * @param name A String. |
| * @param charset The charset to encode the name with. |
| * @return An Email. |
| * @throws EmailException Indicates an invalid email address or charset. |
| * @since 1.1 |
| */ |
| public Email addTo(final String email, final String name, final String charset) |
| throws EmailException |
| { |
| this.toList.add(createInternetAddress(email, name, charset)); |
| return this; |
| } |
| |
| /** |
| * Set a list of "TO" addresses. All elements in the specified |
| * {@code Collection} are expected to be of type |
| * {@code java.mail.internet.InternetAddress}. |
| * |
| * @param aCollection collection of {@code InternetAddress} objects. |
| * @return An Email. |
| * @throws EmailException Indicates an invalid email address. |
| * @see javax.mail.internet.InternetAddress |
| * @since 1.0 |
| */ |
| public Email setTo(final Collection<InternetAddress> aCollection) throws EmailException |
| { |
| if (aCollection == null || aCollection.isEmpty()) |
| { |
| throw new EmailException("Address List provided was invalid"); |
| } |
| |
| this.toList = new ArrayList<InternetAddress>(aCollection); |
| return this; |
| } |
| |
| /** |
| * Add a recipient CC to the email. The email |
| * address will also be used as the personal name. |
| * The name will be encoded by the charset of {@link #setCharset(java.lang.String) setCharset()}. |
| * If it is not set, it will be encoded using |
| * the Java platform's default charset (UTF-16) if it contains |
| * non-ASCII characters; otherwise, it is used as is. |
| * |
| * @param email A String. |
| * @return An Email. |
| * @throws EmailException Indicates an invalid email address. |
| * @since 1.0 |
| */ |
| public Email addCc(final String email) |
| throws EmailException |
| { |
| return this.addCc(email, null); |
| } |
| |
| /** |
| * Add an array of CC recipients to the email. The email |
| * addresses will also be used as the personal name. |
| * The names will be encoded by the charset of |
| * {@link #setCharset(java.lang.String) setCharset()}. |
| * If it is not set, it will be encoded using |
| * the Java platform's default charset (UTF-16) if it contains |
| * non-ASCII characters; otherwise, it is used as is. |
| * |
| * @param emails A String array. |
| * @return An Email. |
| * @throws EmailException Indicates an invalid email address. |
| * @since 1.3 |
| */ |
| public Email addCc(final String... emails) |
| throws EmailException |
| { |
| if (emails == null || emails.length == 0) |
| { |
| throw new EmailException("Address List provided was invalid"); |
| } |
| |
| for (final String email : emails) |
| { |
| addCc(email, null); |
| } |
| |
| return this; |
| } |
| |
| /** |
| * Add a recipient CC to the email using the specified address and the |
| * specified personal name. |
| * The name will be encoded by the charset of {@link #setCharset(java.lang.String) setCharset()}. |
| * If it is not set, it will be encoded using |
| * the Java platform's default charset (UTF-16) if it contains |
| * non-ASCII characters; otherwise, it is used as is. |
| * |
| * @param email A String. |
| * @param name A String. |
| * @return An Email. |
| * @throws EmailException Indicates an invalid email address. |
| * @since 1.0 |
| */ |
| public Email addCc(final String email, final String name) |
| throws EmailException |
| { |
| return addCc(email, name, this.charset); |
| } |
| |
| /** |
| * Add a recipient CC to the email using the specified address, personal |
| * name, and charset encoding for the name. |
| * |
| * @param email A String. |
| * @param name A String. |
| * @param charset The charset to encode the name with. |
| * @return An Email. |
| * @throws EmailException Indicates an invalid email address or charset. |
| * @since 1.1 |
| */ |
| public Email addCc(final String email, final String name, final String charset) |
| throws EmailException |
| { |
| this.ccList.add(createInternetAddress(email, name, charset)); |
| return this; |
| } |
| |
| /** |
| * Set a list of "CC" addresses. All elements in the specified |
| * {@code Collection} are expected to be of type |
| * {@code java.mail.internet.InternetAddress}. |
| * |
| * @param aCollection collection of {@code InternetAddress} objects. |
| * @return An Email. |
| * @throws EmailException Indicates an invalid email address. |
| * @see javax.mail.internet.InternetAddress |
| * @since 1.0 |
| */ |
| public Email setCc(final Collection<InternetAddress> aCollection) throws EmailException |
| { |
| if (aCollection == null || aCollection.isEmpty()) |
| { |
| throw new EmailException("Address List provided was invalid"); |
| } |
| |
| this.ccList = new ArrayList<InternetAddress>(aCollection); |
| return this; |
| } |
| |
| /** |
| * Add a blind BCC recipient to the email. The email |
| * address will also be used as the personal name. |
| * The name will be encoded by the charset of {@link #setCharset(java.lang.String) setCharset()}. |
| * If it is not set, it will be encoded using |
| * the Java platform's default charset (UTF-16) if it contains |
| * non-ASCII characters; otherwise, it is used as is. |
| * |
| * @param email A String. |
| * @return An Email. |
| * @throws EmailException Indicates an invalid email address |
| * @since 1.0 |
| */ |
| public Email addBcc(final String email) |
| throws EmailException |
| { |
| return this.addBcc(email, null); |
| } |
| |
| /** |
| * Add an array of blind BCC recipients to the email. The email |
| * addresses will also be used as the personal name. |
| * The names will be encoded by the charset of |
| * {@link #setCharset(java.lang.String) setCharset()}. |
| * If it is not set, it will be encoded using |
| * the Java platform's default charset (UTF-16) if it contains |
| * non-ASCII characters; otherwise, it is used as is. |
| * |
| * @param emails A String array. |
| * @return An Email. |
| * @throws EmailException Indicates an invalid email address |
| * @since 1.3 |
| */ |
| public Email addBcc(final String... emails) |
| throws EmailException |
| { |
| if (emails == null || emails.length == 0) |
| { |
| throw new EmailException("Address List provided was invalid"); |
| } |
| |
| for (final String email : emails) |
| { |
| addBcc(email, null); |
| } |
| |
| return this; |
| } |
| |
| /** |
| * Add a blind BCC recipient to the email using the specified address and |
| * the specified personal name. |
| * The name will be encoded by the charset of {@link #setCharset(java.lang.String) setCharset()}. |
| * If it is not set, it will be encoded using |
| * the Java platform's default charset (UTF-16) if it contains |
| * non-ASCII characters; otherwise, it is used as is. |
| * |
| * @param email A String. |
| * @param name A String. |
| * @return An Email. |
| * @throws EmailException Indicates an invalid email address |
| * @since 1.0 |
| */ |
| public Email addBcc(final String email, final String name) |
| throws EmailException |
| { |
| return addBcc(email, name, this.charset); |
| } |
| |
| /** |
| * Add a blind BCC recipient to the email using the specified address, |
| * personal name, and charset encoding for the name. |
| * |
| * @param email A String. |
| * @param name A String. |
| * @param charset The charset to encode the name with. |
| * @return An Email. |
| * @throws EmailException Indicates an invalid email address |
| * @since 1.1 |
| */ |
| public Email addBcc(final String email, final String name, final String charset) |
| throws EmailException |
| { |
| this.bccList.add(createInternetAddress(email, name, charset)); |
| return this; |
| } |
| |
| /** |
| * Set a list of "BCC" addresses. All elements in the specified |
| * {@code Collection} are expected to be of type |
| * {@code java.mail.internet.InternetAddress}. |
| * |
| * @param aCollection collection of {@code InternetAddress} objects |
| * @return An Email. |
| * @throws EmailException Indicates an invalid email address |
| * @see javax.mail.internet.InternetAddress |
| * @since 1.0 |
| */ |
| public Email setBcc(final Collection<InternetAddress> aCollection) throws EmailException |
| { |
| if (aCollection == null || aCollection.isEmpty()) |
| { |
| throw new EmailException("Address List provided was invalid"); |
| } |
| |
| this.bccList = new ArrayList<InternetAddress>(aCollection); |
| return this; |
| } |
| |
| /** |
| * Add a reply to address to the email. The email |
| * address will also be used as the personal name. |
| * The name will be encoded by the charset of {@link #setCharset(java.lang.String) setCharset()}. |
| * If it is not set, it will be encoded using |
| * the Java platform's default charset (UTF-16) if it contains |
| * non-ASCII characters; otherwise, it is used as is. |
| * |
| * @param email A String. |
| * @return An Email. |
| * @throws EmailException Indicates an invalid email address |
| * @since 1.0 |
| */ |
| public Email addReplyTo(final String email) |
| throws EmailException |
| { |
| return this.addReplyTo(email, null); |
| } |
| |
| /** |
| * Add a reply to address to the email using the specified address and |
| * the specified personal name. |
| * The name will be encoded by the charset of {@link #setCharset(java.lang.String) setCharset()}. |
| * If it is not set, it will be encoded using |
| * the Java platform's default charset (UTF-16) if it contains |
| * non-ASCII characters; otherwise, it is used as is. |
| * |
| * @param email A String. |
| * @param name A String. |
| * @return An Email. |
| * @throws EmailException Indicates an invalid email address |
| * @since 1.0 |
| */ |
| public Email addReplyTo(final String email, final String name) |
| throws EmailException |
| { |
| return addReplyTo(email, name, this.charset); |
| } |
| |
| /** |
| * Add a reply to address to the email using the specified address, |
| * personal name, and charset encoding for the name. |
| * |
| * @param email A String. |
| * @param name A String. |
| * @param charset The charset to encode the name with. |
| * @return An Email. |
| * @throws EmailException Indicates an invalid email address or charset. |
| * @since 1.1 |
| */ |
| public Email addReplyTo(final String email, final String name, final String charset) |
| throws EmailException |
| { |
| this.replyList.add(createInternetAddress(email, name, charset)); |
| return this; |
| } |
| |
| /** |
| * Set a list of reply to addresses. All elements in the specified |
| * {@code Collection} are expected to be of type |
| * {@code java.mail.internet.InternetAddress}. |
| * |
| * @param aCollection collection of {@code InternetAddress} objects |
| * @return An Email. |
| * @throws EmailException Indicates an invalid email address |
| * @see javax.mail.internet.InternetAddress |
| * @since 1.1 |
| */ |
| public Email setReplyTo(final Collection<InternetAddress> aCollection) throws EmailException |
| { |
| if (aCollection == null || aCollection.isEmpty()) |
| { |
| throw new EmailException("Address List provided was invalid"); |
| } |
| |
| this.replyList = new ArrayList<InternetAddress>(aCollection); |
| return this; |
| } |
| |
| /** |
| * Used to specify the mail headers. Example: |
| * |
| * X-Mailer: Sendmail, X-Priority: 1( highest ) |
| * or 2( high ) 3( normal ) 4( low ) and 5( lowest ) |
| * Disposition-Notification-To: user@domain.net |
| * |
| * @param map A Map. |
| * @throws IllegalArgumentException if either of the provided header / value is null or empty |
| * @since 1.0 |
| */ |
| public void setHeaders(final Map<String, String> map) |
| { |
| this.headers.clear(); |
| |
| for (final Map.Entry<String, String> entry : map.entrySet()) |
| { |
| addHeader(entry.getKey(), entry.getValue()); |
| } |
| } |
| |
| /** |
| * Adds a header ( name, value ) to the headers Map. |
| * |
| * @param name A String with the name. |
| * @param value A String with the value. |
| * @since 1.0 |
| * @throws IllegalArgumentException if either {@code name} or {@code value} is null or empty |
| */ |
| public void addHeader(final String name, final String value) |
| { |
| if (EmailUtils.isEmpty(name)) |
| { |
| throw new IllegalArgumentException("name can not be null or empty"); |
| } |
| if (EmailUtils.isEmpty(value)) |
| { |
| throw new IllegalArgumentException("value can not be null or empty"); |
| } |
| |
| this.headers.put(name, value); |
| } |
| |
| /** |
| * Gets the specified header. |
| * |
| * @param header A string with the header. |
| * @return The value of the header, or null if no such header. |
| * @since 1.5 |
| */ |
| public String getHeader(final String header) |
| { |
| return this.headers.get(header); |
| } |
| |
| /** |
| * Gets all headers on an Email. |
| * |
| * @return a Map of all headers. |
| * @since 1.5 |
| */ |
| public Map<String, String> getHeaders() |
| { |
| return this.headers; |
| } |
| |
| /** |
| * Sets the email subject. Replaces end-of-line characters with spaces. |
| * |
| * @param aSubject A String. |
| * @return An Email. |
| * @since 1.0 |
| */ |
| public Email setSubject(final String aSubject) |
| { |
| this.subject = EmailUtils.replaceEndOfLineCharactersWithSpaces(aSubject); |
| return this; |
| } |
| |
| /** |
| * Gets the "bounce address" of this email. |
| * |
| * @return the bounce address as string |
| * @since 1.4 |
| */ |
| public String getBounceAddress() |
| { |
| return this.bounceAddress; |
| } |
| |
| /** |
| * Set the "bounce address" - the address to which undeliverable messages |
| * will be returned. If this value is never set, then the message will be |
| * sent to the address specified with the System property "mail.smtp.from", |
| * or if that value is not set, then to the "from" address. |
| * |
| * @param email A String. |
| * @return An Email. |
| * @throws IllegalStateException if the mail session is already initialized |
| * @since 1.0 |
| */ |
| public Email setBounceAddress(final String email) |
| { |
| checkSessionAlreadyInitialized(); |
| |
| if (email != null && !email.isEmpty()) |
| { |
| try |
| { |
| this.bounceAddress = createInternetAddress(email, null, this.charset).getAddress(); |
| } |
| catch (final EmailException e) |
| { |
| // Can't throw 'EmailException' to keep backward-compatibility |
| throw new IllegalArgumentException("Failed to set the bounce address : " + email, e); |
| } |
| } |
| else |
| { |
| this.bounceAddress = email; |
| } |
| |
| return this; |
| } |
| |
| /** |
| * Define the content of the mail. It should be overridden by the |
| * subclasses. |
| * |
| * @param msg A String. |
| * @return An Email. |
| * @throws EmailException generic exception. |
| * @since 1.0 |
| */ |
| public abstract Email setMsg(String msg) throws EmailException; |
| |
| /** |
| * Does the work of actually building the MimeMessage. Please note that |
| * a user rarely calls this method directly and only if he/she is |
| * interested in the sending the underlying MimeMessage without |
| * commons-email. |
| * |
| * @throws IllegalStateException if the MimeMessage was already built |
| * @throws EmailException if there was an error. |
| * @since 1.0 |
| */ |
| public void buildMimeMessage() throws EmailException |
| { |
| if (this.message != null) |
| { |
| // [EMAIL-95] we assume that an email is not reused therefore invoking |
| // buildMimeMessage() more than once is illegal. |
| throw new IllegalStateException("The MimeMessage is already built."); |
| } |
| |
| try |
| { |
| this.message = this.createMimeMessage(this.getMailSession()); |
| |
| if (EmailUtils.isNotEmpty(this.subject)) |
| { |
| if (EmailUtils.isNotEmpty(this.charset)) |
| { |
| this.message.setSubject(this.subject, this.charset); |
| } |
| else |
| { |
| this.message.setSubject(this.subject); |
| } |
| } |
| |
| // update content type (and encoding) |
| this.updateContentType(this.contentType); |
| |
| if (this.content != null) |
| { |
| if (EmailConstants.TEXT_PLAIN.equalsIgnoreCase(this.contentType) |
| && this.content instanceof String) |
| { |
| // EMAIL-104: call explicitly setText to use default mime charset |
| // (property "mail.mime.charset") in case none has been set |
| this.message.setText(this.content.toString(), this.charset); |
| } |
| else |
| { |
| this.message.setContent(this.content, this.contentType); |
| } |
| } |
| else if (this.emailBody != null) |
| { |
| if (this.contentType == null) |
| { |
| this.message.setContent(this.emailBody); |
| } |
| else |
| { |
| this.message.setContent(this.emailBody, this.contentType); |
| } |
| } |
| else |
| { |
| this.message.setText(""); |
| } |
| |
| if (this.fromAddress != null) |
| { |
| this.message.setFrom(this.fromAddress); |
| } |
| else |
| { |
| if (session.getProperty(EmailConstants.MAIL_SMTP_FROM) == null |
| && session.getProperty(EmailConstants.MAIL_FROM) == null) |
| { |
| throw new EmailException("From address required"); |
| } |
| } |
| |
| if (this.toList.size() + this.ccList.size() + this.bccList.size() == 0) |
| { |
| throw new EmailException("At least one receiver address required"); |
| } |
| |
| if (this.toList.size() > 0) |
| { |
| this.message.setRecipients( |
| Message.RecipientType.TO, |
| this.toInternetAddressArray(this.toList)); |
| } |
| |
| if (this.ccList.size() > 0) |
| { |
| this.message.setRecipients( |
| Message.RecipientType.CC, |
| this.toInternetAddressArray(this.ccList)); |
| } |
| |
| if (this.bccList.size() > 0) |
| { |
| this.message.setRecipients( |
| Message.RecipientType.BCC, |
| this.toInternetAddressArray(this.bccList)); |
| } |
| |
| if (this.replyList.size() > 0) |
| { |
| this.message.setReplyTo( |
| this.toInternetAddressArray(this.replyList)); |
| } |
| |
| |
| if (this.headers.size() > 0) |
| { |
| for (final Map.Entry<String, String> entry : this.headers.entrySet()) |
| { |
| final String foldedValue = createFoldedHeaderValue(entry.getKey(), entry.getValue()); |
| this.message.addHeader(entry.getKey(), foldedValue); |
| } |
| } |
| |
| if (this.message.getSentDate() == null) |
| { |
| this.message.setSentDate(getSentDate()); |
| } |
| |
| if (this.popBeforeSmtp) |
| { |
| final Store store = session.getStore("pop3"); |
| store.connect(this.popHost, this.popUsername, this.popPassword); |
| } |
| } |
| catch (final MessagingException me) |
| { |
| throw new EmailException(me); |
| } |
| } |
| |
| /** |
| * Sends the previously created MimeMessage to the SMTP server. |
| * |
| * @return the message id of the underlying MimeMessage |
| * @throws IllegalArgumentException if the MimeMessage has not been created |
| * @throws EmailException the sending failed |
| */ |
| public String sendMimeMessage() |
| throws EmailException |
| { |
| EmailUtils.notNull(this.message, "MimeMessage has not been created yet"); |
| |
| try |
| { |
| Transport.send(this.message); |
| return this.message.getMessageID(); |
| } |
| catch (final Throwable t) |
| { |
| final String msg = "Sending the email to the following server failed : " |
| + this.getHostName() |
| + ":" |
| + this.getSmtpPort(); |
| |
| throw new EmailException(msg, t); |
| } |
| } |
| |
| /** |
| * Returns the internal MimeMessage. Please note that the |
| * MimeMessage is built by the buildMimeMessage() method. |
| * |
| * @return the MimeMessage |
| */ |
| public MimeMessage getMimeMessage() |
| { |
| return this.message; |
| } |
| |
| /** |
| * Sends the email. Internally we build a MimeMessage |
| * which is afterwards sent to the SMTP server. |
| * |
| * @return the message id of the underlying MimeMessage |
| * @throws IllegalStateException if the MimeMessage was already built, ie {@link #buildMimeMessage()} |
| * was already called |
| * @throws EmailException the sending failed |
| */ |
| public String send() throws EmailException |
| { |
| this.buildMimeMessage(); |
| return this.sendMimeMessage(); |
| } |
| |
| /** |
| * Sets the sent date for the email. The sent date will default to the |
| * current date if not explicitly set. |
| * |
| * @param date Date to use as the sent date on the email |
| * @since 1.0 |
| */ |
| public void setSentDate(final Date date) |
| { |
| if (date != null) |
| { |
| // create a separate instance to keep findbugs happy |
| this.sentDate = new Date(date.getTime()); |
| } |
| } |
| |
| /** |
| * Gets the sent date for the email. |
| * |
| * @return date to be used as the sent date for the email |
| * @since 1.0 |
| */ |
| public Date getSentDate() |
| { |
| if (this.sentDate == null) |
| { |
| return new Date(); |
| } |
| return new Date(this.sentDate.getTime()); |
| } |
| |
| /** |
| * Gets the subject of the email. |
| * |
| * @return email subject |
| */ |
| public String getSubject() |
| { |
| return this.subject; |
| } |
| |
| /** |
| * Gets the sender of the email. |
| * |
| * @return from address |
| */ |
| public InternetAddress getFromAddress() |
| { |
| return this.fromAddress; |
| } |
| |
| /** |
| * Gets the host name of the SMTP server, |
| * |
| * @return host name |
| */ |
| public String getHostName() |
| { |
| if (this.session != null) |
| { |
| return this.session.getProperty(EmailConstants.MAIL_HOST); |
| } |
| else if (EmailUtils.isNotEmpty(this.hostName)) |
| { |
| return this.hostName; |
| } |
| return null; |
| } |
| |
| /** |
| * Gets the listening port of the SMTP server. |
| * |
| * @return smtp port |
| */ |
| public String getSmtpPort() |
| { |
| if (this.session != null) |
| { |
| return this.session.getProperty(EmailConstants.MAIL_PORT); |
| } |
| else if (EmailUtils.isNotEmpty(this.smtpPort)) |
| { |
| return this.smtpPort; |
| } |
| return null; |
| } |
| |
| /** |
| * Gets whether the client is configured to require STARTTLS. |
| * |
| * @return true if using STARTTLS for authentication, false otherwise |
| * @since 1.3 |
| */ |
| public boolean isStartTLSRequired() |
| { |
| return this.startTlsRequired; |
| } |
| |
| /** |
| * Gets whether the client is configured to try to enable STARTTLS. |
| * |
| * @return true if using STARTTLS for authentication, false otherwise |
| * @since 1.3 |
| */ |
| public boolean isStartTLSEnabled() |
| { |
| return this.startTlsEnabled || tls; |
| } |
| |
| /** |
| * Gets whether the client is configured to try to enable STARTTLS. |
| * See EMAIL-105 for reason of deprecation. |
| * |
| * @deprecated since 1.3, use isStartTLSEnabled() instead |
| * @return true if using STARTTLS for authentication, false otherwise |
| * @since 1.1 |
| */ |
| @Deprecated |
| public boolean isTLS() |
| { |
| return isStartTLSEnabled(); |
| } |
| |
| /** |
| * Utility to copy List of known InternetAddress objects into an |
| * array. |
| * |
| * @param list A List. |
| * @return An InternetAddress[]. |
| * @since 1.0 |
| */ |
| protected InternetAddress[] toInternetAddressArray(final List<InternetAddress> list) |
| { |
| return list.toArray(new InternetAddress[list.size()]); |
| } |
| |
| /** |
| * Set details regarding "pop3 before smtp" authentication. |
| * |
| * @param newPopBeforeSmtp Whether or not to log into pop3 server before sending mail. |
| * @param newPopHost The pop3 host to use. |
| * @param newPopUsername The pop3 username. |
| * @param newPopPassword The pop3 password. |
| * @since 1.0 |
| */ |
| public void setPopBeforeSmtp( |
| final boolean newPopBeforeSmtp, |
| final String newPopHost, |
| final String newPopUsername, |
| final String newPopPassword) |
| { |
| this.popBeforeSmtp = newPopBeforeSmtp; |
| this.popHost = newPopHost; |
| this.popUsername = newPopUsername; |
| this.popPassword = newPopPassword; |
| } |
| |
| /** |
| * Returns whether SSL/TLS encryption for the transport is currently enabled (SMTPS/POPS). |
| * See EMAIL-105 for reason of deprecation. |
| * |
| * @deprecated since 1.3, use isSSLOnConnect() instead |
| * @return true if SSL enabled for the transport |
| */ |
| @Deprecated |
| public boolean isSSL() |
| { |
| return isSSLOnConnect(); |
| } |
| |
| /** |
| * Returns whether SSL/TLS encryption for the transport is currently enabled (SMTPS/POPS). |
| * |
| * @return true if SSL enabled for the transport |
| * @since 1.3 |
| */ |
| public boolean isSSLOnConnect() |
| { |
| return sslOnConnect || ssl; |
| } |
| |
| /** |
| * Sets whether SSL/TLS encryption should be enabled for the SMTP transport upon connection (SMTPS/POPS). |
| * See EMAIL-105 for reason of deprecation. |
| * |
| * @deprecated since 1.3, use setSSLOnConnect() instead |
| * @param ssl whether to enable the SSL transport |
| */ |
| @Deprecated |
| public void setSSL(final boolean ssl) |
| { |
| setSSLOnConnect(ssl); |
| } |
| |
| /** |
| * Sets whether SSL/TLS encryption should be enabled for the SMTP transport upon connection (SMTPS/POPS). |
| * Takes precedence over {@link #setStartTLSRequired(boolean)} |
| * <p> |
| * Defaults to {@link #sslSmtpPort}; can be overridden by using {@link #setSslSmtpPort(String)} |
| * |
| * @param ssl whether to enable the SSL transport |
| * @return An Email. |
| * @throws IllegalStateException if the mail session is already initialized |
| * @since 1.3 |
| */ |
| public Email setSSLOnConnect(final boolean ssl) |
| { |
| checkSessionAlreadyInitialized(); |
| this.sslOnConnect = ssl; |
| this.ssl = ssl; |
| return this; |
| } |
| |
| /** |
| * Is the server identity checked as specified by RFC 2595 |
| * |
| * @return true if the server identity is checked |
| * @since 1.3 |
| */ |
| public boolean isSSLCheckServerIdentity() |
| { |
| return sslCheckServerIdentity; |
| } |
| |
| /** |
| * Sets whether the server identity is checked as specified by RFC 2595 |
| * |
| * @param sslCheckServerIdentity whether to enable server identity check |
| * @return An Email. |
| * @throws IllegalStateException if the mail session is already initialized |
| * @since 1.3 |
| */ |
| public Email setSSLCheckServerIdentity(final boolean sslCheckServerIdentity) |
| { |
| checkSessionAlreadyInitialized(); |
| this.sslCheckServerIdentity = sslCheckServerIdentity; |
| return this; |
| } |
| |
| /** |
| * Returns the current SSL port used by the SMTP transport. |
| * |
| * @return the current SSL port used by the SMTP transport |
| */ |
| public String getSslSmtpPort() |
| { |
| if (this.session != null) |
| { |
| return this.session.getProperty(EmailConstants.MAIL_SMTP_SOCKET_FACTORY_PORT); |
| } |
| else if (EmailUtils.isNotEmpty(this.sslSmtpPort)) |
| { |
| return this.sslSmtpPort; |
| } |
| return null; |
| } |
| |
| /** |
| * Sets the SSL port to use for the SMTP transport. Defaults to the standard |
| * port, 465. |
| * |
| * @param sslSmtpPort the SSL port to use for the SMTP transport |
| * @throws IllegalStateException if the mail session is already initialized |
| * @see #setSmtpPort(int) |
| */ |
| public void setSslSmtpPort(final String sslSmtpPort) |
| { |
| checkSessionAlreadyInitialized(); |
| this.sslSmtpPort = sslSmtpPort; |
| } |
| |
| /** |
| * If partial sending of email enabled. |
| * |
| * @return true if sending partial email is enabled |
| * @since 1.3.2 |
| */ |
| public boolean isSendPartial() |
| { |
| return sendPartial; |
| } |
| |
| /** |
| * Sets whether the email is partially send in case of invalid addresses. |
| * <p> |
| * In case the mail server rejects an address as invalid, the call to {@link #send()} |
| * may throw a {@link javax.mail.SendFailedException}, even if partial send mode is enabled (emails |
| * to valid addresses will be transmitted). In case the email server does not reject |
| * invalid addresses immediately, but return a bounce message, no exception will be thrown |
| * by the {@link #send()} method. |
| * |
| * @param sendPartial whether to enable partial send mode |
| * @return An Email. |
| * @throws IllegalStateException if the mail session is already initialized |
| * @since 1.3.2 |
| */ |
| public Email setSendPartial(final boolean sendPartial) |
| { |
| checkSessionAlreadyInitialized(); |
| this.sendPartial = sendPartial; |
| return this; |
| } |
| |
| /** |
| * Get the list of "To" addresses. |
| * |
| * @return List addresses |
| */ |
| public List<InternetAddress> getToAddresses() |
| { |
| return this.toList; |
| } |
| |
| /** |
| * Get the list of "CC" addresses. |
| * |
| * @return List addresses |
| */ |
| public List<InternetAddress> getCcAddresses() |
| { |
| return this.ccList; |
| } |
| |
| /** |
| * Get the list of "Bcc" addresses. |
| * |
| * @return List addresses |
| */ |
| public List<InternetAddress> getBccAddresses() |
| { |
| return this.bccList; |
| } |
| |
| /** |
| * Get the list of "Reply-To" addresses. |
| * |
| * @return List addresses |
| */ |
| public List<InternetAddress> getReplyToAddresses() |
| { |
| return this.replyList; |
| } |
| |
| /** |
| * Get the socket connection timeout value in milliseconds. |
| * |
| * @return the timeout in milliseconds. |
| * @since 1.2 |
| */ |
| public int getSocketConnectionTimeout() |
| { |
| return this.socketConnectionTimeout; |
| } |
| |
| /** |
| * Set the socket connection timeout value in milliseconds. |
| * Default is a 60 second timeout. |
| * |
| * @param socketConnectionTimeout the connection timeout |
| * @throws IllegalStateException if the mail session is already initialized |
| * @since 1.2 |
| */ |
| public void setSocketConnectionTimeout(final int socketConnectionTimeout) |
| { |
| checkSessionAlreadyInitialized(); |
| this.socketConnectionTimeout = socketConnectionTimeout; |
| } |
| |
| /** |
| * Get the socket I/O timeout value in milliseconds. |
| * |
| * @return the socket I/O timeout |
| * @since 1.2 |
| */ |
| public int getSocketTimeout() |
| { |
| return this.socketTimeout; |
| } |
| |
| /** |
| * Set the socket I/O timeout value in milliseconds. |
| * Default is 60 second timeout. |
| * |
| * @param socketTimeout the socket I/O timeout |
| * @throws IllegalStateException if the mail session is already initialized |
| * @since 1.2 |
| */ |
| public void setSocketTimeout(final int socketTimeout) |
| { |
| checkSessionAlreadyInitialized(); |
| this.socketTimeout = socketTimeout; |
| } |
| |
| /** |
| * Factory method to create a customized MimeMessage which can be |
| * implemented by a derived class, e.g. to set the message id. |
| * |
| * @param aSession mail session to be used |
| * @return the newly created message |
| */ |
| protected MimeMessage createMimeMessage(final Session aSession) |
| { |
| return new MimeMessage(aSession); |
| } |
| |
| /** |
| * Create a folded header value containing 76 character chunks. |
| * |
| * @param name the name of the header |
| * @param value the value of the header |
| * @return the folded header value |
| * @throws IllegalArgumentException if either the name or value is null or empty |
| */ |
| private String createFoldedHeaderValue(final String name, final String value) |
| { |
| if (EmailUtils.isEmpty(name)) |
| { |
| throw new IllegalArgumentException("name can not be null or empty"); |
| } |
| if (value == null || EmailUtils.isEmpty(value)) |
| { |
| throw new IllegalArgumentException("value can not be null or empty"); |
| } |
| |
| try |
| { |
| return MimeUtility.fold(name.length() + 2, MimeUtility.encodeText(value, this.charset, null)); |
| } |
| catch (final UnsupportedEncodingException e) |
| { |
| return value; |
| } |
| } |
| |
| /** |
| * Creates a InternetAddress. |
| * |
| * @param email An email address. |
| * @param name A name. |
| * @param charsetName The name of the charset to encode the name with. |
| * @return An internet address. |
| * @throws EmailException Thrown when the supplied address, name or charset were invalid. |
| */ |
| private InternetAddress createInternetAddress(final String email, final String name, final String charsetName) |
| throws EmailException |
| { |
| InternetAddress address; |
| |
| try |
| { |
| address = new InternetAddress(new IDNEmailAddressConverter().toASCII(email)); |
| |
| // check name input |
| if (EmailUtils.isNotEmpty(name)) |
| { |
| // check charset input. |
| if (EmailUtils.isEmpty(charsetName)) |
| { |
| address.setPersonal(name); |
| } |
| else |
| { |
| // canonicalize the charset name and make sure |
| // the current platform supports it. |
| final Charset set = Charset.forName(charsetName); |
| address.setPersonal(name, set.name()); |
| } |
| } |
| |
| // run sanity check on new InternetAddress object; if this fails |
| // it will throw AddressException. |
| address.validate(); |
| } |
| catch (final AddressException e) |
| { |
| throw new EmailException(e); |
| } |
| catch (final UnsupportedEncodingException e) |
| { |
| throw new EmailException(e); |
| } |
| return address; |
| } |
| |
| /** |
| * When a mail session is already initialized setting the |
| * session properties has no effect. In order to flag the |
| * problem throw an IllegalStateException. |
| * |
| * @throws IllegalStateException when the mail session is already initialized |
| */ |
| private void checkSessionAlreadyInitialized() |
| { |
| if (this.session != null) |
| { |
| throw new IllegalStateException("The mail session is already initialized"); |
| } |
| } |
| } |