You are viewing a plain text version of this content. The canonical link for it is here.
Posted to server-dev@james.apache.org by ch...@apache.org on 2001/05/11 10:50:45 UTC
cvs commit: jakarta-james/src/org/apache/mailet GenericMailet.java GenericMatcher.java GenericRecipientMatcher.java Mail.java MailAddress.java Mailet.java MailetConfig.java MailetContext.java MailetException.java Matcher.java MatcherConfig.java
charlesb 01/05/11 01:50:44
Added: src/java/org/apache/mailet GenericMailet.java
GenericMatcher.java GenericRecipientMatcher.java
Mail.java MailAddress.java Mailet.java
MailetConfig.java MailetContext.java
MailetException.java Matcher.java
MatcherConfig.java
Removed: src/org/apache/mailet GenericMailet.java GenericMatcher.java
GenericRecipientMatcher.java Mail.java
MailAddress.java Mailet.java MailetConfig.java
MailetContext.java MailetException.java
Matcher.java MatcherConfig.java
Log:
Moved src/org/apache/mailet/* to src/java/org/apache/mailet
Revision Changes Path
1.1 jakarta-james/src/java/org/apache/mailet/GenericMailet.java
Index: GenericMailet.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.mailet;
import java.util.*;
import javax.mail.*;
/**
* GenericMailet makes writing mailets easier. It provides simple
* versions of the lifecycle methods init and destroy and of the methods
* in the MailetConfig interface. GenericMailet also implements the log
* method, declared in the MailetContext interface.
* <p>
* To write a generic mailet, you need only override the abstract service
* method.
*
* @version 1.0.0, 24/04/1999
* @author Federico Barbieri <sc...@pop.systemy.it>
* @author Stefano Mazzocchi <st...@apache.org>
* @author Pierpaolo Fumagalli <pi...@apache.org>
* @author Serge Knystautas <se...@lokitech.com>
*/
public abstract class GenericMailet implements Mailet, MailetConfig {
private MailetConfig config = null;
/**
* Called by the mailer container to indicate to a mailet that the
* mailet is being taken out of service.
*/
public void destroy() {
//Do nothing
}
/**
* Returns a String containing the value of the named initialization
* parameter, or null if the parameter does not exist.
* <p>
* This method is supplied for convenience. It gets the value of the
* named parameter from the mailet's MailetConfig object.
*
* @param name - a String specifying the name of the initialization parameter
* @return String a String containing the value of the initalization parameter
*/
public String getInitParameter(String name) {
return config.getInitParameter(name);
}
/**
* Returns the names of the mailet's initialization parameters as an
* Iterator of String objects, or an empty Iterator if the mailet has no
* initialization parameters.
* <p>
* This method is supplied for convenience. It gets the parameter names from
* the mailet's MailetConfig object.
*
* @return Iterator an iterator of String objects containing the names of
* the mailet's initialization parameters
*/
public Iterator getInitParameterNames() {
return config.getInitParameterNames();
}
/**
* Returns this matcher's MailetConfig object.
*
* @return MailetConfig the MailetConfig object that initialized this mailet
*/
public MailetConfig getMailetConfig() {
return config;
}
/**
* Returns a reference to the MailetContext in which this mailet is
* running.
*
* @return MailetContext the MailetContext object passed to this mailet by the init method
*/
public MailetContext getMailetContext() {
return getMailetConfig().getMailetContext();
}
/**
* Returns information about the mailet, such as author, version, and
* copyright. By default, this method returns an empty string. Override
* this method to have it return a meaningful value.
*
* @return String information about this mailet, by default an empty string
*/
public String getMailetInfo() {
return "";
}
/**
* Returns the name of this mailet instance.
*
* @return the name of this mailet instance
*/
public String getMailetName() {
return config.getMailetName();
}
/**
* Called by the mailet container to indicate to a mailet that the
* mailet is being placed into service.
*
* This implementation stores the MailetConfig object it receives from
* the mailet container for alter use. When overriding this form of the
* method, call super.init(config).
*
* @param MailetConfig config - the MailetConfig object that contains
* configutation information for this mailet
* @throws MessagingException
* if an exception occurs that interrupts the mailet's normal operation
*/
public void init(MailetConfig newConfig) throws MessagingException {
config = newConfig;
init();
}
/**
* A convenience method which can be overridden so that there's no
* need to call super.init(config).
*
* Instead of overriding init(MailetConfig), simply override this
* method and it will be called by GenericMailet.init(MailetConfig config).
* The MailetConfig object can still be retrieved via getMailetConfig().
*
* @throws MessagingException
* if an exception occurs that interrupts the mailet's normal operation
*/
public void init() throws MessagingException {
//Do nothing... can be overriden
}
/**
* Writes the specified message to a mailet log file, prepended by
* the mailet's name.
*
* @param msg - a String specifying the message to be written to the log file
*/
public void log(String message) {
getMailetContext().log(config.getMailetName() + ": " + message);
}
/**
* Writes an explanatory message and a stack trace for a given Throwable
* exception to the mailet log file, prepended by the mailet's name.
*
* @param message - a String that describes the error or exception
* @param t - the java.lang.Throwable error or exception
*/
public void log(String message, Throwable t) {
getMailetContext().log(config.getMailetName() + ": " + message, t);
}
/**
* Called by the mailet container to allow the mailet to process a
* message.
*
* This method is declared abstract so subclasses must override it.
*
* @param mail - the Mail object that contains the MimeMessage and
* routing information
* @throws javax.mail.MessagingException - if an exception occurs that interferes with the mailet's normal operation
* occurred
*/
public abstract void service(Mail mail) throws javax.mail.MessagingException;
}
1.1 jakarta-james/src/java/org/apache/mailet/GenericMatcher.java
Index: GenericMatcher.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.mailet;
import java.util.*;
import javax.mail.*;
/**
* GenericMatcher implements the Matcher and MatcherConfig interfaces.
* GenericMatcher makes writing matchers easier. It provides simple versions of
* the lifecycle methods init and destroy and of the methods in the MatcherConfig
* interface. GenericMatcher also implements the log method, declared in the
* MatcherContext interface.
* <p>
* To write a generic matcher, you need only override the abstract match method.
*
* @version 1.0.0, 24/04/1999
* @author Serge Knystautas <se...@lokitech.com>
*/
public abstract class GenericMatcher implements Matcher, MatcherConfig {
MatcherConfig config = null;
/**
* Called by the mailet container to indicate to a matcher that the
* matcher is being taken out of service.
*/
public void destroy() {
//Do nothing
}
/**
* Returns a String containing the value of the named initialization
* parameter, or null if the parameter does not exist.
* <p>
* This method is supplied for convenience. It gets the value of the
* named parameter from the matcher's MatcherConfig object.
*
* @return String a String containing the value of the initalization parameter
*/
public String getCondition() {
return config.getCondition();
}
/**
* Returns this matcher's MatcherConfig object.
*
* @return MatcherConfig the MatcherConfig object that initialized this matcher
*/
public MatcherConfig getMatcherConfig() {
return config;
}
/**
* Returns a reference to the MailetContext in which this matcher is
* running.
*
* @return MailetContext the MailetContext object passed to this matcher by the init method
*/
public MailetContext getMailetContext() {
return getMatcherConfig().getMailetContext();
}
/**
* Returns information about the matcher, such as author, version, and
* copyright. By default, this method returns an empty string. Override
* this method to have it return a meaningful value.
*
* @return String information about this matcher, by default an empty string
*/
public String getMatcherInfo() {
return "";
}
/**
* Returns the name of this matcher instance.
*
* @return the name of this matcher instance
*/
public String getMatcherName() {
return config.getMatcherName();
}
/**
* Called by the matcher container to indicate to a matcher that the
* matcher is being placed into service.
*
* This implementation stores the MatcherConfig object it receives from
* the matcher container for alter use. When overriding this form of the
* method, call super.init(config).
*
* @param MatcherConfig config - the MatcherConfig object that contains
* configutation information for this matcher
* @throws MessagingException
* if an exception occurs that interrupts the matcher's normal operation
*/
public void init(MatcherConfig newConfig) throws MessagingException {
config = newConfig;
init();
}
/**
* A convenience method which can be overridden so that there's no
* need to call super.init(config).
*
* Instead of overriding init(MatcherConfig), simply override this
* method and it will be called by GenericMatcher.init(MatcherConfig config).
* The MatcherConfig object can still be retrieved via getMatcherConfig().
*
* @throws MatcherException
* if an exception occurs that interrupts the matcher's normal operation
*/
public void init() throws MessagingException {
//Do nothing... can be overriden
}
/**
* Writes the specified message to a matcher log file, prepended by
* the matcher's name.
*
* @param msg - a String specifying the message to be written to the log file
*/
public void log(String message) {
getMailetContext().log(getMatcherName() + ": " + message);
}
/**
* Writes an explanatory message and a stack trace for a given Throwable
* exception to the matcher log file, prepended by the matcher's name.
*
* @param message - a String that describes the error or exception
* @param t - the java.lang.Throwable error or exception
*/
public void log(String message, Throwable t) {
getMailetContext().log(getMatcherName() + ": " + message, t);
}
/**
* Called by the matcher container to allow the matcher to process a
* message.
*
* This method is declared abstract so subclasses must override it.
*
* @param mail - the Mail object that contains the MimeMessage and
* routing information
* @return java.util.Collection - the recipients that the mailet container should have the
* mailet affect.
* @throws javax.mail.MessagingException - if an exception occurs that interferes with the mailet's normal operation
* occurred
*/
public abstract Collection match(Mail mail) throws MessagingException;
}
1.1 jakarta-james/src/java/org/apache/mailet/GenericRecipientMatcher.java
Index: GenericRecipientMatcher.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.mailet;
import java.util.*;
import javax.mail.*;
/**
* GenericMatcher makes writing recipient based matchers easier. It provides
* simple versions of the lifecycle methods init and destroy and of the methods
* in the MatcherConfig interface. GenericMatcher also implements the log method,
* declared in the
* MatcherContext interface.
*
* @version 1.0.0, 24/04/1999
* @author Federico Barbieri <sc...@pop.systemy.it>
* @author Serge Knystautas <se...@lokitech.com>
*/
public abstract class GenericRecipientMatcher extends GenericMatcher {
/**
* Matches each recipient one by one through matchRecipient(MailAddress
* recipient) method. Handles splitting the recipients Collection
* as appropriate.
*
* @param mail - the message and routing information to determine whether to match
* @return Collection the Collection of MailAddress objects that have been matched
*/
public final Collection match(Mail mail) throws MessagingException {
Collection matching = new Vector();
for (Iterator i = mail.getRecipients().iterator(); i.hasNext(); ) {
MailAddress rec = (MailAddress) i.next();
if (matchRecipient(rec)) {
matching.add(rec);
}
}
return matching;
}
/**
* Simple check to match exclusively on the email address (not
* message information).
*
* @param recipient - the address to determine whether to match
* @return boolean whether the recipient is a match
*/
public abstract boolean matchRecipient(MailAddress recipient) throws MessagingException;
}
1.1 jakarta-james/src/java/org/apache/mailet/Mail.java
Index: Mail.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.mailet;
import java.io.*;
import java.net.*;
import java.util.*;
import javax.mail.*;
import javax.mail.internet.*;
/**
* Wrap a MimeMessage with routing information (from SMTP) such
* as SMTP specified recipients, sender, and ip address and hostname
* of sending server. It also contains its state which represents
* which processor in the mailet container it is currently running.
* Special processor names are "root" and "error".
*
* @author Federico Barbieri <sc...@systemy.it>
* @author Serge Knystautas <se...@lokitech.com>
* @version 0.9
*/
public interface Mail extends Serializable, Cloneable {
String GHOST = "ghost";
String DEFAULT = "root";
String ERROR = "error";
String TRANSPORT = "transport";
/**
* Returns the MimeMessage stored in this message
*
* @return the MimeMessage that this Mail object wraps
* @throws MessagingException - an error occured while loading this object
*/
MimeMessage getMessage() throws MessagingException;
/**
* Returns a Collection of MailAddress objects that are recipients of this message
*
* @return a Collection of MailAddress objects that are recipients of this message
*/
Collection getRecipients();
/**
* The sender of the message, as specified by the MAIL FROM header, or internally defined
*
* @return a MailAddress of the sender of this message
*/
MailAddress getSender();
/**
* The current state of the message, such as GHOST, ERROR, or DEFAULT
*
* @return the state of this message
*/
String getState();
/**
* The remote hostname of the server that connected to send this message
*
* @return a String of the hostname of the server that connected to send this message
*/
String getRemoteHost();
/**
* The remote ip address of the server that connected to send this message
*
* @return a String of the ip address of the server that connected to send this message
*/
String getRemoteAddr();
/**
* The error message, if any, associated with this message. Not sure why this is needed.
*
* @return a String of a descriptive error message
*/
String getErrorMessage();
/**
* Sets the error message associated with this message. Not sure why this is needed.
*
* @param msg - a descriptive error message
*/
void setErrorMessage(String msg);
/**
* Sets the MimeMessage associated with this message via an inputstream. The Mail
* object will parse out the inputstream and construct a MimeMessage object.
*
* @param in - the inputstream to read to construct the MimeMessage
* @throws MessagingException - if there was an error parsing the inputstream
*/
void setMessage(InputStream in) throws MessagingException;
/**
* Sets the MimeMessage associated with this message via the object.
*
* @param message - the new MimeMessage that this Mail object will wrap
*/
void setMessage(MimeMessage message);
/**
* Sets the state of this message.
*
* @param state - the new state of this message
*/
void setState(String state);
}
1.1 jakarta-james/src/java/org/apache/mailet/MailAddress.java
Index: MailAddress.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.mailet;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.ParseException;
/**
* A representation of an email address.
* <p>This class encapsulates functionalities to access to different
* parts of an email address without dealing with its parsing.
* <p>
* A MailAddress is an address specified in the MAIL FROM and
* RCPT TO commands in SMTP sessions. These are either passed by
* an external server to the mailet-compliant SMTP server, or they
* are created programmatically by the mailet-compliant server to
* send to another (external) SMTP server. Mailets and matchers
* use the MailAddress for the purpose of evaluating the sender
* and recipient(s) of a message.
* <p>
* MailAddress parses an email address as defined in RFC 821
* (SMTP) p. 30 and 31 where addresses are defined in BNF convention.
* As the mailet API does not support the aged "SMTP-relayed mail"
* addressing protocol, this leaves all addresses to be a <mailbox>,
* as per the spec. The MailAddress's "user" is the <local-part> of
* the <mailbox> and "host" is the <domain> of the mailbox.
* <p>
* This class is a good way to validate email addresses as there are
* some valid addresses which would fail with a simpler approach
* to parsing address. It also removes parsing burden from
* mailets and matchers that might not realize the flexibility of an
* SMTP address. For instance, "serge@home"@lokitech.com is a valid
* SMTP address (the quoted text serge@home is the user and
* lokitech.com is the host). This means all current parsing to date
* is incorrect as we just find the first @ and use that to separate
* user from host.
* <p>
* This parses an address as per the BNF specification for <mailbox>
* from RFC 821 on page 30 and 31, section 4.1.2. COMMAND SYNTAX.
* http://www.freesoft.org/CIE/RFC/821/15.htm
*
* @version 1.0
* @author Roberto Lo Giacco <rl...@mail.com>
* @author Serge Knystautas <se...@lokitech.com>
*/
public class MailAddress implements java.io.Serializable {
//We hardcode the serialVersionUID so that from James 1.2 on,
// MailAddress will be deserializable (so your mail doesn't get lost)
public static final long serialVersionUID = 2779163542539434916L;
private final static char[] SPECIAL =
{'<', '>', '(', ')', '[', ']', '\\', '.', ',', ';', ':', '@', '\"'};
private String user = null;
private String host = null;
//Used for parsing
private int pos = 0;
/**
* Construct a MailAddress parsing the provided <code>String</code> object.
* <p>The <code>personal</code> variable is left empty.
*
* @param address the email address compliant to the RFC822 format
* @throws ParseException if the parse failed
*/
public MailAddress(String address) throws ParseException {
address = address.trim();
StringBuffer userSB = new StringBuffer();
StringBuffer hostSB = new StringBuffer();
//Begin parsing
//<mailbox> ::= <local-part> "@" <domain>
try {
//parse local-part
//<local-part> ::= <dot-string> | <quoted-string>
if (address.charAt(pos) == '\"') {
userSB.append(parseQuotedLocalPart(address));
} else {
userSB.append(parseUnquotedLocalPart(address));
}
if (userSB.toString().length() == 0) {
throw new ParseException("No local-part (user account) found at position " + (pos + 1));
}
//find @
if (address.charAt(pos) != '@') {
throw new ParseException("Did not find @ between local-part and domain at position " + (pos + 1));
}
pos++;
//parse domain
//<domain> ::= <element> | <element> "." <domain>
//<element> ::= <name> | "#" <number> | "[" <dotnum> "]"
while (true) {
if (address.charAt(pos) == '#') {
hostSB.append(parseNumber(address));
} else if (address.charAt(pos) == '[') {
hostSB.append(parseDotNum(address));
} else {
hostSB.append(parseDomainName(address));
}
if (pos >= address.length()) {
break;
}
if (address.charAt(pos) == '.') {
hostSB.append('.');
pos++;
continue;
}
break;
}
if (hostSB.toString().length() == 0) {
throw new ParseException("No domain found at position " + (pos + 1));
}
} catch (ArrayIndexOutOfBoundsException aioobe) {
throw new ParseException("Out of data at position " + (pos + 1));
}
user = userSB.toString();
host = hostSB.toString();
}
/**
* Construct a MailAddress with the provided personal name and email
* address.
*
* @param user the username or account name on the mail server
* @param host the server that should accept messages for this user
* @throws ParseException if the parse failed
*/
public MailAddress(String newUser, String newHost) throws ParseException {
/* NEEDS TO BE REWORKED TO VALIDATE EACH CHAR */
user = newUser;
host = newHost;
}
/**
* Constructs a MailAddress from a JavaMail InternetAddress, using only the
* email address portion, discarding the personal name.
*/
public MailAddress(InternetAddress address) throws ParseException {
this(address.getAddress());
}
/**
* Return the host part.
*
* @return a <code>String</code> object representing the host part
* of this email address.
* @throws AddressException if the parse failed
*/
public String getHost() {
return host;
}
/**
* Return the user part.
*
* @return a <code>String</code> object representing the user part
* of this email address.
* @throws AddressException if the parse failed
*/
public String getUser() {
return user;
}
public String toString() {
return user + "@" + host;
}
public InternetAddress toInternetAddress() {
try {
return new InternetAddress(toString());
} catch (javax.mail.internet.AddressException ae) {
//impossible really
return null;
}
}
public boolean equals(Object obj) {
if (obj == null) {
return false;
} else if (obj instanceof String) {
return toString().equalsIgnoreCase(obj.toString());
} else if (obj instanceof MailAddress) {
MailAddress addr = (MailAddress)obj;
return getUser().equalsIgnoreCase(addr.getUser()) && getHost().equalsIgnoreCase(addr.getHost());
}
return false;
}
/**
* Return a hashCode for this object which should be identical for addresses
* which are equivalent. This is implemented by obtaining the default
* hashcode of the String representation of the MailAddress. Without this
* explicit definition, the default hashCode will create different hashcodes
* for separate object instances.
*
* @returns the hashcode.
* @author Stuart Roebuck <st...@adolos.com>
*/
public int hashCode() {
return toString().toLowerCase().hashCode();
}
private String parseQuotedLocalPart(String address) throws ParseException {
StringBuffer resultSB = new StringBuffer();
resultSB.append('\"');
pos++;
//<quoted-string> ::= """ <qtext> """
//<qtext> ::= "\" <x> | "\" <x> <qtext> | <q> | <q> <qtext>
while (true) {
if (address.charAt(pos) == '\"') {
resultSB.append('\"');
//end of quoted string... move forward
pos++;
break;
}
if (address.charAt(pos) == '\\') {
resultSB.append('\\');
pos++;
//<x> ::= any one of the 128 ASCII characters (no exceptions)
char x = address.charAt(pos);
if (x < 0 || x > 128) {
throw new ParseException("Invalid \\ syntaxed character at position " + (pos + 1));
}
resultSB.append(x);
pos++;
} else {
//<q> ::= any one of the 128 ASCII characters except <CR>,
//<LF>, quote ("), or backslash (\)
char q = address.charAt(pos);
if (q <= 0 || q == '\n' || q == '\r' || q == '\"' || q == '\\') {
throw new ParseException("Unquoted local-part (user account) must be one of the 128 ASCI characters exception <CR>, <LF>, quote (\"), or backslash (\\) at position " + (pos + 1));
}
resultSB.append(q);
pos++;
}
}
return resultSB.toString();
}
private String parseUnquotedLocalPart(String address) throws ParseException {
StringBuffer resultSB = new StringBuffer();
//<dot-string> ::= <string> | <string> "." <dot-string>
boolean lastCharDot = false;
while (true) {
//<string> ::= <char> | <char> <string>
//<char> ::= <c> | "\" <x>
if (address.charAt(pos) == '\\') {
resultSB.append('\\');
pos++;
//<x> ::= any one of the 128 ASCII characters (no exceptions)
char x = address.charAt(pos);
if (x < 0 || x > 128) {
throw new ParseException("Invalid \\ syntaxed character at position " + (pos + 1));
}
resultSB.append(x);
pos++;
lastCharDot = false;
} else if (address.charAt(pos) == '.') {
resultSB.append('.');
pos++;
lastCharDot = true;
} else if (address.charAt(pos) == '@') {
//End of local-part
break;
} else {
//<c> ::= any one of the 128 ASCII characters, but not any
// <special> or <SP>
//<special> ::= "<" | ">" | "(" | ")" | "[" | "]" | "\" | "."
// | "," | ";" | ":" | "@" """ | the control
// characters (ASCII codes 0 through 31 inclusive and
// 127)
//<SP> ::= the space character (ASCII code 32)
char c = address.charAt(pos);
if (c <= 31 || c == 127 || c == ' ') {
throw new ParseException("Invalid character in local-part (user account) at position " + (pos + 1));
}
for (int i = 0; i < SPECIAL.length; i++) {
if (c == SPECIAL[i]) {
throw new ParseException("Invalid character in local-part (user account) at position " + (pos + 1));
}
}
resultSB.append(c);
pos++;
lastCharDot = false;
}
}
if (lastCharDot) {
throw new ParseException("local-part (user account) ended with a \".\", which is invalid.");
}
return resultSB.toString();
}
private String parseNumber(String address) throws ParseException {
//<number> ::= <d> | <d> <number>
StringBuffer resultSB = new StringBuffer();
//We keep the position from the class level pos field
while (true) {
if (pos >= address.length()) {
break;
}
//<d> ::= any one of the ten digits 0 through 9
char d = address.charAt(pos);
if (d == '.') {
break;
}
if (d < '0' || d > '9') {
throw new ParseException("In domain, did not find a number in # address at position " + (pos + 1));
}
resultSB.append(d);
pos++;
}
return resultSB.toString();
}
private String parseDotNum(String address) throws ParseException {
StringBuffer resultSB = new StringBuffer();
//<dotnum> ::= <snum> "." <snum> "." <snum> "." <snum>
for (int octet = 0; octet < 4; octet++) {
//<snum> ::= one, two, or three digits representing a decimal
// integer value in the range 0 through 255
//<d> ::= any one of the ten digits 0 through 9
StringBuffer snumSB = new StringBuffer();
for (int digits = 0; digits < 3; digits++) {
char d = address.charAt(pos);
if (d == '.') {
break;
}
if (d == ']') {
break;
}
if (d < '0' || d > '9') {
throw new ParseException("Invalid number at position " + (pos + 1));
}
snumSB.append(d);
pos++;
}
if (snumSB.toString().length() == 0) {
throw new ParseException("Number not found at position " + (pos + 1));
}
try {
int snum = Integer.parseInt(snumSB.toString());
if (snum > 255) {
throw new ParseException("Invalid number at position " + (pos + 1));
}
} catch (NumberFormatException nfe) {
throw new ParseException("Invalid number at position " + (pos + 1));
}
resultSB.append(snumSB.toString());
if (address.charAt(pos) == ']') {
if (octet < 3) {
throw new ParseException("End of number reached too quickly at " + (pos + 1));
} else {
break;
}
}
if (address.charAt(pos) == '.') {
resultSB.append('.');
pos++;
}
}
if (address.charAt(pos) != ']') {
throw new ParseException("Did not find closing bracket \"]\" in domain at position " + (pos + 1));
}
resultSB.append(']');
pos++;
return resultSB.toString();
}
private String parseDomainName(String address) throws ParseException {
StringBuffer resultSB = new StringBuffer();
//<name> ::= <a> <ldh-str> <let-dig>
//<ldh-str> ::= <let-dig-hyp> | <let-dig-hyp> <ldh-str>
//<let-dig> ::= <a> | <d>
//<let-dig-hyp> ::= <a> | <d> | "-"
//<a> ::= any one of the 52 alphabetic characters A through Z
// in upper case and a through z in lower case
//<d> ::= any one of the ten digits 0 through 9
//basically, this is a series of letters, digits, and hyphens,
// but it can't start with a digit or hypthen
// and can't end with a hyphen
//by practice though, we should relax this as domain names can start
// with digits as well as letters. So only check that doesn't start
// or end with hyphen.
while (true) {
if (pos >= address.length()) {
break;
}
char ch = address.charAt(pos);
if (ch >= '0' && ch <= '9' || ch >= 'a' && ch <= 'z' || ch >= 'A' && ch <= 'Z'
|| ch == '-') {
resultSB.append(ch + "");
pos++;
continue;
}
if (ch == '.') {
break;
}
throw new ParseException("Invalid character at " + pos);
}
String result = resultSB.toString();
if (result.startsWith("-") || result.endsWith("-")) {
throw new ParseException("Domain name cannot begin or end with a hyphen \"-\" at position " + (pos + 1));
}
return result;
}
}
1.1 jakarta-james/src/java/org/apache/mailet/Mailet.java
Index: Mailet.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.mailet;
/**
* Draft of a Mailet inteface. The <code>service</code> perform all needed work
* on the Mail object. Whatever remains at the end of the service is considered
* to need futher processing and will go to the next Mailet if there is one
* configured or will go to the error processor if not.
* Setting a Mail state (setState(String)) to Mail.GHOST or cleaning its recipient
* list has the same meaning that s no more processing is needed.
* Instead of creating new messages, the mailet can put a message with new recipients
* at the top of the mail queue, or insert them immediately after it's execution
* through the API are provided by the MailetContext interface.
* <p>
* This interface defines methods to initialize a mailet, to service messages, and to
* remove a mailet from the server. These are known as life-cycle methods and are called
* in the following sequence:
* <ol>
* <li>The mailet is constructed, then initialized with the init method. </li>
* <li>Any messages for the service method are handled.</li>
* <li>The mailet is taken out of service, then destroyed with the destroy method,
* then garbage collected and finalized.</li>
* </ol>
* In addition to the life-cycle methods, this interface provides the getMailletConfig
* method, which the mailet can use to get any startup information, and the
* getMailetInfo method, which allows the mailet to return basic information about itself,
* such as author, version, and copyright.
*
* @version 1.0.0, 24/04/1999
* @author Federico Barbieri <sc...@pop.systemy.it>
* @author Stefano Mazzocchi <st...@apache.org>
* @author Pierpaolo Fumagalli <pi...@apache.org>
* @author Serge Knystautas <se...@lokitech.com>
*/
public interface Mailet {
/**
* Called by the mailet container to indicate to a mailet that the
* mailet is being taken out of service. This method is only called once
* all threads within the mailet's service method have exited or after a
* timeout period has passed. After the mailet container calls this method,
* it will not call the service method again on this mailet.
* <p>
* This method gives the mailet an opportunity to clean up any resources that
* are being held (for example, memory, file handles, threads) and make sure
* that any persistent state is synchronized with the mailet's current state in memory.
*/
void destroy();
/**
* Returns information about the mailet, such as author, version, and
* copyright.
* <p>
* The string that this method returns should be plain text and not markup
* of any kind (such as HTML, XML, etc.).
*
* @return a String containing servlet information
*/
String getMailetInfo();
/**
* Returns a MailetConfig object, which contains initialization and
* startup parameters for this mailet.
* <p>
* Implementations of this interface are responsible for storing the MailetConfig
* object so that this method can return it. The GenericMailet class, which implements
* this interface, already does this.
*
* @return the MailletConfig object that initializes this mailet
*/
MailetConfig getMailetConfig();
/**
* Called by the mailet container to indicate to a mailet that the
* mailet is being placed into service.
* <p>
* The mailet container calls the init method exactly once after
* instantiating the mailet. The init method must complete successfully
* before the mailet can receive any requests.
*
* @param config - a MailetConfig object containing the mailet's configuration
* and initialization parameters
* @throws MessagingException - if an exception has occurred that interferes with
* the mailet's normal operation
*/
void init(MailetConfig config) throws javax.mail.MessagingException;
/**
* Called by the mailet container to allow the mailet to process to
* a message message.
* <p>
* This method is only called after the mailet's init() method has completed
* successfully.
* <p>
* Mailets typically run inside multithreaded mailet containers that can handle
* multiple requests concurrently. Developers must be aware to synchronize access
* to any shared resources such as files, network connections, and as well as the
* mailet's class and instance variables. More information on multithreaded
* programming in Java is available in <a href="http://java.sun.com/Series/Tutorial/java/threads/multithreaded.html">the
* Java tutorial on multi-threaded programming</a>.
*
* @param mail - the Mail object that contains the message and routing information
* @throws javax.mail.MessagingException - if an message or address parsing exception occurs or
* an exception that interferes with the mailet's normal operation
*/
void service(Mail mail) throws javax.mail.MessagingException;
}
1.1 jakarta-james/src/java/org/apache/mailet/MailetConfig.java
Index: MailetConfig.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.mailet;
import java.util.*;
/**
* A mailet configuration object used by a mailet container used to pass information
* to a mailet during initialization.
* <p>
* The configuration information contains initialization parameters, which are a set
* of name/value pairs, and a MailetContext object, which gives the mailet information
* about the server.
*
* @version 1.0.0, 24/04/1999
* @author Serge Knystautas <se...@lokitech.com>
*/
public interface MailetConfig {
/**
* Returns a String containing the value of the named initialization
* parameter, or null if the parameter does not exist.
*
* @param name - a String specifying the name of the initialization parameter
* @return a String containing the value of the initialization parameter
*/
String getInitParameter(String name);
/**
* Returns the names of the mailet's initialization parameters as an
* Iterator of String objects, or an empty Iterator if the mailet has
* no initialization parameters.
*
* @return an Iterator of String objects containing the names of the mailet's
* initialization parameters
*/
Iterator getInitParameterNames();
/**
* Returns a reference to the MailetContext in which the mailet is
* executing.
*
* @return a MailetContext object, used by the mailet to interact with its
* mailet container
*/
MailetContext getMailetContext();
/**
* Returns the name of this mailet instance. The name may be provided via
* server administration, assigned in the application deployment descriptor,
* or for an unregistered (and thus unnamed) mailet instance it will be the
* mailet's class name.
*
* @return the name of the mailet instance
*/
String getMailetName();
}
1.1 jakarta-james/src/java/org/apache/mailet/MailetContext.java
Index: MailetContext.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.mailet;
import java.util.*;
import javax.mail.*;
import javax.mail.internet.*;
/**
* Defines a set of methods that a mailet or matcher uses to communicate
* with its mailet container, for example, to send a new message, to
* deliver a message locally, or write to a log file.
*
* The MailetContext object is contained within the MailetConfig and
* MatcherConfig objects, which the mailet container provides the
* mailets and matchers when they are initialized.
*
* @version 1.0.0, 24/04/1999
* @author Federico Barbieri <sc...@pop.systemy.it>
* @author Stefano Mazzocchi <st...@apache.org>
* @author Pierpaolo Fumagalli <pi...@apache.org>
* @author Serge Knystautas <se...@lokitech.com>
*/
public interface MailetContext {
/**
* Bounces the message using a stanard format with the given message.
* Will be sent back to the sender from the postmaster as specified for
* this mailet context, adding message to top of mail server queue using
* sendMail().
*
* @param mail - the message that is to be bounced and sender to whom to return the message
* @param message - a descriptive message as to why the message bounced
*/
void bounce(Mail mail, String message) throws MessagingException;
/**
* Bounces the email message using the provided email address as the
* sender of the bounce.
*
* @param mail - the message that is to be bounced and sender to whom to return the message
* @param message - a descriptive message as to why the message bounced
* @param bouncer - the address to give as the sender of the bounced message
*/
void bounce(Mail mail, String message, MailAddress bouncer) throws MessagingException;
/**
* Returns a Collection of Strings of hostnames or ip addresses that
* are specified as mail server listeners for the given hostname.
* This is done using MX records, and the hostnames or ip addresses
* are returned sorted by MX priority.
*
* @param host - the domain name for which to find mail servers
* @return a Collection of Strings of hostnames, sorted by priority
*/
Collection getMailServers(String host);
/**
* Returns the postmaster's address for this mailet context.
*
* @return a MailAddress of the Postmaster's address
*/
MailAddress getPostmaster();
/**
* Returns the mailet container attribute with the given name, or null
* if there is no attribute by that name. An attribute allows a mailet container
* to give the mailet additional information not already provided by this interface.
* See * your server documentation for information about its attributes. A list of
* supported attributes can be retrieved using getAttributeNames.
* <p>
* The attribute is returned as a java.lang.Object or some subclass. Attribute
* names should follow the same convention as package names. The Java Mailet API
* specification reserves names matching java.*, javax.*, and sun.*
*
* @param name - a String specifying the name of the attribute
* @return an Object containing the value of the attribute, or null if no attribute
* exists matching the given name
*/
Object getAttribute(String name);
/**
* Returns an Iterator containing the attribute names available within
* this mailet context. Use the getAttribute(java.lang.String) method with an
* attribute name to get the value of an attribute.
*
* @return an Iterator of attribute names
*/
Iterator getAttributeNames();
/**
* Returns the minor version of the Mailet API that this mailet
* container supports. All implementations that comply with Version 1.2 must have
* this method return the integer 1.
*
* @return 1
*/
int getMajorVersion();
/**
* Returns the minor version of the Mailet API that this mailet
* container supports. All implementations that comply with Version 1.2 must have
* this method return the integer 2.
*
* @return 2
*/
int getMinorVersion();
/**
* Returns the name and version of the mailet container on which
* the mailet is running.
* <p>
* The form of the returned string is servername/versionnumber. For example,
* JAMES may return the string JAMES/1.2.
* <p>
* The mailet container may return other optional information after the primary
* string in parentheses, for example, JAMES/1.2 (JDK 1.3.0; Windows NT 4.0 x86).
*
* @return a String containing at least the mailet container name and version number
*/
String getServerInfo();
/**
* Checks if a server is serviced by mail context
*
* @param serverName - name of server.
* @return true if server is local, i.e. serviced by this mail context
*/
boolean isLocalServer(String serverName);
/**
* Checks if a user account is exists in the mail context.
*
* @param userAccount - user identifier.
* @return true if the acount is a local account
*/
boolean isLocalUser(String userAccount);
/**
* Writes the specified message to a mailet log file, usually an event
* log. The name and type of the mailet log file is specific to the mailet
* container.
*
* @param msg - a String specifying the message to be written to the log file
*/
void log(String message);
/**
* Writes an explanatory message and a stack trace for a given Throwable
* exception to the mailet log file.
*
* @param message - a String that describes the error or exception
* @param throwable - the Throwable error or exception
*/
void log(String message, Throwable t);
/**
* Removes the attribute with the given name from the mailet context. After
* removal, subsequent calls to getAttribute(java.lang.String) to retrieve
* the attribute's value will return null.
*
* @param name - a String specifying the name of the attribute to be removed
*/
void removeAttribute(String name);
/**
* Send an outgoing message to the top of this mailet container's root queue.
* This is the equivalent of opening an SMTP session to localhost.
* This uses sender and recipients as specified in the message itself.
*
* @param msg - the MimeMessage of the headers and body content of the outgoing message
* @throws MessagingException - if the message fails to parse
*/
void sendMail(MimeMessage msg)
throws MessagingException;
/**
* Send an outgoing message to the top of this mailet container's root queue.
* Is the equivalent of opening an SMTP session to localhost.
*
* @param sender - the sender of the message
* @param recipients - a Collection of String objects of recipients
* @param msg - the MimeMessage of the headers and body content of the outgoing message
* @throws MessagingException - if the message fails to parse
*/
void sendMail(MailAddress sender, Collection recipients, MimeMessage msg)
throws MessagingException;
/**
* Send an outgoing message to the top of this mailet container queue for the
* appropriate processor that is specified.
*
* @param sender - the sender of the message
* @param recipients - a Collection of String objects of recipients
* @param msg - the MimeMessage of the headers and body content of the outgoing message
* @param state - the state of the message, indicates which processor to use
* @throws MessagingException - if the message fails to parse
*/
void sendMail(MailAddress sender, Collection recipients, MimeMessage msg, String state)
throws MessagingException;
/**
* Binds an object to a given attribute name in this mailet context. If the name
* specified is already used for an attribute, this method will remove the old
* attribute and bind the name to the new attribute.
* <p>
* Attribute names should follow the same convention as package names. The Java
* Mailet API specification reserves names matching java.*, javax.*, and sun.*.
*
* @param name - a String specifying the name of the attribute
* @param object - an Object representing the attribute to be bound
*/
void setAttribute(String name, Object object);
/**
* Stores mail into local accounts (POP3 by default, or the IMAP4 Inbox)
*
* @param sender - the sender of the incoming message
* @param recipient - the user who is receiving this message (as a complete email address)
* @param msg - the MimeMessage to store in a local mailbox
* @throws MessagingException - if the message fails to parse
*/
void storeMail(MailAddress sender, MailAddress recipient, MimeMessage msg)
throws MessagingException;
}
1.1 jakarta-james/src/java/org/apache/mailet/MailetException.java
Index: MailetException.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.mailet;
import javax.mail.*;
/**
* Defines a general exception a mailet can throw when it encounters difficulty.
*
* @version 1.0.0, 24/04/1999
* @author Serge Knystautas <se...@lokitech.com>
*/
public class MailetException extends MessagingException {
/**
* Constructs a new mailet exception.
*/
public MailetException() {
super();
}
/**
* Constructs a new mailet exception with the specified message.
*/
public MailetException(String message) {
super(message);
}
/**
* Constructs a new mailet exception when the mailet needs to throw
* an exception and include a message about the "root cause" exception
* that interfered with its normal operation, including a description
* message.
*/
public MailetException(String message, Exception e) {
super(message, e);
}
}
1.1 jakarta-james/src/java/org/apache/mailet/Matcher.java
Index: Matcher.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.mailet;
import java.util.*;
/**
* This interface define the behaviour of the message "routing" inside
* the mailet container. The match(Mail) method returns a Collection of
* recipients that meet this class's criteria.
* <p>
* An important feature of the mailet container is the ability to fork
* processing of messages. When a message first arrives at the server,
* it might have multiple recipients specified. As a message is passed
* to a matcher, the matcher might only "match" one of the listed
* recipients. It would then return only the matching recipient in
* the Collection. The mailet container should then duplicate the
* message splitting the recipient list across the two messages as per
* what the matcher returned.
* <p>
* <b>[THIS PARAGRAPH NOT YET IMPLEMENTED]</b>
* <i>The matcher can extend this forking to further separation by returning
* a Collection of Collection objects. This allows a matcher to fork
* multiple processes if there are multiple recipients that require
* separate processing. For example, we could write a ListservMatcher
* that handles multiple listservs. When someone cross-posts across
* multiple listservs that this matcher handles, it could put each
* listserv address (recipient) that it handles in a separate Collection
* object. By returning each of these Collections within a container
* Collection object, it could indicate to the mailet container how
* many forks to spawn.</i>
* <p>
* This interface defines methods to initialize a matcher, to match
* messages, and to remove a matcher from the server. These are known
* as life-cycle methods and are called in the following sequence:
* <ol>
* <li>The matcher is constructed, then initialized with the init method.</li>
* <li>Any calls from clients to the match method are handled.</li>
* <li>The matcher is taken out of service, then destroyed with the
* destroy method, then garbage collected and finalized.</li>
* </ol>
* In addition to the life-cycle methods, this interface provides the
* getMatcherConfig method, which the matcher can use to get any startup
* information, and the getMatcherInfo method, which allows the matcher
* to return basic information about itself, such as author, version,
* and copyright.
*
* @version 1.0.0, 24/04/1999
* @author Federico Barbieri <sc...@pop.systemy.it>
* @author Serge Knystautas <se...@lokitech.com>
*/
public interface Matcher {
/**
* Called by the mailet container to indicate to a matcher that the matcher
* is being taken out of service. This method is only called once all threads
* within the matcher's service method have exited or after a timeout period
* has passed. After the mailet container calls this method, it will not call
* the match method again on this matcher.
* <p>
* This method gives the matcher an opportunity to clean up any resources that
* are being held (for example, memory, file handles, threads) and make sure
* that any persistent state is synchronized with the matcher's current state in memory.
*/
void destroy();
/**
* Returns a MatcherConfig object, which contains initialization and
* startup parameters for this matcher.
* <p>
* Implementations of this interface are responsible for storing the
* MatcherConfig object so that this method can return it. The GenericMatcher
* class, which implements this interface, already does this.
*
* @return the MatcherConfig object that initializes this matcher
*/
MatcherConfig getMatcherConfig();
/**
* Returns information about the matcher, such as author, version, and copyright.
* <p>
* The string that this method returns should be plain text and not markup
* of any kind (such as HTML, XML, etc.).
*
* @return a String containing matcher information
*/
String getMatcherInfo();
/**
* Called by the mailet container to indicate to a matcher that the
* matcher is being placed into service.
* <p>
* The mailet container calls the init method exactly once after instantiating
* the matcher. The init method must complete successfully before the matcher
* can receive any messages.
*
* @param config - a MatcherConfig object containing the matcher's configuration
* and initialization parameters
* @throws javax.mail.MessagingException - if an exception has occurred that
* interferes with the matcher's normal operation
*/
void init( MatcherConfig config ) throws javax.mail.MessagingException;
/**
* Takes a Mail message, looks at any pertinent information, and then returns a subset
* of recipients that meet the "match" conditions.
* <p>
* This method is only called after the matcher's init() method has completed
* successfully.
* <p>
* Matchers typically run inside multithreaded mailet containers that can handle
* multiple requests concurrently. Developers must be aware to synchronize access
* to any shared resources such as files, network connections, and as well as the
* matcher's class and instance variables. More information on multithreaded
* programming in Java is available in <a href="http://java.sun.com/Series/Tutorial/java/threads/multithreaded.html">the
* Java tutorial on multi-threaded programming</a>.
*
* @param mail - the Mail object that contains the message and routing information
* @return a Collection of String objects (recipients) that meet the match criteria
* @throws MessagingException - if an message or address parsing exception occurs or
* an exception that interferes with the matcher's normal operation
*/
Collection match( Mail mail ) throws javax.mail.MessagingException;
}
1.1 jakarta-james/src/java/org/apache/mailet/MatcherConfig.java
Index: MatcherConfig.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.mailet;
/**
* A matcher configuration object used by a mailet container used to pass information
* to a matcher during initialization.
* <p>
* The configuration information contains an initialization parameter,
* which is set as a condition String, and a MailetContext object,
* which gives the mailet information about the mailet container.
*
* @version 1.0.0, 24/04/1999
* @author Serge Knystautas <se...@lokitech.com>
*/
public interface MatcherConfig {
/**
* The simple condition defined for this matcher, e.g., for
* SenderIs=admin@localhost, this would return admin@localhost.
*
* @return a String containing the value of the initialization parameter
*/
String getCondition();
/**
* Returns a reference to the MailetContext in which the matcher is executing
*
* @return a MailetContext object, used by the matcher to interact with its
* mailet container
*/
MailetContext getMailetContext();
/**
* Returns the name of this matcher instance. The name may be provided via server
* administration, assigned in the application deployment descriptor, or for
* an unregistered (and thus unnamed) matcher instance it will be the matcher's
* class name.
*
* @return the name of the matcher instance
*/
String getMatcherName();
}
---------------------------------------------------------------------
To unsubscribe, e-mail: james-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: james-dev-help@jakarta.apache.org