Building custom plugins for Jsmtpd

Plugins in Jsmtpd

It's quite easy to develop a plugin for Jsmtpd, althought it will require a basic knowledge of Java and XML.

Jsmtpd can be divided in three main blocks :

  • The core : basic functionalities for receiving, queueing and sending mail. It also defines a simple model for processing mails, plus interfaces allowing to implement functionalities.
  • A set of plugin management tools. Plugins are automaticly loaded and configured by the plugin loader. They are stored in a sort of trivial registry. It's very similar to a light bean management framework, thus not proving advanced functionalities.
  • A set of simple plugins : Mailbox writer, remote sender, Acces control plugins, filters, smtp extensions... etc.

Get ready

You can grab the sources on the subversion, on http://sourceforge.net/project/showfiles.php?group_id=132129 , or in the auto-built packages.

The project is writen using eclipse, so you can check out sources directly inside a project : it will set classpath and other stuff for you. If you're using vi or emacs as IDE, well you're on your own ;) You can see in the startup scripts hint of the classpath used.

Let's write some code

The first thing you should look at is the interface IgenericPlugin. It defines a common behavior for all plugins. All other plugin interfaces inherits from this one.

public interface IGenericPlugin {
    /**
     * @return this plugin's name
     */
    public String getPluginName();

    /**
     * Perform initialisation of the plugin. 
     * if an error
     * occurs, the plugin is not functional
     * @throws PluginInitException
     */
    public void initPlugin() throws PluginInitException;
    /**
     * Invoked on server shutdown 
     */
    public void shutdownPlugin();

}

Two other importants things :

  • Plugins may (are) invoked from a multi-threaded environement. A single instance of the plugin exists. It's up to you to ensure thread safety when needed.
  • Plugins are configured automaticly by the PluginLoader. When it reads a property fron the xml configuration file, it will try to find a corresponding setter method, perfom a type cast, and then invoke it using Java reflection.

Here is how a plugin is started :

  1. The PluginLoader reads an entry in the XML file, lookup the class name of your plugin. It then creates an instance of it.
  2. Each property defined in the XML is set using reflection. If the setter is not found or not accesible (private), an error is thrown, and Jsmtpd does not starts.
  3. When all properties are set, Jsmtpd invokes the initPlugin method of your plugin. You should perform any initializations here. If your code cannot initalize, it should throw a PluginInitException
  4. The initialized plugin is store in the PluginStore instance, ready to be used elsewhere.
  5. When Jsmtpd shuts down, the shutdownPlugin methdod is invoked on each plugin.

Additionnaly, the getPluginName method is invoked whenever the core needs to know the plugin's name, most commonly to print it in logs.

Types of plugin in Jsmtpd

There are several kind of plugins in Jsmtpd :