The Apache Software Foundation

Configure Custom SMTP hooks

The current project demonstrates how to write custom behaviors for Apache James SMTP server by the means of SMTP hooks.

SMTP hooks allow integrating third party systems with the SMTP stack and writing additional SMTP extensions, for instance.

Start by importing the dependencies:

    Allows writing the following hooks:
  • AuthHook: hook in the AUTH Command
  • HeloHook: hook in the HELO Command
  • MailHook: hook in the MAIL Command
  • MailParametersHook: hook in the MAIL Command parameters
  • RcptHook: hook in the RCPT Command
  • MessageHook: hook in the DATA Command
  • QuitHook: hook in the QUIT Command
  • UnknownHook: hook for unknown commands

James comes bundled with provided SMTP hooks for common features. We encourage you to review them before starting writing your own hooks.

    Allows writing the following hooks:
  • JamesMessageHook: DATA command. Allows access to the message content.

Writing your own hooks

Find this example on GitHub.

In this example we implement a single RCPT hook:

public class LoggingRcptHook implements RcptHook {
    public HookResult doRcpt(SMTPSession session, MaybeSender sender, MailAddress rcpt, Map<String, String> parameters) {
        System.out.println("RCPT TO " + rcpt + "with parameters " + parameters);

        // Continue the SMTP transaction
        return HookResult.DECLINED;

You can compile this example project:

mvn clean install

Then embed your extension into a James server. First configure your hook:

<?xml version="1.0"?>
    <smtpserver enabled="true">
        <tls socketTLS="false" startTLS="false">
        <!-- ... -->
            <handler class="org.apache.james.smtpserver.fastfail.ValidRcptHandler"/>
            <handler class="org.apache.james.smtpserver.CoreCmdHandlerLoader"/>
            <handler class="org.apache.james.examples.LoggingRcptHook"/>

Create a keystore (default password being james72laBalle):

keytool -genkey -alias james -keyalg RSA -keystore keystore

Then start a James server with your JAR and the configuration:

docker run -d \
  -v $PWD/smtpserver.xml:/root/conf/smtpserver.xml \
  -v $PWD/exts:/root/extensions-jars \
  -v $PWD/keystore:/root/conf/keystore \
  -p 25:25 \

You can play with telnet utility with the resulting server:

$ telnet 25
Connected to
Escape character is '^]'.
220 Apache JAMES awesome SMTP Server
250-177b73020637 Hello [])
503 5.5.0 Need MAIL before RCPT
250 2.1.0 Sender <> OK
550 5.7.1 Requested action not taken: relaying denied

Now looking at the logs we can verify that our RCPT have well been executed:

06:49:15.734 [INFO ] o.a.j.GuiceJamesServer - JAMES server started
06:49:30.275 [INFO ] o.a.j.p.n.BasicChannelUpstreamHandler - Connection established from
06:50:18.892 [INFO ] o.a.j.i.n.ImapChannelUpstreamHandler - Connection established from
06:50:19.152 [INFO ] o.a.j.i.n.ImapChannelUpstreamHandler - Connection closed for
RCPT TO c@d.comwith parameters {TO:=, <>=}

Note that hooks can also be written for the LMTP protocol.