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:18 UTC

[james-project] 06/29: JAMES-3431 MockSMTPServer: Capture MAIL FROM ESMTP parameters

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 0bb27042ed0205a5f1d459b0da8529651a4cb28b
Author: Benoit Tellier <bt...@linagora.com>
AuthorDate: Thu Dec 24 09:02:17 2020 +0700

    JAMES-3431 MockSMTPServer: Capture MAIL FROM ESMTP parameters
---
 .../mock/smtp/server/ExtendedMailFromCommand.java  | 109 +++++++++++++++++++++
 .../james/mock/smtp/server/MockMessageHandler.java |  12 +++
 .../james/mock/smtp/server/MockSMTPServer.java     |   1 +
 .../james/mock/smtp/server/MockSMTPServerTest.java |  40 ++++++++
 4 files changed, 162 insertions(+)

diff --git a/server/mailet/mock-smtp-server/src/main/java/org/apache/james/mock/smtp/server/ExtendedMailFromCommand.java b/server/mailet/mock-smtp-server/src/main/java/org/apache/james/mock/smtp/server/ExtendedMailFromCommand.java
new file mode 100644
index 0000000..89fe612
--- /dev/null
+++ b/server/mailet/mock-smtp-server/src/main/java/org/apache/james/mock/smtp/server/ExtendedMailFromCommand.java
@@ -0,0 +1,109 @@
+/****************************************************************
+ * 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.Collection;
+import java.util.Locale;
+
+import org.apache.james.mock.smtp.server.model.Mail;
+import org.subethamail.smtp.DropConnectionException;
+import org.subethamail.smtp.RejectException;
+import org.subethamail.smtp.server.BaseCommand;
+import org.subethamail.smtp.server.Session;
+import org.subethamail.smtp.util.EmailUtils;
+
+import com.github.steveash.guavate.Guavate;
+import com.google.common.base.Preconditions;
+import com.google.common.base.Splitter;
+
+public class ExtendedMailFromCommand extends BaseCommand {
+    public ExtendedMailFromCommand() {
+        super("MAIL", "Specifies the sender.", "FROM: <sender> [ <parameters> ]");
+    }
+
+    public void execute(String commandString, Session sess) throws IOException, DropConnectionException {
+        if (sess.getHasMailFrom()) {
+            sess.sendResponse("503 Sender already specified.");
+        } else {
+            if (commandString.trim().equals("MAIL FROM:")) {
+                sess.sendResponse("501 Syntax: MAIL FROM: <address>");
+                return;
+            }
+
+            String args = this.getArgPredicate(commandString);
+            if (!args.toUpperCase(Locale.ENGLISH).startsWith("FROM:")) {
+                sess.sendResponse("501 Syntax: MAIL FROM: <address>  Error in parameters: \"" + this.getArgPredicate(commandString) + "\"");
+                return;
+            }
+
+            String emailAddress = EmailUtils.extractEmailAddress(args, 5);
+            if (EmailUtils.isValidEmailAddress(emailAddress)) {
+                int size = 0;
+                String largs = args.toLowerCase(Locale.ENGLISH);
+                int sizec = largs.indexOf(" size=");
+                if (sizec > -1) {
+                    String ssize = largs.substring(sizec + 6).trim();
+                    if (ssize.length() > 0 && ssize.matches("[0-9]+")) {
+                        size = Integer.parseInt(ssize);
+                    }
+                }
+
+                if (size > sess.getServer().getMaxMessageSize()) {
+                    sess.sendResponse("552 5.3.4 Message size exceeds fixed limit");
+                    return;
+                }
+
+                try {
+                    sess.startMailTransaction();
+                    MockMessageHandler messageHandler = (MockMessageHandler) sess.getMessageHandler();
+                    messageHandler.from(emailAddress, parameters(args));
+                    sess.setDeclaredMessageSize(size);
+                    sess.setHasMailFrom(true);
+                    sess.sendResponse("250 Ok");
+                } catch (DropConnectionException var9) {
+                    throw var9;
+                } catch (RejectException var10) {
+                    sess.sendResponse(var10.getErrorResponse());
+                }
+            } else {
+                sess.sendResponse("553 <" + emailAddress + "> Invalid email address.");
+            }
+        }
+    }
+
+    private Collection<Mail.Parameter> parameters(String argLine) {
+        return Splitter.on(' ').splitToList(argLine)
+            .stream()
+            .filter(argString -> argString.contains("="))
+            .map(this::parameter)
+            .collect(Guavate.toImmutableList());
+    }
+
+    private Mail.Parameter parameter(String argString) {
+        Preconditions.checkArgument(argString.contains("="));
+        int index = argString.indexOf('=');
+
+        return Mail.Parameter.builder()
+            .name(argString.substring(0, index))
+            .value(argString.substring(index + 1))
+            .build();
+    }
+}
diff --git a/server/mailet/mock-smtp-server/src/main/java/org/apache/james/mock/smtp/server/MockMessageHandler.java b/server/mailet/mock-smtp-server/src/main/java/org/apache/james/mock/smtp/server/MockMessageHandler.java
index b0372cb..2cde815 100644
--- a/server/mailet/mock-smtp-server/src/main/java/org/apache/james/mock/smtp/server/MockMessageHandler.java
+++ b/server/mailet/mock-smtp-server/src/main/java/org/apache/james/mock/smtp/server/MockMessageHandler.java
@@ -22,6 +22,7 @@ package org.apache.james.mock.smtp.server;
 import java.io.IOException;
 import java.io.InputStream;
 import java.nio.charset.StandardCharsets;
+import java.util.Collection;
 import java.util.Optional;
 
 import javax.mail.internet.AddressException;
@@ -29,6 +30,7 @@ import javax.mail.internet.AddressException;
 import org.apache.commons.io.IOUtils;
 import org.apache.james.core.MailAddress;
 import org.apache.james.mock.smtp.server.model.Mail;
+import org.apache.james.mock.smtp.server.model.Mail.Parameter;
 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.Response;
@@ -39,6 +41,8 @@ import org.slf4j.LoggerFactory;
 import org.subethamail.smtp.MessageHandler;
 import org.subethamail.smtp.RejectException;
 
+import com.google.common.collect.ImmutableMap;
+
 public class MockMessageHandler implements MessageHandler {
 
     private static final Logger LOGGER = LoggerFactory.getLogger(MockMessageHandler.class);
@@ -119,6 +123,14 @@ public class MockMessageHandler implements MessageHandler {
             .behave(parse(from));
     }
 
+    public void from(String from, Collection<Parameter> parameters) throws RejectException {
+        Optional<Behavior<MailAddress>> fromBehavior = firstMatchedBehavior(SMTPCommand.MAIL_FROM, from);
+
+        fromBehavior
+            .orElseGet(() -> mailAddress -> envelopeBuilder.from(mailAddress).mailParameters(parameters))
+            .behave(parse(from));
+    }
+
     @Override
     public void recipient(String recipient) throws RejectException {
         Optional<Behavior<MailAddress>> recipientBehavior = firstMatchedBehavior(SMTPCommand.RCPT_TO, recipient);
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 1db613f..d008ef4 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
@@ -39,6 +39,7 @@ class MockSMTPServer {
         this.server = new SMTPServer(ctx -> new MockMessageHandler(mailRepository, behaviorRepository));
         this.server.setPort(port);
         this.server.getCommandHandler().addCommand(new ExtendedEhloCommand(behaviorRepository));
+        this.server.getCommandHandler().addCommand(new ExtendedMailFromCommand());
     }
 
     void start() {
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 138b55c..3183837 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
@@ -159,6 +159,46 @@ class MockSMTPServerTest {
     }
 
     @Nested
+    class ESMTPParametersTest {
+        @Test
+        void mailFromParametersShouldBeRecognised() throws Exception {
+            AuthenticatingSMTPClient smtpClient = new AuthenticatingSMTPClient("TLS", "UTF-8");
+
+            try {
+                smtpClient.connect("localhost", mockServer.getPort().getValue());
+                smtpClient.ehlo("localhost");
+                smtpClient.mail("<bo...@james.org> RET=HDRS ENVID=gabouzomeuh");
+                smtpClient.rcpt("<al...@james.org>");
+                smtpClient.sendShortMessageData("A short message...");
+            } finally {
+                smtpClient.disconnect();
+            }
+
+            Mail.Envelope expectedEnvelope = Mail.Envelope.builder()
+                .addMailParameter(Mail.Parameter.builder()
+                    .name("RET")
+                    .value("HDRS")
+                    .build())
+                .addMailParameter(Mail.Parameter.builder()
+                    .name("ENVID")
+                    .value("gabouzomeuh")
+                    .build())
+                .from(new MailAddress(BOB))
+                .addRecipientMailAddress(new MailAddress(ALICE))
+                .build();
+
+            Awaitility.await().atMost(Duration.TEN_SECONDS)
+                .untilAsserted(() -> {
+                    List<Mail> mails = mailRepository.list();
+                    assertThat(mails)
+                        .hasSize(1)
+                        .allSatisfy(Throwing.consumer(assertedMail ->
+                            assertThat(assertedMail.getEnvelope()).isEqualTo(expectedEnvelope)));
+                });
+        }
+    }
+
+    @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