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
The following commit(s) were added to refs/heads/master by this push:
new 81c283387b JAMES-4032 Manage multiple domains with DKIMHook (#2657)
81c283387b is described below
commit 81c283387b6dff8ea73c41535cd9b3594ae9ef89
Author: Benoit TELLIER <[email protected]>
AuthorDate: Thu Feb 27 17:41:50 2025 +0700
JAMES-4032 Manage multiple domains with DKIMHook (#2657)
---
.../java/org/apache/james/smtpserver/DKIMHook.java | 41 ++++++++++++++++------
.../org/apache/james/smtpserver/DKIMHookTest.java | 19 ++++++++--
2 files changed, 48 insertions(+), 12 deletions(-)
diff --git
a/server/protocols/protocols-smtp-dkim/src/main/java/org/apache/james/smtpserver/DKIMHook.java
b/server/protocols/protocols-smtp-dkim/src/main/java/org/apache/james/smtpserver/DKIMHook.java
index e97cda41a8..9425ba9206 100644
---
a/server/protocols/protocols-smtp-dkim/src/main/java/org/apache/james/smtpserver/DKIMHook.java
+++
b/server/protocols/protocols-smtp-dkim/src/main/java/org/apache/james/smtpserver/DKIMHook.java
@@ -22,6 +22,7 @@ package org.apache.james.smtpserver;
import static org.apache.james.protocols.smtp.SMTPRetCode.AUTH_REQUIRED;
import static org.apache.james.protocols.smtp.SMTPRetCode.LOCAL_ERROR;
+import java.util.Collection;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
@@ -52,6 +53,7 @@ import org.slf4j.LoggerFactory;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Preconditions;
+import com.google.common.base.Splitter;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
@@ -91,7 +93,7 @@ public class DKIMHook implements JamesMessageHook {
@FunctionalInterface
interface DKIMCheckNeeded extends Predicate<Mail> {
- static DKIMCheckNeeded or(ImmutableList<DKIMCheckNeeded> checkNeededs)
{
+ static DKIMCheckNeeded or(List<DKIMCheckNeeded> checkNeededs) {
return mail -> checkNeededs.stream()
.anyMatch(predicate -> predicate.test(mail));
}
@@ -138,6 +140,7 @@ public class DKIMHook implements JamesMessageHook {
}
DKIMCheckNeeded ALL = any -> true;
+ DKIMCheckNeeded NONE = any -> false;
}
@FunctionalInterface
@@ -152,6 +155,16 @@ public class DKIMHook implements JamesMessageHook {
};
}
+ static SignatureRecordValidation or(SignatureRecordValidation a,
SignatureRecordValidation b) {
+ return (sender, records) -> {
+ HookResult hookResult = a.validate(sender, records);
+ if (hookResult.equals(HookResult.DECLINED)) {
+ return hookResult;
+ }
+ return b.validate(sender, records);
+ };
+ }
+
static SignatureRecordValidation signatureRequired(boolean required) {
return (sender, records) -> {
if (required && (records == null || records.isEmpty())) {
@@ -194,13 +207,16 @@ public class DKIMHook implements JamesMessageHook {
config.getBoolean("forceCRLF", true),
config.getBoolean("signatureRequired", true),
Optional.ofNullable(config.getString("onlyForSenderDomain",
null))
- .map(Domain::of),
+ .map(s -> Splitter.on(',').splitToStream(s)
+ .map(Domain::of)
+ .toList()),
Optional.ofNullable(config.getString("validatedEntities",
null))
.map(entities -> Stream.of(entities.split(","))
.map(ValidatedEntity::from)
.collect(ImmutableList.toImmutableList()))
.orElse(DEFAULT_VALIDATED_ENTITIES),
- Optional.ofNullable(config.getString("expectedDToken", null)));
+ Optional.ofNullable(config.getString("expectedDToken", null))
+ .map(s -> Splitter.on(',').splitToList(s)));
}
public enum ValidatedEntity {
@@ -219,12 +235,12 @@ public class DKIMHook implements JamesMessageHook {
private final boolean forceCRLF;
private final boolean signatureRequired;
- private final Optional<Domain> onlyForSenderDomain;
+ private final Optional<List<Domain>> onlyForSenderDomain;
private final ImmutableList<ValidatedEntity> validatedEntities;
- private final Optional<String> expectedDToken;
+ private final Optional<List<String>> expectedDToken;
- public Config(boolean forceCRLF, boolean signatureRequired,
Optional<Domain> onlyForSenderDomain,
- ImmutableList<ValidatedEntity> validatedEntities,
Optional<String> expectedDToken) {
+ public Config(boolean forceCRLF, boolean signatureRequired,
Optional<List<Domain>> onlyForSenderDomain,
+ ImmutableList<ValidatedEntity> validatedEntities,
Optional<List<String>> expectedDToken) {
this.forceCRLF = forceCRLF;
this.signatureRequired = signatureRequired;
this.onlyForSenderDomain = onlyForSenderDomain;
@@ -234,15 +250,20 @@ public class DKIMHook implements JamesMessageHook {
DKIMCheckNeeded dkimCheckNeeded() {
return onlyForSenderDomain
- .map(domain ->
DKIMCheckNeeded.or(computeDKIMChecksNeeded(domain)))
+ .map(domains -> DKIMCheckNeeded.or(domains.stream()
+ .map(this::computeDKIMChecksNeeded)
+ .flatMap(Collection::stream)
+ .toList()))
.orElse(DKIMCheckNeeded.ALL);
}
SignatureRecordValidation signatureRecordValidation() {
return SignatureRecordValidation.and(
SignatureRecordValidation.signatureRequired(signatureRequired),
- expectedDToken.map(SignatureRecordValidation::expectedDToken)
- .orElse(SignatureRecordValidation.ALLOW_ALL));
+ expectedDToken.map(tokens -> tokens.stream()
+ .map(SignatureRecordValidation::expectedDToken)
+ .reduce(SignatureRecordValidation::or)
+ .get()).orElse(SignatureRecordValidation.ALLOW_ALL));
}
private ImmutableList<DKIMCheckNeeded> computeDKIMChecksNeeded(Domain
domain) {
diff --git
a/server/protocols/protocols-smtp-dkim/src/test/java/org/apache/james/smtpserver/DKIMHookTest.java
b/server/protocols/protocols-smtp-dkim/src/test/java/org/apache/james/smtpserver/DKIMHookTest.java
index dbb1184f9a..710dc09bf5 100644
---
a/server/protocols/protocols-smtp-dkim/src/test/java/org/apache/james/smtpserver/DKIMHookTest.java
+++
b/server/protocols/protocols-smtp-dkim/src/test/java/org/apache/james/smtpserver/DKIMHookTest.java
@@ -22,6 +22,7 @@ package org.apache.james.smtpserver;
import static
org.apache.james.smtpserver.DKIMHook.Config.DEFAULT_VALIDATED_ENTITIES;
import static org.assertj.core.api.Assertions.assertThat;
+import java.util.List;
import java.util.Optional;
import org.apache.commons.configuration2.BaseHierarchicalConfiguration;
@@ -250,8 +251,22 @@ class DKIMHookTest {
configuration.addProperty("expectedDToken", "apache.org");
assertThat(DKIMHook.Config.parse(configuration))
- .isEqualTo(new DKIMHook.Config(false, false,
Optional.of(Domain.of("linagora.com")),
- ImmutableList.of(ValidatedEntity.envelope),
Optional.of("apache.org")));
+ .isEqualTo(new DKIMHook.Config(false, false,
Optional.of(List.of(Domain.of("linagora.com"))),
+ ImmutableList.of(ValidatedEntity.envelope),
Optional.of(List.of("apache.org"))));
+ }
+
+ @Test
+ void multivaluedConfiguration() {
+ BaseHierarchicalConfiguration configuration = new
BaseHierarchicalConfiguration();
+ configuration.addProperty("forceCRLF", false);
+ configuration.addProperty("signatureRequired", false);
+ configuration.addProperty("onlyForSenderDomain",
"linagora.com,linto.ai");
+ configuration.addProperty("validatedEntities", "envelope");
+ configuration.addProperty("expectedDToken",
"apache.org,linagora.vn");
+
+ assertThat(DKIMHook.Config.parse(configuration))
+ .isEqualTo(new DKIMHook.Config(false, false,
Optional.of(List.of(Domain.of("linagora.com"), Domain.of("linto.ai"))),
+ ImmutableList.of(ValidatedEntity.envelope),
Optional.of(List.of("apache.org", "linagora.vn"))));
}
}
}
\ No newline at end of file
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]