| BaseMailSender.java |
/*
* JBoss, the OpenSource J2EE webOS
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*
* Created on Jan 9, 2004
*/
package org.jboss.net.axis.transport.mailto.client;
import java.io.IOException;
import java.io.InputStream;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Properties;
import javax.activation.DataHandler;
import javax.mail.Address;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.AddressException;
import javax.mail.internet.InternetAddress;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import org.apache.axis.AxisFault;
import org.apache.axis.MessageContext;
import org.apache.axis.handlers.BasicHandler;
import org.apache.axis.message.addressing.AddressingHeaders;
import org.apache.axis.message.addressing.Constants;
import org.apache.axis.message.addressing.EndpointReference;
import org.apache.axis.message.addressing.RelatesTo;
import org.apache.log4j.Logger;
import org.jboss.net.axis.transport.mailto.MailConstants;
import org.jboss.net.axis.transport.mailto.MailMessage;
import org.jboss.net.axis.transport.mailto.SOAPDataSource;
/**
* <dl>
* <dt><b>Title: </b><dd>Mail Sender</dd>
* <p>
* <dt><b>Description: </b><dd>This is the Email Transport's Client Side Pivot. This handler manages sending email
* and attempting to get a response email from the server.<br>
* To properly setup this transport you will need a client-deploy.wsdd that contains something like:
* <pre>
* <handler name="MailSender" type="java:org.jboss.net.axis.transport.mail.client.MailSender" >
* <parameter name="username" value="user"/>
* <parameter name="password" value="pass"/>
* <parameter name="timeout" value="120"/>
* <!-- any relavent javamail properties may be set here, these are just an example of some posibilities -->
* <parameter name="mail.store.protocol" value="pop3"/>
* <parameter name="mail.transport.protocol" value="smtp"/>
* <parameter name="mail.host" value="mail.someserver.com"/>
* <parameter name="mail.user" value="user"/>
* <parameter name="mail.from" value="user@someserver.com"/>
* <parameter name="mail.debug" value="false"/>
* </handler>
* <transport name="mail" pivot="MailSender"/>
* </pre>
* The parameters "username" and "password" are optional. If your mail server doesn't require authentication they can
* be omitted. The parameter "timeout" is to specify the number of minutes the transport will attempt to retrieve a
* response from the server. The default is 30 minutes. Any valid Javamail properties may be specified as parameters,
* and they will be read and used by the transport.
*
* </dd>
* </dl>
* @author <a href="mailto:jasone@greenrivercomputing.com">Jason Essington</a>
* @version $Revision: 1.1 $
*/
public class BaseMailSender extends BasicHandler implements MailConstants
{
public static final String MAIL_PROPS = "MailTransportClient.properties";
public static final String TRANS_PROPS = "transport.properties";
public static final String SESSION_NAME = "SessionName";
protected Logger log = Logger.getLogger(getClass());
/** If a JavaMail session is not stored in jndi, this field will hold the
* JavaMail properties used to create a session. */
static protected Properties mailProps = null;
/** The name of a javamail session from jndi that we should use rather than
* creating a new one. */
static protected String mailSessionName = null;
/* (non-Javadoc)
* @see org.apache.axis.Handler#invoke(org.apache.axis.MessageContext)
*/
public void invoke(MessageContext ctx) throws AxisFault
{
if (mailSessionName == null && mailProps == null)
{
if ((mailSessionName = (String) getOption(SESSION_NAME)) == null)
{
mailProps = getJavaMailProperties();
}
}
String msgID = sendMail(ctx);
// hook to store our request for reference while we are waiting for a response.
archiveMessage(msgID, ctx);
// hook just incase you want to do email synchronously
checkResponse(ctx);
}
protected String sendMail(MessageContext ctx) throws AxisFault
{
MailMessage mailMsg;
org.apache.axis.Message soapMsg = ctx.getRequestMessage();
Session session = getMailSession();
String msgID = null;
AddressingHeaders headers = (AddressingHeaders) ctx.getProperty(Constants.ENV_ADDRESSING_REQUEST_HEADERS);
try
{
mailMsg = new MailMessage(session);
mailMsg.setRecipients(Message.RecipientType.TO, new Address[]{new InternetAddress(headers.getTo().getPath())});
try
{
// from must be a reasonable email address
EndpointReference from = headers.getFrom();
if (from != null && !Constants.NS_URI_ANONYMOUS.equals(from.getAddress().toString()))
{
mailMsg.setFrom(new InternetAddress(from.getAddress().getPath()));
}
else
{
mailMsg.setFrom(InternetAddress.getLocalAddress(session));
}
}
catch (AddressException ae)
{
// Our from address not a valid email address, so just use the from address defined in the mail session
mailMsg.setFrom(InternetAddress.getLocalAddress(session));
}
if (headers.getMessageID() != null)
{
mailMsg.setMessageID(headers.getMessageID().toString());
}
if (headers.getRelatesTo() != null)
{
List relatesTo = headers.getRelatesTo();
for (Iterator iter = relatesTo.iterator(); iter.hasNext();)
{
RelatesTo rt = (RelatesTo) iter.next();
if (Constants.QNAME_RESPONSE.equals(rt.getType()))
{
mailMsg.setHeader(HEADER_IN_REPLY_TO, rt.getURI().toString());
}
}
}
// TODO do we need to set any more headers?
mailMsg.setDataHandler(new DataHandler(new SOAPDataSource(soapMsg)));
Transport.send(mailMsg);
msgID = mailMsg.getMessageID();
} catch (MessagingException e)
{
log.fatal("There was a problem creating the request email message", e);
throw new AxisFault("Unable to create request message");
}
if (log.isDebugEnabled())
log.debug("message-id: " + msgID);
return msgID;
}
/**
* Override this method if you need to store outgoing messages.<br>
* Note: If web service security handlers are in the handler chain,
* the message will be signed/encrypted here.
* @param msgID
* @param msgCtx
*/
protected void archiveMessage(String msgID, MessageContext msgCtx)
{
}
/**
* Override this method if you want the client to block until it recieves a response.<br>
* In reality, this is probably only usefull for testing since email is not really a synchronous operation.
* @param ctx
* @throws AxisFault
*/
protected void checkResponse(MessageContext ctx) throws AxisFault
{
}
/**
* This handler expects the JavaMail properties to be specified in the wsdd (if no SessionName is set).
* If the properties aren't there it will look for a parameter by the name of transport.properties that holds the
* name of a properties file (to be loaded by the classloader) with the required properties (only javamail properties
* will be loaded from this file, timeout and authentication information, if included, will be ignored). As a last
* resort the handler will search the classpath for MailTransportClient.properties.
*
* The precidence is transport.properties, properties in the options, then default file.
* @return
*/
protected Properties getJavaMailProperties() throws AxisFault
{
Properties props = null;
Hashtable opts = getOptions();
if (opts != null)
{
for (Iterator iter = opts.keySet().iterator(); iter.hasNext();)
{
String key = (String) iter.next();
if (key != null && key.startsWith("mail."))
{
if (props == null)
props = new Properties();
props.setProperty(key, (String) opts.get(key));
}
}
}
if (props == null)
{
String propfileName = (String) getOption(TRANS_PROPS);
// o.k. we made it this far without properties so lets try to load them from a file
// either the file specified by the transport.properties option or our default file
propfileName = propfileName == null ? MAIL_PROPS : propfileName;
InputStream is = getClass().getClassLoader().getResourceAsStream(propfileName);
if (is == null)
throw new AxisFault(propfileName + " not found.");
props = new Properties();
try
{
props.load(is);
} catch (IOException e)
{
throw new AxisFault("Unable to load mail properties.", e);
}
}
return props;
}
/**
* Fetch a mail session.
* @return Session
*/
protected Session getMailSession() throws AxisFault
{
if (log.isDebugEnabled())
log.debug("Entering: getMailSession()");
Context ctx = null;
Session mail = null;
if (mailSessionName == null)
{
mail = Session.getInstance(mailProps);
} else
{
try
{
ctx = new InitialContext();
mail = (Session) ctx.lookup(mailSessionName);
} catch (NamingException ne)
{
log.fatal("NamingException: getMailSession()\n", ne);
throw new AxisFault("Unable to find Email Session.");
} finally
{
if (ctx != null)
try
{
ctx.close();
} catch (NamingException ne)
{
}
}
}
if (log.isDebugEnabled())
log.debug("Leaving: getMailSession()");
return mail;
}
}| BaseMailSender.java |