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:

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 {

}


A command

public interface Command{

}


A rule

public interface Rule{

}


A response

public interface Response{

extended SMTPResponse

}


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)