CPD Results
The following document contains the results of PMD's CPD 7.2.0.
Duplications
File |
Project |
Line |
org/apache/commons/mail2/jakarta/Email.java |
Apache Commons Email for Jakarta |
60 |
org/apache/commons/mail2/javax/Email.java |
Apache Commons Email for Javax |
59 |
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();
}
}
}
} |
File |
Project |
Line |
org/apache/commons/mail2/jakarta/HtmlEmail.java |
Apache Commons Email for Jakarta |
82 |
org/apache/commons/mail2/javax/HtmlEmail.java |
Apache Commons Email for Javax |
82 |
public class HtmlEmail extends MultiPartEmail {
/**
* Private bean class that encapsulates data about URL contents that are embedded in the final email.
*
* @since 1.1
*/
private static final class InlineImage {
/** Content id. */
private final String cid;
/** {@code DataSource} for the content. */
private final DataSource dataSource;
/** The {@code MimeBodyPart} that contains the encoded data. */
private final MimeBodyPart mimeBodyPart;
/**
* Creates an InlineImage object to represent the specified content ID and {@code MimeBodyPart}.
*
* @param cid the generated content ID, not null.
* @param dataSource the {@code DataSource} that represents the content, not null.
* @param mimeBodyPart the {@code MimeBodyPart} that contains the encoded data, not null.
*/
private InlineImage(final String cid, final DataSource dataSource, final MimeBodyPart mimeBodyPart) {
this.cid = Objects.requireNonNull(cid, "cid");
this.dataSource = Objects.requireNonNull(dataSource, "dataSource");
this.mimeBodyPart = Objects.requireNonNull(mimeBodyPart, "mimeBodyPart");
}
@Override
public boolean equals(final Object obj) {
if (this == obj) {
return true;
}
if (!(obj instanceof InlineImage)) {
return false;
}
final InlineImage other = (InlineImage) obj;
return Objects.equals(cid, other.cid);
}
/**
* Returns the unique content ID of this InlineImage.
*
* @return the unique content ID of this InlineImage
*/
private String getCid() {
return cid;
}
/**
* Returns the {@code DataSource} that represents the encoded content.
*
* @return the {@code DataSource} representing the encoded content
*/
private DataSource getDataSource() {
return dataSource;
}
/**
* Returns the {@code MimeBodyPart} that contains the encoded InlineImage data.
*
* @return the {@code MimeBodyPart} containing the encoded InlineImage data
*/
private MimeBodyPart getMimeBodyPart() {
return mimeBodyPart;
}
@Override
public int hashCode() {
return Objects.hash(cid);
}
}
/** Definition of the length of generated CID's. */
public static final int CID_LENGTH = 10;
/** Prefix for default HTML mail. */
private static final String HTML_MESSAGE_START = "<html><body><pre>";
/** Suffix for default HTML mail. */
private static final String HTML_MESSAGE_END = "</pre></body></html>";
/**
* Text part of the message. This will be used as alternative text if the email client does not support HTML messages.
*/
private String text;
/**
* HTML part of the message.
*/
private String html;
/**
* Embedded images Map<String, InlineImage> where the key is the user-defined image name.
*/
private final Map<String, InlineImage> inlineEmbeds = new HashMap<>();
/**
* Constructs a new instance.
*/
public HtmlEmail() {
// empty
}
/**
* @throws EmailException EmailException
* @throws MessagingException MessagingException
*/
private void build() throws MessagingException, EmailException {
final MimeMultipart rootContainer = getContainer();
MimeMultipart bodyEmbedsContainer = rootContainer;
MimeMultipart bodyContainer = rootContainer;
MimeBodyPart msgHtml = null;
MimeBodyPart msgText = null;
rootContainer.setSubType("mixed");
// determine how to form multiparts of email
if (EmailUtils.isNotEmpty(html) && !EmailUtils.isEmpty(inlineEmbeds)) {
// If HTML body and embeds are used, create a related container and add it to the root container
bodyEmbedsContainer = new MimeMultipart("related");
bodyContainer = bodyEmbedsContainer;
addPart(bodyEmbedsContainer, 0);
// If TEXT body was specified, create a alternative container and add it to the embeds container
if (EmailUtils.isNotEmpty(text)) {
bodyContainer = new MimeMultipart("alternative");
final BodyPart bodyPart = createBodyPart();
try {
bodyPart.setContent(bodyContainer);
bodyEmbedsContainer.addBodyPart(bodyPart, 0);
} catch (final MessagingException e) {
throw new EmailException(e);
}
}
} else if (EmailUtils.isNotEmpty(text) && EmailUtils.isNotEmpty(html)) {
// EMAIL-142: if we have both an HTML and TEXT body, but no attachments or
// inline images, the root container should have mimetype
// "multipart/alternative".
// reference: https://tools.ietf.org/html/rfc2046#section-5.1.4
if (!EmailUtils.isEmpty(inlineEmbeds) || isBoolHasAttachments()) {
// If both HTML and TEXT bodies are provided, create an alternative
// container and add it to the root container
bodyContainer = new MimeMultipart("alternative");
this.addPart(bodyContainer, 0);
} else {
// no attachments or embedded images present, change the mimetype
// of the root container (= body container)
rootContainer.setSubType("alternative");
}
}
if (EmailUtils.isNotEmpty(html)) {
msgHtml = new MimeBodyPart();
bodyContainer.addBodyPart(msgHtml, 0);
// EMAIL-104: call explicitly setText to use default mime charset
// (property "mail.mime.charset") in case none has been set
msgHtml.setText(html, getCharsetName(), EmailConstants.TEXT_SUBTYPE_HTML);
// EMAIL-147: work-around for buggy JavaMail implementations;
// in case setText(...) does not set the correct content type,
// use the setContent() method instead.
final String contentType = msgHtml.getContentType();
if (contentType == null || !contentType.equals(EmailConstants.TEXT_HTML)) {
// apply default charset if one has been set
if (EmailUtils.isNotEmpty(getCharsetName())) {
msgHtml.setContent(html, EmailConstants.TEXT_HTML + "; charset=" + getCharsetName());
} else {
// unfortunately, MimeUtility.getDefaultMIMECharset() is package private
// and thus can not be used to set the default system charset in case
// no charset has been provided by the user
msgHtml.setContent(html, EmailConstants.TEXT_HTML);
}
}
for (final InlineImage image : inlineEmbeds.values()) {
bodyEmbedsContainer.addBodyPart(image.getMimeBodyPart());
}
}
if (EmailUtils.isNotEmpty(text)) {
msgText = new MimeBodyPart();
bodyContainer.addBodyPart(msgText, 0);
// EMAIL-104: call explicitly setText to use default mime charset
// (property "mail.mime.charset") in case none has been set
msgText.setText(text, getCharsetName());
}
}
/**
* 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 EmailException if there was an error.
* @since 1.0
*/
@Override
public void buildMimeMessage() throws EmailException {
try {
build();
} catch (final MessagingException e) {
throw new EmailException(e);
}
super.buildMimeMessage();
}
/**
* Embeds the specified {@code DataSource} in the HTML using a randomly generated Content-ID. Returns the generated Content-ID string.
*
* @param dataSource the {@code DataSource} to embed
* @param name the name that will be set in the file name header field
* @return the generated Content-ID for this {@code DataSource}
* @throws EmailException if the embedding fails or if {@code name} is null or empty
* @see #embed(DataSource, String, String)
* @since 1.1
*/
public String embed(final DataSource dataSource, final String name) throws EmailException {
// check if the DataSource has already been attached;
// if so, return the cached CID value.
final InlineImage inlineImage = inlineEmbeds.get(name);
if (inlineImage != null) {
// make sure the supplied URL points to the same thing
// as the one already associated with this name.
if (dataSource.equals(inlineImage.getDataSource())) {
return inlineImage.getCid();
}
throw new EmailException("embedded DataSource '" + name + "' is already bound to name " + inlineImage.getDataSource().toString()
+ "; existing names cannot be rebound");
}
final String cid = EmailUtils.toLower(EmailUtils.randomAlphabetic(CID_LENGTH));
return embed(dataSource, name, cid);
}
/**
* Embeds the specified {@code DataSource} in the HTML using the specified Content-ID. Returns the specified Content-ID string.
*
* @param dataSource the {@code DataSource} to embed
* @param name the name that will be set in the file name header field
* @param cid the Content-ID to use for this {@code DataSource}
* @return the URL encoded Content-ID for this {@code DataSource}
* @throws EmailException if the embedding fails or if {@code name} is null or empty
* @since 1.1
*/
public String embed(final DataSource dataSource, final String name, final String cid) throws EmailException {
EmailException.checkNonEmpty(name, () -> "Name cannot be null or empty");
final MimeBodyPart mbp = new MimeBodyPart();
try {
// URL encode the cid according to RFC 2392
final String encodedCid = EmailUtils.encodeUrl(cid);
mbp.setDataHandler(new DataHandler(dataSource));
mbp.setFileName(name);
mbp.setDisposition(EmailAttachment.INLINE);
mbp.setContentID("<" + encodedCid + ">");
this.inlineEmbeds.put(name, new InlineImage(encodedCid, dataSource, mbp));
return encodedCid;
} catch (final MessagingException e) {
throw new EmailException(e);
}
}
/**
* Embeds a file in the HTML. This implementation delegates to {@link #embed(File, String)}.
*
* @param file The {@code File} object to embed
* @return A String with the Content-ID of the file.
* @throws EmailException when the supplied {@code File} cannot be used; also see {@link jakarta.mail.internet.MimeBodyPart} for definitions
*
* @see #embed(File, String)
* @since 1.1
*/
public String embed(final File file) throws EmailException {
return embed(file, EmailUtils.toLower(EmailUtils.randomAlphabetic(CID_LENGTH)));
}
/**
* Embeds a file in the HTML.
*
* <p>
* This method embeds a file located by an URL into the mail body. It allows, for instance, to add inline images to the email. Inline files may be
* referenced with a {@code cid:xxxxxx} URL, where xxxxxx is the Content-ID returned by the embed function. Files are bound to their names, which is the
* value returned by {@link java.io.File#getName()}. If the same file is embedded multiple times, the same CID is guaranteed to be returned.
*
* <p>
* While functionally the same as passing {@code FileDataSource} to {@link #embed(DataSource, String, String)}, this method attempts to validate the file
* before embedding it in the message and will throw {@code EmailException} if the validation fails. In this case, the {@code HtmlEmail} object will not be
* changed.
*
* @param file The {@code File} to embed
* @param cid the Content-ID to use for the embedded {@code File}
* @return A String with the Content-ID of the file.
* @throws EmailException when the supplied {@code File} cannot be used or if the file has already been embedded; also see
* {@link jakarta.mail.internet.MimeBodyPart} for definitions
* @since 1.1
*/
public String embed(final File file, final String cid) throws EmailException {
EmailException.checkNonEmpty(file.getName(), () -> "File name cannot be null or empty");
// verify that the File can provide a canonical path
String filePath = null;
try {
filePath = file.getCanonicalPath();
} catch (final IOException e) {
throw new EmailException("couldn't get canonical path for " + file.getName(), e);
}
// check if a FileDataSource for this name has already been attached;
// if so, return the cached CID value.
final InlineImage inlineImage = inlineEmbeds.get(file.getName());
if (inlineImage != null) {
final FileDataSource fileDataSource = (FileDataSource) inlineImage.getDataSource();
// make sure the supplied file has the same canonical path
// as the one already associated with this name.
String existingFilePath = null;
try {
existingFilePath = fileDataSource.getFile().getCanonicalPath();
} catch (final IOException e) {
throw new EmailException("couldn't get canonical path for file " + fileDataSource.getFile().getName() + "which has already been embedded", e);
}
if (filePath.equals(existingFilePath)) {
return inlineImage.getCid();
}
throw new EmailException(
"embedded name '" + file.getName() + "' is already bound to file " + existingFilePath + "; existing names cannot be rebound");
}
// verify that the file is valid
if (!file.exists()) {
throw new EmailException("file " + filePath + " doesn't exist");
}
if (!file.isFile()) {
throw new EmailException("file " + filePath + " isn't a normal file");
}
if (!file.canRead()) {
throw new EmailException("file " + filePath + " isn't readable");
}
return embed(new FileDataSource(file), file.getName(), cid);
}
/**
* Parses the specified {@code String} as a URL that will then be embedded in the message.
*
* @param urlString String representation of the URL.
* @param name The name that will be set in the file name header field.
* @return A String with the Content-ID of the URL.
* @throws EmailException when URL supplied is invalid or if {@code name} is null or empty; also see {@link jakarta.mail.internet.MimeBodyPart} for
* definitions
*
* @see #embed(URL, String)
* @since 1.1
*/
public String embed(final String urlString, final String name) throws EmailException {
try {
return embed(new URL(urlString), name);
} catch (final MalformedURLException e) {
throw new EmailException("Invalid URL", e);
}
}
/**
* Embeds an URL in the HTML.
*
* <p>
* This method embeds a file located by an URL into the mail body. It allows, for instance, to add inline images to the email. Inline files may be
* referenced with a {@code cid:xxxxxx} URL, where xxxxxx is the Content-ID returned by the embed function. It is an error to bind the same name to more
* than one URL; if the same URL is embedded multiple times, the same Content-ID is guaranteed to be returned.
* </p>
* <p>
* While functionally the same as passing {@code URLDataSource} to {@link #embed(DataSource, String, String)}, this method attempts to validate the URL
* before embedding it in the message and will throw {@code EmailException} if the validation fails. In this case, the {@code HtmlEmail} object will not be
* changed.
* </p>
* <p>
* NOTE: Clients should take care to ensure that different URLs are bound to different names. This implementation tries to detect this and throw
* {@code EmailException}. However, it is not guaranteed to catch all cases, especially when the URL refers to a remote HTTP host that may be part of a
* virtual host cluster.
* </p>
*
* @param url The URL of the file.
* @param name The name that will be set in the file name header field.
* @return A String with the Content-ID of the file.
* @throws EmailException when URL supplied is invalid or if {@code name} is null or empty; also see {@link jakarta.mail.internet.MimeBodyPart} for
* definitions
* @since 1.0
*/
public String embed(final URL url, final String name) throws EmailException {
EmailException.checkNonEmpty(name, () -> "Name cannot be null or empty");
// check if a URLDataSource for this name has already been attached;
// if so, return the cached CID value.
final InlineImage inlineImage = inlineEmbeds.get(name);
if (inlineImage != null) {
final URLDataSource urlDataSource = (URLDataSource) inlineImage.getDataSource();
// make sure the supplied URL points to the same thing
// as the one already associated with this name.
// NOTE: Comparing URLs with URL.equals() is a blocking operation
// in the case of a network failure therefore we use
// url.toExternalForm().equals() here.
if (url.toExternalForm().equals(urlDataSource.getURL().toExternalForm())) {
return inlineImage.getCid();
}
throw new EmailException("embedded name '" + name + "' is already bound to URL " + urlDataSource.getURL() + "; existing names cannot be rebound");
}
// verify that the URL is valid
try (InputStream inputStream = url.openStream()) {
// Make sure we can read.
inputStream.read();
} catch (final IOException e) {
throw new EmailException("Invalid URL", e);
}
return embed(new URLDataSource(url), name);
}
/**
* Gets the HTML content.
*
* @return the HTML content.
* @since 1.6.0
*/
public String getHtml() {
return html;
}
/**
* Gets the message text.
*
* @return the message text.
* @since 1.6.0
*/
public String getText() {
return text;
}
/**
* Sets the HTML content.
*
* @param html A String.
* @return An HtmlEmail.
* @throws EmailException see jakarta.mail.internet.MimeBodyPart for definitions
* @since 1.0
*/
public HtmlEmail setHtmlMsg(final String html) throws EmailException {
this.html = EmailException.checkNonEmpty(html, () -> "Invalid message.");
return this;
}
/**
* Sets the message.
*
* <p>
* This method overrides {@link MultiPartEmail#setMsg(String)} in order to send an HTML message instead of a plain text message in the mail body. The
* message is formatted in HTML for the HTML part of the message; it is left as is in the alternate text part.
* </p>
*
* @param msg the message text to use
* @return this {@code HtmlEmail}
* @throws EmailException if msg is null or empty; see jakarta.mail.internet.MimeBodyPart for definitions
* @since 1.0
*/
@Override
public Email setMsg(final String msg) throws EmailException {
setTextMsg(msg);
final StringBuilder htmlMsgBuf = new StringBuilder(msg.length() + HTML_MESSAGE_START.length() + HTML_MESSAGE_END.length());
htmlMsgBuf.append(HTML_MESSAGE_START).append(msg).append(HTML_MESSAGE_END);
setHtmlMsg(htmlMsgBuf.toString());
return this;
}
/**
* Sets the text content.
*
* @param text A String.
* @return An HtmlEmail.
* @throws EmailException see jakarta.mail.internet.MimeBodyPart for definitions
* @since 1.0
*/
public HtmlEmail setTextMsg(final String text) throws EmailException {
this.text = EmailException.checkNonEmpty(text, () -> "Invalid message.");
return this;
}
} |
File |
Project |
Line |
org/apache/commons/mail2/jakarta/MultiPartEmail.java |
Apache Commons Email for Jakarta |
56 |
org/apache/commons/mail2/javax/MultiPartEmail.java |
Apache Commons Email for Javax |
56 |
public class MultiPartEmail extends Email {
/** Body portion of the email. */
private MimeMultipart container;
/** The message container. */
private BodyPart primaryBodyPart;
/** The MIME subtype. */
private String subType;
/** Indicates if the message has been initialized. */
private boolean initialized;
/** Indicates if attachments have been added to the message. */
private boolean hasAttachments;
/**
* Constructs a new instance.
*/
public MultiPartEmail() {
// empty
}
/**
* Adds a new part to the email.
*
* @param multipart The MimeMultipart.
* @return An Email.
* @throws EmailException see jakarta.mail.internet.MimeBodyPart for definitions
* @since 1.0
*/
public Email addPart(final MimeMultipart multipart) throws EmailException {
try {
return addPart(multipart, getContainer().getCount());
} catch (final MessagingException e) {
throw new EmailException(e);
}
}
/**
* Adds a new part to the email.
*
* @param multipart The part to add.
* @param index The index to add at.
* @return The email.
* @throws EmailException An error occurred while adding the part.
* @since 1.0
*/
public Email addPart(final MimeMultipart multipart, final int index) throws EmailException {
final BodyPart bodyPart = createBodyPart();
try {
bodyPart.setContent(multipart);
getContainer().addBodyPart(bodyPart, index);
} catch (final MessagingException e) {
throw new EmailException(e);
}
return this;
}
/**
* Adds a new part to the email.
*
* @param partContent The content.
* @param partContentType The content type.
* @return An Email.
* @throws EmailException see jakarta.mail.internet.MimeBodyPart for definitions
* @since 1.0
*/
public Email addPart(final String partContent, final String partContentType) throws EmailException {
final BodyPart bodyPart = createBodyPart();
try {
bodyPart.setContent(partContent, partContentType);
getContainer().addBodyPart(bodyPart);
} catch (final MessagingException e) {
throw new EmailException(e);
}
return this;
}
/**
* Attaches a file specified as a DataSource interface.
*
* @param dataSource A DataSource interface for the file.
* @param name The name field for the attachment.
* @param description A description for the attachment.
* @return A MultiPartEmail.
* @throws EmailException see jakarta.mail.internet.MimeBodyPart for definitions
* @since 1.0
*/
public MultiPartEmail attach(final DataSource dataSource, final String name, final String description) throws EmailException {
EmailException.checkNonNull(dataSource, () -> "Invalid Datasource.");
// verify that the DataSource is valid
try (InputStream inputStream = dataSource.getInputStream()) {
EmailException.checkNonNull(inputStream, () -> "Invalid Datasource.");
} catch (final IOException e) {
throw new EmailException("Invalid Datasource.", e);
}
return attach(dataSource, name, description, EmailAttachment.ATTACHMENT);
}
/**
* Attaches a file specified as a DataSource interface.
*
* @param dataSource A DataSource interface for the file.
* @param name The name field for the attachment.
* @param description A description for the attachment.
* @param disposition Either mixed or inline.
* @return A MultiPartEmail.
* @throws EmailException see jakarta.mail.internet.MimeBodyPart for definitions
* @since 1.0
*/
public MultiPartEmail attach(final DataSource dataSource, String name, final String description, final String disposition) throws EmailException {
if (EmailUtils.isEmpty(name)) {
name = dataSource.getName();
}
try {
final BodyPart bodyPart = createBodyPart();
bodyPart.setDisposition(disposition);
bodyPart.setFileName(MimeUtility.encodeText(name));
bodyPart.setDescription(description);
bodyPart.setDataHandler(new DataHandler(dataSource));
getContainer().addBodyPart(bodyPart);
} catch (final UnsupportedEncodingException | MessagingException e) {
// in case the file name could not be encoded
throw new EmailException(e);
}
setBoolHasAttachments(true);
return this;
}
/**
* Attaches an EmailAttachment.
*
* @param attachment An EmailAttachment.
* @return A MultiPartEmail.
* @throws EmailException see jakarta.mail.internet.MimeBodyPart for definitions
* @since 1.0
*/
public MultiPartEmail attach(final EmailAttachment attachment) throws EmailException {
EmailException.checkNonNull(attachment, () -> "Invalid attachment.");
MultiPartEmail result = null;
final URL url = attachment.getURL();
if (url == null) {
String fileName = null;
try {
fileName = attachment.getPath();
final File file = new File(fileName);
if (!file.exists()) {
throw new IOException("\"" + fileName + "\" does not exist");
}
result = attach(new FileDataSource(file), attachment.getName(), attachment.getDescription(), attachment.getDisposition());
} catch (final IOException e) {
throw new EmailException("Cannot attach file \"" + fileName + "\"", e);
}
} else {
result = attach(url, attachment.getName(), attachment.getDescription(), attachment.getDisposition());
}
return result;
}
/**
* Attaches a file.
*
* @param file A file attachment
* @return A MultiPartEmail.
* @throws EmailException see jakarta.mail.internet.MimeBodyPart for definitions
* @since 1.3
*/
public MultiPartEmail attach(final File file) throws EmailException {
final String fileName = file.getAbsolutePath();
try {
if (!file.exists()) {
throw new IOException("\"" + fileName + "\" does not exist");
}
return attach(new FileDataSource(file), file.getName(), null, EmailAttachment.ATTACHMENT);
} catch (final IOException e) {
throw new EmailException("Cannot attach file \"" + fileName + "\"", e);
}
}
/**
* Attaches a path.
*
* @param file A file attachment.
* @param options options for opening file streams.
* @return A MultiPartEmail.
* @throws EmailException see jakarta.mail.internet.MimeBodyPart for definitions
* @since 1.6.0
*/
public MultiPartEmail attach(final Path file, final OpenOption... options) throws EmailException {
final Path fileName = file.toAbsolutePath();
try {
if (!Files.exists(file)) {
throw new IOException("\"" + fileName + "\" does not exist");
}
return attach(new PathDataSource(file, FileTypeMap.getDefaultFileTypeMap(), options), Objects.toString(file.getFileName(), null), null,
EmailAttachment.ATTACHMENT);
} catch (final IOException e) {
throw new EmailException("Cannot attach file \"" + fileName + "\"", e);
}
}
/**
* Attaches a file located by its URL. The disposition of the file is set to mixed.
*
* @param url The URL of the file (may be any valid URL).
* @param name The name field for the attachment.
* @param description A description for the attachment.
* @return A MultiPartEmail.
* @throws EmailException see jakarta.mail.internet.MimeBodyPart for definitions
* @since 1.0
*/
public MultiPartEmail attach(final URL url, final String name, final String description) throws EmailException {
return attach(url, name, description, EmailAttachment.ATTACHMENT);
}
/**
* Attaches a file located by its URL.
*
* @param url The URL of the file (may be any valid URL).
* @param name The name field for the attachment.
* @param description A description for the attachment.
* @param disposition Either mixed or inline.
* @return A MultiPartEmail.
* @throws EmailException see jakarta.mail.internet.MimeBodyPart for definitions
* @since 1.0
*/
public MultiPartEmail attach(final URL url, final String name, final String description, final String disposition) throws EmailException {
// verify that the URL is valid
try {
url.openStream().close();
} catch (final IOException e) {
throw new EmailException("Invalid URL set:" + url, e);
}
return attach(new URLDataSource(url), name, description, disposition);
}
/**
* 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 EmailException if there was an error.
* @since 1.0
*/
@Override
public void buildMimeMessage() throws EmailException {
try {
if (primaryBodyPart != null) {
// before a multipart message can be sent, we must make sure that
// the content for the main body part was actually set. If not,
// an IOException will be thrown during super.send().
final BodyPart body = getPrimaryBodyPart();
try {
body.getContent();
} catch (final IOException e) { // NOPMD
// do nothing here.
// content will be set to an empty string as a result.
// (Should this really be rethrown as an email exception?)
// throw new EmailException(e);
}
}
if (subType != null) {
getContainer().setSubType(subType);
}
super.buildMimeMessage();
} catch (final MessagingException e) {
throw new EmailException(e);
}
}
/**
* Creates a body part object. Can be overridden if you don't want to create a BodyPart.
*
* @return the created body part
*/
protected BodyPart createBodyPart() {
return new MimeBodyPart();
}
/**
* Creates a mime multipart object.
*
* @return the created mime part
*/
protected MimeMultipart createMimeMultipart() {
return new MimeMultipart();
}
/**
* Gets the message container.
*
* @return The message container.
* @since 1.0
*/
protected MimeMultipart getContainer() {
if (!initialized) {
init();
}
return container;
}
/**
* Gets first body part of the message.
*
* @return The primary body part.
* @throws MessagingException An error occurred while getting the primary body part.
* @since 1.0
*/
protected BodyPart getPrimaryBodyPart() throws MessagingException {
if (!initialized) {
init();
}
// Add the first body part to the message. The fist body part must be
if (primaryBodyPart == null) {
primaryBodyPart = createBodyPart();
getContainer().addBodyPart(primaryBodyPart, 0);
}
return primaryBodyPart;
}
/**
* Gets the MIME subtype of the email.
*
* @return MIME subtype of the email
* @since 1.0
*/
public String getSubType() {
return subType;
}
/**
* Initialize the multipart email.
*
* @since 1.0
*/
protected void init() {
if (initialized) {
throw new IllegalStateException("Already initialized");
}
container = createMimeMultipart();
super.setContent(container);
initialized = true;
}
/**
* Tests whether there are attachments.
*
* @return true if there are attachments
* @since 1.0
*/
public boolean isBoolHasAttachments() {
return hasAttachments;
}
/**
* Tests if this object is initialized.
*
* @return true if initialized
*/
protected boolean isInitialized() {
return initialized;
}
/**
* Sets whether there are attachments.
*
* @param hasAttachments the attachments flag
* @since 1.0
*/
public void setBoolHasAttachments(final boolean hasAttachments) {
this.hasAttachments = hasAttachments;
}
/**
* Sets the initialized status of this object.
*
* @param initialized the initialized status flag
*/
protected void setInitialized(final boolean initialized) {
this.initialized = initialized;
}
/**
* Sets the message of the email.
*
* @param msg A String.
* @return An Email.
* @throws EmailException see jakarta.mail.internet.MimeBodyPart for definitions
* @since 1.0
*/
@Override
public Email setMsg(final String msg) throws EmailException {
EmailException.checkNonEmpty(msg, () -> "Invalid message.");
try {
final BodyPart primary = getPrimaryBodyPart();
if (primary instanceof MimePart && EmailUtils.isNotEmpty(getCharsetName())) {
((MimePart) primary).setText(msg, getCharsetName());
} else {
primary.setText(msg);
}
} catch (final MessagingException e) {
throw new EmailException(e);
}
return this;
}
/**
* Sets the MIME subtype of the email.
*
* @param subType MIME subtype of the email
* @since 1.0
*/
public void setSubType(final String subType) {
this.subType = subType;
}
} |
File |
Project |
Line |
org/apache/commons/mail2/jakarta/util/MimeMessageParser.java |
Apache Commons Email for Jakarta |
50 |
org/apache/commons/mail2/javax/util/MimeMessageParser.java |
Apache Commons Email for Javax |
50 |
public class MimeMessageParser {
/** The MimeMessage to convert. */
private final MimeMessage mimeMessage;
/** Plain mail content from MimeMessage. */
private String plainContent;
/** HTML mail content from MimeMessage. */
private String htmlContent;
/** List of attachments of MimeMessage. */
private final List<DataSource> attachmentList;
/** Attachments stored by their content-id. */
private final Map<String, DataSource> cidMap;
/** Is this a Multipart email. */
private boolean isMultiPart;
/**
* Constructs an instance with the MimeMessage to be extracted.
*
* @param mimeMessage the message to parse
*/
public MimeMessageParser(final MimeMessage mimeMessage) {
this.attachmentList = new ArrayList<>();
this.cidMap = new HashMap<>();
this.mimeMessage = mimeMessage;
this.isMultiPart = false;
}
private List<Address> asList(final Address[] recipients) {
return recipients != null ? Arrays.asList(recipients) : new ArrayList<>();
}
/**
* Parses the MimePart to create a DataSource.
*
* @param parent the parent multi-part
* @param part the current part to be processed
* @return the DataSource
* @throws MessagingException creating the DataSource failed
* @throws IOException error getting InputStream or unsupported encoding
*/
@SuppressWarnings("resource") // Caller closes InputStream
protected DataSource createDataSource(final Multipart parent, final MimePart part) throws MessagingException, IOException {
final DataSource dataSource = part.getDataHandler().getDataSource();
final String contentType = getBaseMimeType(dataSource.getContentType());
final String dataSourceName = getDataSourceName(part, dataSource);
return new InputStreamDataSource(dataSource.getInputStream(), contentType, dataSourceName);
}
/**
* Find an attachment using its content-id.
* <p>
* The content-id must be stripped of any angle brackets, i.e. "part1" instead of "<part1>".
* </p>
*
* @param cid the content-id of the attachment
* @return the corresponding datasource or null if nothing was found
* @since 1.3.4
*/
public DataSource findAttachmentByCid(final String cid) {
return cidMap.get(cid);
}
/**
* Find an attachment using its name.
*
* @param name the name of the attachment
* @return the corresponding datasource or null if nothing was found
*/
public DataSource findAttachmentByName(final String name) {
for (final DataSource dataSource : getAttachmentList()) {
if (name.equalsIgnoreCase(dataSource.getName())) {
return dataSource;
}
}
return null;
}
/**
* Gets the attachment list.
*
* @return Returns the attachment list.
*/
public List<DataSource> getAttachmentList() {
return attachmentList;
}
/**
* Gets the MIME type.
*
* @param fullMimeType the mime type from the mail API
* @return the real mime type
*/
private String getBaseMimeType(final String fullMimeType) {
final int pos = fullMimeType.indexOf(';');
return pos < 0 ? fullMimeType : fullMimeType.substring(0, pos);
}
/**
* Gets the BCC Address list.
*
* @return the 'BCC' recipients of the message
* @throws MessagingException determining the recipients failed
*/
public List<Address> getBcc() throws MessagingException {
return asList(mimeMessage.getRecipients(Message.RecipientType.BCC));
}
/**
* Gets the CC Address list.
*
* @return the 'CC' recipients of the message
* @throws MessagingException determining the recipients failed
*/
public List<Address> getCc() throws MessagingException {
return asList(mimeMessage.getRecipients(Message.RecipientType.CC));
}
/**
* Returns a collection of all content-ids in the parsed message.
* <p>
* The content-ids are stripped of any angle brackets, i.e. "part1" instead of "<part1>".
* </p>
*
* @return the collection of content ids.
* @since 1.3.4
*/
public Collection<String> getContentIds() {
return Collections.unmodifiableSet(cidMap.keySet());
}
/**
* Determines the name of the data source if it is not already set.
*
* @param part the mail part
* @param dataSource the data source
* @return the name of the data source or {@code null} if no name can be determined
* @throws MessagingException accessing the part failed
* @throws UnsupportedEncodingException decoding the text failed
*/
protected String getDataSourceName(final Part part, final DataSource dataSource) throws MessagingException, UnsupportedEncodingException {
String result = dataSource.getName();
if (isEmpty(result)) {
result = part.getFileName();
}
if (!isEmpty(result)) {
result = MimeUtility.decodeText(result);
} else {
result = null;
}
return result;
}
/**
* Gets the FROM field.
*
* @return the FROM field of the message
* @throws MessagingException parsing the mime message failed
*/
public String getFrom() throws MessagingException {
final Address[] addresses = mimeMessage.getFrom();
if (isEmpty(addresses)) {
return null;
}
return ((InternetAddress) addresses[0]).getAddress();
}
/**
* Gets the htmlContent if any.
*
* @return Returns the htmlContent if any
*/
public String getHtmlContent() {
return htmlContent;
}
/**
* Gets the MimeMessage.
*
* @return Returns the mimeMessage.
*/
public MimeMessage getMimeMessage() {
return mimeMessage;
}
/**
* Gets the plain content if any.
*
* @return Returns the plainContent if any
*/
public String getPlainContent() {
return plainContent;
}
/**
* Gets the 'replyTo' address of the email.
*
* @return the 'replyTo' address of the email
* @throws MessagingException parsing the mime message failed
*/
public String getReplyTo() throws MessagingException {
final Address[] addresses = mimeMessage.getReplyTo();
if (isEmpty(addresses)) {
return null;
}
return ((InternetAddress) addresses[0]).getAddress();
}
/**
* Gets the MIME message subject.
*
* @return the MIME message subject.
* @throws MessagingException parsing the mime message failed.
*/
public String getSubject() throws MessagingException {
return mimeMessage.getSubject();
}
/**
* Gets the MIME message 'to' list.
*
* @return the 'to' recipients of the message.
* @throws MessagingException determining the recipients failed
*/
public List<Address> getTo() throws MessagingException {
return asList(mimeMessage.getRecipients(Message.RecipientType.TO));
}
/**
* Tests if attachments are present.
*
* @return true if attachments are present.
*/
public boolean hasAttachments() {
return !attachmentList.isEmpty();
}
/**
* Tests is HTML content is present.
*
* @return true if HTML content is present.
*/
public boolean hasHtmlContent() {
return htmlContent != null;
}
/**
* Tests is plain content is present.
*
* @return true if a plain content is present.
*/
public boolean hasPlainContent() {
return plainContent != null;
}
private boolean isEmpty(final Object[] array) {
return array == null || array.length == 0;
}
private boolean isEmpty(final String result) {
return result == null || result.isEmpty();
}
/**
* Tests whether the MimePart contains an object of the given mime type.
*
* @param part the current MimePart
* @param mimeType the mime type to check
* @return {@code true} if the MimePart matches the given mime type, {@code false} otherwise
* @throws MessagingException parsing the MimeMessage failed
*/
private boolean isMimeType(final MimePart part, final String mimeType) throws MessagingException {
// Do not use part.isMimeType(String) as it is broken for MimeBodyPart
// and does not really check the actual content type.
try {
return new ContentType(part.getDataHandler().getContentType()).match(mimeType);
} catch (final ParseException ex) {
return part.getContentType().equalsIgnoreCase(mimeType);
}
}
/**
* Tests whether this is multipart.
*
* @return Returns the isMultiPart.
*/
public boolean isMultipart() {
return isMultiPart;
}
/**
* Does the actual extraction.
*
* @return this instance
* @throws MessagingException parsing the mime message failed
* @throws IOException parsing the mime message failed
*/
public MimeMessageParser parse() throws MessagingException, IOException {
parse(null, mimeMessage);
return this;
}
/**
* Extracts the content of a MimeMessage recursively.
*
* @param parent the parent multi-part
* @param part the current MimePart
* @throws MessagingException parsing the MimeMessage failed
* @throws IOException parsing the MimeMessage failed
*/
protected void parse(final Multipart parent, final MimePart part) throws MessagingException, IOException {
if (isMimeType(part, "text/plain") && plainContent == null && !Part.ATTACHMENT.equalsIgnoreCase(part.getDisposition())) {
plainContent = (String) part.getContent();
} else if (isMimeType(part, "text/html") && htmlContent == null && !Part.ATTACHMENT.equalsIgnoreCase(part.getDisposition())) {
htmlContent = (String) part.getContent();
} else if (isMimeType(part, "multipart/*")) {
isMultiPart = true;
final Multipart multipart = (Multipart) part.getContent();
final int count = multipart.getCount();
// iterate over all MimeBodyPart
for (int i = 0; i < count; i++) {
parse(multipart, (MimeBodyPart) multipart.getBodyPart(i));
}
} else {
final String cid = stripContentId(part.getContentID());
final DataSource dataSource = createDataSource(parent, part);
if (cid != null) {
cidMap.put(cid, dataSource);
}
attachmentList.add(dataSource);
}
}
/**
* Strips the content id of any whitespace and angle brackets.
*
* @param contentId the string to strip
* @return a stripped version of the content id
*/
private String stripContentId(final String contentId) {
return contentId == null ? null : contentId.trim().replaceAll("[\\<\\>]", "");
}
} |
File |
Project |
Line |
org/apache/commons/mail2/jakarta/ImageHtmlEmail.java |
Apache Commons Email for Jakarta |
45 |
org/apache/commons/mail2/javax/ImageHtmlEmail.java |
Apache Commons Email for Javax |
45 |
public class ImageHtmlEmail extends HtmlEmail {
// Regular Expression to find all <IMG SRC="..."> entries in an HTML
// document.It needs to cater for various things, like more whitespaces
// including newlines on any place, HTML is not case sensitive and there
// can be arbitrary text between "IMG" and "SRC" like IDs and other things.
/** Regexp for extracting {@code <img>} tags */
public static final String REGEX_IMG_SRC = "(<[Ii][Mm][Gg]\\s*[^>]*?\\s+[Ss][Rr][Cc]\\s*=\\s*[\"'])([^\"']+?)([\"'])";
/** Regexp for extracting {@code <script>} tags */
public static final String REGEX_SCRIPT_SRC = "(<[Ss][Cc][Rr][Ii][Pp][Tt]\\s*.*?\\s+[Ss][Rr][Cc]\\s*=\\s*[\"'])([^\"']+?)([\"'])";
// this pattern looks for the HTML image tag which indicates embedded images,
// the grouping is necessary to allow to replace the element with the CID
/** Pattern for extracting {@code <img>} tags */
private static final Pattern IMG_PATTERN = Pattern.compile(REGEX_IMG_SRC);
/** Pattern for extracting {@code <script>} tags */
private static final Pattern SCRIPT_PATTERN = Pattern.compile(REGEX_SCRIPT_SRC);
/** Resolve the images and script resources to a DataSource */
private DataSourceResolver dataSourceResolver;
/**
* Constructs a new instance.
*/
public ImageHtmlEmail() {
// empty
}
/**
* Does the work of actually building the MimeMessage.
*
* @see org.apache.commons.mail2.jakarta.HtmlEmail#buildMimeMessage()
* @throws EmailException building the MimeMessage failed
*/
@Override
public void buildMimeMessage() throws EmailException {
try {
// embed all the matching image and script resources within the email
String temp = replacePattern(getHtml(), IMG_PATTERN);
temp = replacePattern(temp, SCRIPT_PATTERN);
setHtmlMsg(temp);
super.buildMimeMessage();
} catch (final IOException e) {
throw new EmailException("Building the MimeMessage failed", e);
}
}
/**
* Gets the data source resolver.
*
* @return the resolver
*/
public DataSourceResolver getDataSourceResolver() {
return dataSourceResolver;
}
/**
* Replace the regexp matching resource locations with "cid:..." references.
*
* @param htmlMessage the HTML message to analyze
* @param pattern the regular expression to find resources
* @return the HTML message containing "cid" references
* @throws EmailException creating the email failed
* @throws IOException resolving the resources failed
*/
private String replacePattern(final String htmlMessage, final Pattern pattern) throws EmailException, IOException {
DataSource dataSource;
final StringBuffer stringBuffer = new StringBuffer();
// maps "cid" --> name
final Map<String, String> cidCache = new HashMap<>();
// maps "name" --> dataSource
final Map<String, DataSource> dataSourceCache = new HashMap<>();
// in the String, replace all "img src" with a CID and embed the related
// image file if we find it.
final Matcher matcher = pattern.matcher(htmlMessage);
// the matcher returns all instances one by one
while (matcher.find()) {
// in the RegEx we have the <src> element as second "group"
final String resourceLocation = matcher.group(2);
// avoid loading the same data source more than once
if (dataSourceCache.get(resourceLocation) == null) {
// in lenient mode we might get a 'null' data source if the resource was not found
dataSource = getDataSourceResolver().resolve(resourceLocation);
if (dataSource != null) {
dataSourceCache.put(resourceLocation, dataSource);
}
} else {
dataSource = dataSourceCache.get(resourceLocation);
}
if (dataSource != null) {
String name = dataSource.getName();
if (EmailUtils.isEmpty(name)) {
name = resourceLocation;
}
String cid = cidCache.get(name);
if (cid == null) {
cid = embed(dataSource, name);
cidCache.put(name, cid);
}
// if we embedded something, then we need to replace the URL with
// the CID, otherwise the Matcher takes care of adding the
// non-replaced text afterwards, so no else is necessary here!
matcher.appendReplacement(stringBuffer, Matcher.quoteReplacement(matcher.group(1) + "cid:" + cid + matcher.group(3)));
}
}
// append the remaining items...
matcher.appendTail(stringBuffer);
cidCache.clear();
dataSourceCache.clear();
return stringBuffer.toString();
}
/**
* Sets the data source resolver.
*
* @param dataSourceResolver the resolver
*/
public void setDataSourceResolver(final DataSourceResolver dataSourceResolver) {
this.dataSourceResolver = dataSourceResolver;
}
} |
File |
Project |
Line |
org/apache/commons/mail2/jakarta/resolver/DataSourceClassPathResolver.java |
Apache Commons Email for Jakarta |
32 |
org/apache/commons/mail2/javax/resolver/DataSourceClassPathResolver.java |
Apache Commons Email for Javax |
32 |
public class DataSourceClassPathResolver extends DataSourceBaseResolver {
/** The base string of the resource relative to the classpath when resolving relative paths */
private final String classPathBase;
/**
* Constructs a new instance.
*/
public DataSourceClassPathResolver() {
this("/");
}
/**
* Constructs a new instance.
*
* @param classPathBase a base class path
*/
public DataSourceClassPathResolver(final String classPathBase) {
this(classPathBase, false);
}
/**
* Constructs a new instance.
*
* @param classPathBase a base class path
* @param lenient shall we ignore resources not found or throw an exception?
*/
public DataSourceClassPathResolver(final String classPathBase, final boolean lenient) {
super(lenient);
this.classPathBase = classPathBase.endsWith("/") ? classPathBase : classPathBase + "/";
}
/**
* Gets the class path base.
*
* @return the classPathBase
*/
public String getClassPathBase() {
return classPathBase;
}
/**
* Returns the resource name for a given resource location.
*
* @param resourceLocation the resource location
* @return {@link #getClassPathBase()} + {@code resourceLocation}
* @see #getClassPathBase()
*/
private String getResourceName(final String resourceLocation) {
return (getClassPathBase() + resourceLocation).replace("//", "/");
}
/** {@inheritDoc} */
@Override
public DataSource resolve(final String resourceLocation) throws IOException {
return resolve(resourceLocation, isLenient());
}
/** {@inheritDoc} */
@Override
public DataSource resolve(final String resourceLocation, final boolean isLenient) throws IOException {
try {
if (!isCid(resourceLocation) && !isHttpUrl(resourceLocation)) {
final String mimeType = FileTypeMap.getDefaultFileTypeMap().getContentType(resourceLocation);
final String resourceName = getResourceName(resourceLocation);
try (InputStream inputStream = DataSourceClassPathResolver.class.getResourceAsStream(resourceName)) {
if (inputStream == null) {
if (isLenient) {
return null;
}
throw new IOException("The following class path resource was not found : " + resourceLocation);
}
final ByteArrayDataSource ds = new ByteArrayDataSource(inputStream, mimeType);
// EMAIL-125: set the name of the DataSource to the normalized resource URL
// similar to other DataSource implementations, e.g. FileDataSource, URLDataSource
final URL resource = DataSourceClassPathResolver.class.getResource(resourceName);
if (resource != null) {
ds.setName(resource.toString());
} else if (isLenient) {
return null;
} else {
throw new IOException("The following class path resource was not found : " + resourceName);
}
return ds;
}
}
return null;
} catch (final IOException e) {
if (isLenient) {
return null;
}
throw e;
}
}
} |
File |
Project |
Line |
org/apache/commons/mail2/jakarta/util/MimeMessageUtils.java |
Apache Commons Email for Jakarta |
40 |
org/apache/commons/mail2/javax/util/MimeMessageUtils.java |
Apache Commons Email for Javax |
40 |
public final class MimeMessageUtils {
/**
* Creates a MimeMessage.
*
* @param session the mail session.
* @param source the input data.
* @return the MimeMessage.
* @throws MessagingException creating the MimeMessage failed.
* @throws IOException creating the MimeMessage failed.
*/
public static MimeMessage createMimeMessage(final Session session, final byte[] source) throws MessagingException, IOException {
try (InputStream inputStream = new SharedByteArrayInputStream(source)) {
return new MimeMessage(session, inputStream);
}
}
/**
* Creates a MimeMessage.
*
* @param session the mail session.
* @param source the input data.
* @return the MimeMessage.
* @throws MessagingException creating the MimeMessage failed.
* @throws IOException creating the MimeMessage failed.
*/
public static MimeMessage createMimeMessage(final Session session, final File source) throws MessagingException, IOException {
try (InputStream inputStream = new FileInputStream(source)) {
return createMimeMessage(session, inputStream);
}
}
/**
* Creates a MimeMessage.
*
* @param session the mail session.
* @param source the input data.
* @return the MimeMessage.
* @throws MessagingException creating the MimeMessage failed.
*/
public static MimeMessage createMimeMessage(final Session session, final InputStream source) throws MessagingException {
return new MimeMessage(session, source);
}
/**
* Creates a MimeMessage.
*
* @param session the mail session.
* @param source the input data.
* @param options options specifying how the file is opened.
* @return the MimeMessage.
* @throws MessagingException creating the MimeMessage failed.
* @throws IOException creating the MimeMessage failed.
*/
public static MimeMessage createMimeMessage(final Session session, final Path source, final OpenOption... options) throws MessagingException, IOException {
try (InputStream inputStream = Files.newInputStream(source, options)) {
return createMimeMessage(session, inputStream);
}
}
/**
* Creates a MimeMessage using the platform's default character encoding.
*
* @param session the mail session.
* @param source the input data.
* @return the MimeMessage.
* @throws MessagingException creating the MimeMessage failed.
* @throws IOException creating the MimeMessage failed.
*/
public static MimeMessage createMimeMessage(final Session session, final String source) throws MessagingException, IOException {
// RFC1341: https://www.w3.org/Protocols/rfc1341/7_1_Text.html
return createMimeMessage(session, source.getBytes(StandardCharsets.US_ASCII));
}
/**
* Writes a MimeMessage into a file.
*
* @param mimeMessage the MimeMessage to write.
* @param resultFile the file containing the MimeMessage.
* @throws MessagingException accessing MimeMessage failed.
* @throws IOException writing the MimeMessage failed.
*/
public static void writeMimeMessage(final MimeMessage mimeMessage, final File resultFile) throws MessagingException, IOException {
if (!resultFile.getParentFile().exists() && !resultFile.getParentFile().mkdirs()) {
throw new IOException("Failed to create the following parent directories: " + resultFile.getParentFile());
}
try (OutputStream outputStream = new FileOutputStream(resultFile)) {
mimeMessage.writeTo(outputStream);
outputStream.flush();
}
}
/**
* Instances should NOT be constructed in standard programming.
*/
private MimeMessageUtils() {
}
} |
File |
Project |
Line |
org/apache/commons/mail2/jakarta/resolver/DataSourceUrlResolver.java |
Apache Commons Email for Jakarta |
34 |
org/apache/commons/mail2/javax/resolver/DataSourceUrlResolver.java |
Apache Commons Email for Javax |
34 |
public class DataSourceUrlResolver extends DataSourceBaseResolver {
/** The base url of the resource when resolving relative paths */
private final URL baseUrl;
/**
* Constructs a new instance.
*
* @param baseUrl the base URL used for resolving relative resource locations
*/
public DataSourceUrlResolver(final URL baseUrl) {
this.baseUrl = baseUrl;
}
/**
* Constructs a new instance.
*
* @param baseUrl the base URL used for resolving relative resource locations
* @param lenient shall we ignore resources not found or complain with an exception
*/
public DataSourceUrlResolver(final URL baseUrl, final boolean lenient) {
super(lenient);
this.baseUrl = baseUrl;
}
/**
* Create an URL based on a base URL and a resource location suitable for loading the resource.
*
* @param resourceLocation a resource location
* @return the corresponding URL
* @throws java.net.MalformedURLException creating the URL failed
*/
protected URL createUrl(final String resourceLocation) throws MalformedURLException {
// if we get an non-existing base url than the resource can
// be directly used to create an URL
if (baseUrl == null) {
return new URL(resourceLocation);
}
// if we get an non-existing location what we shall do?
if (EmailUtils.isEmpty(resourceLocation)) {
throw new IllegalArgumentException("No resource defined");
}
// if we get a stand-alone resource than ignore the base url
if (isFileUrl(resourceLocation) || isHttpUrl(resourceLocation)) {
return new URL(resourceLocation);
}
return new URL(getBaseUrl(), resourceLocation.replace("&", "&"));
}
/**
* Gets the base URL used for resolving relative resource locations.
*
* @return the baseUrl
*/
public URL getBaseUrl() {
return baseUrl;
}
/** {@inheritDoc} */
@Override
public DataSource resolve(final String resourceLocation) throws IOException {
return resolve(resourceLocation, isLenient());
}
/** {@inheritDoc} */
@Override
public DataSource resolve(final String resourceLocation, final boolean isLenient) throws IOException {
DataSource result = null;
try {
if (!isCid(resourceLocation)) {
result = new URLDataSource(createUrl(resourceLocation));
// validate we can read.
try (InputStream inputStream = result.getInputStream()) {
inputStream.read();
}
}
return result;
} catch (final IOException e) {
if (isLenient) {
return null;
}
throw e;
}
}
} |
File |
Project |
Line |
org/apache/commons/mail2/jakarta/resolver/DataSourcePathResolver.java |
Apache Commons Email for Jakarta |
35 |
org/apache/commons/mail2/javax/resolver/DataSourcePathResolver.java |
Apache Commons Email for Javax |
35 |
public final class DataSourcePathResolver extends DataSourceBaseResolver {
/**
* The base directory of the resource when resolving relative paths.
*/
private final Path baseDir;
/**
* NIO options to open the data source.
*/
private final OpenOption[] options;
/**
* Constructs a new instance.
*/
public DataSourcePathResolver() {
this(Paths.get("."));
}
/**
* Constructs a new instance.
*
* @param baseDir the base directory of the resource when resolving relative paths
*/
public DataSourcePathResolver(final Path baseDir) {
this(baseDir, false);
}
/**
* Constructs a new instance.
*
* @param baseDir the base directory of the resource when resolving relative paths
* @param lenient shall we ignore resources not found or complain with an exception
* @param options options for opening streams.
*/
public DataSourcePathResolver(final Path baseDir, final boolean lenient, final OpenOption... options) {
super(lenient);
this.baseDir = baseDir;
this.options = options;
}
/**
* Gets the base directory used for resolving relative resource locations.
*
* @return the baseUrl
*/
public Path getBaseDir() {
return baseDir;
}
/** {@inheritDoc} */
@Override
public DataSource resolve(final String resourceLocation) throws IOException {
return resolve(resourceLocation, isLenient());
}
/** {@inheritDoc} */
@Override
public DataSource resolve(final String resourceLocation, final boolean isLenient) throws IOException {
Path file;
DataSource result = null;
if (!isCid(resourceLocation)) {
file = Paths.get(resourceLocation);
if (!file.isAbsolute()) {
file = getBaseDir() != null ? getBaseDir().resolve(resourceLocation) : Paths.get(resourceLocation);
}
if (Files.exists(file)) {
result = new PathDataSource(file, FileTypeMap.getDefaultFileTypeMap(), options);
} else if (!isLenient) {
throw new IOException("Cant resolve the following file resource :" + file.toAbsolutePath());
}
}
return result;
}
} |
File |
Project |
Line |
org/apache/commons/mail2/jakarta/resolver/DataSourceFileResolver.java |
Apache Commons Email for Jakarta |
30 |
org/apache/commons/mail2/javax/resolver/DataSourceFileResolver.java |
Apache Commons Email for Javax |
30 |
public class DataSourceFileResolver extends DataSourceBaseResolver {
/** The base directory of the resource when resolving relative paths */
private final File baseDir;
/**
* Constructs a new instance.
*/
public DataSourceFileResolver() {
baseDir = new File(".");
}
/**
* Constructs a new instance.
*
* @param baseDir the base directory of the resource when resolving relative paths
*/
public DataSourceFileResolver(final File baseDir) {
this.baseDir = baseDir;
}
/**
* Constructs a new instance.
*
* @param baseDir the base directory of the resource when resolving relative paths
* @param lenient shall we ignore resources not found or complain with an exception
*/
public DataSourceFileResolver(final File baseDir, final boolean lenient) {
super(lenient);
this.baseDir = baseDir;
}
/**
* Gets the base directory used for resolving relative resource locations.
*
* @return the baseUrl
*/
public File getBaseDir() {
return baseDir;
}
/** {@inheritDoc} */
@Override
public DataSource resolve(final String resourceLocation) throws IOException {
return resolve(resourceLocation, isLenient());
}
/** {@inheritDoc} */
@Override
public DataSource resolve(final String resourceLocation, final boolean isLenient) throws IOException {
File file;
DataSource result = null;
if (!isCid(resourceLocation)) {
file = new File(resourceLocation);
if (!file.isAbsolute()) {
file = getBaseDir() != null ? new File(getBaseDir(), resourceLocation) : new File(resourceLocation);
}
if (file.exists()) {
result = new FileDataSource(file);
} else if (!isLenient) {
throw new IOException("Cant resolve the following file resource :" + file.getAbsolutePath());
}
}
return result;
}
} |
File |
Project |
Line |
org/apache/commons/mail2/jakarta/resolver/DataSourceCompositeResolver.java |
Apache Commons Email for Jakarta |
30 |
org/apache/commons/mail2/javax/resolver/DataSourceCompositeResolver.java |
Apache Commons Email for Javax |
30 |
public class DataSourceCompositeResolver extends DataSourceBaseResolver {
/** The list of resolvers */
private final DataSourceResolver[] dataSourceResolvers;
/**
* Constructs a new instance.
*
* @param dataSourceResolvers a list of resolvers being used
*/
public DataSourceCompositeResolver(final DataSourceResolver[] dataSourceResolvers) {
this.dataSourceResolvers = dataSourceResolvers.clone();
}
/**
* Constructs a new instance.
*
* @param dataSourceResolvers a list of resolvers being used
* @param isLenient shall we ignore resources not found or throw an exception?
*/
public DataSourceCompositeResolver(final DataSourceResolver[] dataSourceResolvers, final boolean isLenient) {
super(isLenient);
this.dataSourceResolvers = dataSourceResolvers.clone();
}
/**
* Gets the underlying data source resolvers.
*
* @return underlying data source resolvers
*/
public DataSourceResolver[] getDataSourceResolvers() {
// clone the internal array to prevent external modification (see EMAIL-116)
return dataSourceResolvers.clone();
}
/** {@inheritDoc} */
@Override
public DataSource resolve(final String resourceLocation) throws IOException {
final DataSource result = resolve(resourceLocation, true);
if (isLenient() || result != null) {
return result;
}
throw new IOException("The following resource was not found : " + resourceLocation);
}
/** {@inheritDoc} */
@Override
public DataSource resolve(final String resourceLocation, final boolean isLenient) throws IOException {
for (final DataSourceResolver dataSourceResolver : dataSourceResolvers) {
final DataSource dataSource = dataSourceResolver.resolve(resourceLocation, isLenient);
if (dataSource != null) {
return dataSource;
}
}
if (isLenient) {
return null;
}
throw new IOException("The following resource was not found : " + resourceLocation);
}
} |
File |
Project |
Line |
org/apache/commons/mail2/jakarta/util/IDNEmailAddressConverter.java |
Apache Commons Email for Jakarta |
34 |
org/apache/commons/mail2/javax/util/IDNEmailAddressConverter.java |
Apache Commons Email for Javax |
34 |
public class IDNEmailAddressConverter {
/**
* Constructs a new instance.
*/
public IDNEmailAddressConverter() {
// empty
}
/**
* Extracts the domain part of the email address.
*
* @param email email address.
* @param idx index of '@' character.
* @return domain part of email
*/
private String getDomainPart(final String email, final int idx) {
return email.substring(idx + 1);
}
/**
* Extracts the local part of the email address.
*
* @param email email address.
* @param idx index of '@' character.
* @return local part of email
*/
private String getLocalPart(final String email, final int idx) {
return email.substring(0, idx);
}
/**
* Converts an email address to its ASCII representation using "Punycode".
*
* @param email email address.
* @return The ASCII representation
*/
public String toASCII(final String email) {
return toString(email, IDN::toASCII);
}
private String toString(final String email, final Function<String, String> converter) {
final int idx = email == null ? -1 : email.indexOf('@');
if (idx < 0) {
return email;
}
return getLocalPart(email, idx) + '@' + converter.apply(getDomainPart(email, idx));
}
/**
* Converts the address part of an InternetAddress to its Unicode representation.
*
* @param address email address.
* @return The Unicode representation
*/
String toUnicode(final InternetAddress address) {
return address != null ? toUnicode(address.getAddress()) : null;
}
/**
* Converts an "Punycode" email address to its Unicode representation.
*
* @param email email address.
* @return The Unicode representation
*/
String toUnicode(final String email) {
return toString(email, IDN::toUnicode);
}
} |
File |
Project |
Line |
org/apache/commons/mail2/jakarta/activation/PathDataSource.java |
Apache Commons Email for Jakarta |
41 |
org/apache/commons/mail2/javax/activation/PathDataSource.java |
Apache Commons Email for Javax |
41 |
public final class PathDataSource implements DataSource {
/**
* The source.
*/
private final Path path;
/**
* Defaults to {@link FileTypeMap#getDefaultFileTypeMap()}.
*/
private final FileTypeMap typeMap;
/**
* NIO options to open the source Path.
*/
private final OpenOption[] options;
/**
* Creates a new instance from a Path.
* <p>
* The file will not actually be opened until a method is called that requires the path to be opened.
* </p>
* <p>
* The type map defaults to {@link FileTypeMap#getDefaultFileTypeMap()}.
*
* @param path the path
*/
public PathDataSource(final Path path) {
this(path, FileTypeMap.getDefaultFileTypeMap());
}
/**
* Creates a new instance from a Path.
* <p>
* The file will not actually be opened until a method is called that requires the path to be opened.
* </p>
*
* @param path the path, non-null.
* @param typeMap the type map, non-null.
* @param options options for opening file streams.
*/
public PathDataSource(final Path path, final FileTypeMap typeMap, final OpenOption... options) {
this.path = Objects.requireNonNull(path, "path");
this.typeMap = Objects.requireNonNull(typeMap, "typeMap");
this.options = options;
}
/**
* Gets the MIME type of the data as a String. This method uses the currently installed FileTypeMap. If there is no FileTypeMap explicitly set, the
* FileDataSource will call the {@link FileTypeMap#getDefaultFileTypeMap} method to acquire a default FileTypeMap.
* <p>
* By default, the {@link FileTypeMap} used will be a {@link MimetypesFileTypeMap}.
* </p>
*
* @return the MIME Type
* @see FileTypeMap#getDefaultFileTypeMap
*/
@Override
public String getContentType() {
return typeMap.getContentType(getName());
}
/**
* Gets an InputStream representing the the data and will throw an IOException if it can not do so. This method will return a new instance of InputStream
* with each invocation.
*
* @return an InputStream
*/
@Override
public InputStream getInputStream() throws IOException {
return Files.newInputStream(path, options);
}
/**
* Gets the <em>name</em> of this object. The FileDataSource will return the file name of the object.
*
* @return the name of the object or null.
* @see jakarta.activation.DataSource
*/
@Override
public String getName() {
return Objects.toString(path.getFileName(), null);
}
/**
* Gets an OutputStream representing the the data and will throw an IOException if it can not do so. This method will return a new instance of OutputStream
* with each invocation.
*
* @return an OutputStream
*/
@Override
public OutputStream getOutputStream() throws IOException {
return Files.newOutputStream(path, options);
}
/**
* Gets the File object that corresponds to this PathDataSource.
*
* @return the File object for the file represented by this object.
*/
public Path getPath() {
return path;
}
} |
File |
Project |
Line |
org/apache/commons/mail2/jakarta/EmailAttachment.java |
Apache Commons Email for Jakarta |
32 |
org/apache/commons/mail2/javax/EmailAttachment.java |
Apache Commons Email for Javax |
32 |
public static final String INLINE = jakarta.mail.Part.INLINE;
/** The name of this attachment. */
private String name = "";
/** The description of this attachment. */
private String description = "";
/** The path to this attachment (ie c:/path/to/file.jpg). */
private String path = "";
/** The HttpURI where the file can be got. */
private URL url;
/** The disposition. */
private String disposition = ATTACHMENT;
/**
* Constructs a new instance.
*/
public EmailAttachment() {
// empty
}
/**
* Gets the description.
*
* @return A String.
* @since 1.0
*/
public String getDescription() {
return description;
}
/**
* Gets the disposition.
*
* @return A String.
* @since 1.0
*/
public String getDisposition() {
return disposition;
}
/**
* Gets the name.
*
* @return A String.
* @since 1.0
*/
public String getName() {
return name;
}
/**
* Gets the path.
*
* @return A String.
* @since 1.0
*/
public String getPath() {
return path;
}
/**
* Gets the URL.
*
* @return A URL.
* @since 1.0
*/
public URL getURL() {
return url;
}
/**
* Sets the description.
*
* @param desc A String.
* @since 1.0
*/
public void setDescription(final String desc) {
this.description = desc;
}
/**
* Sets the disposition.
*
* @param aDisposition A String.
* @since 1.0
*/
public void setDisposition(final String aDisposition) {
this.disposition = aDisposition;
}
/**
* Sets the name.
*
* @param aName A String.
* @since 1.0
*/
public void setName(final String aName) {
this.name = aName;
}
/**
* Sets the path to the attachment. The path can be absolute or relative and should include the file name.
* <p>
* Example: /home/user/images/image.jpg<br>
* Example: images/image.jpg
*
* @param aPath A String.
* @since 1.0
*/
public void setPath(final String aPath) {
this.path = aPath;
}
/**
* Sets the URL.
*
* @param aUrl A URL.
* @since 1.0
*/
public void setURL(final URL aUrl) {
this.url = aUrl;
}
} |
File |
Project |
Line |
org/apache/commons/mail2/jakarta/activation/InputStreamDataSource.java |
Apache Commons Email for Jakarta |
34 |
org/apache/commons/mail2/javax/activation/InputStreamDataSource.java |
Apache Commons Email for Javax |
34 |
public final class InputStreamDataSource implements DataSource {
/**
* Default content type documented in {@link DataSource#getContentType()}.
*/
private static final String DEFAULT_CONTENT_TYPE = "application/octet-stream";
/**
* The MIME content type.
*/
private final String contentType;
/**
* The source.
*/
private final InputStream inputStream;
/**
* The optional name.
*/
private final String name;
/**
* Constructs a new instance.
*
* @param inputStream An input stream.
* @param contentType A content type.
*/
public InputStreamDataSource(final InputStream inputStream, final String contentType) {
this(inputStream, contentType, null);
}
/**
* Constructs a new instance.
*
* @param inputStream An input stream.
* @param contentType A content type.
* @param name A name.
*/
public InputStreamDataSource(final InputStream inputStream, final String contentType, final String name) {
this.inputStream = inputStream;
this.contentType = contentType != null ? contentType : DEFAULT_CONTENT_TYPE;
this.name = name;
}
@Override
public String getContentType() {
return contentType;
}
@Override
public InputStream getInputStream() throws IOException {
return inputStream;
}
@Override
public String getName() {
return name;
}
/**
* Always throws {@link UnsupportedOperationException}.
*
* @return Always throws {@link UnsupportedOperationException}.
* @throws UnsupportedOperationException Always throws {@link UnsupportedOperationException}.
*/
@Override
public OutputStream getOutputStream() {
throw new UnsupportedOperationException();
}
} |
File |
Project |
Line |
org/apache/commons/mail2/jakarta/resolver/DataSourceBaseResolver.java |
Apache Commons Email for Jakarta |
26 |
org/apache/commons/mail2/javax/resolver/DataSourceBaseResolver.java |
Apache Commons Email for Javax |
26 |
public abstract class DataSourceBaseResolver implements DataSourceResolver {
/** Whether to ignore resources not found or complain with an exception. */
private final boolean lenient;
/**
* Constructs a new instance.
*/
public DataSourceBaseResolver() {
this.lenient = false;
}
/**
* Constructs a new instance.
*
* @param lenient shall we ignore resources not found or throw an exception?
*/
public DataSourceBaseResolver(final boolean lenient) {
this.lenient = lenient;
}
/**
* Tests whether the argument is a content id.
*
* @param resourceLocation the resource location to test.
* @return true if it is a CID.
*/
protected boolean isCid(final String resourceLocation) {
return resourceLocation.startsWith("cid:");
}
/**
* Tests whether this a file URL.
*
* @param urlString the URL string.
* @return true if it is a file URL.
*/
protected boolean isFileUrl(final String urlString) {
return urlString.startsWith("file:/");
}
/**
* Tests whether this a HTTP or HTTPS URL.
*
* @param urlString the URL string to test.
* @return true if it is a HTTP or HTTPS URL.
*/
protected boolean isHttpUrl(final String urlString) {
return urlString.startsWith("http://") || urlString.startsWith("https://");
}
/**
* Tests whether to ignore resources not found or throw an exception.
*
* @return the lenient flag.
*/
public boolean isLenient() {
return lenient;
}
} |
|