charlesb 01/05/11 03:36:43
Added: src/java/org/apache/james AccessControlException.java
AuthenticationException.java
AuthorizationException.java
BaseConnectionHandler.java Constants.java
James.java James.xinfo MailHeaders.java Main.java
src/java/org/apache/james/transport JamesSpoolManager.java
JamesSpoolManager.xinfo LinearProcessor.java
MailetLoader.java MatchLoader.java Resources.java
Removed: src/org/apache/james AccessControlException.java
AuthenticationException.java
AuthorizationException.java
BaseConnectionHandler.java Constants.java
James.java James.xinfo MailHeaders.java Main.java
src/org/apache/james/transport JamesSpoolManager.java
JamesSpoolManager.xinfo LinearProcessor.java
MailetLoader.java MatchLoader.java Resources.java
Log:
Moving from src/org to src/java/org
Revision Changes Path
1.1
jakarta-james/src/java/org/apache/james/AccessControlException.java
Index: AccessControlException.java
===================================================================
/*
* Copyright (C) The Apache Software Foundation. All rights reserved.
*
* This software is published under the terms of the Apache Software License
* version 1.1, a copy of which has been included with this distribution in
* the LICENSE file.
*/
package org.apache.james;
/**
* Thrown when a user attempts to access something (e.g. a mailbox) for which
* they do not have appropriate rights.
*
* @author <a href="mailto:[EMAIL PROTECTED]">Charles Benett</a>
* @version 0.1 on 14 Dec 2000
*/
public class AccessControlException
extends Exception {
/**
* Construct a new <code>AccessControlException</code> instance.
*
* @param message The detail message for this exception (mandatory).
*/
public AccessControlException(String message) {
super(message);
}
}
1.1
jakarta-james/src/java/org/apache/james/AuthenticationException.java
Index: AuthenticationException.java
===================================================================
/*
* Copyright (C) The Apache Software Foundation. All rights reserved.
*
* This software is published under the terms of the Apache Software License
* version 1.1, a copy of which has been included with this distribution in
* the LICENSE file.
*/
package org.apache.james;
/**
* Thrown when a user fails to authenticate either because their identity is
* not recognised or because their credentials are wrong.
*
* @author <a href="mailto:[EMAIL PROTECTED]">Charles Benett</a>
* @version 0.1 on 14 Dec 2000
*/
public class AuthenticationException
extends Exception {
private boolean userNotKnown;
private boolean badCredentials;
/**
* Construct a new <code>AuthenticationException</code> instance.
*
* @param message The detail message for this exception (mandatory).
*/
public AuthenticationException( final String message,
final boolean unknownUser,
final boolean credentialsFailed ) {
super(message);
this.userNotKnown = unknownUser;
this.badCredentials = credentialsFailed;
}
public boolean isUserNotKnown() {
return userNotKnown;
}
public boolean isBadCredentials() {
return badCredentials;
}
}
1.1
jakarta-james/src/java/org/apache/james/AuthorizationException.java
Index: AuthorizationException.java
===================================================================
/*
* Copyright (C) The Apache Software Foundation. All rights reserved.
*
* This software is published under the terms of the Apache Software License
* version 1.1, a copy of which has been included with this distribution in
* the LICENSE file.
*/
package org.apache.james;
/**
* Thrown when a user attempts to do something (e.g. alter mailbox) for which
* they do not have appropriate rights.
*
* @author <a href="mailto:[EMAIL PROTECTED]">Charles Benett</a>
* @version 0.1 on 14 Dec 2000
*/
public class AuthorizationException
extends Exception {
/**
* Construct a new <code>AuthorizationException</code> instance.
*
* @param message The detail message for this exception (mandatory).
*/
public AuthorizationException( final String message ) {
super( message );
}
}
1.1
jakarta-james/src/java/org/apache/james/BaseConnectionHandler.java
Index: BaseConnectionHandler.java
===================================================================
/*
* Copyright (C) The Apache Software Foundation. All rights reserved.
*
* This software is published under the terms of the Apache Software License
* version 1.1, a copy of which has been included with this distribution in
* the LICENSE file.
*/
package org.apache.james;
import java.io.*;
import java.net.*;
import java.text.*;
import java.util.*;
import javax.mail.internet.*;
import org.apache.avalon.framework.logger.AbstractLoggable;
import org.apache.avalon.framework.activity.Initializable;
import org.apache.avalon.framework.activity.Disposable;
import org.apache.avalon.framework.component.ComponentException;
import org.apache.avalon.framework.component.ComponentManager;
import org.apache.avalon.framework.component.Composable;
import org.apache.avalon.framework.configuration.Configurable;
import org.apache.avalon.framework.configuration.Configuration;
import org.apache.avalon.framework.configuration.ConfigurationException;
import org.apache.avalon.framework.context.Context;
import org.apache.avalon.framework.context.ContextException;
import org.apache.avalon.framework.context.Contextualizable;
import org.apache.avalon.cornerstone.services.connection.ConnectionHandler;
import org.apache.avalon.cornerstone.services.scheduler.PeriodicTimeTrigger;
import org.apache.avalon.cornerstone.services.scheduler.Target;
import org.apache.avalon.cornerstone.services.scheduler.TimeScheduler;
import org.apache.james.AccessControlException;
import org.apache.james.AuthenticationException;
import org.apache.james.AuthorizationException;
import org.apache.james.Constants;
import org.apache.james.services.*;
import org.apache.james.util.InternetPrintWriter;
import org.apache.log.LogKit;
import org.apache.log.Logger;
/**
* Different connection handlers extend this class
* Common Connection Handler code could be factored into this class.
* At present(April 28' 2001) there is not much in this class
*/
public class BaseConnectionHandler extends AbstractLoggable implements Configurable {
protected int timeout;
protected String helloName;
public void configure( final Configuration configuration )
throws ConfigurationException {
timeout = configuration.getChild( "connectiontimeout" ).getValueAsInteger(
1800000 );
String hostName = null;
try {
hostName = InetAddress.getLocalHost().getHostName();
} catch (UnknownHostException ue) {
hostName = "localhost";
}
Configuration helloConf = configuration.getChild("helloName");
String autodetect = null;
try {
autodetect = helloConf.getAttribute("autodetect");
} catch(ConfigurationException ex) {
autodetect = "TRUE";
}
if ("TRUE".equals(autodetect))
helloName = hostName;
else
helloName = helloConf.getValue("localhost");
getLogger().info("Hello Name is: " + helloName);
}
}
1.1 jakarta-james/src/java/org/apache/james/Constants.java
Index: Constants.java
===================================================================
/*
* Copyright (C) The Apache Software Foundation. All rights reserved.
*
* This software is published under the terms of the Apache Software License
* version 1.1, a copy of which has been included with this distribution in
* the LICENSE file.
*/
package org.apache.james;
/**
* @version 1.0.0, 24/04/1999
* @author Federico Barbieri <[EMAIL PROTECTED]>
*/
public class Constants {
public static final String SOFTWARE_VERSION = "@@version@@";
public static final String SOFTWARE_NAME = "JAMES Mail Server";
public static final String SERVER_NAMES = "SERVER_NAMES";
public static final String SPOOL_REPOSITORY = "SPOOL_REPOSITORY";
public static final String LOCAL_USERS = "LOCAL_USERS";
public static final String POSTMASTER = "POSTMASTER";
public static final int HEADERLIMIT = 2048;
public static final String AVALON_COMPONENT_MANAGER = "AVALON_COMP_MGR";
}
1.1 jakarta-james/src/java/org/apache/james/James.java
Index: James.java
===================================================================
/*
* Copyright (C) The Apache Software Foundation. All rights reserved.
*
* This software is published under the terms of the Apache Software License
* version 1.1, a copy of which has been included with this distribution in
* the LICENSE file.
*/
package org.apache.james;
import java.io.*;
import java.net.*;
import java.util.*;
import javax.mail.Address;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.internet.*;
import org.apache.avalon.framework.activity.Initializable;
import org.apache.avalon.framework.component.Component;
import org.apache.avalon.framework.component.ComponentException;
import org.apache.avalon.framework.component.ComponentManager;
import org.apache.avalon.framework.component.Composable;
import org.apache.avalon.framework.component.DefaultComponentManager;
import org.apache.avalon.framework.configuration.Configurable;
import org.apache.avalon.framework.configuration.Configuration;
import org.apache.avalon.framework.configuration.ConfigurationException;
import org.apache.avalon.framework.configuration.DefaultConfiguration;
import org.apache.avalon.framework.context.Context;
import org.apache.avalon.framework.context.Contextualizable;
import org.apache.avalon.framework.context.Contextualizable;
import org.apache.avalon.framework.context.DefaultContext;
import org.apache.avalon.framework.logger.AbstractLoggable;
import org.apache.avalon.excalibur.thread.ThreadPool;
import org.apache.james.core.*;
import org.apache.james.imapserver.*;
import org.apache.james.services.*;
import org.apache.james.transport.*;
import org.apache.log.Logger;
import org.apache.log.Priority;
import org.apache.mailet.*;
import org.apache.avalon.phoenix.Block;
import org.apache.avalon.phoenix.BlockContext;
/**
* Core class for JAMES. Provides three primary services:
* <br> 1) Instantiates resources, such as user repository, and protocol
* handlers
* <br> 2) Handles interactions between components
* <br> 3) Provides container services for Mailets
*
* @version
* @author Federico Barbieri <[EMAIL PROTECTED]>
* @author Serge
* @author <a href="mailto:[EMAIL PROTECTED]">Charles Benett</a>
*/
public class James
extends AbstractLoggable
implements Block, Contextualizable, Composable, Configurable, Initializable,
MailServer, MailetContext {
public final static String VERSION = "James 1.2.2 Alpha";
private DefaultComponentManager compMgr; //Components shared
private DefaultContext context;
private Configuration conf;
private Logger mailetLogger = null;
//private ThreadPool workerPool;
private MailStore mailstore;
private UsersStore usersStore;
private SpoolRepository spool;
private MailRepository localInbox;
private String inboxRootURL;
private UsersRepository localusers;
private Collection serverNames;
// this used to be long, but increment operations on long are not
// thread safe. Changed to int. 'int' should be ok, because id generation
// is based on System time and count
private static int count;
private MailAddress postmaster;
private Map mailboxes; //Not to be shared!
private Hashtable attributes = new Hashtable();
// IMAP related fields
private boolean useIMAPstorage = false;
private IMAPSystem imapSystem;
private Host imapHost;
protected BlockContext blockContext;
public void contextualize( final Context context )
{
this.blockContext = (BlockContext)context;
}
public void configure(Configuration conf) {
this.conf = conf;
}
/**
* Override compose method of AbstractBlock to create new ComponentManager object
*/
public void compose(ComponentManager comp) {
//throws ConfigurationException {
compMgr = new DefaultComponentManager(comp);
mailboxes = new HashMap(31);
}
public void initialize() throws Exception {
getLogger().info("JAMES init...");
//TODO: This should retrieve a more specific named thread pool from
BlockContext
//that is set up in server.xml
//workerPool = blockContext.getThreadPool( "default" );
try {
mailstore = (MailStore)
compMgr.lookup("org.apache.james.services.MailStore");
} catch (Exception e) {
getLogger().warn("Can't get Store: " + e);
}
getLogger().debug("Using MailStore: " + mailstore.toString());
try {
usersStore = (UsersStore)
compMgr.lookup("org.apache.james.services.UsersStore");
} catch (Exception e) {
getLogger().warn("Can't get Store: " + e);
}
getLogger().debug("Using UsersStore: " + usersStore.toString());
context = new DefaultContext();
String hostName = null;
try {
hostName = InetAddress.getLocalHost().getHostName();
} catch (UnknownHostException ue) {
hostName = "localhost";
}
getLogger().info("Local host is: " + hostName);
// Get the domains and hosts served by this instance
serverNames = new Vector();
Configuration serverConf = conf.getChild("servernames");
if (serverConf.getAttribute("autodetect").equals("TRUE") &&
(!hostName.equals("localhost"))) {
serverNames.add(hostName);
}
final Configuration[] serverNameConfs =
conf.getChild( "servernames" ).getChildren( "servername" );
for ( int i = 0; i < serverNameConfs.length; i++ )
{
serverNames.add( serverNameConfs[i].getValue() );
}
if (serverNames.isEmpty()) {
throw new ConfigurationException( "Fatal configuration error: no
servernames specified!");
}
for (Iterator i = serverNames.iterator(); i.hasNext(); ) {
getLogger().info("Handling mail for: " + i.next());
}
context.put(Constants.SERVER_NAMES, this.serverNames);
// Get postmaster
String postMasterAddress =
conf.getChild("postmaster").getValue("root@localhost");
this.postmaster = new MailAddress( postMasterAddress );
context.put( Constants.POSTMASTER, postmaster );
//Get localusers
try {
localusers = (UsersRepository) usersStore.getRepository("LocalUsers");
} catch (Exception e) {
getLogger().error("Cannot open private UserRepository");
throw e;
}
//}
compMgr.put("org.apache.james.services.UsersRepository",
(Component)localusers);
getLogger().info("Local users repository opened");
// Get storage system
if (conf.getChild("storage").getValue().equals("IMAP")) {
useIMAPstorage = true;
}
//IMAPServer instance is controlled via assembly.xml.
//Assumption is that assembly.xml will set the correct IMAP Store
//if IMAP is enabled.
//if (provideIMAP && (! useIMAPstorage)) {
// throw new ConfigurationException ("Fatal configuration error: IMAP
service requires IMAP storage ");
//}
// Get the LocalInbox repository
if (useIMAPstorage) {
Configuration imapSetup = conf.getChild("imapSetup");
String imapSystemClass = imapSetup.getAttribute("systemClass");
String imapHostClass = imapSetup.getAttribute("hostClass");
try {
// We will need to use a no-args constructor for flexibility
//imapSystem = new Class.forName(imapSystemClass).newInstance();
imapSystem = new SimpleSystem();
imapSystem.configure(conf.getChild("imapHost"));
imapSystem.contextualize(context);
imapSystem.compose(compMgr);
if (imapSystem instanceof Initializable) {
((Initializable)imapSystem).initialize();
}
compMgr.put("org.apache.james.imapserver.IMAPSystem",
(Component)imapSystem);
getLogger().info("Using SimpleSystem.");
imapHost = (Host) Class.forName(imapHostClass).newInstance();
//imapHost = new JamesHost();
imapHost.configure(conf.getChild("imapHost"));
imapHost.contextualize(context);
imapHost.compose(compMgr);
if (imapHost instanceof Initializable) {
((Initializable)imapHost).initialize();
}
compMgr.put("org.apache.james.imapserver.Host", (Component)imapHost);
getLogger().info("Using: " + imapHostClass);
} catch (Exception e) {
getLogger().error("Exception in IMAP Storage init: " +
e.getMessage());
throw e;
}
} else {
Configuration inboxConf = conf.getChild("inboxRepository");
Configuration inboxRepConf = inboxConf.getChild("repository");
try {
localInbox = (MailRepository) mailstore.select(inboxRepConf);
} catch (Exception e) {
getLogger().error("Cannot open private MailRepository");
throw e;
}
inboxRootURL = inboxRepConf.getAttribute("destinationURL");
}
getLogger().info("Private Repository LocalInbox opened");
// Add this to comp
compMgr.put("org.apache.james.services.MailServer", this);
Configuration spoolConf = conf.getChild("spoolRepository");
Configuration spoolRepConf = spoolConf.getChild("repository");
try {
this.spool = (SpoolRepository) mailstore.select(spoolRepConf);
} catch (Exception e) {
getLogger().error("Cannot open private SpoolRepository");
throw e;
}
getLogger().info("Private SpoolRepository Spool opened: "+spool.hashCode());
//compMgr.put("org.apache.james.services.SpoolRepository", (Component)spool);
// For mailet engine provide MailetContext
//compMgr.put("org.apache.mailet.MailetContext", this);
// For AVALON aware mailets and matchers, we put the Component object as
// an attribute
attributes.put(Constants.AVALON_COMPONENT_MANAGER, compMgr);
// int threads =
conf.getConfiguration("spoolmanagerthreads").getValueAsInt(1);
//while (threads-- > 0) {
/*
try {
JamesSpoolManager spoolMgr = new JamesSpoolManager();
setupLogger( spoolMgr, "SpoolManager" );
spoolMgr.configure(conf.getChild("spoolmanager"));
spoolMgr.contextualize(context);
spoolMgr.compose(compMgr);
spoolMgr.initialize();
workerPool.execute(spoolMgr);
getLogger().info("SpoolManager started");
} catch (Exception e) {
getLogger().error("Exception in SpoolManager init: " + e.getMessage());
throw e;
}
*/
System.out.println("James "+VERSION);
getLogger().info("JAMES ...init end");
}
public void sendMail(MimeMessage message) throws MessagingException {
MailAddress sender = new MailAddress((InternetAddress)message.getFrom()[0]);
Collection recipients = new HashSet();
Address addresses[] = message.getAllRecipients();
for (int i = 0; i < addresses.length; i++) {
recipients.add(new MailAddress((InternetAddress)addresses[i]));
}
sendMail(sender, recipients, message);
}
public void sendMail(MailAddress sender, Collection recipients, MimeMessage
message)
throws MessagingException {
//FIX ME!!! we should validate here MimeMessage. - why? (SK)
sendMail(sender, recipients, message, Mail.DEFAULT);
}
public void sendMail(MailAddress sender, Collection recipients, MimeMessage
message, String state)
throws MessagingException {
//FIX ME!!! we should validate here MimeMessage.
MailImpl mail = new MailImpl(getId(), sender, recipients, message);
mail.setState(state);
sendMail(mail);
}
public synchronized void sendMail(MailAddress sender, Collection recipients,
InputStream msg)
throws MessagingException {
// parse headers
MailHeaders headers = new MailHeaders(msg);
// if headers do not contains minimum REQUIRED headers fields throw Exception
if (!headers.isValid()) {
throw new MessagingException("Some REQURED header field is missing.
Invalid Message");
}
// headers.setReceivedStamp("Unknown", (String)
serverNames.elementAt(0));
ByteArrayInputStream headersIn = new
ByteArrayInputStream(headers.toByteArray());
sendMail(new MailImpl(getId(), sender, recipients, new
SequenceInputStream(headersIn, msg)));
}
public synchronized void sendMail(Mail mail) throws MessagingException {
MailImpl mailimpl = (MailImpl)mail;
try {
spool.store(mailimpl);
} catch (Exception e) {
try {
spool.remove(mailimpl);
} catch (Exception ignored) {
}
throw new MessagingException("Exception spooling message: " +
e.getMessage());
}
getLogger().info("Mail " + mailimpl.getName() + " pushed in spool");
}
/**
* For POP3 server only - at the momment.
*/
public synchronized MailRepository getUserInbox(String userName) {
MailRepository userInbox = (MailRepository) null;
userInbox = (MailRepository) mailboxes.get(userName);
if (userInbox != null) {
return userInbox;
} else if (mailboxes.containsKey(userName)) {
// we have a problem
getLogger().error("Null mailbox for non-null key");
throw new RuntimeException("Error in getUserInbox.");
} else {
// need mailbox object
getLogger().info("Need inbox for " + userName );
String destination = inboxRootURL + userName + File.separator;;
DefaultConfiguration mboxConf
= new DefaultConfiguration("repository",
"generated:AvalonFileRepository.compose()");
mboxConf.addAttribute("destinationURL", destination);
mboxConf.addAttribute("type", "MAIL");
mboxConf.addAttribute("model", "SYNCHRONOUS");
try {
userInbox = (MailRepository) mailstore.select(mboxConf);
mailboxes.put(userName, userInbox);
} catch (Exception e) {
getLogger().error("Cannot open user Mailbox" + e);
throw new RuntimeException("Error in getUserInbox." + e);
}
return userInbox;
}
}
public String getId() {
return "Mail" + System.currentTimeMillis() + "-" + count++;
}
public static void main(String[] args) {
System.out.println("ERROR!");
System.out.println("Cannot execute James as a stand alone application.");
System.out.println("To run James, you need to have the Avalon framework
installed.");
System.out.println("Please refer to the Readme file to know how to run
James.");
}
//Methods for MailetContext
public Collection getMailServers(String host) {
DNSServer dnsServer = null;
try {
dnsServer = (DNSServer)
compMgr.lookup("org.apache.james.services.DNSServer");
} catch ( final ComponentException cme ) {
getLogger().error("Fatal configuration error - DNS Servers lost!", cme );
throw new RuntimeException("Fatal configuration error - DNS Servers
lost!");
}
return dnsServer.findMXRecords(host);
}
public Object getAttribute(String key) {
return attributes.get(key);
}
public void setAttribute(String key, Object object) {
attributes.put(key, object);
}
public void removeAttribute(String key) {
attributes.remove(key);
}
public Iterator getAttributeNames() {
Vector names = new Vector();
for (Enumeration e = attributes.keys(); e.hasMoreElements(); ) {
names.add(e.nextElement());
}
return names.iterator();
}
public void bounce(Mail mail, String message) throws MessagingException {
bounce(mail, message, getPostmaster());
}
public void bounce(Mail mail, String message, MailAddress bouncer) throws
MessagingException {
MimeMessage orig = mail.getMessage();
//Create the reply message
MimeMessage reply = (MimeMessage) orig.reply(false);
//Create the list of recipients in our MailAddress format
Collection recipients = new HashSet();
Address addresses[] = reply.getAllRecipients();
for (int i = 0; i < addresses.length; i++) {
recipients.add(new MailAddress((InternetAddress)addresses[i]));
}
//Change the sender...
reply.setFrom(bouncer.toInternetAddress());
try {
//Create the message body
MimeMultipart multipart = new MimeMultipart();
//Add message as the first mime body part
MimeBodyPart part = new MimeBodyPart();
part.setContent(message, "text/plain");
part.setHeader("Content-Type", "text/plain");
multipart.addBodyPart(part);
//Add the original message as the second mime body part
part = new MimeBodyPart();
part.setContent(orig.getContent(), orig.getContentType());
part.setHeader("Content-Type", orig.getContentType());
multipart.addBodyPart(part);
reply.setContent(multipart);
reply.setHeader("Content-Type", multipart.getContentType());
} catch (IOException ioe) {
throw new MessagingException("Unable to create multipart body");
}
//Send it off...
sendMail(bouncer, recipients, reply);
}
public boolean isLocalUser(String userAccout) {
return localusers.contains(userAccout);
}
public MailAddress getPostmaster() {
return postmaster;
}
public void storeMail(MailAddress sender, MailAddress recipient, MimeMessage
message) {
if (useIMAPstorage) {
ACLMailbox mbox = null;
try {
String folderName = "#users." + recipient.getUser() + ".INBOX";
getLogger().debug("Want to store to: " + folderName);
mbox = imapHost.getMailbox(MailServer.MDA, folderName);
if(mbox.store(message,MailServer.MDA)) {
getLogger().info("Message " + message.getMessageID() +" stored
in " + folderName);
} else {
throw new RuntimeException("Failed to store mail: ");
}
imapHost.releaseMailbox(MailServer.MDA, mbox);
mbox = null;
} catch (Exception e) {
getLogger().error("Exception storing mail: " + e);
e.printStackTrace();
if (mbox != null) {
imapHost.releaseMailbox(MailServer.MDA, mbox);
mbox = null;
}
throw new RuntimeException("Exception storing mail: " + e);
}
} else {
Collection recipients = new HashSet();
recipients.add(recipient);
MailImpl mailImpl = new MailImpl(getId(), sender, recipients, message);
getUserInbox(recipient.getUser()).store(mailImpl);
}
}
public int getMajorVersion() {
return 1;
}
public int getMinorVersion() {
return 2;
}
public boolean isLocalServer( final String serverName ) {
return serverNames.contains( serverName );
}
public String getServerInfo() {
return "JAMES/1.2";
}
private Logger getMailetLogger() {
if ( mailetLogger == null )
mailetLogger = getLogger().getChildLogger("Mailet");
return mailetLogger;
}
public void log(String message) {
getMailetLogger().info(message);
}
public void log(String message, Throwable t) {
//System.err.println(message);
//t.printStackTrace(); //DEBUG
getMailetLogger().log(Priority.INFO,message,t);
}
/**
* Adds a user to this mail server. Currently just adds user to a
* UsersRepository.
* <p> As we move to IMAP support this will also create mailboxes and
* access control lists.
*
* @param userName String representing user name, that is the portion of
* an email address before the '@<domain>'.
* @param password String plaintext password
* @returns boolean true if user added succesfully, else false.
*/
public boolean addUser(String userName, String password) {
localusers.addUser(userName, password);
if (useIMAPstorage) {
JamesHost jh = (JamesHost) imapHost;
if (jh.createPrivateMailAccount(userName)) {
getLogger().info("New MailAccount created for" + userName);
}
}
return true;
}
}
1.1 jakarta-james/src/java/org/apache/james/James.xinfo
Index: James.xinfo
===================================================================
<?xml version="1.0"?>
<blockinfo>
<meta>
<contributors>
<author name="Federico Barbieri" email="?"/>
<author name="Serge" email="?"/>
<author name="Charles Benett" email="[EMAIL PROTECTED]"/>
</contributors>
</meta>
<!-- services that are offered by this block -->
<services>
<service name="org.apache.james.services.MailServer" version="1.0" />
<service name="org.apache.mailet.MailetContext" version="1.0" />
</services>
<dependencies>
<dependency>
<role>org.apache.james.services.DNSServer</role>
<service name="org.apache.james.services.DNSServer" version="1.0"/>
</dependency>
<dependency>
<role>org.apache.james.services.MailStore</role>
<service name="org.apache.james.services.MailStore" version="1.0"/>
</dependency>
<dependency>
<role>org.apache.james.services.UsersStore</role>
<service name="org.apache.james.services.UsersStore" version="1.0"/>
</dependency>
<dependency>
<role>org.apache.avalon.cornerstone.services.connection.ConnectionManager</role>
<service
name="org.apache.avalon.cornerstone.services.connection.ConnectionManager"
version="1.0"/>
</dependency>
<dependency>
<role>org.apache.avalon.cornerstone.services.sockets.SocketManager</role>
<service name="org.apache.avalon.cornerstone.services.sockets.SocketManager"
version="1.0"/>
</dependency>
<dependency>
<role>org.apache.avalon.cornerstone.services.scheduler.TimeScheduler</role>
<service name="org.apache.avalon.cornerstone.services.scheduler.TimeScheduler"
version="1.0"/>
</dependency>
</dependencies>
</blockinfo>
1.1 jakarta-james/src/java/org/apache/james/MailHeaders.java
Index: MailHeaders.java
===================================================================
/*****************************************************************************
* Copyright (C) The Apache Software Foundation. All rights reserved. *
* ------------------------------------------------------------------------- *
* This software is published under the terms of the Apache Software License *
* version 1.1, a copy of which has been included with this distribution in *
* the LICENSE file. *
*****************************************************************************/
package org.apache.james;
import java.io.*;
import java.text.*;
import java.util.*;
import javax.mail.internet.*;
import javax.mail.MessagingException;
/**
* This interface defines a container for mail headers. Each header must use
* MIME format: <pre>name: value</pre>.
*
* @author Federico Barbieri <[EMAIL PROTECTED]>
*/
public class MailHeaders extends InternetHeaders implements Serializable, Cloneable {
public MailHeaders()
throws MessagingException {
super();
}
public MailHeaders(InputStream in)
throws MessagingException {
super(in);
}
public void writeTo(PrintStream writer) {
for (Enumeration e = super.getAllHeaderLines(); e.hasMoreElements(); ) {
writer.println((String) e.nextElement());
}
writer.println("");
}
public void writeTo(OutputStream out) {
writeTo(new PrintStream(out));
}
public byte[] toByteArray() {
ByteArrayOutputStream headersBytes = new ByteArrayOutputStream();
writeTo(headersBytes);
return headersBytes.toByteArray();
}
public boolean isSet(String name) {
String[] value = super.getHeader(name);
return (value != null && value.length != 0);
}
public boolean isValid() {
// Check if MimeMessage contains REQUIRED headers fields as specified in
RFC 822.
return (isSet("Date") && isSet("To") && isSet("From")); }
}
1.1 jakarta-james/src/java/org/apache/james/Main.java
Index: Main.java
===================================================================
/*****************************************************************************
* Copyright (C) The Apache Software Foundation. All rights reserved. *
* ------------------------------------------------------------------------- *
* This software is published under the terms of the Apache Software License *
* version 1.1, a copy of which has been included with this distribution in *
* the LICENSE file. *
*****************************************************************************/
package org.apache.james;
/**
* This is a fake class to display an error message if you try to execute James
* without having Avalon installed.
*
* @version 1.0.0 (CVS $Revision: 1.1 $ $Date: 2001/05/11 10:36:17 $)
* @author <a href="mailto:[EMAIL PROTECTED]">Federico Barbieri</a>
*/
public class Main {
public static void main(String[] args) {
System.out.println("ERROR!");
System.out.println("Cannot execute James as a stand alone application.");
System.out.println("To run James, you need to have the Avalon framework
installed.");
System.out.println("Please refer to the Readme file to know how to run
James.");
}
}
1.1
jakarta-james/src/java/org/apache/james/transport/JamesSpoolManager.java
Index: JamesSpoolManager.java
===================================================================
/*
* Copyright (C) The Apache Software Foundation. All rights reserved.
*
* This software is published under the terms of the Apache Software License
* version 1.1, a copy of which has been included with this distribution in
* the LICENSE file.
*/
package org.apache.james.transport;
import java.io.*;
import java.net.*;
import java.util.*;
import javax.mail.MessagingException;
import org.apache.avalon.framework.activity.Initializable;
import org.apache.avalon.framework.activity.Disposable;
import org.apache.avalon.framework.component.ComponentManager;
import org.apache.avalon.framework.component.Composable;
import org.apache.avalon.framework.component.DefaultComponentManager;
import org.apache.avalon.framework.configuration.Configurable;
import org.apache.avalon.framework.configuration.Configuration;
import org.apache.avalon.framework.configuration.ConfigurationException;
import org.apache.avalon.framework.context.Context;
import org.apache.avalon.framework.context.Contextualizable;
import org.apache.avalon.framework.context.DefaultContext;
import org.apache.avalon.framework.logger.AbstractLoggable;
import org.apache.avalon.excalibur.thread.ThreadPool;
import org.apache.james.*;
import org.apache.james.core.*;
import org.apache.james.services.*;
import org.apache.mailet.*;
import org.apache.avalon.phoenix.Block;
import org.apache.avalon.phoenix.BlockContext;
/**
* @author Serge Knystautas <[EMAIL PROTECTED]>
* @author Federico Barbieri <[EMAIL PROTECTED]>
*/
public class JamesSpoolManager
extends AbstractLoggable
implements Composable, Configurable, Initializable, Runnable, Disposable,
Contextualizable, Block {
private DefaultComponentManager compMgr;
//using implementation as we need put method.
private Configuration conf;
private Context context;
private SpoolRepository spool;
private MailetContext mailetcontext;
private HashMap processors;
private int threads;
protected BlockContext blockContext;
private ThreadPool workerPool;
public void configure(Configuration conf) throws ConfigurationException {
this.conf = conf;
threads = conf.getChild("threads").getValueAsInteger(1);
}
public void contextualize(Context context) {
this.context = new DefaultContext( context );
this.blockContext = (BlockContext)context;
}
public void compose(ComponentManager comp) {
compMgr = new DefaultComponentManager(comp);
}
public void initialize() throws Exception {
getLogger().info("JamesSpoolManager init...");
workerPool = blockContext.getThreadPool( "default" );
Configuration spoolConf = conf.getChild("spoolRepository");
Configuration spoolRepConf = spoolConf.getChild("repository");
MailStore mailstore = (MailStore)
compMgr.lookup("org.apache.james.services.MailStore");
try {
this.spool = (SpoolRepository) mailstore.select(spoolRepConf);
} catch (Exception e) {
getLogger().error("Cannot open private SpoolRepository");
throw e;
}
getLogger().info("Private SpoolRepository Spool opened: "+spool.hashCode());
//compMgr.put("org.apache.james.services.SpoolRepository", (Component)spool);
//spool = (SpoolRepository)
compMgr.lookup("org.apache.james.services.SpoolRepository");
mailetcontext = (MailetContext)
compMgr.lookup("org.apache.mailet.MailetContext");
MailetLoader mailetLoader = new MailetLoader();
MatchLoader matchLoader = new MatchLoader();
try {
mailetLoader.configure(conf.getChild("mailetpackages"));
matchLoader.configure(conf.getChild("matcherpackages"));
compMgr.put(Resources.MAILET_LOADER, mailetLoader);
compMgr.put(Resources.MATCH_LOADER, matchLoader);
} catch (ConfigurationException ce) {
final String message =
"Unable to configure mailet/matcher Loaders: " + ce.getMessage();
getLogger().error( message, ce );
throw new RuntimeException( message );
}
//A processor is a Collection of
processors = new HashMap();
final Configuration[] processorConfs = conf.getChildren( "processor" );
for ( int i = 0; i < processorConfs.length; i++ )
{
Configuration processorConf = processorConfs[i];
String processorName = processorConf.getAttribute("name");
try {
LinearProcessor processor = new LinearProcessor();
setupLogger(processor, processorName);
processor.setSpool(spool);
processor.initialize();
processors.put(processorName, processor);
//If this is the root processor, add the PostmasterAlias mailet
silently
// to the top
if (processorName.equals("root")) {
Matcher matcher = matchLoader.getMatcher("All", mailetcontext);
Mailet mailet =
mailetLoader.getMailet("PostmasterAlias", mailetcontext,
null);
processor.add(matcher, mailet);
}
final Configuration[] mailetConfs = processorConf.getChildren(
"mailet" );
for ( int j = 0; j < mailetConfs.length; j++ )
{
Configuration c = mailetConfs[j];
String mailetClassName = c.getAttribute("class");
String matcherName = c.getAttribute("match");
Mailet mailet = null;
Matcher matcher = null;
try {
matcher = matchLoader.getMatcher(matcherName, mailetcontext);
//The matcher itself should log that it's been inited.
getLogger().info("Matcher " + matcherName + " instantiated");
} catch (MessagingException ex) {
// **** Do better job printing out exception
getLogger().error( "Unable to init matcher " + matcherName +
": " + ex.toString(), ex );
throw ex;
}
try {
mailet = mailetLoader.getMailet(mailetClassName,
mailetcontext, c);
getLogger().info("Mailet " + mailetClassName + "
instantiated");
} catch (MessagingException ex) {
// **** Do better job printing out exception
getLogger().error("Unable to init mailet " + mailetClassName
+ ": " + ex.getMessage());
throw ex;
}
//Add this pair to the proces
processor.add(matcher, mailet);
}
//Loop through all mailets within processor initializing them
//Add a Null mailet with All matcher to the processor
// this is so if a message gets to the end of a processor, it will
always be
// ghosted
Matcher matcher = matchLoader.getMatcher("All", mailetcontext);
Mailet mailet = mailetLoader.getMailet("Null", mailetcontext, null);
processor.add(matcher, mailet);
getLogger().info("processor " + processorName + " instantiated");
} catch (Exception ex) {
getLogger().error("Unable to init processor " + processorName + ": "
+ ex.getMessage());
throw ex;
}
}
getLogger().info("Spooler Manager uses "+threads+" Thread(s)");
for ( int i = 0 ; i < threads ; i++ )
workerPool.execute(this);
}
/**
* This routinely checks the message spool for messages, and processes them as
necessary
*/
public void run() {
getLogger().info("run JamesSpoolManager: "+Thread.currentThread().getName());
getLogger().info("spool="+spool.getClass().getName());
while(true) {
try {
String key = spool.accept();
MailImpl mail = spool.retrieve(key);
getLogger().info("==== Begin processing mail " + mail.getName() + "
====");
process(mail);
spool.remove(key);
getLogger().info("==== Removed from spool mail " + mail.getName() +
" ====");
mail = null;
} catch (Exception e) {
e.printStackTrace();
getLogger().error("Exception in JamesSpoolManager.run " +
e.getMessage());
}
}
}
/**
* Process this mail message by the appropriate processor as designated
* in the state of the Mail object.
*/
protected void process(MailImpl mail) {
while (true) {
String processorName = mail.getState();
try {
LinearProcessor processor =
(LinearProcessor)processors.get(processorName);
if (processor == null) {
throw new MailetException("Unable to find processor " +
processorName);
}
getLogger().info("Processing " + mail.getName() + " through " +
processorName);
processor.service(mail);
return;
} catch (Exception e) {
//This is a strange error situation that shouldn't ordinarily happen
System.err.println("Exception in processor <" + processorName + ">");
e.printStackTrace();
if (processorName.equals(Mail.ERROR)) {
//We got an error on the error processor... kill the message
mail.setState(Mail.GHOST);
mail.setErrorMessage(e.getMessage());
} else {
//We got an error... send it to the error processor
mail.setState(Mail.ERROR);
mail.setErrorMessage(e.getMessage());
}
}
getLogger().info("Processed " + mail.getName() + " through " +
processorName);
getLogger().info("Result was " + mail.getState());
}
}
public void dispose() {}
}
1.1
jakarta-james/src/java/org/apache/james/transport/JamesSpoolManager.xinfo
Index: JamesSpoolManager.xinfo
===================================================================
<?xml version="1.0"?>
<blockinfo>
<services>
<service name="org.apache.avalon.framework.component.Component" version="1.0"/>
</services>
<dependencies>
<dependency>
<role>org.apache.mailet.MailetContext</role>
<service name="org.apache.mailet.MailetContext" version="1.0"/>
</dependency>
<dependency>
<role>org.apache.james.services.MailStore</role>
<service name="org.apache.james.services.MailStore" version="1.0"/>
</dependency>
</dependencies>
</blockinfo>
1.1
jakarta-james/src/java/org/apache/james/transport/LinearProcessor.java
Index: LinearProcessor.java
===================================================================
/*
* Copyright (C) The Apache Software Foundation. All rights reserved.
*
* This software is published under the terms of the Apache Software License
* version 1.1, a copy of which has been included with this distribution in
* the LICENSE file.
*/
package org.apache.james.transport;
import java.io.*;
import java.util.*;
import javax.mail.*;
import org.apache.avalon.framework.logger.AbstractLoggable;
import org.apache.avalon.framework.activity.Initializable;
import org.apache.james.*;
import org.apache.james.core.*;
import org.apache.james.services.SpoolRepository;
import org.apache.log.Logger;
import org.apache.mailet.*;
/**
* @author Serge Knystautas <[EMAIL PROTECTED]>
* @author Federico Barbieri <[EMAIL PROTECTED]>
*
* SAMPLE CONFIGURATION
* <processor name="try" onerror="return,log">
* <mailet match="RecipientIsLocal" class="LocalDelivery">
* </mailet>
* <mailet match="All" class="RemoteDelivery">
* <delayTime>21600000</delayTime>
* <maxRetries>5</maxRetries>
* </mailet>
* </processor>
*
* Note that the 'onerror' attribute is not yet supported.
*/
public class LinearProcessor
extends AbstractLoggable
implements Initializable {
private final static boolean DEEP_DEBUG = true;
private List mailets;
private List matchers;
private List[] unprocessed;
private Collection tempUnprocessed;
private Random random;
private Logger logger;
private SpoolRepository spool;
public void setSpool(SpoolRepository spool) {
this.spool = spool;
if (DEEP_DEBUG) getLogger().debug("Using spool: " + spool);
}
public void initialize() {
this.matchers = new Vector();
this.mailets = new Vector();
tempUnprocessed = new Vector();
tempUnprocessed.add(new Vector(2, 2));
random = new Random();
}
public void add(Matcher matcher, Mailet mailet) {
matchers.add(matcher);
mailets.add(mailet);
//Make the collections array one larger
tempUnprocessed.add(new Vector(2, 2));
}
public synchronized void service(MailImpl mail) throws MessagingException {
if (DEEP_DEBUG) getLogger().debug("Servicing mail: " + mail.getName());
//make sure we have the array built
if (unprocessed == null) {
//Need to construct that object
unprocessed = (List[])tempUnprocessed.toArray(new List[0]);
tempUnprocessed = null;
}
//Wipe all the data (just to be sure)
for (int i = 0; i < unprocessed.length; i++) {
unprocessed[i].clear();
}
//Add the object to the bottom of the list
unprocessed[0].add(mail);
//This is the original state of the message
String originalState = mail.getState();
//We'll use these as temporary variables in the loop
mail = null;
int i = 0;
while (true) {
//The last element in the unprocessed array is a bucket of mail messages
// that went through the entire processor. We want them to just die,
// so we clear that List so they are GC'd.
unprocessed[unprocessed.length - 1].clear();
//Reset this to null before we start scanning for it
mail = null;
//Try to find a message to process
for (i = 0; i < unprocessed.length; i++) {
if (unprocessed[i].size() > 0) {
//Get the first element from the queue, and remove it from there
mail = (MailImpl)unprocessed[i].get(0);
unprocessed[i].remove(mail);
break;
}
}
//See if we didn't find any messages to process
if (mail == null) {
//We're done
return;
}
//Call the matcher and find what recipients match
Collection recipients = null;
Matcher matcher = (Matcher) matchers.get(i);
try {
recipients = matcher.match(mail);
if (recipients == null) {
//In case the matcher returned null, create an empty Vector
recipients = new Vector();
}
//Make sure all the objects are MailAddress objects
verifyMailAddresses(recipients);
} catch (MessagingException me) {
handleException(me, mail,
matcher.getMatcherConfig().getMatcherName());
}
//Split the recipients into two pools
Collection notRecipients = new Vector();
notRecipients.addAll(mail.getRecipients());
notRecipients.removeAll(recipients);
if (recipients.size() == 0) {
//Everything was not a match... store it in the next spot in the
array
unprocessed[i + 1].add(mail);
continue;
}
if (notRecipients.size() != 0) {
//There are a mix of recipients and not recipients.
//We need to clone this message, put the notRecipients on the clone
// and store it in the next spot
MailImpl notMail = (MailImpl)mail.duplicate(newName(mail));
notMail.setRecipients(notRecipients);
unprocessed[i + 1].add(notMail);
//We have to set the reduce possible recipients on the old message
mail.setRecipients(recipients);
}
//We have messages that need to process... time to run the mailet.
Mailet mailet = (Mailet) mailets.get(i);
try {
mailet.service(mail);
//Make sure all the recipients are still MailAddress objects
verifyMailAddresses(mail.getRecipients());
} catch (MessagingException me) {
handleException(me, mail, mailet.getMailetConfig().getMailetName());
}
//See if the state was changed by the mailet
if (!mail.getState().equals(originalState)) {
getLogger().debug("State changed by: " + mailet.getMailetInfo());
//If this message was ghosted, we just want to let it die
if (mail.getState().equals(mail.GHOST)) {
//let this instance die...
mail = null;
continue;
}
//This was just set to another state... store this back in the spool
// and it will get picked up and run in that processor
//Note we need to store this with a new mail name, otherwise it
// will get deleted upon leaving this processor
mail.setName(newName(mail));
spool.store(mail);
mail = null;
continue;
} else {
//Ok, we made it through with the same state... move it to the next
// spot in the array
getLogger().debug("State not changed by: " + mailet.getMailetInfo());
unprocessed[i + 1].add(mail);
}
}
}
/**
* Create a unique new primary key name
*/
private String newName(MailImpl mail) {
String name = mail.getName();
return name + "-!" + Math.abs(random.nextInt());
}
/**
* Checks that all objects in this class are of the form MailAddress
*/
private void verifyMailAddresses(Collection col) throws MessagingException {
MailAddress addresses[] = (MailAddress[])col.toArray(new MailAddress[0]);
if (addresses.length != col.size()) {
throw new MailetException("The recipient list contains objects other
than MailAddress objects");
}
}
private void handleException(MessagingException me, Mail mail, String
offendersName) throws MessagingException {
mail.setState(Mail.ERROR);
StringWriter sout = new StringWriter();
PrintWriter out = new PrintWriter(sout, true);
out.println("Exception calling " + offendersName + ": " + me.getMessage());
Exception e = me;
while (e != null) {
e.printStackTrace(out);
if (e instanceof MessagingException) {
e = ((MessagingException)e).getNextException();
} else {
e = null;
}
}
mail.setErrorMessage(sout.toString());
getLogger().error(sout.toString());
throw me;
}
}
1.1
jakarta-james/src/java/org/apache/james/transport/MailetLoader.java
Index: MailetLoader.java
===================================================================
/*
* Copyright (C) The Apache Software Foundation. All rights reserved.
*
* This software is published under the terms of the Apache Software License
* version 1.1, a copy of which has been included with this distribution in
* the LICENSE file.
*/
package org.apache.james.transport;
import java.util.*;
import javax.mail.*;
import org.apache.avalon.framework.component.Component;
import org.apache.avalon.framework.configuration.Configurable;
import org.apache.avalon.framework.configuration.Configuration;
import org.apache.avalon.framework.configuration.ConfigurationException;
import org.apache.james.core.*;
import org.apache.mailet.*;
/**
* @author Serge Knystautas <[EMAIL PROTECTED]>
* @author Federico Barbieri <[EMAIL PROTECTED]>
*/
public class MailetLoader implements Component, Configurable {
private Configuration conf;
private Vector mailetPackages;
public void configure(Configuration conf) throws ConfigurationException {
mailetPackages = new Vector();
mailetPackages.addElement("");
final Configuration[] pkgConfs = conf.getChildren( "mailetpackage" );
for ( int i = 0; i < pkgConfs.length; i++ )
{
Configuration c = pkgConfs[i];
String packageName = c.getValue();
if (!packageName.endsWith(".")) {
packageName += ".";
}
mailetPackages.addElement(packageName);
}
}
public Mailet getMailet(String mailetName, MailetContext context, Configuration
configuration)
throws MessagingException {
try {
for (int i = 0; i < mailetPackages.size(); i++) {
String className = (String)mailetPackages.elementAt(i) + mailetName;
try {
MailetConfigImpl configImpl = new MailetConfigImpl();
configImpl.setMailetName(mailetName);
configImpl.setConfiguration(configuration);
configImpl.setMailetContext(context);
Mailet mailet = (Mailet) Class.forName(className).newInstance();
mailet.init(configImpl);
return mailet;
} catch (ClassNotFoundException cnfe) {
//do this so we loop through all the packages
}
}
throw new ClassNotFoundException("Requested mailet not found: " +
mailetName + ". looked in " + mailetPackages.toString());
} catch (MessagingException me) {
throw me;
} catch (Exception e) {
throw new MailetException("Could not load mailet (" + mailetName + ")",
e);
}
}
}
1.1
jakarta-james/src/java/org/apache/james/transport/MatchLoader.java
Index: MatchLoader.java
===================================================================
/*
* Copyright (C) The Apache Software Foundation. All rights reserved.
*
* This software is published under the terms of the Apache Software License
* version 1.1, a copy of which has been included with this distribution in
* the LICENSE file.
*/
package org.apache.james.transport;
import java.util.*;
import javax.mail.*;
import org.apache.avalon.framework.component.Component;
import org.apache.avalon.framework.configuration.Configurable;
import org.apache.avalon.framework.configuration.Configuration;
import org.apache.avalon.framework.configuration.ConfigurationException;
import org.apache.james.core.*;
import org.apache.mailet.*;
/**
* @author Serge Knystautas <[EMAIL PROTECTED]>
* @author Federico Barbieri <[EMAIL PROTECTED]>
*/
public class MatchLoader implements Component, Configurable {
private Configuration conf;
private Vector matcherPackages;
public void configure(Configuration conf) throws ConfigurationException {
matcherPackages = new Vector();
matcherPackages.addElement("");
final Configuration[] pkgConfs = conf.getChildren( "matcherpackage" );
for ( int i = 0; i < pkgConfs.length; i++ )
{
Configuration c = pkgConfs[i];
String packageName = c.getValue();
if (!packageName.endsWith(".")) {
packageName += ".";
}
matcherPackages.addElement(packageName);
}
}
public Matcher getMatcher(String matchName, MailetContext context)
throws MessagingException {
try {
String condition = (String) null;
int i = matchName.indexOf('=');
if (i != -1) {
condition = matchName.substring(i + 1);
matchName = matchName.substring(0, i);
}
for (i = 0; i < matcherPackages.size(); i++) {
String className = (String)matcherPackages.elementAt(i) + matchName;
try {
MatcherConfigImpl configImpl = new MatcherConfigImpl();
configImpl.setCondition(condition);
configImpl.setMailetContext(context);
Matcher matcher = (Matcher)
Class.forName(className).newInstance();
matcher.init(configImpl);
return matcher;
} catch (ClassNotFoundException cnfe) {
//do this so we loop through all the packages
}
}
throw new ClassNotFoundException("Requested matcher not found: " +
matchName + ". looked in " + matcherPackages.toString());
} catch (MessagingException me) {
throw me;
} catch (Exception e) {
throw new MailetException("Could not load matcher (" + matchName + ")",
e);
}
}
}
1.1 jakarta-james/src/java/org/apache/james/transport/Resources.java
Index: Resources.java
===================================================================
/*
* Copyright (C) The Apache Software Foundation. All rights reserved.
*
* This software is published under the terms of the Apache Software License
* version 1.1, a copy of which has been included with this distribution in
* the LICENSE file.
*/
package org.apache.james.transport;
/**
* @version 1.0.0, 24/04/1999
* @author Federico Barbieri <[EMAIL PROTECTED]>
*/
public class Resources {
//Already defined in Constants
//public static final String SERVER_NAMES = "SERVER_NAMES";
public static final String USERS_MANAGER = "USERS_MANAGER";
//Already defined in Constants
//public static final String POSTMASTER = "POSTMASTER";
public static final String MAIL_SERVER = "MAIL_SERVER";
public static final String TRANSPORT = "TRANSPORT";
public static final String TMP_REPOSITORY = "TMP_REPOSITORY";
public static final String MAILET_LOADER = "MAILET_LOADER";
public static final String MATCH_LOADER = "MATCH_LOADER";
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]