<!--
    Licensed to the Apache Software Foundation (ASF) under one
    or more contributor license agreements. See the NOTICE file
    distributed with this work for additional information
    regarding copyright ownership. The ASF licenses this file
    to you under the Apache License, Version 2.0 (the
    "License"); you may not use this file except in compliance
    with the License. You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing,
    software distributed under the License is distributed on an
    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
    KIND, either express or implied. See the License for the
    specific language governing permissions and limitations
    under the License.
-->
<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8"/>
        <title>Apache James</title>

        <link rel="stylesheet" type="text/css" href="/assets/css/main.css">
        <link rel="stylesheet" type="text/css" href="/assets/css/font-awesome.min.css">
        <link rel="stylesheet" type="text/css" href="/assets/css/ie8.css">
        <link rel="stylesheet" type="text/css" href="/assets/css/ie9.css">
        <link rel="shortcut icon" href="/images/james-logo.png">
    </head>
<body>
    <!--
    Licensed to the Apache Software Foundation (ASF) under one
    or more contributor license agreements. See the NOTICE file
    distributed with this work for additional information
    regarding copyright ownership. The ASF licenses this file
    to you under the Apache License, Version 2.0 (the
    "License"); you may not use this file except in compliance
    with the License. You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing,
    software distributed under the License is distributed on an
    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
    KIND, either express or implied. See the License for the
    specific language governing permissions and limitations
    under the License.
-->

<div id="wrapper">
    <div class="apache_ref">
        <a href="https://www.apache.org" alt="apache foundation link"><img src="https://www.apache.org/foundation/press/kit/asf_logo.svg" title="apache foundation logo"/></a>
    </div>
    <div class="apache_ref_mobile">
        <a href="https://www.apache.org" alt="apache foundation link">The Apache Software Foundation</a>
    </div>
    <div class="apache_ref_left">
        <a href="https://www.apache.org/events/current-event.html" alt="apache foundation event"><img src="https://www.apache.org/events/current-event-234x60.png" title="apache foundation event logo"/></a>
    </div>
    <div class="apache_ref_left_mobile">
        <a href="https://www.apache.org/events/current-event.html" alt="apache foundation event"><img src="https://www.apache.org/events/current-event-234x60.png" title="apache foundation event logo"/></a>
    </div>

    <!--
    Licensed to the Apache Software Foundation (ASF) under one
    or more contributor license agreements. See the NOTICE file
    distributed with this work for additional information
    regarding copyright ownership. The ASF licenses this file
    to you under the Apache License, Version 2.0 (the
    "License"); you may not use this file except in compliance
    with the License. You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing,
    software distributed under the License is distributed on an
    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
    KIND, either express or implied. See the License for the
    specific language governing permissions and limitations
    under the License.
-->

<header id="header" class="alt">
    <div class="logo"><a href="/index.html" alt="Apache James"><img src="/images/james.svg" alt="james logo"/></a></div>
    <h1 class="hidden">James Enterprise Mail Server</h1>
    <h2>Emails at the heart of your business logic</h2>
</header>

    <!--
    Licensed to the Apache Software Foundation (ASF) under one
    or more contributor license agreements. See the NOTICE file
    distributed with this work for additional information
    regarding copyright ownership. The ASF licenses this file
    to you under the Apache License, Version 2.0 (the
    "License"); you may not use this file except in compliance
    with the License. You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing,
    software distributed under the License is distributed on an
    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
    KIND, either express or implied. See the License for the
    specific language governing permissions and limitations
    under the License.
-->

<!-- Main -->
<div id="main">

    <!-- Introduction -->
    <section id="intro" class="main special">
        <div class="">
            <div class="content align-left">
                <header class="major">
                    <h1><b>Configure Custom SMTP commands</b></h1>
                </header>

                <p>
                    The current project demonstrates how to write custom commands for Apache James SMTP server.
                </p>

                <p>
                    Find this example on <a href="https://github.com/apache/james-project/tree/master/examples/custom-imap">GitHub</a>.
                </p>

                <p>
                    Start by importing the dependencies:
                </p>

                <pre><code>&lt;dependency&gt;
    &lt;groupId&gt;org.apache.james&lt;/groupId&gt;
    &lt;artifactId&gt;james-server-protocols-smtp&lt;/artifactId&gt;
&lt;/dependency&gt;
                </code></pre>

                <p>You can write your commands by extending the <code>CommandHandler&lt;SMTPSession&gt;</code> class. For instance:</p>

                <pre><code>/**
  * Copy of NoopCmdHandler
  */
public class MyNoopCmdHandler implements CommandHandler&lt;SMTPSession&gt; {
    private static final Collection&lt;String&gt; COMMANDS = ImmutableSet.of(&quot;MYNOOP&quot;);

    private static final Response NOOP = new SMTPResponse(SMTPRetCode.MAIL_OK,
        DSNStatus.getStatus(DSNStatus.SUCCESS, DSNStatus.UNDEFINED_STATUS) + &quot; OK&quot;)
        .immutable();

    @Override
    public Response onCommand(SMTPSession session, Request request) {
        return NOOP;
    }

    @Override
    public Collection&lt;String&gt; getImplCommands() {
        return COMMANDS;
    }
}</code></pre>

                <p>You then need to list the exposed SMTP commands with a <code>HandlersPackage</code>. For instance:</p>

                <pre><code>/**
 * This class copies CoreCmdHandlerLoader adding support for MYNOOP command
 */
public class MyCmdHandlerLoader implements HandlersPackage {

    private final List&lt;String&gt; commands = new LinkedList&lt;&gt;();

    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&lt;String&gt; getHandlers() {
        return commands;
    }
}</code></pre>

                <p>You can compile this example project:</p>

                <pre><code>mvn clean install</code></pre>

                <p>Write a configuration file telling James to use your <code>HandlerPackage</code>:</p>

                <pre><code>&lt;smtpservers&gt;
    &lt;smtpserver enabled=&quot;true&quot;&gt;
        &lt;jmxName&gt;smtpserver-global&lt;/jmxName&gt;
        &lt;bind&gt;0.0.0.0:25&lt;/bind&gt;
        &lt;connectionBacklog&gt;200&lt;/connectionBacklog&gt;
        &lt;tls socketTLS=&quot;false&quot; startTLS=&quot;false&quot;&gt;
            &lt;keystore&gt;file://conf/keystore&lt;/keystore&gt;
            &lt;secret&gt;james72laBalle&lt;/secret&gt;
            &lt;provider&gt;org.bouncycastle.jce.provider.BouncyCastleProvider&lt;/provider&gt;
            &lt;algorithm&gt;SunX509&lt;/algorithm&gt;
        &lt;/tls&gt;
        &lt;!-- ... --&gt;
        &lt;handlerchain coreHandlersPackage=&quot;org.apache.james.examples.MyCmdHandlerLoader&quot;&gt;
            &lt;handler class=&quot;org.apache.james.smtpserver.fastfail.ValidRcptHandler&quot;/&gt;
        &lt;/handlerchain&gt;
    &lt;/smtpserver&gt;
&lt;/smtpservers&gt;</code></pre>

                <p>Then start a James server with your JAR and the configuration:</p>

                <pre><code>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
                </code></pre>

                <p>You can play with <code>telnet</code> utility with the resulting server and use the <code>MYNOOP</code> command:</p>

                <pre><code>$ $ 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.</code></pre>
            </div>
            <footer class="major">
                <ul class="actions align-center">
                    <li><a href="index.html" class="button">go back to other how-tos</a></li>
                </ul>
            </footer>
        </div>
    </section>

</div>


    <!--
    Licensed to the Apache Software Foundation (ASF) under one
    or more contributor license agreements. See the NOTICE file
    distributed with this work for additional information
    regarding copyright ownership. The ASF licenses this file
    to you under the Apache License, Version 2.0 (the
    "License"); you may not use this file except in compliance
    with the License. You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing,
    software distributed under the License is distributed on an
    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
    KIND, either express or implied. See the License for the
    specific language governing permissions and limitations
    under the License.
-->

<footer id="footer" class="major">
    <section>
        <h2>James</h2>
        <ul class="no-padding">
            <li class="no-padding"><a href="https://james.apache.org/#intro" class="active">About</a></li>
            <li class="no-padding"><a href="https://james.apache.org/#first">Get Started</a></li>
            <li class="no-padding"><a href="https://james.apache.org/#posts">Last Posts</a></li>
            <li class="no-padding"><a href="https://james.apache.org/#second">Community</a></li>
            <li class="no-padding"><a href="https://james.apache.org/#third">Contribute</a></li>
            <li class="no-padding"><a href="https://james.apache.org/"><span class="fa fa-external-link"></span> Documentation</a></li>
        </ul>
    </section>
    <section>
        <h2>Connect</h2>
        <ul class="icons">
            <li><a href="https://james.apache.org/mail.html" class="icon fa-envelope-o alt"><span class="label">Mailing-list</span></a></li>
            <li><a href="https://gitter.im/apache/james-project" class="icon fa-wechat alt"><span class="label">Gitter</span></a></li>
            <li><a href="https://github.com/apache/james-project" class="icon fa-github alt"><span class="label">GitHub</span></a></li>
            <li><a href="https://twitter.com/ApacheJames" class="icon fa-twitter alt"><span class="label">Twitter</span></a></li>
            <li><a href="https://james.apache.org/support.html" class="icon fa-briefcase alt"><span class="label">Support</span></a></li>
            <li><a href="http://www.apache.org/events/current-event" class="icon fa-calendar alt"><span class="label">Apache Foundation events</span></a></li>
        </ul>
    </section>
    <section class="legal-section">
        <h2>Copyright</h2>
        Apache James and related projects are trademarks of the Apache Software Foundation.<br/>
        <a href="https://www.apache.org/">Copyright 2006-2021 The Apache Software Foundation. All Rights Reserved.</a><br/>
        <a href="https://www.apache.org/licenses/">License</a><br/>
        <a href="https://www.apache.org/foundation/sponsorship.html">Donate</a> to support the Apache Foundation<br/>
        <a href="https://www.apache.org/foundation/thanks.html">Thanks</a><br/>
        Design: <a href="https://html5up.net">HTML5 UP</a><br/>
        Thanks to <a href="http://www.neoma-interactive.com/">Neoma by Linagora</a> for the website design
    </section>
</footer>
</div>

</body>
</html>
