Read this page on the website.
The current project demonstrates how to write custom commands for Apache James SMTP server.
Start by importing the dependencies:
<dependency>
<groupId>org.apache.james.protocols</groupId>
<artifactId>protocols-smtp/artifactId>
</dependency>
You can write your commands by extending the CommandHandler<SMTPSession>
class. For instance:
/**
* Copy of NoopCmdHandler
*/
public class MyNoopCmdHandler implements CommandHandler<SMTPSession> {
private static final Collection<String> COMMANDS = ImmutableSet.of("MYNOOP");
private static final Response NOOP = new SMTPResponse(SMTPRetCode.MAIL_OK,
DSNStatus.getStatus(DSNStatus.SUCCESS, DSNStatus.UNDEFINED_STATUS) + " OK")
.immutable();
@Override
public Response onCommand(SMTPSession session, Request request) {
return NOOP;
}
@Override
public Collection<String> getImplCommands() {
return COMMANDS;
}
}
You then need to list the exposed SMTP commands with a HandlersPackage
. For instance:
/**
* This class copies CoreCmdHandlerLoader adding support for MYNOOP command
*/
public class MyCmdHandlerLoader implements HandlersPackage {
private final List<String> commands = new LinkedList<>();
public MyCmdHandlerLoader() {
Stream.of(
JamesWelcomeMessageHandler.class,
CommandDispatcher.class,
AuthCmdHandler.class,
JamesDataCmdHandler.class,
EhloCmdHandler.class,
ExpnCmdHandler.class,
HeloCmdHandler.class,
HelpCmdHandler.class,
JamesMailCmdHandler.class,
NoopCmdHandler.class,
QuitCmdHandler.class,
JamesRcptCmdHandler.class,
RsetCmdHandler.class,
VrfyCmdHandler.class,
MailSizeEsmtpExtension.class,
UsersRepositoryAuthHook.class,
AuthRequiredToRelayRcptHook.class,
SenderAuthIdentifyVerificationHook.class,
PostmasterAbuseRcptHook.class,
ReceivedDataLineFilter.class,
DataLineJamesMessageHookHandler.class,
StartTlsCmdHandler.class,
AddDefaultAttributesMessageHook.class,
SendMailHandler.class,
UnknownCmdHandler.class,
CommandHandlerResultLogger.class,
HookResultLogger.class,
// Support MYNOOP
MyNoopCmdHandler.class)
.map(Class::getName)
.forEachOrdered(commands::add);
}
@Override
public List<String> getHandlers() {
return commands;
}
}
Then compile this little project:
mvn clean install
Write a configuration file telling James to use your HandlerPackage
:
<smtpservers>
<smtpserver enabled="true">
<jmxName>smtpserver-global</jmxName>
<bind>0.0.0.0:25</bind>
<connectionBacklog>200</connectionBacklog>
<tls socketTLS="false" startTLS="false">
<keystore>file://conf/keystore</keystore>
<secret>james72laBalle</secret>
<provider>org.bouncycastle.jce.provider.BouncyCastleProvider</provider>
<algorithm>SunX509</algorithm>
</tls>
<!-- ... -->
<handlerchain coreHandlersPackage="org.apache.james.examples.MyCmdHandlerLoader">
<handler class="org.apache.james.smtpserver.fastfail.ValidRcptHandler"/>
</handlerchain>
</smtpserver>
</smtpservers>
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 \
-p 25:25 \
apache/james:memory-latest --generate-keystore
You can play with telnet
utility with the resulting server:
$ telnet 127.0.0.1 25
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
220 Apache JAMES awesome SMTP Server
MYNOOP
250 2.0.0 OK
quit
221 2.0.0 1f0274082fc6 Service closing transmission channel
Connection closed by foreign host.