JAMES-2529 Address contentMatching should be symetric

We need to apply a similar transformation to the matched value and to the 
toMatch value.

This allows to get rid of a hard-to-understand Stream::concat call that 
obviously would lead to invalid results in case of mutli-address Header


Project: http://git-wip-us.apache.org/repos/asf/james-project/repo
Commit: http://git-wip-us.apache.org/repos/asf/james-project/commit/9fc30a40
Tree: http://git-wip-us.apache.org/repos/asf/james-project/tree/9fc30a40
Diff: http://git-wip-us.apache.org/repos/asf/james-project/diff/9fc30a40

Branch: refs/heads/master
Commit: 9fc30a403b0acbe9f490c46eaee4ab9e8dee5835
Parents: 1d889b7
Author: Benoit Tellier <[email protected]>
Authored: Mon Oct 29 11:20:11 2018 +0700
Committer: Benoit Tellier <[email protected]>
Committed: Wed Oct 31 08:48:30 2018 +0700

----------------------------------------------------------------------
 .../jmap/mailet/filter/ContentMatcher.java      | 36 +++++++++++++++-----
 .../jmap/mailet/filter/HeaderExtractor.java     |  6 ++--
 .../jmap/mailet/filter/JMAPFilteringTest.java   |  5 +++
 3 files changed, 34 insertions(+), 13 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/9fc30a40/server/protocols/jmap/src/main/java/org/apache/james/jmap/mailet/filter/ContentMatcher.java
----------------------------------------------------------------------
diff --git 
a/server/protocols/jmap/src/main/java/org/apache/james/jmap/mailet/filter/ContentMatcher.java
 
b/server/protocols/jmap/src/main/java/org/apache/james/jmap/mailet/filter/ContentMatcher.java
index 9940c01..884f1b6 100644
--- 
a/server/protocols/jmap/src/main/java/org/apache/james/jmap/mailet/filter/ContentMatcher.java
+++ 
b/server/protocols/jmap/src/main/java/org/apache/james/jmap/mailet/filter/ContentMatcher.java
@@ -28,6 +28,7 @@ import javax.mail.internet.InternetAddress;
 
 import org.apache.commons.lang3.StringUtils;
 import org.apache.james.jmap.api.filtering.Rule;
+import org.apache.james.util.OptionalUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -45,8 +46,11 @@ public interface ContentMatcher {
         private AddressHeader(String fullAddress) {
             this.fullAddress = fullAddress;
             Optional<InternetAddress> internetAddress = parseFullAddress();
-            this.personal = internetAddress.map(InternetAddress::getPersonal);
             this.address = internetAddress.map(InternetAddress::getAddress);
+            this.personal = OptionalUtils.or(
+                internetAddress.map(InternetAddress::getPersonal),
+                address,
+                Optional.of(fullAddress));
         }
 
         private Optional<InternetAddress> parseFullAddress() {
@@ -57,6 +61,26 @@ public interface ContentMatcher {
                 return Optional.empty();
             }
         }
+
+        boolean exactMatch(AddressHeader other) {
+            return fullAddress.equalsIgnoreCase(other.fullAddress)
+                || OptionalUtils.matches(address, other.address, 
String::equalsIgnoreCase)
+                || OptionalUtils.matches(personal, other.personal, 
String::equalsIgnoreCase);
+        }
+    }
+
+    class ExactAddressContentMatcher implements ContentMatcher {
+        @Override
+        public boolean match(Stream<String> contents, String valueToMatch) {
+            AddressHeader addressHeaderToMatch =  
HeaderExtractor.toAddressContents(new String[] {valueToMatch})
+                .map(AddressHeader::new)
+                .findAny()
+                .orElse(new AddressHeader(valueToMatch));
+
+            return contents.map(ContentMatcher::asAddressHeader)
+                .anyMatch(addressHeaderToMatch::exactMatch);
+        }
+
     }
 
     ContentMatcher STRING_CONTAINS_MATCHER = (contents, valueToMatch) -> 
contents.anyMatch(content -> StringUtils.contains(content, valueToMatch));
@@ -68,18 +92,12 @@ public interface ContentMatcher {
         .map(ContentMatcher::asAddressHeader)
         .anyMatch(addressHeader -> 
StringUtils.containsIgnoreCase(addressHeader.fullAddress, valueToMatch));
     ContentMatcher ADDRESS_NOT_CONTAINS_MATCHER = 
negate(ADDRESS_CONTAINS_MATCHER);
-    ContentMatcher ADDRESS_EXACTLY_EQUALS_MATCHER = (contents, valueToMatch) 
-> contents
-        .map(ContentMatcher::asAddressHeader)
-        .anyMatch(addressHeader ->
-            valueToMatch.equalsIgnoreCase(addressHeader.fullAddress)
-                || 
addressHeader.address.map(valueToMatch::equalsIgnoreCase).orElse(false)
-                || 
addressHeader.personal.map(valueToMatch::equalsIgnoreCase).orElse(false));
-    ContentMatcher ADDRESS_NOT_EXACTLY_EQUALS_MATCHER = 
negate(ADDRESS_EXACTLY_EQUALS_MATCHER);
+    ContentMatcher ADDRESS_NOT_EXACTLY_EQUALS_MATCHER = negate(new 
ExactAddressContentMatcher());
 
     Map<Rule.Condition.Comparator, ContentMatcher> 
HEADER_ADDRESS_MATCHER_REGISTRY = ImmutableMap.<Rule.Condition.Comparator, 
ContentMatcher>builder()
         .put(Rule.Condition.Comparator.CONTAINS, ADDRESS_CONTAINS_MATCHER)
         .put(Rule.Condition.Comparator.NOT_CONTAINS, 
ADDRESS_NOT_CONTAINS_MATCHER)
-        .put(Rule.Condition.Comparator.EXACTLY_EQUALS, 
ADDRESS_EXACTLY_EQUALS_MATCHER)
+        .put(Rule.Condition.Comparator.EXACTLY_EQUALS, new 
ExactAddressContentMatcher())
         .put(Rule.Condition.Comparator.NOT_EXACTLY_EQUALS, 
ADDRESS_NOT_EXACTLY_EQUALS_MATCHER)
         .build();
 

http://git-wip-us.apache.org/repos/asf/james-project/blob/9fc30a40/server/protocols/jmap/src/main/java/org/apache/james/jmap/mailet/filter/HeaderExtractor.java
----------------------------------------------------------------------
diff --git 
a/server/protocols/jmap/src/main/java/org/apache/james/jmap/mailet/filter/HeaderExtractor.java
 
b/server/protocols/jmap/src/main/java/org/apache/james/jmap/mailet/filter/HeaderExtractor.java
index b2bea2c..b8e05ee 100644
--- 
a/server/protocols/jmap/src/main/java/org/apache/james/jmap/mailet/filter/HeaderExtractor.java
+++ 
b/server/protocols/jmap/src/main/java/org/apache/james/jmap/mailet/filter/HeaderExtractor.java
@@ -84,11 +84,9 @@ public interface HeaderExtractor extends 
ThrowingFunction<Mail, Stream<String>>
     }
 
     static Stream<String> toAddressContents(String[] headers) {
-        return Stream.concat(
-            StreamUtils.ofNullable(headers),
-            StreamUtils.ofNullable(headers)
+        return StreamUtils.ofNullable(headers)
                 .map(Throwing.function(string -> 
InternetAddress.parseHeader(string, !STRICT_PARSING)))
-                .flatMap(AddressHelper::asStringStream));
+                .flatMap(AddressHelper::asStringStream);
     }
 
     static Optional<HeaderExtractor> asHeaderExtractor(Rule.Condition.Field 
field) {

http://git-wip-us.apache.org/repos/asf/james-project/blob/9fc30a40/server/protocols/jmap/src/test/java/org/apache/james/jmap/mailet/filter/JMAPFilteringTest.java
----------------------------------------------------------------------
diff --git 
a/server/protocols/jmap/src/test/java/org/apache/james/jmap/mailet/filter/JMAPFilteringTest.java
 
b/server/protocols/jmap/src/test/java/org/apache/james/jmap/mailet/filter/JMAPFilteringTest.java
index f534d3b..2105c43 100644
--- 
a/server/protocols/jmap/src/test/java/org/apache/james/jmap/mailet/filter/JMAPFilteringTest.java
+++ 
b/server/protocols/jmap/src/test/java/org/apache/james/jmap/mailet/filter/JMAPFilteringTest.java
@@ -335,6 +335,11 @@ class JMAPFilteringTest {
                     argumentBuilder(fieldAndHeader.field)
                         .description("Full header exact match in a full " + 
fieldAndHeader.headerName + " with an invalid structure")
                         .header(fieldAndHeader.headerName, "Benoit <invalid")
+                        .valueToMatch("Benoit <invalid"),
+
+                    argumentBuilder(fieldAndHeader.field)
+                        .description("Full header exact match in a full " + 
fieldAndHeader.headerName + " with an invalid structure - multi address")
+                        .header(fieldAndHeader.headerName, "Valid 
<[email protected]>, Benoit <invalid")
                         .valueToMatch("Benoit <invalid"))
                     .flatMap(JMAPFilteringTest::forBothCase)),
 


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

Reply via email to