com.anaptecs.jeaf.serviceproviders.mail.MailServiceProviderImpl Maven / Gradle / Ivy
The newest version!
/*
* anaptecs GmbH, Burgstr. 96, 72764 Reutlingen, Germany
*
* Copyright 2004 - 2015 All rights reserved.
*/
package com.anaptecs.jeaf.serviceproviders.mail;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Properties;
import java.util.Set;
import javax.mail.Address;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMessage.RecipientType;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import com.anaptecs.jeaf.spi.mail.MailServiceProvider;
import com.anaptecs.jeaf.spi.mail.MailServiceProviderMessages;
import com.anaptecs.jeaf.spi.mail.MailSystemException;
import com.anaptecs.jeaf.tools.api.Tools;
import com.anaptecs.jeaf.xfun.api.XFun;
import com.anaptecs.jeaf.xfun.api.checks.Assert;
import com.anaptecs.jeaf.xfun.api.checks.Check;
import com.anaptecs.jeaf.xfun.api.errorhandling.ErrorCode;
import com.anaptecs.jeaf.xfun.api.errorhandling.FailureMessage;
import com.anaptecs.jeaf.xfun.api.errorhandling.JEAFSystemException;
import com.anaptecs.jeaf.xfun.api.errorhandling.SystemException;
import com.anaptecs.jeaf.xfun.api.health.CheckLevel;
import com.anaptecs.jeaf.xfun.api.health.HealthCheckResult;
import com.anaptecs.jeaf.xfun.api.health.HealthStatus;
import com.anaptecs.jeaf.xfun.api.info.RuntimeEnvironment;
import com.anaptecs.jeaf.xfun.api.trace.Trace;
import com.sun.mail.smtp.SMTPTransport;
/**
* This class is an implementation of JEAF's MailServiceProvider
interface.
*
* @author JEAF Development Team
* @version 1.0
*/
final class MailServiceProviderImpl extends MailServiceProviderImplBase implements MailServiceProvider {
/** The Constant DEFAULT_MAIL_DEBUG. */
private static final boolean DEFAULT_MAIL_DEBUG = false;
/** The Constant DEFAULT_MAIL_FROM. */
private static final String DEFAULT_MAIL_FROM = "";
/** The Constant DEFAULT_MAIL_SMTP_AUTH. */
private static final boolean DEFAULT_MAIL_SMTP_AUTH = false;
/** The Constant DEFAULT_MAIL_SMTP_HOST. */
private static final String DEFAULT_MAIL_SMTP_HOST = "localhost";
/** The Constant DEFAULT_MAIL_SMTP_PASSWORD. */
private static final String DEFAULT_MAIL_SMTP_PASSWORD = "";
/** The Constant DEFAULT_MAIL_SMTP_PORT. */
private static final int DEFAULT_MAIL_SMTP_PORT = 25;
/** The Constant DEFAULT_MAIL_SMTP_SENDPARTIAL. */
private static final boolean DEFAULT_MAIL_SMTP_SENDPARTIAL = false;
/** The Constant DEFAULT_MAIL_SMTP_SSL_ENABLE. */
private static final boolean DEFAULT_MAIL_SMTP_SSL_ENABLE = false;
/** The Constant DEFAULT_MAIL_SMTP_STARTTLS_ENABLE. */
private static final boolean DEFAULT_MAIL_SMTP_STARTTLS_ENABLE = false;
/** The Constant DEFAULT_MAIL_SMTP_USER. */
private static final String DEFAULT_MAIL_SMTP_USER = "";
/** The Constant DEFAULT_MAIL_STORE_PROTOCOL. */
private static final String DEFAULT_MAIL_STORE_PROTOCOL = "pop3";
/** The Constant DEFAULT_MAIL_TANSPORT_PROTOCOL. */
private static final String DEFAULT_MAIL_TANSPORT_PROTOCOL = "smtp";
/**
* Session that will be used to send an e-mail. Actually the session should be set in the initialize method. However
* this is not possible due to the fact that properties are not accessible at this phase of the bootstrapping of JEAF.
* Thus the session is loaded lazy. To retrieve a session method getSession has to be used.
*/
private Session session;
/**
* Constructor has reduced visibility in order to ensure that all service provider implementations are created through
* the factory.
*/
MailServiceProviderImpl( ) {
}
/**
* Method checks the current state of the service provider. Therefore JEAF defines three different check levels:
* internal Checks, infrastructure checks and external checks. For further details about the check levels
* {@see CheckLevel}. This service does not implement any checks.
*
* @param pLevel Check level on which the check should be performed. Parameter will be ignored.
* @return {@link CheckResult} Since the method does not implement any checks it will always return null.
*/
public HealthCheckResult check( CheckLevel pLevel ) {
List lWarnings = new ArrayList(1);
List lErrors = new ArrayList(1);
// Check if sending of mails is disabled. This will cause a warning.
if (this.getMailDisableSending() == true) {
FailureMessage lWarning = new FailureMessage(MailServiceProviderMessages.SENDING_MAILS_DISABLED, null, null);
lWarnings.add(lWarning);
}
// Check if sender mail address is set. This will cause an error.
if (this.getMailFrom() == null) {
FailureMessage lError = new FailureMessage(MailServiceProviderMessages.MAIL_FROM_NO_SET, null, null);
lErrors.add(lError);
}
// Check if mail from personal is not set. This will cause an warning.
if (this.getMailFromPersonal() == null) {
FailureMessage lWarning = new FailureMessage(MailServiceProviderMessages.MAIL_FROM_PERSONAL_NO_SET, null, null);
lWarnings.add(lWarning);
}
return new HealthCheckResult(HealthStatus.ERROR, lWarnings, lErrors);
}
/**
* This method will be called at startup by JEAF and enables the service provider to perform its specific
* initialization routines.
*
* @throws SystemException Service provider specific exception in order to show that the initialization was not
* successful.
*/
public void initialize( ) throws SystemException {
// Nothing what we can do here.
}
/**
* Method sends an e-mail using the passed message object. The subject, content and recipients of the message have to
* be specified inside the passed message object.
*
* @param pMessage Message to be sent. The parameter must not be null.
*/
public void sendMail( Message pMessage ) {
// Check parameter.
Check.checkInvalidParameterNull(pMessage, "pMessage");
SMTPTransport lSMTPTransport = null;
// Send the message.
try {
// Prepare trace message
Trace lTrace = XFun.getTrace();
List lAllRecipients = Arrays.asList(pMessage.getAllRecipients());
String lSubject = pMessage.getSubject();
if (this.getMailDisableSending() == false) {
// Trace message.
lTrace.write(MailServiceProviderMessages.SENDING_MAIL, lSubject, lAllRecipients.toString());
// Get the transport and establish the connection
Session lSession = this.getSession();
lSMTPTransport = (SMTPTransport) lSession.getTransport();
boolean lAuthentictionRequired = this.getMailSmtpAuth();
String lHost = lSession.getProperty(JavaMailConstants.MAIL_SMTP_HOST);
int lPort = Integer.valueOf(lSession.getProperty(JavaMailConstants.MAIL_SMTP_PORT)).intValue();
if (lAuthentictionRequired == true) {
String lUser = lSession.getProperty(JavaMailConstants.MAIL_SMTP_USER);
String lPassword = lSession.getProperty(JavaMailConstants.MAIL_SMTP_PASSWORD);
lTrace.debug("Establishing connection to smtp server " + lHost + ":" + lPort + " with user " + lUser);
lSMTPTransport.connect(lHost, lPort, lUser, lPassword);
}
else {
lTrace.debug("Establishing anonymous connection to smtp server " + lHost + ":" + lPort);
lSMTPTransport.connect(lHost, lPort, null, null);
}
// Send the message through SMTP transport
lSMTPTransport.sendMessage(pMessage, pMessage.getAllRecipients());
}
// Just write trace message that mail was not send as sending is disabled.
else {
lTrace.write(MailServiceProviderMessages.NOT_SENDING_MAIL, lSubject, lAllRecipients.toString());
}
}
catch (MessagingException e) {
throw new MailSystemException(MailServiceProviderMessages.MAIL_MESSAGE_SEND_ERROR, e, e.getLocalizedMessage());
}
finally {
// Close SMTP transport if necessary
if (lSMTPTransport != null && lSMTPTransport.isConnected()) {
try {
lSMTPTransport.close();
}
catch (MessagingException e) {
throw new MailSystemException(MailServiceProviderMessages.MAIL_MESSAGE_SEND_ERROR, e,
e.getLocalizedMessage());
}
}
}
}
/**
* Method sends an e-mail using a newly created message with the passed subject, content and recipients objects.
*
* @param pContent The content of the message. The parameter can be empty but must not be null.
* @param pSubject The subject of the message. The parameter can be empty but must not be null.
* @param pRecipients The recipients of the message. The parameter must at least contain one valid
* Address
and must not be null.
*/
public void sendMail( String pContent, String pSubject, Set pRecipients ) {
// Check parameters.
Check.checkInvalidParameterNull(pContent, "pContent");
Check.checkInvalidParameterNull(pSubject, "pSubject");
Check.checkInvalidParameterNull(pRecipients, "pRecipients");
// Create the MimeMessage.
Message lMessage = this.createMessage(pContent, pSubject, pRecipients);
// Send the message.
this.sendMail(lMessage);
}
/**
* Method creates and returns an empty message object.
*
* @return {@link MimeMessage} An empty MimeMessage
. The method must not return null.
*/
public MimeMessage createMessage( ) {
// Create new message and use sender address that is defined as property.
Session lSession = this.getSession();
MimeMessage lMessage = new MimeMessage(lSession);
try {
String lMailFrom = this.getMailFrom();
Assert.assertNotNull(lMailFrom, "Dynamic Property 'mailFrom'");
InternetAddress lAddress = new InternetAddress(lMailFrom);
String lMailFromPersonal = this.getMailFromPersonal();
if (lMailFromPersonal != null) {
lAddress.setPersonal(lMailFromPersonal);
}
lMessage.setFrom(lAddress);
}
catch (MessagingException e) {
final ErrorCode lErrorCode = MailServiceProviderMessages.MAIL_MESSAGE_SET_FIELD_ERROR;
throw new MailSystemException(lErrorCode, e);
}
catch (UnsupportedEncodingException e) {
final ErrorCode lErrorCode = MailServiceProviderMessages.MAIL_MESSAGE_SET_FIELD_ERROR;
throw new MailSystemException(lErrorCode, e);
}
return lMessage;
}
/**
* Method creates and returns a message object using the passed content, subject and recipients objects.
*
* @param pContent The content of the message. The parameter can be empty but must not be null.
* @param pSubject The subject of the message. The parameter can be empty but must not be null.
* @param pRecipients The recipients of the message. The parameter must at least contain one valid
* Address
and must not be null.
* @return {@link MimeMessage} A MimeMessage
filled with the passed parameters. The method must not
* return null.
*/
public MimeMessage createMessage( String pContent, String pSubject, Set pRecipients ) {
// Check parameters.
Check.checkInvalidParameterNull(pContent, "pContent");
Check.checkInvalidParameterNull(pSubject, "pSubject");
Check.checkInvalidParameterNull(pRecipients, "pRecipients");
try {
// Create an empty message object.
MimeMessage lMailMessage = this.createMessage();
// Fill the empty message object with the passed parameters.
lMailMessage.setSubject(pSubject);
lMailMessage.setText(pContent);
lMailMessage.setSentDate(new Date());
for (Address bAddress : pRecipients) {
lMailMessage.addRecipient(RecipientType.TO, bAddress);
}
// Return create mail message.
return lMailMessage;
}
catch (MessagingException e) {
final ErrorCode lErrorCode = MailServiceProviderMessages.MAIL_MESSAGE_SET_FIELD_ERROR;
throw new MailSystemException(lErrorCode, e);
}
}
/**
* Method returns the mail session that can be used to create and send messages.
*
* @return {@link Session} Session that can be used to create a message. The method never returns null.
*/
private synchronized Session getSession( ) {
// Check if session is still working.
if (session != null) {
String lMailTransportProtocol = this.getMailTransportProtocol();
try {
// Check if session is connected. If not any more than we need a new session.
Transport lTransport = session.getTransport(lMailTransportProtocol);
boolean lConnected = lTransport.isConnected();
if (lConnected == false) {
session = null;
XFun.getTrace().info("Invalidating current mail session as it is not connected any more.");
}
}
// Unable to create transport object. This might be a configuration problem.
catch (MessagingException e) {
throw new MailSystemException(MailServiceProviderMessages.MAIL_MESSAGE_SEND_ERROR, e, e.getLocalizedMessage());
}
}
// Currently no mail session is available. So we have to create one.
if (session == null) {
XFun.getTrace().info("Trying to create a new mail session.");
// Execute platform dependent "lookup" for a session.
RuntimeEnvironment lRuntimeEnvironment = XFun.getInfoProvider().getRuntimeEnvironment();
switch (lRuntimeEnvironment) {
// In JavaSE environments the session has to be created using a Properties object.
// The transport object is created using the transport protocol specified in the properties.
case JSE:
Properties lJSEProperties = this.loadJavaSEProperties();
session = Session.getInstance(lJSEProperties);
break;
// Within the EJB container a JNDI lookup for the session has to be performed.
// The transport object is created using the transport protocol specified in the application server's
// configuration. If the JNDI path is not specified a fallback is performed that creates the session using a
// Properties object.
case EJB_CONTAINER:
// Get mailSessionJNDI Property
String lMailSessionJndi = this.getMailSessionJNDI();
if (Tools.getStringTools().isBlank(lMailSessionJndi)) {
Properties lEJBProperties = this.loadJavaSEProperties();
session = Session.getInstance(lEJBProperties);
}
else {
try {
InitialContext lContext = new InitialContext();
session = (Session) lContext.lookup(lMailSessionJndi);
lContext.close();
}
catch (NamingException e) {
throw new JEAFSystemException(MailServiceProviderMessages.MAIL_JNDI_LOOKUP_ERROR, e, lMailSessionJndi);
}
}
break;
// All other environments are currently not supported for the use with this service provider implementation.
default:
throw new JEAFSystemException(MailServiceProviderMessages.UNSUPPORTED_RUNTIME,
lRuntimeEnvironment.toString());
}
}
// Return existing session
return session;
}
/**
* Loads the MailServiceProvider property list. This method should be used for a JavaSE Runtime Environment.
*
* @return {@link Properties} A property list. The method must not return null.
*/
private Properties loadJavaSEProperties( ) {
// Prevent the getters from passing on null to the property list by instead using default values.
boolean lMailDebug = this.getMailDebug() == null ? DEFAULT_MAIL_DEBUG : this.getMailDebug();
String lMailFrom = Tools.getStringTools().isBlank(this.getMailFrom()) ? DEFAULT_MAIL_FROM : this.getMailFrom();
boolean lMailSmtpAuth = this.getMailSmtpAuth() == null ? DEFAULT_MAIL_SMTP_AUTH : this.getMailSmtpAuth();
String lMailSmtpHost =
Tools.getStringTools().isBlank(this.getMailSmtpHost()) ? DEFAULT_MAIL_SMTP_HOST : this.getMailSmtpHost();
int lMailSmtpPort = this.getMailSmtpPort() == null ? DEFAULT_MAIL_SMTP_PORT : this.getMailSmtpPort();
boolean lMailSmtpSendpartial =
this.getMailSmtpSendpartial() == null ? DEFAULT_MAIL_SMTP_SENDPARTIAL : this.getMailSmtpSendpartial();
String lMailSmtpPassword = Tools.getStringTools().isBlank(this.getMailSmtpPassword()) ? DEFAULT_MAIL_SMTP_PASSWORD
: this.getMailSmtpPassword();
String lMailSmtpUser =
Tools.getStringTools().isBlank(this.getMailSmtpUser()) ? DEFAULT_MAIL_SMTP_USER : this.getMailSmtpUser();
String lMailStoreProtocol =
Tools.getStringTools().isBlank(this.getMailStoreProtocol()) ? DEFAULT_MAIL_STORE_PROTOCOL
: this.getMailStoreProtocol();
String lMailTransportProtocol =
Tools.getStringTools().isBlank(this.getMailTransportProtocol()) ? DEFAULT_MAIL_TANSPORT_PROTOCOL
: this.getMailTransportProtocol();
boolean lMailSmtpStarttlsEnable =
this.getMailSmtpStarttlsEnable() == null ? DEFAULT_MAIL_SMTP_STARTTLS_ENABLE : this.getMailSmtpStarttlsEnable();
boolean lMailSmtpSslEnable =
this.getMailSmtpSslEnable() == null ? DEFAULT_MAIL_SMTP_SSL_ENABLE : this.getMailSmtpSslEnable();
// Add the values from the getters to the property list.
Properties lProperties = new Properties();
lProperties.setProperty(JavaMailConstants.MAIL_DEBUG, Boolean.toString(lMailDebug));
lProperties.setProperty(JavaMailConstants.MAIL_FROM, lMailFrom);
lProperties.setProperty(JavaMailConstants.MAIL_SMTP_AUTH, Boolean.toString(lMailSmtpAuth));
lProperties.setProperty(JavaMailConstants.MAIL_SMTP_AUTH_PLAIN_DISABLE, Boolean.toString(false));
lProperties.setProperty(JavaMailConstants.MAIL_SMTP_AUTH_LOGIN_DISABLE, Boolean.toString(false));
lProperties.setProperty(JavaMailConstants.MAIL_SMTP_AUTH_DIGESTMD5_DISABLE, Boolean.toString(true));
lProperties.setProperty(JavaMailConstants.MAIL_SMTP_AUTH_NTLM_DISABLE, Boolean.toString(true));
lProperties.setProperty(JavaMailConstants.MAIL_SMTP_HOST, lMailSmtpHost);
lProperties.setProperty(JavaMailConstants.MAIL_SMTP_PASSWORD, lMailSmtpPassword);
lProperties.setProperty(JavaMailConstants.MAIL_SMTP_PORT, Integer.toString(lMailSmtpPort));
lProperties.setProperty(JavaMailConstants.MAIL_SMTP_SENDPARTIAL, Boolean.toString(lMailSmtpSendpartial));
lProperties.setProperty(JavaMailConstants.MAIL_SMTP_STARTTLS_ENABLE, Boolean.toString(lMailSmtpStarttlsEnable));
lProperties.setProperty(JavaMailConstants.MAIL_SMTP_SSL_ENABLE, Boolean.toString(lMailSmtpSslEnable));
lProperties.setProperty(JavaMailConstants.MAIL_SMTP_USER, lMailSmtpUser);
lProperties.setProperty(JavaMailConstants.MAIL_STORE_PROTOCOL, lMailStoreProtocol);
lProperties.setProperty(JavaMailConstants.MAIL_TRANSPORT_PROTOCOL, lMailTransportProtocol);
lProperties.setProperty(JavaMailConstants.MAIL_SMTP_TIMEOUT, "60000");
lProperties.setProperty(JavaMailConstants.MAIL_SMTP_CONNECTIONTIMEOUT, "60000");
lProperties.setProperty(JavaMailConstants.MAIL_USER, lMailSmtpUser);
lProperties.setProperty(JavaMailConstants.MAIL_PASSWORD, lMailSmtpPassword);
return lProperties;
}
}