| /* |
| * 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.mail2.jakarta; |
| |
| import java.io.UnsupportedEncodingException; |
| import java.nio.charset.Charset; |
| import java.time.Duration; |
| 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.Objects; |
| import java.util.Properties; |
| |
| import javax.naming.Context; |
| import javax.naming.InitialContext; |
| import javax.naming.NamingException; |
| |
| import org.apache.commons.mail2.core.EmailConstants; |
| import org.apache.commons.mail2.core.EmailException; |
| import org.apache.commons.mail2.core.EmailUtils; |
| import org.apache.commons.mail2.jakarta.util.IDNEmailAddressConverter; |
| |
| import jakarta.mail.Authenticator; |
| import jakarta.mail.Message; |
| import jakarta.mail.MessagingException; |
| import jakarta.mail.Session; |
| import jakarta.mail.Store; |
| import jakarta.mail.Transport; |
| import jakarta.mail.internet.AddressException; |
| import jakarta.mail.internet.InternetAddress; |
| import jakarta.mail.internet.MimeMessage; |
| import jakarta.mail.internet.MimeMultipart; |
| import jakarta.mail.internet.MimeUtility; |
| |
| /** |
| * The abstract class for all email messages. This class sets the sender's email, name, receiver's email, name, subject, and send date. |
| * <p> |
| * Subclasses are responsible for setting the message body. |
| * </p> |
| * |
| * @since 1.0 |
| */ |
| public abstract class Email { |
| |
| /** |
| * Empty array. |
| */ |
| private static final InternetAddress[] EMPTY_INTERNET_ADDRESS_ARRAY = {}; |
| |
| /** |
| * The email message to send. |
| */ |
| private MimeMessage message; |
| |
| /** |
| * The charset to use for this message. |
| */ |
| private String charset; |
| |
| /** |
| * The Address of the sending party, mandatory. |
| */ |
| private InternetAddress fromAddress; |
| |
| /** |
| * The Subject. |
| */ |
| private String subject; |
| |
| /** |
| * An attachment. |
| */ |
| private MimeMultipart emailBody; |
| |
| /** |
| * The content. |
| */ |
| private Object content; |
| |
| /** |
| * The content type. |
| */ |
| private String contentType; |
| |
| /** |
| * Set session debugging on or off. |
| */ |
| private boolean debug; |
| |
| /** |
| * Sent date. |
| */ |
| private Date sentDate; |
| |
| /** |
| * Instance of an {@code Authenticator} object that will be used when authentication is requested from the mail server. |
| */ |
| private 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. |
| */ |
| private String hostName; |
| |
| /** |
| * The port number of the mail server to connect to. Defaults to the standard port ( 25 ). |
| */ |
| private String smtpPort = "25"; |
| |
| /** |
| * The port number of the SSL enabled SMTP server; defaults to the standard port, 465. |
| */ |
| private String sslSmtpPort = "465"; |
| |
| /** |
| * List of "to" email addresses. |
| */ |
| private List<InternetAddress> toList = new ArrayList<>(); |
| |
| /** |
| * List of "cc" email addresses. |
| */ |
| private List<InternetAddress> ccList = new ArrayList<>(); |
| |
| /** |
| * List of "bcc" email addresses. |
| */ |
| private List<InternetAddress> bccList = new ArrayList<>(); |
| |
| /** |
| * List of "replyTo" email addresses. |
| */ |
| private List<InternetAddress> replyList = new ArrayList<>(); |
| |
| /** |
| * 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}. |
| */ |
| private 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 |
| */ |
| private final Map<String, String> headers = new HashMap<>(); |
| |
| /** |
| * Whether to use POP3 before SMTP, and if so the settings. |
| */ |
| private boolean popBeforeSmtp; |
| |
| /** |
| * The host name of the POP3 server. |
| */ |
| private String popHost; |
| |
| /** |
| * The user name to log into the POP3 server. |
| */ |
| private String popUsername; |
| |
| /** |
| * The password to log into the POP3 server. |
| */ |
| private String popPassword; |
| |
| /** |
| * Does server require TLS encryption for authentication? |
| */ |
| private boolean tls; |
| |
| /** |
| * Does the current transport use SSL/TLS encryption upon connection? |
| */ |
| private boolean ssl; |
| |
| /** |
| * Socket I/O timeout value in milliseconds. |
| */ |
| private int socketTimeout = Math.toIntExact(EmailConstants.SOCKET_TIMEOUT.toMillis()); |
| |
| /** |
| * Socket connection timeout value in milliseconds. |
| */ |
| private int socketConnectionTimeout = Math.toIntExact(EmailConstants.SOCKET_TIMEOUT.toMillis()); |
| |
| /** |
| * 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; |
| |
| /** |
| * Constructs a new instance. |
| */ |
| public Email() { |
| // empty |
| } |
| |
| /** |
| * Adds 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(String)}. 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 addBcc(email, null); |
| } |
| |
| /** |
| * Adds 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(String)}. 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 { |
| EmailException.checkNonEmpty(emails, () -> "BCC list invalid."); |
| for (final String email : emails) { |
| addBcc(email, null); |
| } |
| return this; |
| } |
| |
| /** |
| * Adds 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(String)}. 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, charset); |
| } |
| |
| /** |
| * Adds 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 { |
| bccList.add(createInternetAddress(email, name, charset)); |
| return this; |
| } |
| |
| /** |
| * Adds 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(String)}. 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 addCc(email, null); |
| } |
| |
| /** |
| * Adds 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(String)}. 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 { |
| EmailException.checkNonEmpty(emails, () -> "CC list invalid."); |
| for (final String email : emails) { |
| addCc(email, null); |
| } |
| return this; |
| } |
| |
| /** |
| * Adds 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(String)}. 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, charset); |
| } |
| |
| /** |
| * Adds 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 { |
| ccList.add(createInternetAddress(email, name, charset)); |
| return this; |
| } |
| |
| /** |
| * 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"); |
| } |
| headers.put(name, value); |
| } |
| |
| /** |
| * Adds 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(String)}. 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 addReplyTo(email, null); |
| } |
| |
| /** |
| * Adds 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(String)}. 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, charset); |
| } |
| |
| /** |
| * Adds 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 { |
| replyList.add(createInternetAddress(email, name, charset)); |
| return this; |
| } |
| |
| /** |
| * Adds 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(String)}. 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); |
| } |
| |
| /** |
| * Adds 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(String)}. 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 { |
| EmailException.checkNonEmpty(emails, () -> "To list invalid."); |
| for (final String email : emails) { |
| addTo(email, null); |
| } |
| return this; |
| } |
| |
| /** |
| * Adds 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(String)}. 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, charset); |
| } |
| |
| /** |
| * Adds 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 { |
| toList.add(createInternetAddress(email, name, charset)); |
| return this; |
| } |
| |
| /** |
| * Builds 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 (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 { |
| message = createMimeMessage(getMailSession()); |
| |
| if (EmailUtils.isNotEmpty(subject)) { |
| if (EmailUtils.isNotEmpty(charset)) { |
| message.setSubject(subject, charset); |
| } else { |
| message.setSubject(subject); |
| } |
| } |
| |
| // update content type (and encoding) |
| updateContentType(contentType); |
| |
| if (content != null) { |
| if (EmailConstants.TEXT_PLAIN.equalsIgnoreCase(contentType) && content instanceof String) { |
| // EMAIL-104: call explicitly setText to use default mime charset |
| // (property "mail.mime.charset") in case none has been set |
| message.setText(content.toString(), charset); |
| } else { |
| message.setContent(content, contentType); |
| } |
| } else if (emailBody != null) { |
| if (contentType == null) { |
| message.setContent(emailBody); |
| } else { |
| message.setContent(emailBody, contentType); |
| } |
| } else { |
| message.setText(""); |
| } |
| |
| if (fromAddress != null) { |
| message.setFrom(fromAddress); |
| } else if (session.getProperty(EmailConstants.MAIL_SMTP_FROM) == null && session.getProperty(EmailConstants.MAIL_FROM) == null) { |
| throw new EmailException("From address required"); |
| } |
| |
| if (toList.size() + ccList.size() + bccList.size() == 0) { |
| throw new EmailException("At least one receiver address required"); |
| } |
| |
| if (!EmailUtils.isEmpty(toList)) { |
| message.setRecipients(Message.RecipientType.TO, toInternetAddressArray(toList)); |
| } |
| |
| if (!EmailUtils.isEmpty(ccList)) { |
| message.setRecipients(Message.RecipientType.CC, toInternetAddressArray(ccList)); |
| } |
| |
| if (!EmailUtils.isEmpty(bccList)) { |
| message.setRecipients(Message.RecipientType.BCC, toInternetAddressArray(bccList)); |
| } |
| |
| if (!EmailUtils.isEmpty(replyList)) { |
| message.setReplyTo(toInternetAddressArray(replyList)); |
| } |
| |
| if (!EmailUtils.isEmpty(headers)) { |
| for (final Map.Entry<String, String> entry : headers.entrySet()) { |
| final String foldedValue = createFoldedHeaderValue(entry.getKey(), entry.getValue()); |
| message.addHeader(entry.getKey(), foldedValue); |
| } |
| } |
| |
| if (message.getSentDate() == null) { |
| message.setSentDate(getSentDate()); |
| } |
| |
| if (popBeforeSmtp) { |
| // TODO Why is this not a Store leak? When to close? |
| final Store store = session.getStore("pop3"); |
| store.connect(popHost, popUsername, popPassword); |
| } |
| } catch (final MessagingException e) { |
| throw new EmailException(e); |
| } |
| } |
| |
| /** |
| * 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 (session != null) { |
| throw new IllegalStateException("The mail session is already initialized"); |
| } |
| } |
| |
| /** |
| * Creates 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 (EmailUtils.isEmpty(value)) { |
| throw new IllegalArgumentException("value can not be null or empty"); |
| } |
| try { |
| return MimeUtility.fold(name.length() + 2, MimeUtility.encodeText(value, charset, null)); |
| } catch (final UnsupportedEncodingException e) { |
| return value; |
| } |
| } |
| |
| /** |
| * Creates an 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 { |
| try { |
| final InternetAddress 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(); |
| return address; |
| } catch (final AddressException | UnsupportedEncodingException e) { |
| throw new EmailException(e); |
| } |
| } |
| |
| /** |
| * Creates 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); |
| } |
| |
| /** |
| * Gets the authenticator. |
| * |
| * @return the authenticator. |
| * @since 1.6.0 |
| */ |
| public Authenticator getAuthenticator() { |
| return authenticator; |
| } |
| |
| /** |
| * Gets the list of "Bcc" addresses. |
| * |
| * @return List addresses |
| */ |
| public List<InternetAddress> getBccAddresses() { |
| return bccList; |
| } |
| |
| /** |
| * Gets the "bounce address" of this email. |
| * |
| * @return the bounce address as string |
| * @since 1.4 |
| */ |
| public String getBounceAddress() { |
| return bounceAddress; |
| } |
| |
| /** |
| * Gets the list of "CC" addresses. |
| * |
| * @return List addresses |
| */ |
| public List<InternetAddress> getCcAddresses() { |
| return ccList; |
| } |
| |
| /** |
| * Gets the Charset. |
| * |
| * @return the Charset. |
| * @since 1.6.0 |
| */ |
| public String getCharsetName() { |
| return charset; |
| } |
| |
| /** |
| * Gets the content. |
| * |
| * @return the content. |
| * @since 1.6.0 |
| */ |
| public Object getContent() { |
| return content; |
| } |
| |
| /** |
| * Gets the content type. |
| * |
| * @return the content type. |
| * @since 1.6.0 |
| */ |
| public String getContentType() { |
| return contentType; |
| } |
| |
| /** |
| * Gets the email body. |
| * |
| * @return the email body. |
| * @since 1.6.0 |
| */ |
| public MimeMultipart getEmailBody() { |
| return emailBody; |
| } |
| |
| /** |
| * Gets the sender of the email. |
| * |
| * @return from address |
| */ |
| public InternetAddress getFromAddress() { |
| return fromAddress; |
| } |
| |
| /** |
| * 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 headers.get(header); |
| } |
| |
| /** |
| * Gets all headers on an Email. |
| * |
| * @return a Map of all headers. |
| * @since 1.5 |
| */ |
| public Map<String, String> getHeaders() { |
| return headers; |
| } |
| |
| /** |
| * Gets the host name of the SMTP server, |
| * |
| * @return host name |
| */ |
| public String getHostName() { |
| if (session != null) { |
| return session.getProperty(EmailConstants.MAIL_HOST); |
| } |
| if (EmailUtils.isNotEmpty(hostName)) { |
| return hostName; |
| } |
| return null; |
| } |
| |
| /** |
| * Gets 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 (session == null) { |
| final Properties properties = new Properties(System.getProperties()); |
| properties.setProperty(EmailConstants.MAIL_TRANSPORT_PROTOCOL, EmailConstants.SMTP); |
| |
| if (EmailUtils.isEmpty(hostName)) { |
| hostName = properties.getProperty(EmailConstants.MAIL_HOST); |
| } |
| |
| EmailException.checkNonEmpty(hostName, () -> "Cannot find valid hostname for mail session"); |
| |
| properties.setProperty(EmailConstants.MAIL_PORT, smtpPort); |
| properties.setProperty(EmailConstants.MAIL_HOST, hostName); |
| properties.setProperty(EmailConstants.MAIL_DEBUG, String.valueOf(debug)); |
| |
| properties.setProperty(EmailConstants.MAIL_TRANSPORT_STARTTLS_ENABLE, Boolean.toString(isStartTLSEnabled())); |
| properties.setProperty(EmailConstants.MAIL_TRANSPORT_STARTTLS_REQUIRED, Boolean.toString(isStartTLSRequired())); |
| |
| properties.setProperty(EmailConstants.MAIL_SMTP_SEND_PARTIAL, Boolean.toString(isSendPartial())); |
| properties.setProperty(EmailConstants.MAIL_SMTPS_SEND_PARTIAL, Boolean.toString(isSendPartial())); |
| |
| if (authenticator != null) { |
| properties.setProperty(EmailConstants.MAIL_SMTP_AUTH, "true"); |
| } |
| |
| if (isSSLOnConnect()) { |
| properties.setProperty(EmailConstants.MAIL_PORT, sslSmtpPort); |
| properties.setProperty(EmailConstants.MAIL_SMTP_SOCKET_FACTORY_PORT, 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 (bounceAddress != null) { |
| properties.setProperty(EmailConstants.MAIL_SMTP_FROM, bounceAddress); |
| } |
| |
| if (socketTimeout > 0) { |
| properties.setProperty(EmailConstants.MAIL_SMTP_TIMEOUT, Integer.toString(socketTimeout)); |
| } |
| |
| if (socketConnectionTimeout > 0) { |
| properties.setProperty(EmailConstants.MAIL_SMTP_CONNECTIONTIMEOUT, Integer.toString(socketConnectionTimeout)); |
| } |
| |
| // changed this (back) to getInstance due to security exceptions |
| // caused when testing using Maven |
| session = Session.getInstance(properties, authenticator); |
| } |
| return session; |
| } |
| |
| /** |
| * Gets the message. |
| * |
| * @return the message. |
| * @since 1.6.0 |
| */ |
| public MimeMessage getMessage() { |
| return message; |
| } |
| |
| /** |
| * Gets the internal MimeMessage. Please note that the MimeMessage is built by the buildMimeMessage() method. |
| * |
| * @return the MimeMessage |
| */ |
| public MimeMessage getMimeMessage() { |
| return message; |
| } |
| |
| /** |
| * Gets the POP3 host. |
| * |
| * @return the POP3 host. |
| * @since 1.6.0 |
| */ |
| public String getPopHost() { |
| return popHost; |
| } |
| |
| /** |
| * Gets the POP3 password. |
| * |
| * @return the POP3 password. |
| * @since 1.6.0 |
| */ |
| public String getPopPassword() { |
| return popPassword; |
| } |
| |
| /** |
| * Gets the POP3 user name. |
| * |
| * @return the POP3 user name. |
| * @since 1.6.0 |
| */ |
| public String getPopUserName() { |
| return popUsername; |
| } |
| |
| /** |
| * Gets the list of "Reply-To" addresses. |
| * |
| * @return List addresses |
| */ |
| public List<InternetAddress> getReplyToAddresses() { |
| return replyList; |
| } |
| |
| /** |
| * 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 (sentDate == null) { |
| return new Date(); |
| } |
| return new Date(sentDate.getTime()); |
| } |
| |
| /** |
| * Gets the listening port of the SMTP server. |
| * |
| * @return SMTP port |
| */ |
| public String getSmtpPort() { |
| if (session != null) { |
| return session.getProperty(EmailConstants.MAIL_PORT); |
| } |
| if (EmailUtils.isNotEmpty(smtpPort)) { |
| return smtpPort; |
| } |
| return null; |
| } |
| |
| /** |
| * Gets the socket connection timeout value in milliseconds. |
| * |
| * @return the timeout in milliseconds. |
| * @since 1.2 |
| */ |
| public int getSocketConnectionTimeout() { |
| return socketConnectionTimeout; |
| } |
| |
| /** |
| * Gets the socket I/O timeout value in milliseconds. |
| * |
| * @return the socket I/O timeout |
| * @since 1.2 |
| */ |
| public int getSocketTimeout() { |
| return socketTimeout; |
| } |
| |
| /** |
| * Gets the current SSL port used by the SMTP transport. |
| * |
| * @return the current SSL port used by the SMTP transport |
| */ |
| public String getSslSmtpPort() { |
| if (session != null) { |
| return session.getProperty(EmailConstants.MAIL_SMTP_SOCKET_FACTORY_PORT); |
| } |
| if (EmailUtils.isNotEmpty(sslSmtpPort)) { |
| return sslSmtpPort; |
| } |
| return null; |
| } |
| |
| /** |
| * Gets the subject of the email. |
| * |
| * @return email subject |
| */ |
| public String getSubject() { |
| return subject; |
| } |
| |
| /** |
| * Gets the list of "To" addresses. |
| * |
| * @return List addresses |
| */ |
| public List<InternetAddress> getToAddresses() { |
| return toList; |
| } |
| |
| /** |
| * Tests whether debug is on. |
| * |
| * @return whether debug is on. |
| * @since 1.6.0 |
| */ |
| public boolean isDebug() { |
| return debug; |
| } |
| |
| /** |
| * Tests whether to use POP3 before SMTP, and if so the settings. |
| * |
| * @return whether to use POP3 before SMTP, and if so the settings. |
| * @since 1.6.0 |
| */ |
| public boolean isPopBeforeSmtp() { |
| return popBeforeSmtp; |
| } |
| |
| /** |
| * Tests whether partial sending of email is enabled. |
| * |
| * @return true if sending partial email is enabled. |
| * @since 1.3.2 |
| */ |
| public boolean isSendPartial() { |
| return sendPartial; |
| } |
| |
| /** |
| * Tests whether 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; |
| } |
| |
| /** |
| * Tests 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; |
| } |
| |
| /** |
| * Tests 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 startTlsEnabled || tls; |
| } |
| |
| /** |
| * Tests whether the client is configured to require STARTTLS. |
| * |
| * @return true if using STARTTLS for authentication, false otherwise. |
| * @since 1.3 |
| */ |
| public boolean isStartTLSRequired() { |
| return startTlsRequired; |
| } |
| |
| /** |
| * 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, that is, {@link #buildMimeMessage()} was already called |
| * @throws EmailException the sending failed |
| */ |
| public String send() throws EmailException { |
| buildMimeMessage(); |
| return sendMimeMessage(); |
| } |
| |
| /** |
| * 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 { |
| Objects.requireNonNull(message, "MimeMessage has not been created yet"); |
| try { |
| Transport.send(message); |
| return message.getMessageID(); |
| } catch (final Throwable t) { |
| throw new EmailException("Sending the email to the following server failed : " + this.getHostName() + ":" + getSmtpPort(), t); |
| } |
| } |
| |
| /** |
| * 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. |
| * </p> |
| * |
| * @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. |
| * </p> |
| * |
| * @param authenticator the {@code Authenticator} object. |
| * @see Authenticator |
| * @since 1.0 |
| */ |
| public void setAuthenticator(final Authenticator authenticator) { |
| this.authenticator = authenticator; |
| } |
| |
| /** |
| * Sets a list of "BCC" addresses. All elements in the specified {@code Collection} are expected to be of type {@code java.mail.internet.InternetAddress}. |
| * |
| * @param collection collection of {@code InternetAddress} objects |
| * @return An Email. |
| * @throws EmailException Indicates an invalid email address |
| * @see jakarta.mail.internet.InternetAddress |
| * @since 1.0 |
| */ |
| public Email setBcc(final Collection<InternetAddress> collection) throws EmailException { |
| EmailException.checkNonEmpty(collection, () -> "BCC list invalid"); |
| bccList = new ArrayList<>(collection); |
| return this; |
| } |
| |
| /** |
| * Sets 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 (!EmailUtils.isEmpty(email)) { |
| try { |
| bounceAddress = createInternetAddress(email, null, 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 { |
| bounceAddress = email; |
| } |
| |
| return this; |
| } |
| |
| /** |
| * Sets a list of "CC" addresses. All elements in the specified {@code Collection} are expected to be of type {@code java.mail.internet.InternetAddress}. |
| * |
| * @param collection collection of {@code InternetAddress} objects. |
| * @return An Email. |
| * @throws EmailException Indicates an invalid email address. |
| * @see jakarta.mail.internet.InternetAddress |
| * @since 1.0 |
| */ |
| public Email setCc(final Collection<InternetAddress> collection) throws EmailException { |
| EmailException.checkNonEmpty(collection, () -> "CC list invalid"); |
| ccList = new ArrayList<>(collection); |
| return this; |
| } |
| |
| /** |
| * Sets the charset of the message. Please note that you should set the charset before adding the message content. |
| * |
| * @param charset 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 charset) { |
| final Charset set = Charset.forName(charset); |
| this.charset = set.name(); |
| } |
| |
| /** |
| * Sets the emailBody to a MimeMultiPart |
| * |
| * @param mimeMultipart aMimeMultipart |
| * @since 1.0 |
| */ |
| public void setContent(final MimeMultipart mimeMultipart) { |
| this.emailBody = mimeMultipart; |
| } |
| |
| /** |
| * Sets the content. |
| * |
| * @param content the content. |
| * @return {@code this} instance. |
| * @since 1.6.0 |
| */ |
| public Email setContent(final Object content) { |
| this.content = content; |
| return this; |
| } |
| |
| /** |
| * Sets the content and contentType. |
| * |
| * @param content content. |
| * @param contentType content type. |
| * @since 1.0 |
| */ |
| public void setContent(final Object content, final String contentType) { |
| this.content = content; |
| updateContentType(contentType); |
| } |
| |
| /** |
| * Sets the content type. |
| * |
| * @param contentType the content type. |
| * @return {@code this} instance. |
| * @since 1.6.0 |
| */ |
| public Email setContentType(final String contentType) { |
| this.contentType = contentType; |
| return this; |
| } |
| |
| /** |
| * Sets the display of debug information. |
| * |
| * @param debug A boolean. |
| * @since 1.0 |
| */ |
| public void setDebug(final boolean debug) { |
| this.debug = debug; |
| } |
| |
| /** |
| * Sets 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(String)}. 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); |
| } |
| |
| /** |
| * Sets 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(String)}. 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, charset); |
| } |
| |
| /** |
| * Sets 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 { |
| fromAddress = createInternetAddress(email, name, charset); |
| return this; |
| } |
| |
| /** |
| * Sets the From address. |
| * |
| * @param fromAddress the From address. |
| * @return {@code this} instance. |
| * @since 1.6.0 |
| */ |
| public Email setFromAddress(final InternetAddress fromAddress) { |
| this.fromAddress = fromAddress; |
| return this; |
| |
| } |
| |
| /** |
| * Sets 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) { |
| headers.clear(); |
| for (final Map.Entry<String, String> entry : map.entrySet()) { |
| addHeader(entry.getKey(), entry.getValue()); |
| } |
| } |
| |
| /** |
| * Sets the hostname of the outgoing mail server. |
| * |
| * @param hostName aHostName |
| * @throws IllegalStateException if the mail session is already initialized |
| * @since 1.0 |
| */ |
| public void setHostName(final String hostName) { |
| checkSessionAlreadyInitialized(); |
| this.hostName = hostName; |
| } |
| |
| /** |
| * Sets 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 user name and password is supplied the implementation assumes that you have set a authenticator and will use the |
| * existing mail session (as expected). |
| * |
| * @param session mail session to be used |
| * @throws NullPointerException if {@code aSession} is {@code null} |
| * @since 1.0 |
| */ |
| public void setMailSession(final Session session) { |
| Objects.requireNonNull(session, "no mail session supplied"); |
| |
| final Properties sessionProperties = session.getProperties(); |
| final String auth = sessionProperties.getProperty(EmailConstants.MAIL_SMTP_AUTH); |
| |
| if (Boolean.parseBoolean(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 |
| authenticator = new DefaultAuthenticator(userName, password); |
| this.session = Session.getInstance(sessionProperties, authenticator); |
| } else { |
| // assume that the given mail session contains a working authenticator |
| this.session = session; |
| } |
| } else { |
| this.session = session; |
| } |
| } |
| |
| /** |
| * Sets a mail Session object from a JNDI directory. |
| * |
| * @param jndiName name of JNDI resource (jakarta.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"); |
| |
| } |
| setMailSession((Session) ctx.lookup(jndiName)); |
| } |
| |
| /** |
| * Sets the MIME message. |
| * |
| * @param message the MIME message. |
| */ |
| public void setMessage(final MimeMessage message) { |
| this.message = message; |
| } |
| |
| /** |
| * Sets 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; |
| |
| /** |
| * Sets whether to use POP3 before SMTP, and if so the settings. |
| * |
| * @param popBeforeSmtp whether to use POP3 before SMTP, and if so the settings. |
| * @return {@code this} instance. |
| * @since 1.6.0 |
| */ |
| public Email setPopBeforeSmtp(final boolean popBeforeSmtp) { |
| this.popBeforeSmtp = popBeforeSmtp; |
| return this; |
| |
| } |
| |
| /** |
| * Sets details regarding "POP3 before SMTP" authentication. |
| * |
| * @param popBeforeSmtp Whether or not to log into POP3 server before sending mail. |
| * @param popHost The POP3 host to use. |
| * @param popUserName The POP3 user name. |
| * @param popPassword The POP3 password. |
| * @since 1.0 |
| */ |
| public void setPopBeforeSmtp(final boolean popBeforeSmtp, final String popHost, final String popUserName, final String popPassword) { |
| this.popBeforeSmtp = popBeforeSmtp; |
| this.popHost = popHost; |
| this.popUsername = popUserName; |
| this.popPassword = popPassword; |
| } |
| |
| /** |
| * Sets the POP3 host. |
| * |
| * @param popHost The POP3 host. |
| * @return {@code this} instance. |
| * @since 1.6.0 |
| */ |
| public Email setPopHost(final String popHost) { |
| this.popHost = popHost; |
| return this; |
| |
| } |
| |
| /** |
| * Sets the POP3 password. |
| * |
| * @param popPassword the POP3 password. |
| * @return {@code this} instance. |
| * @since 1.6.0 |
| */ |
| public Email setPopPassword(final String popPassword) { |
| this.popPassword = popPassword; |
| return this; |
| |
| } |
| |
| /** |
| * Sets the POP3 user name. |
| * |
| * @param popUserName the POP3 user name. |
| * @return {@code this} instance. |
| * @since 1.6.0 |
| */ |
| public Email setPopUsername(final String popUserName) { |
| this.popUsername = popUserName; |
| return this; |
| |
| } |
| |
| /** |
| * Sets 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 collection collection of {@code InternetAddress} objects |
| * @return An Email. |
| * @throws EmailException Indicates an invalid email address |
| * @see jakarta.mail.internet.InternetAddress |
| * @since 1.1 |
| */ |
| public Email setReplyTo(final Collection<InternetAddress> collection) throws EmailException { |
| EmailException.checkNonEmpty(collection, () -> "Reply to list invalid"); |
| replyList = new ArrayList<>(collection); |
| return this; |
| } |
| |
| /** |
| * 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 jakarta.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. |
| * </p> |
| * |
| * @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; |
| } |
| |
| /** |
| * 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 |
| sentDate = new Date(date.getTime()); |
| } |
| } |
| |
| /** |
| * Sets the non-SSL port number of the outgoing mail server. |
| * |
| * @param portNumber 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 portNumber) { |
| checkSessionAlreadyInitialized(); |
| if (portNumber < 1) { |
| throw new IllegalArgumentException("Cannot connect to a port number that is less than 1 ( " + portNumber + " )"); |
| } |
| this.smtpPort = Integer.toString(portNumber); |
| } |
| |
| /** |
| * Sets 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.6.0 |
| */ |
| public void setSocketConnectionTimeout(final Duration socketConnectionTimeout) { |
| checkSessionAlreadyInitialized(); |
| this.socketConnectionTimeout = Math.toIntExact(socketConnectionTimeout.toMillis()); |
| } |
| |
| /** |
| * Sets 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.6.0 |
| */ |
| public void setSocketTimeout(final Duration socketTimeout) { |
| checkSessionAlreadyInitialized(); |
| this.socketTimeout = Math.toIntExact(socketTimeout.toMillis()); |
| } |
| |
| /** |
| * 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; |
| } |
| |
| /** |
| * 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)} |
| * </p> |
| * |
| * @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; |
| } |
| |
| /** |
| * 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; |
| } |
| |
| /** |
| * Sets 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; |
| } |
| |
| /** |
| * Sets or disable the required STARTTLS encryption. |
| * <p> |
| * Defaults to {@link #smtpPort}; can be overridden by using {@link #setSmtpPort(int)} |
| * </p> |
| * |
| * @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; |
| } |
| |
| /** |
| * 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; |
| } |
| |
| /** |
| * Sets a list of "TO" addresses. All elements in the specified {@code Collection} are expected to be of type {@code java.mail.internet.InternetAddress}. |
| * |
| * @param collection collection of {@code InternetAddress} objects. |
| * @return An Email. |
| * @throws EmailException Indicates an invalid email address. |
| * @see jakarta.mail.internet.InternetAddress |
| * @since 1.0 |
| */ |
| public Email setTo(final Collection<InternetAddress> collection) throws EmailException { |
| EmailException.checkNonEmpty(collection, () -> "To list invalid"); |
| this.toList = new ArrayList<>(collection); |
| return this; |
| } |
| |
| /** |
| * Converts 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(EMPTY_INTERNET_ADDRESS_ARRAY); |
| } |
| |
| /** |
| * Updates the contentType. |
| * |
| * @param contentType aContentType |
| * @since 1.2 |
| */ |
| public void updateContentType(final String contentType) { |
| if (EmailUtils.isEmpty(contentType)) { |
| this.contentType = null; |
| } else { |
| // set the content type |
| this.contentType = contentType; |
| // set the charset if the input was properly formed |
| final String strMarker = "; charset="; |
| int charsetPos = EmailUtils.toLower(contentType).indexOf(strMarker); |
| if (charsetPos != -1) { |
| // find the next space (after the marker) |
| charsetPos += strMarker.length(); |
| final int intCharsetEnd = EmailUtils.toLower(contentType).indexOf(" ", charsetPos); |
| if (intCharsetEnd != -1) { |
| this.charset = contentType.substring(charsetPos, intCharsetEnd); |
| } else { |
| this.charset = contentType.substring(charsetPos); |
| } |
| } else if (this.contentType.startsWith("text/") && EmailUtils.isNotEmpty(this.charset)) { |
| // use the default charset, if one exists, for messages |
| // whose content-type is some form of text. |
| final StringBuilder contentTypeBuf = new StringBuilder(this.contentType); |
| contentTypeBuf.append(strMarker); |
| contentTypeBuf.append(this.charset); |
| this.contentType = contentTypeBuf.toString(); |
| } |
| } |
| } |
| } |