You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@james.apache.org by rc...@apache.org on 2020/12/30 03:35:17 UTC

[james-project] 05/29: JAMES-3431 MockSMTPServer: Allow advertising extra extensions upon EHLO

This is an automated email from the ASF dual-hosted git repository.

rcordier pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/james-project.git

commit e632e80d2495a071ce856343a0646d8b641aadb6
Author: Benoit Tellier <bt...@linagora.com>
AuthorDate: Wed Dec 23 17:22:13 2020 +0700

    JAMES-3431 MockSMTPServer: Allow advertising extra extensions upon EHLO
---
 .../mock/smtp/server/ConfigurationClient.java      | 10 +++
 .../mock/smtp/server/ExtendedEhloCommand.java      | 75 ++++++++++++++++++++++
 .../mock/smtp/server/HTTPConfigurationServer.java  | 39 +++++++++++
 .../james/mock/smtp/server/MockSMTPServer.java     |  1 +
 .../mock/smtp/server/SMTPBehaviorRepository.java   | 26 ++++++++
 .../SMTPExtension.java}                            | 49 +++++++-------
 .../SMTPExtensions.java}                           | 50 ++++++++-------
 .../mock/smtp/server/ConfigurationClientTest.java  | 38 +++++++++++
 .../james/mock/smtp/server/MockSMTPServerTest.java | 23 +++++++
 9 files changed, 266 insertions(+), 45 deletions(-)

diff --git a/server/mailet/mock-smtp-server/src/main/java/org/apache/james/mock/smtp/server/ConfigurationClient.java b/server/mailet/mock-smtp-server/src/main/java/org/apache/james/mock/smtp/server/ConfigurationClient.java
index e823cee..dade1ba 100644
--- a/server/mailet/mock-smtp-server/src/main/java/org/apache/james/mock/smtp/server/ConfigurationClient.java
+++ b/server/mailet/mock-smtp-server/src/main/java/org/apache/james/mock/smtp/server/ConfigurationClient.java
@@ -29,6 +29,7 @@ import org.apache.james.mock.smtp.server.model.MockSmtpBehaviors;
 import org.apache.james.mock.smtp.server.model.Operator;
 import org.apache.james.mock.smtp.server.model.Response;
 import org.apache.james.mock.smtp.server.model.SMTPCommand;
+import org.apache.james.mock.smtp.server.model.SMTPExtensions;
 import org.apache.james.util.Host;
 
 import com.fasterxml.jackson.databind.ObjectMapper;
@@ -184,6 +185,15 @@ public interface ConfigurationClient {
     @RequestLine("GET " + HTTPConfigurationServer.SMTP_BEHAVIORS)
     List<MockSMTPBehavior> listBehaviors();
 
+    @RequestLine("PUT " + HTTPConfigurationServer.SMTP_EXTENSIONS)
+    void setSMTPExtensions(SMTPExtensions extensions);
+
+    @RequestLine("DELETE " + HTTPConfigurationServer.SMTP_EXTENSIONS)
+    void clearSMTPExtensions();
+
+    @RequestLine("GET " + HTTPConfigurationServer.SMTP_EXTENSIONS)
+    SMTPExtensions listSMTPExtensions();
+
     @RequestLine("GET " + HTTPConfigurationServer.SMTP_MAILS)
     List<Mail> listMails();
 
diff --git a/server/mailet/mock-smtp-server/src/main/java/org/apache/james/mock/smtp/server/ExtendedEhloCommand.java b/server/mailet/mock-smtp-server/src/main/java/org/apache/james/mock/smtp/server/ExtendedEhloCommand.java
new file mode 100644
index 0000000..45aa322
--- /dev/null
+++ b/server/mailet/mock-smtp-server/src/main/java/org/apache/james/mock/smtp/server/ExtendedEhloCommand.java
@@ -0,0 +1,75 @@
+/****************************************************************
+ * 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.                                           *
+ ****************************************************************/
+
+package org.apache.james.mock.smtp.server;
+
+import java.io.IOException;
+import java.util.List;
+
+import org.subethamail.smtp.AuthenticationHandlerFactory;
+import org.subethamail.smtp.server.BaseCommand;
+import org.subethamail.smtp.server.Session;
+import org.subethamail.smtp.util.TextUtils;
+
+public class ExtendedEhloCommand extends BaseCommand {
+    private final SMTPBehaviorRepository behaviorRepository;
+
+    public ExtendedEhloCommand(SMTPBehaviorRepository behaviorRepository) {
+        super("EHLO", "Introduce yourself.", "<hostname>");
+        this.behaviorRepository = behaviorRepository;
+    }
+
+    public void execute(String commandString, Session sess) throws IOException {
+        String[] args = this.getArgs(commandString);
+        if (args.length < 2) {
+            sess.sendResponse("501 Syntax: EHLO hostname");
+        } else {
+            sess.resetMessageState();
+            sess.setHelo(args[1]);
+            StringBuilder response = new StringBuilder();
+            response.append("250-");
+            response.append(sess.getServer().getHostName());
+            response.append("\r\n250-8BITMIME");
+            int maxSize = sess.getServer().getMaxMessageSize();
+            if (maxSize > 0) {
+                response.append("\r\n250-SIZE ");
+                response.append(maxSize);
+            }
+
+            if (sess.getServer().getEnableTLS() && !sess.getServer().getHideTLS()) {
+                response.append("\r\n250-STARTTLS");
+            }
+
+            AuthenticationHandlerFactory authFact = sess.getServer().getAuthenticationHandlerFactory();
+            if (authFact != null) {
+                List<String> supportedMechanisms = authFact.getAuthenticationMechanisms();
+                if (!supportedMechanisms.isEmpty()) {
+                    response.append("\r\n250-AUTH ");
+                    response.append(TextUtils.joinTogether(supportedMechanisms, " "));
+                }
+            }
+
+            behaviorRepository.getSMTPExtensions()
+                .forEach(smtpExtension -> response.append("\r\n250-").append(smtpExtension.asString()));
+
+            response.append("\r\n250 Ok");
+            sess.sendResponse(response.toString());
+        }
+    }
+}
diff --git a/server/mailet/mock-smtp-server/src/main/java/org/apache/james/mock/smtp/server/HTTPConfigurationServer.java b/server/mailet/mock-smtp-server/src/main/java/org/apache/james/mock/smtp/server/HTTPConfigurationServer.java
index 5a0784b..46925e0 100644
--- a/server/mailet/mock-smtp-server/src/main/java/org/apache/james/mock/smtp/server/HTTPConfigurationServer.java
+++ b/server/mailet/mock-smtp-server/src/main/java/org/apache/james/mock/smtp/server/HTTPConfigurationServer.java
@@ -26,12 +26,15 @@ import static io.netty.handler.codec.http.HttpResponseStatus.NO_CONTENT;
 import static io.netty.handler.codec.http.HttpResponseStatus.OK;
 
 import java.io.IOException;
+import java.util.List;
 import java.util.Optional;
 
 import org.apache.james.mock.smtp.server.jackson.MailAddressModule;
 import org.apache.james.mock.smtp.server.model.Mails;
 import org.apache.james.mock.smtp.server.model.MockSMTPBehaviorInformation;
 import org.apache.james.mock.smtp.server.model.MockSmtpBehaviors;
+import org.apache.james.mock.smtp.server.model.SMTPExtension;
+import org.apache.james.mock.smtp.server.model.SMTPExtensions;
 import org.apache.james.util.Port;
 import org.reactivestreams.Publisher;
 import org.slf4j.Logger;
@@ -92,6 +95,7 @@ public class HTTPConfigurationServer {
     private static final Logger LOGGER = LoggerFactory.getLogger(HTTPConfigurationServer.class);
     private static final int RANDOM_PORT = 0;
     static final String SMTP_BEHAVIORS = "/smtpBehaviors";
+    static final String SMTP_EXTENSIONS = "/smtpExtensions";
     static final String VERSION = "/version";
     static final String SMTP_MAILS = "/smtpMails";
 
@@ -129,9 +133,12 @@ public class HTTPConfigurationServer {
                 .orElse(RANDOM_PORT))
             .route(routes -> routes
                 .get(SMTP_BEHAVIORS, this::getBehaviors)
+                .get(SMTP_EXTENSIONS, this::getExtensions)
                 .get(VERSION, this::getVersion)
                 .put(SMTP_BEHAVIORS, this::putBehaviors)
+                .put(SMTP_EXTENSIONS, this::putExtensions)
                 .delete(SMTP_BEHAVIORS, this::deleteBehaviors)
+                .delete(SMTP_EXTENSIONS, this::deleteExtensions)
                 .get(SMTP_MAILS, this::getMails)
                 .delete(SMTP_MAILS, this::deleteMails))
             .bindNow());
@@ -152,6 +159,19 @@ public class HTTPConfigurationServer {
         }
     }
 
+    private Publisher<Void> getExtensions(HttpServerRequest req, HttpServerResponse res) {
+        List<SMTPExtension> extensions = smtpBehaviorRepository.getSMTPExtensions();
+
+        try {
+            return res.status(OK)
+                .header(CONTENT_TYPE, APPLICATION_JSON)
+                .sendString(Mono.just(OBJECT_MAPPER.writeValueAsString(extensions)));
+        } catch (JsonProcessingException e) {
+            LOGGER.error("Could not serialize JSON", e);
+            return res.status(INTERNAL_SERVER_ERROR).send();
+        }
+    }
+
     private Publisher<Void> getVersion(HttpServerRequest req, HttpServerResponse res) {
         return res.status(OK)
             .sendString(Mono.just("0.2"));
@@ -171,11 +191,30 @@ public class HTTPConfigurationServer {
             });
     }
 
+    private Publisher<Void> putExtensions(HttpServerRequest req, HttpServerResponse res) {
+        return req.receive().aggregate().asInputStream()
+            .flatMap(inputStream -> {
+                try {
+                    List<SMTPExtension> extensions = OBJECT_MAPPER.readValue(inputStream, SMTPExtensions.class).getSmtpExtensions();
+                    smtpBehaviorRepository.setSmtpExtensions(extensions);
+                    return res.status(NO_CONTENT).send();
+                } catch (IOException e) {
+                    LOGGER.info("Bad request", e);
+                    return res.status(BAD_REQUEST).send();
+                }
+            });
+    }
+
     private Publisher<Void> deleteBehaviors(HttpServerRequest req, HttpServerResponse res) {
         smtpBehaviorRepository.clearBehaviors();
         return res.status(NO_CONTENT).send();
     }
 
+    private Publisher<Void> deleteExtensions(HttpServerRequest req, HttpServerResponse res) {
+        smtpBehaviorRepository.clearExtensions();
+        return res.status(NO_CONTENT).send();
+    }
+
     private Publisher<Void> deleteMails(HttpServerRequest req, HttpServerResponse res) {
         receivedMailRepository.clear();
         return res.status(NO_CONTENT).send();
diff --git a/server/mailet/mock-smtp-server/src/main/java/org/apache/james/mock/smtp/server/MockSMTPServer.java b/server/mailet/mock-smtp-server/src/main/java/org/apache/james/mock/smtp/server/MockSMTPServer.java
index 8233d66..1db613f 100644
--- a/server/mailet/mock-smtp-server/src/main/java/org/apache/james/mock/smtp/server/MockSMTPServer.java
+++ b/server/mailet/mock-smtp-server/src/main/java/org/apache/james/mock/smtp/server/MockSMTPServer.java
@@ -38,6 +38,7 @@ class MockSMTPServer {
     private MockSMTPServer(SMTPBehaviorRepository behaviorRepository, ReceivedMailRepository mailRepository, int port) {
         this.server = new SMTPServer(ctx -> new MockMessageHandler(mailRepository, behaviorRepository));
         this.server.setPort(port);
+        this.server.getCommandHandler().addCommand(new ExtendedEhloCommand(behaviorRepository));
     }
 
     void start() {
diff --git a/server/mailet/mock-smtp-server/src/main/java/org/apache/james/mock/smtp/server/SMTPBehaviorRepository.java b/server/mailet/mock-smtp-server/src/main/java/org/apache/james/mock/smtp/server/SMTPBehaviorRepository.java
index 8dad76a..8dab72d 100644
--- a/server/mailet/mock-smtp-server/src/main/java/org/apache/james/mock/smtp/server/SMTPBehaviorRepository.java
+++ b/server/mailet/mock-smtp-server/src/main/java/org/apache/james/mock/smtp/server/SMTPBehaviorRepository.java
@@ -20,22 +20,28 @@
 package org.apache.james.mock.smtp.server;
 
 import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
 import java.util.concurrent.ConcurrentLinkedQueue;
 import java.util.stream.Stream;
 
 import org.apache.james.mock.smtp.server.model.MockSMTPBehavior;
 import org.apache.james.mock.smtp.server.model.MockSMTPBehaviorInformation;
 import org.apache.james.mock.smtp.server.model.MockSmtpBehaviors;
+import org.apache.james.mock.smtp.server.model.SMTPExtension;
 
 import com.github.steveash.guavate.Guavate;
 import com.google.common.annotations.VisibleForTesting;
+import com.google.common.collect.ImmutableList;
 
 class SMTPBehaviorRepository {
 
     private final ConcurrentLinkedQueue<MockSMTPBehaviorInformation> behaviorsInformation;
+    private final ConcurrentLinkedQueue<SMTPExtension> smtpExtensions;
 
     SMTPBehaviorRepository() {
         this.behaviorsInformation = new ConcurrentLinkedQueue<>();
+        this.smtpExtensions = new ConcurrentLinkedQueue<>();
     }
 
     void clearBehaviors() {
@@ -44,6 +50,26 @@ class SMTPBehaviorRepository {
         }
     }
 
+    void clearExtensions() {
+        synchronized (smtpExtensions) {
+            this.smtpExtensions.clear();
+        }
+    }
+
+    void setSmtpExtensions(Collection<SMTPExtension> extensions) {
+        synchronized (smtpExtensions) {
+            clearExtensions();
+
+            smtpExtensions.addAll(extensions);
+        }
+    }
+
+    List<SMTPExtension> getSMTPExtensions() {
+        synchronized (smtpExtensions) {
+            return ImmutableList.copyOf(smtpExtensions);
+        }
+    }
+
     void setBehaviors(MockSmtpBehaviors behaviors) {
         synchronized (behaviorsInformation) {
             clearBehaviors();
diff --git a/server/mailet/mock-smtp-server/src/main/java/org/apache/james/mock/smtp/server/MockSMTPServer.java b/server/mailet/mock-smtp-server/src/main/java/org/apache/james/mock/smtp/server/model/SMTPExtension.java
similarity index 52%
copy from server/mailet/mock-smtp-server/src/main/java/org/apache/james/mock/smtp/server/MockSMTPServer.java
copy to server/mailet/mock-smtp-server/src/main/java/org/apache/james/mock/smtp/server/model/SMTPExtension.java
index 8233d66..781f403 100644
--- a/server/mailet/mock-smtp-server/src/main/java/org/apache/james/mock/smtp/server/MockSMTPServer.java
+++ b/server/mailet/mock-smtp-server/src/main/java/org/apache/james/mock/smtp/server/model/SMTPExtension.java
@@ -17,40 +17,45 @@
  * under the License.                                           *
  ****************************************************************/
 
-package org.apache.james.mock.smtp.server;
+package org.apache.james.mock.smtp.server.model;
 
-import org.apache.james.util.Port;
-import org.subethamail.smtp.server.SMTPServer;
+import java.util.Objects;
 
-class MockSMTPServer {
-    private static final int RANDOM_PORT = 0;
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonValue;
+import com.google.common.base.Preconditions;
 
-    public static MockSMTPServer onRandomPort(SMTPBehaviorRepository behaviorRepository, ReceivedMailRepository mailRepository) {
-        return new MockSMTPServer(behaviorRepository, mailRepository, RANDOM_PORT);
+public class SMTPExtension {
+    public static SMTPExtension of(String name) {
+        return new SMTPExtension(name);
     }
 
-    public static MockSMTPServer onPort(SMTPBehaviorRepository behaviorRepository, ReceivedMailRepository mailRepository, Port port) {
-        return new MockSMTPServer(behaviorRepository, mailRepository, port.getValue());
-    }
+    private final String name;
 
-    private final SMTPServer server;
+    @JsonCreator
+    private SMTPExtension(String name) {
+        Preconditions.checkNotNull(name);
 
-    private MockSMTPServer(SMTPBehaviorRepository behaviorRepository, ReceivedMailRepository mailRepository, int port) {
-        this.server = new SMTPServer(ctx -> new MockMessageHandler(mailRepository, behaviorRepository));
-        this.server.setPort(port);
+        this.name = name;
     }
 
-    void start() {
-        if (!server.isRunning()) {
-           server.start();
-        }
+    @JsonValue
+    public String asString() {
+        return name;
     }
 
-    Port getPort() {
-        return Port.of(server.getPort());
+    @Override
+    public final boolean equals(Object o) {
+        if (o instanceof SMTPExtension) {
+            SMTPExtension that = (SMTPExtension) o;
+
+            return Objects.equals(this.name, that.name);
+        }
+        return false;
     }
 
-    void stop() {
-        server.stop();
+    @Override
+    public final int hashCode() {
+        return Objects.hash(name);
     }
 }
diff --git a/server/mailet/mock-smtp-server/src/main/java/org/apache/james/mock/smtp/server/MockSMTPServer.java b/server/mailet/mock-smtp-server/src/main/java/org/apache/james/mock/smtp/server/model/SMTPExtensions.java
similarity index 52%
copy from server/mailet/mock-smtp-server/src/main/java/org/apache/james/mock/smtp/server/MockSMTPServer.java
copy to server/mailet/mock-smtp-server/src/main/java/org/apache/james/mock/smtp/server/model/SMTPExtensions.java
index 8233d66..39cf2cb 100644
--- a/server/mailet/mock-smtp-server/src/main/java/org/apache/james/mock/smtp/server/MockSMTPServer.java
+++ b/server/mailet/mock-smtp-server/src/main/java/org/apache/james/mock/smtp/server/model/SMTPExtensions.java
@@ -17,40 +17,44 @@
  * under the License.                                           *
  ****************************************************************/
 
-package org.apache.james.mock.smtp.server;
+package org.apache.james.mock.smtp.server.model;
 
-import org.apache.james.util.Port;
-import org.subethamail.smtp.server.SMTPServer;
+import java.util.List;
+import java.util.Objects;
 
-class MockSMTPServer {
-    private static final int RANDOM_PORT = 0;
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonValue;
+import com.google.common.collect.ImmutableList;
 
-    public static MockSMTPServer onRandomPort(SMTPBehaviorRepository behaviorRepository, ReceivedMailRepository mailRepository) {
-        return new MockSMTPServer(behaviorRepository, mailRepository, RANDOM_PORT);
+public class SMTPExtensions {
+    public static SMTPExtensions of(SMTPExtension... extensions) {
+        return new SMTPExtensions(ImmutableList.copyOf(extensions));
     }
 
-    public static MockSMTPServer onPort(SMTPBehaviorRepository behaviorRepository, ReceivedMailRepository mailRepository, Port port) {
-        return new MockSMTPServer(behaviorRepository, mailRepository, port.getValue());
-    }
-
-    private final SMTPServer server;
+    private final List<SMTPExtension> smtpExtensions;
 
-    private MockSMTPServer(SMTPBehaviorRepository behaviorRepository, ReceivedMailRepository mailRepository, int port) {
-        this.server = new SMTPServer(ctx -> new MockMessageHandler(mailRepository, behaviorRepository));
-        this.server.setPort(port);
+    @JsonCreator
+    private SMTPExtensions(List<SMTPExtension> smtpExtensions) {
+        this.smtpExtensions = ImmutableList.copyOf(smtpExtensions);
     }
 
-    void start() {
-        if (!server.isRunning()) {
-           server.start();
-        }
+    @JsonValue
+    public List<SMTPExtension> getSmtpExtensions() {
+        return smtpExtensions;
     }
 
-    Port getPort() {
-        return Port.of(server.getPort());
+    @Override
+    public final boolean equals(Object o) {
+        if (o instanceof SMTPExtensions) {
+            SMTPExtensions that = (SMTPExtensions) o;
+
+            return Objects.equals(this.smtpExtensions, that.smtpExtensions);
+        }
+        return false;
     }
 
-    void stop() {
-        server.stop();
+    @Override
+    public final int hashCode() {
+        return Objects.hash(smtpExtensions);
     }
 }
diff --git a/server/mailet/mock-smtp-server/src/test/java/org/apache/james/mock/smtp/server/ConfigurationClientTest.java b/server/mailet/mock-smtp-server/src/test/java/org/apache/james/mock/smtp/server/ConfigurationClientTest.java
index 33e3c38..0f18c82 100644
--- a/server/mailet/mock-smtp-server/src/test/java/org/apache/james/mock/smtp/server/ConfigurationClientTest.java
+++ b/server/mailet/mock-smtp-server/src/test/java/org/apache/james/mock/smtp/server/ConfigurationClientTest.java
@@ -23,9 +23,12 @@ import static org.apache.james.mock.smtp.server.Fixture.BEHAVIOR_LIST;
 import static org.assertj.core.api.Assertions.assertThat;
 
 import org.apache.james.mock.smtp.server.Fixture.MailsFixutre;
+import org.apache.james.mock.smtp.server.model.SMTPExtension;
+import org.apache.james.mock.smtp.server.model.SMTPExtensions;
 import org.junit.jupiter.api.AfterEach;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
+import org.testcontainers.shaded.com.google.common.collect.ImmutableList;
 
 class ConfigurationClientTest {
     private ConfigurationClient testee;
@@ -55,6 +58,12 @@ class ConfigurationClientTest {
     }
 
     @Test
+    void listSMTPExtensionsShouldReturnEmptyWhenNoSet() {
+        assertThat(testee.listSMTPExtensions().getSmtpExtensions())
+            .isEmpty();
+    }
+
+    @Test
     void listBehaviorsShouldReturnDefinedBehaviors() {
         behaviorRepository.setBehaviors(Fixture.BEHAVIORS);
 
@@ -63,6 +72,35 @@ class ConfigurationClientTest {
     }
 
     @Test
+    void listSMTPExtensionsShouldReturnDefinedExtensions() {
+        SMTPExtensions smtpExtensions = SMTPExtensions.of(SMTPExtension.of("DSN"), SMTPExtension.of("XYZ"));
+        testee.setSMTPExtensions(smtpExtensions);
+
+        assertThat(testee.listSMTPExtensions())
+            .isEqualTo(smtpExtensions);
+    }
+
+    @Test
+    void listSMTPExtensionsShouldOverwritePreviouslyDefinedExtensions() {
+        testee.setSMTPExtensions(SMTPExtensions.of(SMTPExtension.of("XYZ")));
+        testee.setSMTPExtensions(SMTPExtensions.of(SMTPExtension.of("DSN")));
+
+        assertThat(testee.listSMTPExtensions().getSmtpExtensions())
+            .isEqualTo(ImmutableList.of(SMTPExtension.of("DSN")));
+    }
+
+    @Test
+    void listSMTPExtensionsShouldNotReturnPreviouslyClearedExtensions() {
+        SMTPExtensions smtpExtensions = SMTPExtensions.of(SMTPExtension.of("DSN"), SMTPExtension.of("XYZ"));
+        testee.setSMTPExtensions(smtpExtensions);
+
+        testee.clearSMTPExtensions();
+
+        assertThat(testee.listSMTPExtensions().getSmtpExtensions())
+            .isEmpty();
+    }
+
+    @Test
     void setBehaviorsShouldStoreBehaviors() {
         testee.setBehaviors(BEHAVIOR_LIST);
 
diff --git a/server/mailet/mock-smtp-server/src/test/java/org/apache/james/mock/smtp/server/MockSMTPServerTest.java b/server/mailet/mock-smtp-server/src/test/java/org/apache/james/mock/smtp/server/MockSMTPServerTest.java
index ccb475c..138b55c 100644
--- a/server/mailet/mock-smtp-server/src/test/java/org/apache/james/mock/smtp/server/MockSMTPServerTest.java
+++ b/server/mailet/mock-smtp-server/src/test/java/org/apache/james/mock/smtp/server/MockSMTPServerTest.java
@@ -39,6 +39,7 @@ import java.util.List;
 import javax.mail.MessagingException;
 import javax.mail.internet.MimeMessage;
 
+import org.apache.commons.net.smtp.AuthenticatingSMTPClient;
 import org.apache.commons.net.smtp.SMTPConnectionClosedException;
 import org.apache.james.core.MailAddress;
 import org.apache.james.core.builder.MimeMessageBuilder;
@@ -47,6 +48,8 @@ import org.apache.james.mock.smtp.server.model.Mail;
 import org.apache.james.mock.smtp.server.model.MockSMTPBehavior;
 import org.apache.james.mock.smtp.server.model.Operator;
 import org.apache.james.mock.smtp.server.model.Response;
+import org.apache.james.mock.smtp.server.model.SMTPExtension;
+import org.apache.james.mock.smtp.server.model.SMTPExtensions;
 import org.apache.james.util.MimeMessageUtil;
 import org.apache.james.util.Port;
 import org.apache.james.utils.SMTPMessageSender;
@@ -136,6 +139,26 @@ class MockSMTPServerTest {
     }
 
     @Nested
+    class ExtensionTests {
+        @Test
+        void extraExtensionsShouldBeExposed() throws Exception {
+            behaviorRepository.setSmtpExtensions(ImmutableList.of(SMTPExtension.of("DSN")));
+
+            AuthenticatingSMTPClient smtpClient = new AuthenticatingSMTPClient("TLS", "UTF-8");
+
+            try {
+                smtpClient.connect("localhost", mockServer.getPort().getValue());
+                smtpClient.ehlo("localhost");
+
+                assertThat(smtpClient.getReplyString())
+                    .contains("250-DSN");
+            } finally {
+                smtpClient.disconnect();
+            }
+        }
+    }
+
+    @Nested
     class MailMockBehaviorTest {
         @Test
         void serverShouldReceiveMessageFromClient() {


---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@james.apache.org
For additional commands, e-mail: notifications-help@james.apache.org