/*
* JBoss, Home of Professional Open Source Copyright 2009, Red Hat Middleware
* LLC, and individual contributors by the @authors tag. See the copyright.txt
* in the distribution for a full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 2.1 of the License, or (at your option)
* any later version.
*
* This software is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this software; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA, or see the FSF
* site: http://www.fsf.org.
*/
package org.jboss.soa.esb.actions.routing.email;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import javax.mail.MessagingException;
import javax.mail.internet.AddressException;
import javax.mail.internet.InternetAddress;
import org.apache.log4j.Logger;
import org.jboss.soa.esb.ConfigurationException;
import org.jboss.soa.esb.common.Configuration;
import org.jboss.soa.esb.helpers.ConfigTree;
import org.jboss.soa.esb.helpers.Email;
import org.jboss.soa.esb.listeners.message.MessageDeliverException;
import org.jboss.soa.esb.message.Message;
import org.jboss.soa.esb.message.MessagePayloadProxy;
import org.jboss.soa.esb.message.Properties;
import org.jboss.soa.esb.notification.NotifyEmail;
/**
* General Emailer used for both notifiations and router.
* </p>
* This code was lifted from {@link NotifyEmail}.
*
* Configuration properties:
* <lu>
* <li>{@code host} The host name of the SMTP server. If not specified will default to the property 'org.jboss.soa.esb.mail.smtp.host' in jbossesb-properties.xml. </li>
* <li>{@code port} The port for the SMTP server. If not specified will default to the property 'org.jboss.soa.esb.mail.smtp.port' in jbossesb-properties.xml.</li>
* <li>{@code username} The username for the SMTP server. If not specified will default to the property 'org.jboss.soa.esb.mail.smtp.user' in jbossesb-properties.xml.</li>
* <li>{@code password} The password for the above username on the SMTP server. If not specified will default to the property 'org.jboss.soa.esb.mail.smtp.password' in jbossesb-properties.xml </li>
* <li>{@code username} The username for the SMTP server. If not specified will default to the property 'org.jboss.soa.esb.mail.smtp.user' in jbossesb-properties.xml </li>
* <li>{@code auth} If true will attempt to authenticate the user using the AUTH command. If not specified will default to the property 'org.jboss.soa.esb.mail.smtp.auth' in jbossesb-properties.xml </li>
* <li>{@code msgAttachmentName} filename of an attachment containing the message payload (optional). If not specified the message payload will be included in the message body.</li>
* </lu>
* Note that all of the properties except attachments can be specified jboss-esb.xml can be overridden by specifying the same properties on the ESB Message object instance
* passed to this classes sendNotification method.
* <p>
*
* @author <a href="mailto:dbevenius@jboss.com">Daniel Bevenius</a>
*
*/
public class Emailer
{
private Logger log = Logger.getLogger(Emailer.class);
/**
* The name of the attachement config attribute.
*/
private static final String MESSAGE_ATTACHMENT_NAME = "msgAttachmentName";
/**
* {@link MessagePayloadProxy} handles body locations.
*/
private MessagePayloadProxy payloadProxy;
/**
* The ESB {@link ConfigTree}
*/
private ConfigTree config;
public Emailer(final ConfigTree config) throws ConfigurationException
{
this.config = config;
checkValidAddress((String) config.getAttribute(Email.FROM), true);
checkValidAddress((String) config.getAttribute(Email.SENDTO), false);
checkValidAddress((String) config.getAttribute(Email.COPYTO), true);
payloadProxy = new MessagePayloadProxy(config);
}
/**
* Send an Email using Email() using p_o.toString() to fill in the message
* text
*
* @param message
* Object - This object's toString() method will supply contents
* of mail message
*/
public void sendEmail(final Message message) throws MessageDeliverException
{
ConfigTree configTree = config.cloneObj();
overrideSmtpProperties(message, configTree);
Object obj = payloadProxy.getPayload(message);
sendEmail(configTree, obj);
}
public void sendEmail(final Object obj) throws MessageDeliverException
{
sendEmail(config, obj);
}
/**
* Send an Email using Email() using p_o.toString() to fill in the message
* text
*
* @param message
* Object - This object's toString() method will supply contents
* of mail message
*/
public void sendEmail(final ConfigTree config, final Object obj) throws MessageDeliverException
{
try
{
String content;
byte[] payloadBytes;
if(obj instanceof byte[]) {
content = new String((byte[]) obj);
payloadBytes = (byte[])((byte[]) obj).clone();
} else {
content = obj.toString();
payloadBytes = content.getBytes();
}
ConfigTree configTree = config.cloneObj();
String sMsg = configTree.getAttribute(Email.MESSAGE);
sMsg = ((null == sMsg) ? content : (sMsg + "\n" + content));
configTree.setAttribute(Email.MESSAGE, sMsg);
sendEmail(configTree, payloadBytes);
}
catch (final AddressException e)
{
log.error("Send Mail Failed", e);
throw new MessageDeliverException("AddressException while trying to send email", e);
}
catch (final MessagingException e)
{
throw new MessageDeliverException("MessageingException while trying to send email", e);
}
catch (final IOException e)
{
log.error("Send Mail Failed", e);
throw new MessageDeliverException("IOException while trying to send email", e);
}
}
/**
* Send an email notification based on the supplied parameters. <p/> This
* method allows overriding for test purposes.
*
* @param messageParams
* Message parameters.
* @param message
* @throws IOException
*/
protected void sendEmail(ConfigTree messageParams, byte[] msgPayload) throws AddressException, MessagingException, IOException
{
Email esbMail = createEmailInstance(messageParams);
esbMail.setSendTo(messageParams.getAttribute(Email.SENDTO));
esbMail.setFrom(messageParams.getAttribute(Email.FROM));
esbMail.setCopyTo(messageParams.getAttribute(Email.COPYTO));
esbMail.setSubject(messageParams.getAttribute(Email.SUBJECT));
esbMail.setAttachments(messageParams.getTextChildren(Email.ATTACH));
if (messageParams.getAttribute(MESSAGE_ATTACHMENT_NAME) != null) {
esbMail.addAttachment(new ByteArrayInputStream(msgPayload), messageParams.getAttribute(MESSAGE_ATTACHMENT_NAME));
} else {
esbMail.setMessage(messageParams.getAttribute(Email.MESSAGE));
}
esbMail.sendMessage();
}
/**
* Allows smtp overrides by setting properties on the passed-in message. This could be
* populated by a previous action in an action pipline.
*
* @param message The ESB Message object that contains the overrides in its properties.
* @param configTree The configTree the properties on the ESB Message object will override.
*/
public static void overrideSmtpProperties(final Message message, final ConfigTree configTree)
{
final Properties properties = message.getProperties();
override(Email.HOST, properties, configTree);
override(Email.PORT, properties, configTree);
override(Email.USERNAME, properties, configTree);
override(Email.PASSWORD, properties, configTree);
override(Email.AUTH, properties, configTree);
override(Email.FROM, properties, configTree);
override(Email.SENDTO, properties, configTree);
override(Email.COPYTO, properties, configTree);
override(Email.SUBJECT, properties, configTree);
override(MESSAGE_ATTACHMENT_NAME, properties, configTree);
}
private void checkValidAddress(final String address, boolean optional) throws ConfigurationException
{
if (address == null && optional)
return;
try
{
InternetAddress.parse(address);
}
catch (AddressException e)
{
throw new ConfigurationException(address + " is not valid", e);
}
}
private static void override(final String key, final Properties properties, final ConfigTree configTree)
{
final String value = (String) properties.getProperty(key);
if (value != null)
{
configTree.setAttribute(key, value);
}
}
/**
* Creates a new {@link Email} instance using the properties specified in the
* passed-in {@link ConfigTree}.
*
* @param configTree The {@link ConfigTree} containing the SMTP properties uses to create the Email instance.
* @return Email The newly created {@link Email} instance.
* @throws AddressException
* @throws MessagingException
*/
private Email createEmailInstance(final ConfigTree configTree) throws AddressException, MessagingException
{
String portStr = configTree.getAttribute(Email.PORT);
if (portStr == null)
{
portStr = Configuration.getSmtpPort();
}
int port;
try
{
port = Integer.parseInt(portStr);
}
catch(final NumberFormatException e)
{
throw new MessagingException("Could not parse port '" + portStr + "'");
}
String host = configTree.getAttribute(Email.HOST, Configuration.getSmtpHost());
String username = configTree.getAttribute(Email.USERNAME, Configuration.getSmtpUsername());
String password = configTree.getAttribute(Email.PASSWORD,Configuration.getSmtpPassword());
boolean auth = configTree.getBooleanAttribute(Email.AUTH, false);
return new Email(host, port, username, password, auth);
}
}