This is an automated email from the ASF dual-hosted git repository.
btellier pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/james-project.git
The following commit(s) were added to refs/heads/master by this push:
new 5a62eceb21 [ENHANCEMENT] Integration tests for MaxRcptHandler (#2448)
5a62eceb21 is described below
commit 5a62eceb21ff8fd7b34bff387e273f8dc7b8d69e
Author: florentos17 <[email protected]>
AuthorDate: Tue Oct 15 09:04:35 2024 +0200
[ENHANCEMENT] Integration tests for MaxRcptHandler (#2448)
---
.../smtp/core/fastfail/MaxRcptHandler.java | 2 +-
.../mailets/configuration/SmtpConfiguration.java | 50 ++++++++--
.../src/main/resources/smtpserver.xml | 12 ++-
.../configuration/SmtpConfigurationTest.java | 30 ++++++
.../apache/james/smtp/SmtpMaxRcptHandlerTest.java | 108 +++++++++++++++++++++
.../james/smtpserver/fastfail/MaxRcptHandler.java | 2 +-
6 files changed, 190 insertions(+), 14 deletions(-)
diff --git
a/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/core/fastfail/MaxRcptHandler.java
b/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/core/fastfail/MaxRcptHandler.java
index c3ae9b467b..632d69be5e 100644
---
a/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/core/fastfail/MaxRcptHandler.java
+++
b/protocols/smtp/src/main/java/org/apache/james/protocols/smtp/core/fastfail/MaxRcptHandler.java
@@ -45,7 +45,7 @@ public class MaxRcptHandler implements RcptHook {
/**
- * Set the max rcpt for wich should be accepted
+ * Set the max rcpt for which a mail should be accepted
*
* @param maxRcpt
* The max rcpt count
diff --git
a/server/mailet/integration-testing/src/main/java/org/apache/james/mailets/configuration/SmtpConfiguration.java
b/server/mailet/integration-testing/src/main/java/org/apache/james/mailets/configuration/SmtpConfiguration.java
index 743754f46b..39088fa329 100644
---
a/server/mailet/integration-testing/src/main/java/org/apache/james/mailets/configuration/SmtpConfiguration.java
+++
b/server/mailet/integration-testing/src/main/java/org/apache/james/mailets/configuration/SmtpConfiguration.java
@@ -27,6 +27,8 @@ import java.io.StringReader;
import java.io.Writer;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
import java.util.Optional;
import org.apache.commons.io.IOUtils;
@@ -44,9 +46,23 @@ public class SmtpConfiguration implements SerializableAsXml {
static class HookConfigurationEntry {
String hookFqcn;
+ Map<String, String> hookConfig;
+
+ HookConfigurationEntry(String hookFqcn, Map<String, String>
hookConfig) {
+ this.hookFqcn = hookFqcn;
+ this.hookConfig = hookConfig;
+ }
HookConfigurationEntry(String hookFqcn) {
this.hookFqcn = hookFqcn;
+ this.hookConfig = new HashMap<>();
+ }
+
+ private static Map<String, Object>
asMustacheScopes(HookConfigurationEntry hook) {
+ Map<String, Object> hookScope = new HashMap<>();
+ hookScope.put("hookFqcn", hook.hookFqcn);
+ hookScope.put("hookConfigAsXML", hook.hookConfig.entrySet());
+ return hookScope;
}
}
@@ -58,7 +74,7 @@ public class SmtpConfiguration implements SerializableAsXml {
private Optional<SMTPConfiguration.SenderVerificationMode>
verifyIndentity;
private Optional<Boolean> bracketEnforcement;
private Optional<String> authorizedAddresses;
- private ImmutableList.Builder<HookConfigurationEntry> addittionalHooks;
+ private ImmutableList.Builder<HookConfigurationEntry> additionalHooks;
public Builder() {
authorizedAddresses = Optional.empty();
@@ -66,7 +82,7 @@ public class SmtpConfiguration implements SerializableAsXml {
verifyIndentity = Optional.empty();
maxMessageSize = Optional.empty();
bracketEnforcement = Optional.empty();
- addittionalHooks = ImmutableList.builder();
+ additionalHooks = ImmutableList.builder();
}
public Builder withAutorizedAddresses(String authorizedAddresses) {
@@ -111,7 +127,12 @@ public class SmtpConfiguration implements
SerializableAsXml {
}
public Builder addHook(String hookFQCN) {
- this.addittionalHooks.add(new HookConfigurationEntry(hookFQCN));
+ this.additionalHooks.add(new HookConfigurationEntry(hookFQCN));
+ return this;
+ }
+
+ public Builder addHook(String hookFQCN, Map<String, String>
hookConfig) {
+ this.additionalHooks.add(new HookConfigurationEntry(hookFQCN,
hookConfig));
return this;
}
@@ -121,7 +142,7 @@ public class SmtpConfiguration implements SerializableAsXml
{
bracketEnforcement.orElse(true),
verifyIndentity.orElse(SMTPConfiguration.SenderVerificationMode.DISABLED),
maxMessageSize.orElse(DEFAULT_DISABLED),
- addittionalHooks.build());
+ additionalHooks.build());
}
}
@@ -134,16 +155,20 @@ public class SmtpConfiguration implements
SerializableAsXml {
private final boolean bracketEnforcement;
private final SMTPConfiguration.SenderVerificationMode verifyIndentity;
private final String maxMessageSize;
- private final ImmutableList<HookConfigurationEntry> addittionalHooks;
-
- private SmtpConfiguration(Optional<String> authorizedAddresses, boolean
authRequired, boolean bracketEnforcement,
- SMTPConfiguration.SenderVerificationMode
verifyIndentity, String maxMessageSize, ImmutableList<HookConfigurationEntry>
addittionalHooks) {
+ private final ImmutableList<HookConfigurationEntry> additionalHooks;
+
+ private SmtpConfiguration(Optional<String> authorizedAddresses,
+ boolean authRequired,
+ boolean bracketEnforcement,
+ SMTPConfiguration.SenderVerificationMode
verifyIndentity,
+ String maxMessageSize,
+ ImmutableList<HookConfigurationEntry>
additionalHooks) {
this.authorizedAddresses = authorizedAddresses;
this.authRequired = authRequired;
this.bracketEnforcement = bracketEnforcement;
this.verifyIndentity = verifyIndentity;
this.maxMessageSize = maxMessageSize;
- this.addittionalHooks = addittionalHooks;
+ this.additionalHooks = additionalHooks;
}
@Override
@@ -155,7 +180,12 @@ public class SmtpConfiguration implements
SerializableAsXml {
scopes.put("verifyIdentity", verifyIndentity.toString());
scopes.put("maxmessagesize", maxMessageSize);
scopes.put("bracketEnforcement", bracketEnforcement);
- scopes.put("hooks", addittionalHooks);
+
+ List<Map<String, Object>> additionalHooksWithConfig =
additionalHooks.stream()
+ .map(HookConfigurationEntry::asMustacheScopes)
+ .collect(ImmutableList.toImmutableList());
+
+ scopes.put("hooks", additionalHooksWithConfig);
ByteArrayOutputStream byteArrayOutputStream = new
ByteArrayOutputStream();
Writer writer = new OutputStreamWriter(byteArrayOutputStream);
diff --git
a/server/mailet/integration-testing/src/main/resources/smtpserver.xml
b/server/mailet/integration-testing/src/main/resources/smtpserver.xml
index 4f0a039742..2d314ac085 100644
--- a/server/mailet/integration-testing/src/main/resources/smtpserver.xml
+++ b/server/mailet/integration-testing/src/main/resources/smtpserver.xml
@@ -49,7 +49,11 @@
<handler
class="org.apache.james.smtpserver.fastfail.ValidRcptHandler"/>
<handler class="org.apache.james.smtpserver.CoreCmdHandlerLoader"/>
{{#hooks}}
- <handler class="{{hookFqcn}}"/>
+ <handler class="{{hookFqcn}}">
+ {{#hookConfigAsXML}}
+ <{{key}}>{{value}}</{{key}}>
+ {{/hookConfigAsXML}}
+ </handler>
{{/hooks}}
</handlerchain>
<gracefulShutdown>false</gracefulShutdown>
@@ -87,7 +91,11 @@
<handler
class="org.apache.james.smtpserver.fastfail.ValidRcptHandler"/>
<handler class="org.apache.james.smtpserver.CoreCmdHandlerLoader"/>
{{#hooks}}
- <handler class="{{hookFqcn}}"/>
+ <handler class="{{hookFqcn}}">
+ {{#hookConfigAsXML}}
+ <{{key}}>{{value}}</{{key}}>
+ {{/hookConfigAsXML}}
+ </handler>
{{/hooks}}
</handlerchain>
<gracefulShutdown>false</gracefulShutdown>
diff --git
a/server/mailet/integration-testing/src/test/java/org/apache/james/mailets/configuration/SmtpConfigurationTest.java
b/server/mailet/integration-testing/src/test/java/org/apache/james/mailets/configuration/SmtpConfigurationTest.java
index ef029cfd5a..58724e8bf2 100644
---
a/server/mailet/integration-testing/src/test/java/org/apache/james/mailets/configuration/SmtpConfigurationTest.java
+++
b/server/mailet/integration-testing/src/test/java/org/apache/james/mailets/configuration/SmtpConfigurationTest.java
@@ -24,6 +24,7 @@ import static org.hamcrest.MatcherAssert.assertThat;
import static org.xmlunit.matchers.EvaluateXPathMatcher.hasXPath;
import java.io.IOException;
+import java.util.Map;
import javax.xml.transform.Source;
@@ -180,4 +181,33 @@ public class SmtpConfigurationTest {
hasXPath("/smtpservers/smtpserver/verifyIdentity/text()",
is("DISABLED")));
}
+
+ @Test
+ public void addHookShouldRegisterHookWithoutConfig() throws IOException {
+ String hookFqcn = "com.example.hooks.MyCustomHook";
+
+ SmtpConfiguration configuration = SmtpConfiguration.builder()
+ .addHook(hookFqcn)
+ .build();
+
+ assertThat(configuration.serializeAsXml(),
+
hasXPath("/smtpservers/smtpserver/handlerchain/handler[@class='" + hookFqcn +
"']/@class", is(hookFqcn)));
+ }
+
+ @Test
+ public void addHookShouldRegisterHookWithConfig() throws IOException {
+ String hookFqcn = "com.example.hooks.MyCustomHook";
+ Map<String, String> hookConfig = Map.of("param1", "value1", "param2",
"value2");
+
+ SmtpConfiguration configuration = SmtpConfiguration.builder()
+ .addHook(hookFqcn, hookConfig)
+ .build();
+
+ String xmlOutput = configuration.serializeAsXml();
+ assertThat(xmlOutput,
hasXPath("/smtpservers/smtpserver/handlerchain/handler[@class='" + hookFqcn +
"']/@class", is(hookFqcn)));
+ assertThat(xmlOutput,
hasXPath("/smtpservers/smtpserver/handlerchain/handler[@class='" + hookFqcn +
"']/param1/text()", is("value1")));
+ assertThat(xmlOutput,
hasXPath("/smtpservers/smtpserver/handlerchain/handler[@class='" + hookFqcn +
"']/param2/text()", is("value2")));
+ }
+
+
}
diff --git
a/server/mailet/integration-testing/src/test/java/org/apache/james/smtp/SmtpMaxRcptHandlerTest.java
b/server/mailet/integration-testing/src/test/java/org/apache/james/smtp/SmtpMaxRcptHandlerTest.java
new file mode 100644
index 0000000000..77e5fbb37e
--- /dev/null
+++
b/server/mailet/integration-testing/src/test/java/org/apache/james/smtp/SmtpMaxRcptHandlerTest.java
@@ -0,0 +1,108 @@
+/****************************************************************
+ * 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.smtp;
+
+import static org.apache.james.mailets.configuration.Constants.DEFAULT_DOMAIN;
+import static org.apache.james.mailets.configuration.Constants.LOCALHOST_IP;
+import static org.apache.james.mailets.configuration.Constants.PASSWORD;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
+
+import java.io.File;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.IntStream;
+
+import org.apache.james.mailets.TemporaryJamesServer;
+import org.apache.james.mailets.configuration.SmtpConfiguration;
+import org.apache.james.modules.protocols.SmtpGuiceProbe;
+import org.apache.james.probe.DataProbe;
+import org.apache.james.smtpserver.fastfail.MaxRcptHandler;
+import org.apache.james.utils.DataProbeImpl;
+import org.apache.james.utils.SMTPMessageSender;
+import org.apache.james.utils.SMTPSendingException;
+import org.apache.james.utils.SmtpSendingStep;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.RegisterExtension;
+import org.junit.jupiter.api.io.TempDir;
+
+import com.github.fge.lambdas.Throwing;
+import com.google.common.collect.ImmutableList;
+
+class SmtpMaxRcptHandlerTest {
+ private static final String USER = "user@" + DEFAULT_DOMAIN;
+ private static final Integer DEFAULT_MAX_RCPT = 50;
+
+ @RegisterExtension
+ public SMTPMessageSender messageSender = new
SMTPMessageSender(DEFAULT_DOMAIN);
+
+ private TemporaryJamesServer jamesServer;
+
+ @BeforeEach
+ public void createJamesServer(@TempDir File temporaryFolder) throws
Exception {
+ SmtpConfiguration.Builder smtpConfiguration =
SmtpConfiguration.builder()
+ .doNotVerifyIdentity()
+ .addHook(MaxRcptHandler.class.getName(),
+ Map.of("maxRcpt", DEFAULT_MAX_RCPT.toString()));
+
+ jamesServer = TemporaryJamesServer.builder()
+ .withSmtpConfiguration(smtpConfiguration)
+ .build(temporaryFolder);
+ jamesServer.start();
+
+ DataProbe dataProbe = jamesServer.getProbe(DataProbeImpl.class);
+ dataProbe.addDomain(DEFAULT_DOMAIN);
+ dataProbe.addUser(USER, PASSWORD);
+ IntStream.range(0, DEFAULT_MAX_RCPT + 1).forEach(Throwing.intConsumer((
+ i -> dataProbe.addUser("recipient" + i + "@" + DEFAULT_DOMAIN,
PASSWORD))));
+ }
+
+ @AfterEach
+ void tearDown() {
+ if (jamesServer != null) {
+ jamesServer.shutdown();
+ }
+ }
+
+ @Test
+ void messageShouldNotBeAcceptedWhenMaxRcptHandlerExceeded() throws
Exception {
+ assertThatThrownBy(() ->
+ messageSender.connect(LOCALHOST_IP,
jamesServer.getProbe(SmtpGuiceProbe.class).getSmtpPort())
+ .authenticate(USER, PASSWORD)
+ .sendMessageWithHeaders(USER, getRecipients(DEFAULT_MAX_RCPT +
1), "message"))
+ .isEqualTo(new SMTPSendingException(SmtpSendingStep.RCPT, "452
4.5.3 Requested action not taken: max recipients reached\n"));
+ }
+
+ @Test
+ void messageShouldBeAcceptedWhenMaxRcptHandlerWithinLimit() throws
Exception {
+ assertDoesNotThrow(() ->
+ messageSender.connect(LOCALHOST_IP,
jamesServer.getProbe(SmtpGuiceProbe.class).getSmtpPort())
+ .authenticate(USER, PASSWORD)
+ .sendMessageWithHeaders(USER, getRecipients(DEFAULT_MAX_RCPT),
"message"));
+ }
+
+ private List<String> getRecipients(Integer n) {
+ return IntStream.range(0, n)
+ .mapToObj(i -> "recipient" + i + "@" + DEFAULT_DOMAIN)
+ .collect(ImmutableList.toImmutableList());
+ }
+}
diff --git
a/server/protocols/protocols-smtp/src/main/java/org/apache/james/smtpserver/fastfail/MaxRcptHandler.java
b/server/protocols/protocols-smtp/src/main/java/org/apache/james/smtpserver/fastfail/MaxRcptHandler.java
index 8c957601af..b85340b42f 100644
---
a/server/protocols/protocols-smtp/src/main/java/org/apache/james/smtpserver/fastfail/MaxRcptHandler.java
+++
b/server/protocols/protocols-smtp/src/main/java/org/apache/james/smtpserver/fastfail/MaxRcptHandler.java
@@ -27,6 +27,6 @@ public class MaxRcptHandler extends
org.apache.james.protocols.smtp.core.fastfai
@Override
public void init(Configuration config) throws ConfigurationException {
int maxRcpt = config.getInt("maxRcpt", 0);
- setMaxRcpt(maxRcpt);
+ setMaxRcpt(maxRcpt);
}
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]