Differences between revisions 8 and 9
Revision 8 as of 2007-01-08 13:57:53
Size: 5796
Editor: DannyAngus
Comment:
Revision 9 as of 2009-09-20 22:58:46
Size: 5798
Editor: localhost
Comment: converted to 1.6 markup
Deletions are marked like this. Additions are marked like this.
Line 1: Line 1:
'' Thanks to pressure applied by our users, and a [http://code.google.com/summerofcode05.html Google Summer of Code 05] student Anagha Mudigonda, James now supports fast-fail. :-) (DannyAngus)''' '' Thanks to pressure applied by our users, and a [[http://code.google.com/summerofcode05.html|Google Summer of Code 05]] student Anagha Mudigonda, James now supports fast-fail. :-) (DannyAngus)'''

Thanks to pressure applied by our users, and a Google Summer of Code 05 student Anagha Mudigonda, James now supports fast-fail. :-) (DannyAngus)

We are currently talking about plans to implement flexible and powerful fast-fail mechanisms. There has been a lot of discussion on fast-fail on the developers mailing list, but it hasn't entirely converged. There is a certain amount of agreement on a filtering notion per protocol message. Where we have not converged is on how to implement the filtering. This page is an attempt to help converge our plans.


I am DannyAngus and I'm proposing an API for extending James to create extension points for Protocol, Command, and Rule.

The proposal, sumarised from mails sent to server-dev@james:

My original proposal:

  • ProtocolHandler - parses commands per protocol spec.

    CommandHandler - matches command(s) and responds to the protocol handler with a response code & message.

    CommandRule - called by command handler to validate command, responds with a response code & message

You will see that I propose to implement THREE levels of entry into the protocol handling.

a) implement a new protocol

b) implement a new command

c) implement a new rule to be applied to a command

Anyone wishing to do *any* of these three things will be able to do so with no extra knowledge of James internals.

It is much more likely that James' users will wish to modify James' behaviour than they will want to port James functionality to other servers.

If you want to introduce reuse external to James this would require an independant API specification. Which I am *not* proposing.

The mail protocols are all of the same command->response form and the constraints are there to provide consistent extension points to James.

This proposal allows anyone to implement whatever they _really_ want, in terms of commands and fail rules.

Example pseudo-code interfaces


A protocol handler

public interface Protocol {

  • public abstract void handleConnection(Socket connection) throws IOException; public abstract void setCommandMap(Map commands); //map of Commands

}


A command

public interface Command{

  • public abstract String getCommandName(); public abstract Response handleCommand(String command, Map State); public abstract void setRulesList(List rules); // List of Rules

}


A rule

public interface Rule{

  • public abstract Response processArguments(String[] arguments, Map State);

}


A response

public interface Response{

  • public abstract String getResponseCode(); public abstract String getExtendedCode();//possibly only in

extended SMTPResponse

  • public abstract String getMessage(); public abstract String getResponse();

}


DannyAngus



This is a proposal from Noel J. Bergman


Danny and I are largely in agreement on on having some form of handler for each of several kinds of event:

   - onConnect
   - on<PROTOCOL-COMMAND>
   - onMessage

I'm not particularly married as to how it would be done, but I do have requirements:

  • fast
  • flexible
  • extensible
  • configurable

One possibility is doing something like:

  <handlerchain>
    <handler class="org.apache.james.smtpserver.dnsrblhandler">
      <rbl>...</rbl>
    </handler>
    <handler class="org.apache.james.smtpserver.spamassassinhandler">
      ... config ...
    </handler>
    <handler class="my.james.smtpserver.handler" onConnection=false onMessage=false onCommand="HELP,AUTH">
      ... config ...
    </handler>
    <handler class="com.devtech.james.smtpserver.pipeline">
       <root> starting-processor </root>
       <processor name=..." class="...">
          <mailet match="ClamAV" class="SMTPResponse">
             <code>554</code>
             <notice>554 - delivery error: ClamAV reports that it detected {1} in message content.</notice>
          </mailet>
       </processor>
       </processor name=..." class="...">
          ...
       </processor>
    </handler>
    <handler class="org.apache.james.smtpserver.basehandler">
    ... config ...
    </handler>
  </handlerchain>

where the administrator simply liststhe handlers desired, along with their configuration. Internally, we inspect the handler to find out what events it handles. So we would have interfaces (incomplete here):

  interface ConnectionHandler (
    onConnection(Socket)
  }

  interface CommandsHandler {
    Map getCommands()
  }

  interface CommandHandler {
    onCommand(...)
  }

  interface MessageHandler {
    onMessage(...)
  }

and each of the registered handlers would be inspected to see whether or not they implement an interface. For a ConnectionHandler or MessageHandler, it would be appended to the handler chain for that event. For a CommandsHandler instance, it would be queried for the Map, which would be merged into the master Map, such that the master Map would have a single chain for each supported operation.

I have also illustrated here how to handle micromanagement of handler order. In the typical case, having to list each and every operation would make configuration difficult.

Once this is implemented, the MessageHandler provides where we could plugin either special code, e.g., the hypothetical spamassassin handler, or generic code like my example with the pipeline (in-protocol processor) handler. A custom onMessage handler could support an new message management that would come along, such as in-line BSF scripts, jsieve, etc.


FastFail (last edited 2009-09-20 22:58:46 by localhost)