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

commit cdf0abb48746ca9ea7d7c6cab88afc1507f1e205
Author: Benoit Tellier <[email protected]>
AuthorDate: Sat Apr 11 12:24:23 2020 +0700

    JAMES-3147 Group localDomain calls for RecipientIsLocal
---
 .../main/java/org/apache/mailet/MailetContext.java |  8 ++++
 .../james/transport/matchers/HostIsLocal.java      | 37 ++++++++++++++---
 .../james/transport/matchers/RecipientIsLocal.java | 17 ++++----
 .../transport/matchers/RecipientIsLocalTest.java   | 11 +++--
 .../mailetcontainer/impl/JamesMailetContext.java   |  5 +++
 .../james/mailetcontainer/impl/LocalResources.java | 47 ++++++++++++++++++----
 .../impl/JamesMailetContextTest.java               | 31 ++++++++++++++
 .../mailets/RecipientRewriteTableProcessor.java    | 34 +++++++++++++---
 8 files changed, 158 insertions(+), 32 deletions(-)

diff --git a/mailet/api/src/main/java/org/apache/mailet/MailetContext.java 
b/mailet/api/src/main/java/org/apache/mailet/MailetContext.java
index 44c0e9a..459dac0 100644
--- a/mailet/api/src/main/java/org/apache/mailet/MailetContext.java
+++ b/mailet/api/src/main/java/org/apache/mailet/MailetContext.java
@@ -32,6 +32,8 @@ import org.apache.james.core.Domain;
 import org.apache.james.core.MailAddress;
 import org.slf4j.Logger;
 
+import com.github.steveash.guavate.Guavate;
+
 /**
  * Defines a set of methods that can be used to interact with the mailet
  * container. For example, it can be used to send a new message, to deliver
@@ -266,6 +268,12 @@ public interface MailetContext {
      */
     boolean isLocalEmail(MailAddress mailAddress);
 
+    default Collection<MailAddress> localRecipients(Collection<MailAddress> 
recipients) {
+        return recipients.stream()
+            .filter(this::isLocalEmail)
+            .collect(Guavate.toImmutableList());
+    }
+
     /**
      * Returns the hostnames that are specified as mail handlers for
      * the given domain name. The host names are determined using DNS
diff --git 
a/mailet/standard/src/main/java/org/apache/james/transport/matchers/HostIsLocal.java
 
b/mailet/standard/src/main/java/org/apache/james/transport/matchers/HostIsLocal.java
index 46763a9..653bf9c 100644
--- 
a/mailet/standard/src/main/java/org/apache/james/transport/matchers/HostIsLocal.java
+++ 
b/mailet/standard/src/main/java/org/apache/james/transport/matchers/HostIsLocal.java
@@ -21,17 +21,44 @@
 
 package org.apache.james.transport.matchers;
 
+import java.util.Collection;
+import java.util.Map;
+import java.util.stream.Stream;
+
+import javax.mail.MessagingException;
+
+import org.apache.james.core.Domain;
 import org.apache.james.core.MailAddress;
-import org.apache.mailet.base.GenericRecipientMatcher;
+import org.apache.mailet.Mail;
+import org.apache.mailet.base.GenericMatcher;
+
+import com.github.steveash.guavate.Guavate;
 
 /**
  * Matches mail to Domains which are local
  * .
  */
-public class HostIsLocal extends GenericRecipientMatcher {
-
+public class HostIsLocal extends GenericMatcher {
     @Override
-    public boolean matchRecipient(MailAddress recipient) {
-        return getMailetContext().isLocalServer(recipient.getDomain());
+    public Collection<MailAddress> match(Mail mail) throws MessagingException {
+        return recipientsByDomains(mail)
+            .flatMap(this::hasLocalDomain)
+            .collect(Guavate.toImmutableList());
+    }
+
+    private Stream<MailAddress> hasLocalDomain(Map.Entry<Domain, 
Collection<MailAddress>> entry) {
+        if (getMailetContext().isLocalServer(entry.getKey())) {
+            return entry.getValue().stream();
+        }
+        return Stream.empty();
+    }
+
+    private Stream<Map.Entry<Domain, Collection<MailAddress>>> 
recipientsByDomains(Mail mail) {
+        return mail.getRecipients()
+            .stream()
+            .collect(Guavate.toImmutableListMultimap(MailAddress::getDomain))
+            .asMap()
+            .entrySet()
+            .stream();
     }
 }
diff --git 
a/mailet/standard/src/main/java/org/apache/james/transport/matchers/RecipientIsLocal.java
 
b/mailet/standard/src/main/java/org/apache/james/transport/matchers/RecipientIsLocal.java
index e21b056..6e24951 100644
--- 
a/mailet/standard/src/main/java/org/apache/james/transport/matchers/RecipientIsLocal.java
+++ 
b/mailet/standard/src/main/java/org/apache/james/transport/matchers/RecipientIsLocal.java
@@ -21,20 +21,21 @@
 
 package org.apache.james.transport.matchers;
 
+import java.util.Collection;
+
+import javax.mail.MessagingException;
+
 import org.apache.james.core.MailAddress;
-import org.apache.mailet.MailetContext;
-import org.apache.mailet.base.GenericRecipientMatcher;
+import org.apache.mailet.Mail;
+import org.apache.mailet.base.GenericMatcher;
 
 /**
  * Matches mail where the recipient is local.
  * @version 1.0.0, 24/04/1999
  */
-public class RecipientIsLocal extends GenericRecipientMatcher {
-
+public class RecipientIsLocal extends GenericMatcher {
     @Override
-    public boolean matchRecipient(MailAddress recipient) {
-        MailetContext mailetContext = getMailetContext();
-        //This might change after startup
-        return mailetContext.isLocalEmail(recipient);
+    public Collection<MailAddress> match(Mail mail) throws MessagingException {
+        return getMailetContext().localRecipients(mail.getRecipients());
     }
 }
diff --git 
a/mailet/standard/src/test/java/org/apache/james/transport/matchers/RecipientIsLocalTest.java
 
b/mailet/standard/src/test/java/org/apache/james/transport/matchers/RecipientIsLocalTest.java
index eb459f7..d00e5cb 100644
--- 
a/mailet/standard/src/test/java/org/apache/james/transport/matchers/RecipientIsLocalTest.java
+++ 
b/mailet/standard/src/test/java/org/apache/james/transport/matchers/RecipientIsLocalTest.java
@@ -20,6 +20,7 @@
 package org.apache.james.transport.matchers;
 
 import static  org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 
@@ -30,6 +31,7 @@ import org.apache.mailet.base.test.FakeMail;
 import org.apache.mailet.base.test.FakeMatcherConfig;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
+import org.testcontainers.shaded.com.google.common.collect.ImmutableList;
 
 public class RecipientIsLocalTest {
 
@@ -59,24 +61,21 @@ public class RecipientIsLocalTest {
 
     @Test
     public void matchShouldNotReturnNonExistingAddress() throws Exception {
-        when(mailetContext.isLocalEmail(mailAddress1)).thenReturn(false);
-        when(mailetContext.isLocalEmail(mailAddress2)).thenReturn(false);
+        
when(mailetContext.localRecipients(any())).thenReturn(ImmutableList.of());
 
         assertThat(testee.match(mail)).isEmpty();
     }
 
     @Test
     public void matchShouldNotReturnNonExistingAddressIfSomeRecipientsExists() 
throws Exception {
-        when(mailetContext.isLocalEmail(mailAddress1)).thenReturn(true);
-        when(mailetContext.isLocalEmail(mailAddress2)).thenReturn(false);
+        
when(mailetContext.localRecipients(any())).thenReturn(ImmutableList.of(mailAddress1));
 
         assertThat(testee.match(mail)).containsOnly(mailAddress1);
     }
 
     @Test
     public void matchShouldHandleTwoValidAddress() throws Exception {
-        when(mailetContext.isLocalEmail(mailAddress1)).thenReturn(true);
-        when(mailetContext.isLocalEmail(mailAddress2)).thenReturn(true);
+        
when(mailetContext.localRecipients(any())).thenReturn(ImmutableList.of(mailAddress1,
 mailAddress2));
 
         assertThat(testee.match(mail)).containsOnly(mailAddress1, 
mailAddress2);
     }
diff --git 
a/server/mailet/mailetcontainer-camel/src/main/java/org/apache/james/mailetcontainer/impl/JamesMailetContext.java
 
b/server/mailet/mailetcontainer-camel/src/main/java/org/apache/james/mailetcontainer/impl/JamesMailetContext.java
index 98eb92f..99f0c5d 100644
--- 
a/server/mailet/mailetcontainer-camel/src/main/java/org/apache/james/mailetcontainer/impl/JamesMailetContext.java
+++ 
b/server/mailet/mailetcontainer-camel/src/main/java/org/apache/james/mailetcontainer/impl/JamesMailetContext.java
@@ -240,6 +240,11 @@ public class JamesMailetContext implements MailetContext, 
Configurable, Disposab
     }
 
     @Override
+    public Collection<MailAddress> localRecipients(Collection<MailAddress> 
recipients) {
+        return localResources.localEmails(recipients);
+    }
+
+    @Override
     public MailAddress getPostmaster() {
         return postmaster;
     }
diff --git 
a/server/mailet/mailetcontainer-camel/src/main/java/org/apache/james/mailetcontainer/impl/LocalResources.java
 
b/server/mailet/mailetcontainer-camel/src/main/java/org/apache/james/mailetcontainer/impl/LocalResources.java
index 9e76c1b..bd41f84 100644
--- 
a/server/mailet/mailetcontainer-camel/src/main/java/org/apache/james/mailetcontainer/impl/LocalResources.java
+++ 
b/server/mailet/mailetcontainer-camel/src/main/java/org/apache/james/mailetcontainer/impl/LocalResources.java
@@ -19,7 +19,10 @@
 
 package org.apache.james.mailetcontainer.impl;
 
+import java.util.Collection;
 import java.util.EnumSet;
+import java.util.Map;
+import java.util.stream.Stream;
 
 import javax.inject.Inject;
 import javax.mail.internet.ParseException;
@@ -36,6 +39,7 @@ import org.apache.james.user.api.UsersRepository;
 import org.apache.james.user.api.UsersRepositoryException;
 
 import com.github.fge.lambdas.Throwing;
+import com.github.steveash.guavate.Guavate;
 
 class LocalResources {
     private static final EnumSet<Mapping.Type> ALIAS_TYPES = 
EnumSet.of(Mapping.Type.Alias, Mapping.Type.DomainAlias);
@@ -78,18 +82,45 @@ class LocalResources {
             if (!isLocalServer(mailAddress.getDomain())) {
                 return false;
             }
-            try {
-                return isLocaluser(mailAddress)
-                    || isLocalAlias(mailAddress);
-            } catch (UsersRepositoryException e) {
-                throw new RuntimeException("Unable to retrieve users", e);
-            } catch (RecipientRewriteTable.ErrorMappingException | 
RecipientRewriteTableException e) {
-                throw new RuntimeException("Unable to retrieve RRTs", e);
-            }
+            return belongsToALocalUser(mailAddress);
         }
         return false;
     }
 
+    private boolean belongsToALocalUser(MailAddress mailAddress) {
+        try {
+            return isLocaluser(mailAddress)
+                || isLocalAlias(mailAddress);
+        } catch (UsersRepositoryException e) {
+            throw new RuntimeException("Unable to retrieve users", e);
+        } catch (RecipientRewriteTable.ErrorMappingException | 
RecipientRewriteTableException e) {
+            throw new RuntimeException("Unable to retrieve RRTs", e);
+        }
+    }
+
+    Collection<MailAddress> localEmails(Collection<MailAddress> mailAddresses) 
{
+        return addressByDomains(mailAddresses)
+            .flatMap(this::hasLocalDomain)
+            .filter(this::belongsToALocalUser)
+            .collect(Guavate.toImmutableList());
+    }
+
+    private Stream<MailAddress> hasLocalDomain(Map.Entry<Domain, 
Collection<MailAddress>> entry) {
+        if (isLocalServer(entry.getKey())) {
+            return entry.getValue().stream();
+        }
+        return Stream.empty();
+    }
+
+    private Stream<Map.Entry<Domain, Collection<MailAddress>>> 
addressByDomains(Collection<MailAddress> mailAddresses) {
+        return mailAddresses.stream()
+            .collect(Guavate.toImmutableListMultimap(
+                MailAddress::getDomain))
+            .asMap()
+            .entrySet()
+            .stream();
+    }
+
     private boolean isLocaluser(MailAddress mailAddress) throws 
UsersRepositoryException {
         return localUsers.contains(localUsers.getUsername(mailAddress));
     }
diff --git 
a/server/mailet/mailetcontainer-camel/src/test/java/org/apache/james/mailetcontainer/impl/JamesMailetContextTest.java
 
b/server/mailet/mailetcontainer-camel/src/test/java/org/apache/james/mailetcontainer/impl/JamesMailetContextTest.java
index ea2320b..0215f09 100644
--- 
a/server/mailet/mailetcontainer-camel/src/test/java/org/apache/james/mailetcontainer/impl/JamesMailetContextTest.java
+++ 
b/server/mailet/mailetcontainer-camel/src/test/java/org/apache/james/mailetcontainer/impl/JamesMailetContextTest.java
@@ -225,6 +225,37 @@ public class JamesMailetContextTest {
     }
 
     @Test
+    public void localRecipientsShouldReturnAddressWhenUserExists() throws 
Exception {
+        domainList.addDomain(DOMAIN_COM);
+        usersRepository.addUser(USERMAIL, PASSWORD);
+
+        
assertThat(testee.localRecipients(ImmutableList.of(mailAddress))).containsOnly(mailAddress);
+    }
+
+    @Test
+    public void localRecipientsShouldReturnOnlyExistingUsers() throws 
Exception {
+        domainList.addDomain(DOMAIN_COM);
+        usersRepository.addUser(USERMAIL, PASSWORD);
+
+        assertThat(testee.localRecipients(
+            ImmutableList.of(mailAddress,
+                MailAddressFixture.RECIPIENT2)))
+            .containsOnly(mailAddress);
+    }
+
+    @Test
+    public void localRecipientsShouldNotReturnAddressWhenUserDoNotExists() 
throws Exception {
+        domainList.addDomain(DOMAIN_COM);
+
+        
assertThat(testee.localRecipients(ImmutableList.of(mailAddress))).isEmpty();
+    }
+
+    @Test
+    public void localRecipientsShouldNotReturnAddressWhenDomainDoNotExists() 
throws Exception {
+        
assertThat(testee.localRecipients(ImmutableList.of(mailAddress))).isEmpty();
+    }
+
+    @Test
     public void isLocalEmailShouldBeFalseWhenMailIsNull() {
         assertThat(testee.isLocalEmail(null)).isFalse();
     }
diff --git 
a/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/RecipientRewriteTableProcessor.java
 
b/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/RecipientRewriteTableProcessor.java
index dd890c4..2e49953 100644
--- 
a/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/RecipientRewriteTableProcessor.java
+++ 
b/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/RecipientRewriteTableProcessor.java
@@ -26,6 +26,7 @@ import java.util.Set;
 import java.util.function.Function;
 import java.util.function.Supplier;
 import java.util.stream.Collectors;
+import java.util.stream.Stream;
 
 import javax.mail.MessagingException;
 
@@ -47,9 +48,11 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import com.github.fge.lambdas.Throwing;
+import com.github.steveash.guavate.Guavate;
 import com.google.common.annotations.VisibleForTesting;
 import com.google.common.base.Preconditions;
 import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.ImmutableSet;
 
 public class RecipientRewriteTableProcessor {
@@ -179,17 +182,38 @@ public class RecipientRewriteTableProcessor {
     @VisibleForTesting
     List<MailAddress> handleMappings(Mappings mappings, Mail mail, MailAddress 
recipient) {
         boolean isLocal = true;
-        Map<Boolean, List<MailAddress>> mailAddressSplit = mappings.asStream()
-            .map(mapping -> mapping.appendDomainIfNone(defaultDomainSupplier))
-            .map(Mapping::asMailAddress)
-            .flatMap(OptionalUtils::toStream)
-            .collect(Collectors.partitioningBy(mailAddress -> 
mailetContext.isLocalServer(mailAddress.getDomain())));
+        Map<Boolean, List<MailAddress>> mailAddressSplit = 
splitRemoteMailAddresses(mappings);
 
         forwardToRemoteAddress(mail, recipient, 
mailAddressSplit.get(!isLocal));
 
         return mailAddressSplit.get(isLocal);
     }
 
+    private ImmutableMap<Boolean, List<MailAddress>> 
splitRemoteMailAddresses(Mappings mappings) {
+        return mailAddressesPerDomain(mappings)
+            .collect(Collectors.partitioningBy(entry -> 
mailetContext.isLocalServer(entry.getKey())))
+            .entrySet()
+            .stream()
+            .collect(Guavate.toImmutableMap(
+                Map.Entry::getKey,
+                entry -> entry.getValue()
+                    .stream()
+                    .flatMap(domainEntry -> domainEntry.getValue().stream())
+                    .collect(Guavate.toImmutableList())));
+    }
+
+    private Stream<Map.Entry<Domain, Collection<MailAddress>>> 
mailAddressesPerDomain(Mappings mappings) {
+        return mappings.asStream()
+            .map(mapping -> mapping.appendDomainIfNone(defaultDomainSupplier))
+            .map(Mapping::asMailAddress)
+            .flatMap(OptionalUtils::toStream)
+            .collect(Guavate.toImmutableListMultimap(
+                MailAddress::getDomain))
+            .asMap()
+            .entrySet()
+            .stream();
+    }
+
     private void forwardToRemoteAddress(Mail mail, MailAddress recipient, 
Collection<MailAddress> remoteRecipients) {
         if (!remoteRecipients.isEmpty()) {
             try {


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to