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]
