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 <btell...@linagora.com>
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: notifications-unsubscr...@james.apache.org
For additional commands, e-mail: notifications-h...@james.apache.org

Reply via email to