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
The following commit(s) were added to refs/heads/master by this push: new de87ddfbeb JAMES-3491 Implement more actions for filters (#1563) de87ddfbeb is described below commit de87ddfbeb4f778f95af4dc6d47e1d748d471498 Author: Benoit TELLIER <btell...@linagora.com> AuthorDate: Thu May 18 17:33:06 2023 +0700 JAMES-3491 Implement more actions for filters (#1563) --- .../java/org/apache/mailet/StorageDirective.java | 40 +++++-- .../james/jmap/cassandra/filtering/RuleDTO.java | 41 ++++++- .../james/jmap/cassandra/filtering/DTOTest.java | 33 +++++- .../src/test/resources/json/event-v2.json | 43 ++++++++ .../src/test/resources/json/eventComplex-v2.json | 79 ++++++++++++++ .../src/test/resources/json/increment-v2.json | 31 ++++++ .../org/apache/james/jmap/api/filtering/Rule.java | 45 +++++++- .../james/jmap/mailet/filter/ActionApplier.java | 56 +++++++--- .../james/jmap/mailet/filter/JMAPFiltering.java | 27 +++-- .../jmap/mailet/filter/JMAPFilteringTest.java | 118 +++++++++++++++++++++ 10 files changed, 465 insertions(+), 48 deletions(-) diff --git a/mailet/api/src/main/java/org/apache/mailet/StorageDirective.java b/mailet/api/src/main/java/org/apache/mailet/StorageDirective.java index a55f46764e..2d0fe928de 100644 --- a/mailet/api/src/main/java/org/apache/mailet/StorageDirective.java +++ b/mailet/api/src/main/java/org/apache/mailet/StorageDirective.java @@ -19,6 +19,7 @@ package org.apache.mailet; import java.util.Collection; +import java.util.Objects; import java.util.Optional; import java.util.stream.Stream; @@ -84,16 +85,26 @@ public class StorageDirective { } public StorageDirective build() { - Preconditions.checkState( - Booleans.countTrue( - seen.isPresent(), - important.isPresent(), - targetFolder.isPresent(), - keywords.isPresent()) > 0, + Preconditions.checkState(hasChanges(), "Expecting one of the storage directives to be specified: [targetFolder, seen, important, keywords]"); return new StorageDirective(targetFolder, seen, important, keywords); } + + private boolean hasChanges() { + return Booleans.countTrue( + seen.isPresent(), + important.isPresent(), + targetFolder.isPresent(), + keywords.isPresent()) > 0; + } + + public Optional<StorageDirective> buildOptional() { + if (!hasChanges()) { + return Optional.empty(); + } + return Optional.of(build()); + } } private static final String DELIVERY_PATH_PREFIX = "DeliveryPath_"; @@ -209,4 +220,21 @@ public class StorageDirective { public Optional<String> getTargetFolder() { return targetFolder; } + + @Override + public final boolean equals(Object o) { + if (o instanceof StorageDirective) { + StorageDirective other = (StorageDirective) o; + return Objects.equals(targetFolder, other.targetFolder) + && Objects.equals(seen, other.seen) + && Objects.equals(important, other.important) + && Objects.equals(keywords, other.keywords); + } + return false; + } + + @Override + public final int hashCode() { + return Objects.hash(targetFolder, seen, important, keywords); + } } diff --git a/server/data/data-jmap-cassandra/src/main/java/org/apache/james/jmap/cassandra/filtering/RuleDTO.java b/server/data/data-jmap-cassandra/src/main/java/org/apache/james/jmap/cassandra/filtering/RuleDTO.java index c3d8c54fd8..86a39ac00a 100644 --- a/server/data/data-jmap-cassandra/src/main/java/org/apache/james/jmap/cassandra/filtering/RuleDTO.java +++ b/server/data/data-jmap-cassandra/src/main/java/org/apache/james/jmap/cassandra/filtering/RuleDTO.java @@ -131,20 +131,49 @@ public class RuleDTO { } public static ActionDTO from(Rule.Action action) { - return new ActionDTO(AppendInMailboxesDTO.from(action.getAppendInMailboxes())); + return new ActionDTO(AppendInMailboxesDTO.from(action.getAppendInMailboxes()), + action.isMarkAsSeen(), action.isMarkAsImportant(), action.isReject(), ImmutableList.copyOf(action.getWithKeywords())); } @JsonCreator - public ActionDTO(@JsonProperty("appendIn") AppendInMailboxesDTO appendIn) { + public ActionDTO(@JsonProperty("appendIn") AppendInMailboxesDTO appendIn, + @JsonProperty("seen") boolean seen, + @JsonProperty("important") boolean important, + @JsonProperty("reject") boolean reject, + @JsonProperty("keywords") List<String> keyworkds) { this.appendIn = appendIn; + this.keyworkds = keyworkds; + this.seen = seen; + this.important = important; + this.reject = reject; } private final AppendInMailboxesDTO appendIn; + private final boolean seen; + private final boolean important; + private final boolean reject; + private final List<String> keyworkds; public AppendInMailboxesDTO getAppendIn() { return appendIn; } + public boolean isSeen() { + return seen; + } + + public boolean isImportant() { + return important; + } + + public boolean isReject() { + return reject; + } + + public List<String> getKeyworkds() { + return keyworkds; + } + public Rule.Action toAction() { return Rule.Action.of(appendIn.toAppendInMailboxes()); } @@ -154,14 +183,18 @@ public class RuleDTO { if (o instanceof ActionDTO) { ActionDTO actionDTO = (ActionDTO) o; - return Objects.equals(this.appendIn, actionDTO.appendIn); + return Objects.equals(this.appendIn, actionDTO.appendIn) + && Objects.equals(this.seen, actionDTO.seen) + && Objects.equals(this.important, actionDTO.important) + && Objects.equals(this.reject, actionDTO.reject) + && Objects.equals(this.keyworkds, actionDTO.keyworkds); } return false; } @Override public final int hashCode() { - return Objects.hash(appendIn); + return Objects.hash(appendIn, reject, seen, important, keyworkds); } } diff --git a/server/data/data-jmap-cassandra/src/test/java/org/apache/james/jmap/cassandra/filtering/DTOTest.java b/server/data/data-jmap-cassandra/src/test/java/org/apache/james/jmap/cassandra/filtering/DTOTest.java index 3130a5bfd9..25ca063d4a 100644 --- a/server/data/data-jmap-cassandra/src/test/java/org/apache/james/jmap/cassandra/filtering/DTOTest.java +++ b/server/data/data-jmap-cassandra/src/test/java/org/apache/james/jmap/cassandra/filtering/DTOTest.java @@ -27,6 +27,7 @@ import static org.apache.james.jmap.api.filtering.RuleFixture.RULE_SUBJECT; import static org.apache.james.jmap.api.filtering.RuleFixture.RULE_TO; import static org.apache.james.jmap.cassandra.filtering.FilteringRuleSetDefineDTOModules.FILTERING_INCREMENT; import static org.apache.james.jmap.cassandra.filtering.FilteringRuleSetDefineDTOModules.FILTERING_RULE_SET_DEFINED; +import static org.assertj.core.api.Assertions.assertThat; import java.util.Optional; @@ -39,15 +40,19 @@ import org.apache.james.jmap.api.filtering.impl.IncrementalRuleChange; import org.apache.james.jmap.api.filtering.impl.RuleSetDefined; import org.apache.james.json.JsonGenericSerializer; import org.apache.james.util.ClassLoaderUtils; +import org.assertj.core.api.SoftAssertions; import org.junit.jupiter.api.Test; +import com.github.fge.lambdas.Throwing; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; class DTOTest { static final String EVENT_JSON = ClassLoaderUtils.getSystemResourceAsString("json/event.json"); + static final String EVENT_JSON_2 = ClassLoaderUtils.getSystemResourceAsString("json/event-v2.json"); static final String EVENT_EMPTY_JSON = ClassLoaderUtils.getSystemResourceAsString("json/eventEmpty.json"); static final String EVENT_COMPLEX_JSON = ClassLoaderUtils.getSystemResourceAsString("json/eventComplex.json"); + static final String EVENT_COMPLEX_JSON_2 = ClassLoaderUtils.getSystemResourceAsString("json/eventComplex-v2.json"); static final RuleSetDefined SIMPLE_RULE = new RuleSetDefined( new FilteringAggregateId(Username.of("Bart")), @@ -73,15 +78,37 @@ class DTOTest { void shouldSerializeRule() throws Exception { JsonSerializationVerifier.dtoModule(FILTERING_RULE_SET_DEFINED) .testCase(EMPTY_RULE, EVENT_EMPTY_JSON) - .testCase(SIMPLE_RULE, EVENT_JSON) - .testCase(COMPLEX_RULE, EVENT_COMPLEX_JSON) + .testCase(SIMPLE_RULE, EVENT_JSON_2) + .testCase(COMPLEX_RULE, EVENT_COMPLEX_JSON_2) .verify(); } + @Test + void shouldDeserializeV1() { + JsonGenericSerializer<RuleSetDefined, FilteringRuleSetDefinedDTO> serializer = JsonGenericSerializer + .forModules(FILTERING_RULE_SET_DEFINED) + .withoutNestedType(); + + SoftAssertions.assertSoftly(Throwing.consumer(softly -> { + softly.assertThat(serializer.deserialize(EVENT_JSON)).isEqualToComparingFieldByFieldRecursively(SIMPLE_RULE); + softly.assertThat(serializer.deserialize(EVENT_COMPLEX_JSON)).isEqualToComparingFieldByFieldRecursively(COMPLEX_RULE); + })); + } + @Test void shouldSerializeIncrements() throws Exception { JsonSerializationVerifier.dtoModule(FILTERING_INCREMENT) - .testCase(INCREMENT, ClassLoaderUtils.getSystemResourceAsString("json/increment.json")) + .testCase(INCREMENT, ClassLoaderUtils.getSystemResourceAsString("json/increment-v2.json")) .verify(); } + + @Test + void shouldDeserializeV1ForIncrements() throws Exception { + JsonGenericSerializer<IncrementalRuleChange, FilteringIncrementalRuleChangeDTO> serializer = JsonGenericSerializer + .forModules(FILTERING_INCREMENT) + .withoutNestedType(); + + assertThat(serializer.deserialize(ClassLoaderUtils.getSystemResourceAsString("json/increment.json"))) + .isEqualToComparingFieldByFieldRecursively(INCREMENT); + } } diff --git a/server/data/data-jmap-cassandra/src/test/resources/json/event-v2.json b/server/data/data-jmap-cassandra/src/test/resources/json/event-v2.json new file mode 100644 index 0000000000..903a7b877b --- /dev/null +++ b/server/data/data-jmap-cassandra/src/test/resources/json/event-v2.json @@ -0,0 +1,43 @@ +{ + "type":"filtering-rule-set-defined", + "eventId":0, + "aggregateId":"FilteringRule/bart", + "rules":[ + { + "id":"1", + "name":"a name", + "condition": { + "field": "cc", + "comparator": "contains", + "value": "something" + }, + "action": { + "appendIn": { + "mailboxIds":["id-01"] + }, + "important":false, + "keyworkds":[], + "reject":false, + "seen":false + } + }, + { + "id":"2", + "name":"a name", + "condition": { + "field": "cc", + "comparator": "contains", + "value": "something" + }, + "action": { + "appendIn": { + "mailboxIds":["id-01"] + }, + "important":false, + "keyworkds":[], + "reject":false, + "seen":false + } + } + ] +} \ No newline at end of file diff --git a/server/data/data-jmap-cassandra/src/test/resources/json/eventComplex-v2.json b/server/data/data-jmap-cassandra/src/test/resources/json/eventComplex-v2.json new file mode 100644 index 0000000000..93b1c258eb --- /dev/null +++ b/server/data/data-jmap-cassandra/src/test/resources/json/eventComplex-v2.json @@ -0,0 +1,79 @@ +{ + "type":"filtering-rule-set-defined", + "eventId":0, + "aggregateId":"FilteringRule/bart", + "rules":[ + { + "id":"id-from", + "name":"a name", + "condition": { + "field": "from", + "comparator": "contains", + "value": "A value to match 4" + }, + "action": { + "appendIn": { + "mailboxIds":["mbx1"] + }, + "important":false, + "keyworkds":[], + "reject":false, + "seen":false + } + }, + { + "id":"id-rcpt", + "name":"a name", + "condition": { + "field": "recipient", + "comparator": "not-exactly-equals", + "value": "A value to match 3" + }, + "action": { + "appendIn": { + "mailboxIds":["mbx1"] + }, + "important":false, + "keyworkds":[], + "reject":false, + "seen":false + } + }, + { + "id":"id-subject", + "name":"a name", + "condition": { + "field": "subject", + "comparator": "not-contains", + "value": "A value to match 2" + }, + "action": { + "appendIn": { + "mailboxIds":["mbx1"] + }, + "important":false, + "keyworkds":[], + "reject":false, + "seen":false + } + }, + { + "id":"id-to", + "name":"a name", + "condition": { + "field": "to", + "comparator": "exactly-equals", + "value": "A value to match 1" + }, + "action": { + "appendIn": { + "mailboxIds":["mbx1"] + }, + "important":false, + "keyworkds":[], + "reject":false, + "seen":false + } + } + ] +} \ No newline at end of file diff --git a/server/data/data-jmap-cassandra/src/test/resources/json/increment-v2.json b/server/data/data-jmap-cassandra/src/test/resources/json/increment-v2.json new file mode 100644 index 0000000000..dd3b5832b1 --- /dev/null +++ b/server/data/data-jmap-cassandra/src/test/resources/json/increment-v2.json @@ -0,0 +1,31 @@ +{ + "type":"filtering-increment", + "eventId":0, + "aggregateId":"FilteringRule/bart", + "prepended":[ + { + "id":"id-from", + "name":"a name", + "condition":{"field":"from","comparator":"contains","value":"A value to match 4"}, + "action":{"appendIn":{"mailboxIds":["mbx1"]},"important":false,"keyworkds":[],"reject":false,"seen":false} + }, + { + "id":"id-to", + "name":"a name", + "condition":{"field":"to","comparator":"exactly-equals","value":"A value to match 1"}, + "action":{"appendIn":{"mailboxIds":["mbx1"]},"important":false,"keyworkds":[],"reject":false,"seen":false} + }], + "postpended":[{ + "id":"id-rcpt", + "name":"a name", + "condition":{"field":"recipient","comparator":"not-exactly-equals","value":"A value to match 3"}, + "action":{"appendIn":{"mailboxIds":["mbx1"]},"important":false,"keyworkds":[],"reject":false,"seen":false} + }], + "updated":[{ + "id":"id-subject", + "name":"a name", + "condition":{"field":"subject","comparator":"not-contains","value":"A value to match 2"}, + "action":{"appendIn":{"mailboxIds":["mbx1"]},"important":false,"keyworkds":[],"reject":false,"seen":false} + }], + "deleted":["abdcd"] +} \ No newline at end of file diff --git a/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/filtering/Rule.java b/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/filtering/Rule.java index 3d9af273f0..91c79317fa 100644 --- a/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/filtering/Rule.java +++ b/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/filtering/Rule.java @@ -20,6 +20,7 @@ package org.apache.james.jmap.api.filtering; import java.util.Arrays; +import java.util.Collection; import java.util.List; import java.util.Objects; import java.util.Optional; @@ -230,37 +231,73 @@ public class Rule { } public static Action of(AppendInMailboxes appendInMailboxes) { - return new Action(appendInMailboxes); + return new Action(appendInMailboxes, false, false, false, ImmutableList.of()); + } + + public static Action of(AppendInMailboxes appendInMailboxes, boolean markAsSeen, boolean markAsImportant, boolean reject, List<String> withKeywords) { + return new Action(appendInMailboxes, markAsSeen, markAsImportant, reject, withKeywords); } private final AppendInMailboxes appendInMailboxes; + private final boolean markAsSeen; + private final boolean markAsImportant; + private final boolean reject; + private final List<String> withKeywords; - private Action(AppendInMailboxes appendInMailboxes) { + private Action(AppendInMailboxes appendInMailboxes, boolean markAsSeen, boolean markAsImportant, boolean reject, List<String> withKeywords) { this.appendInMailboxes = appendInMailboxes; + this.markAsSeen = markAsSeen; + this.markAsImportant = markAsImportant; + this.reject = reject; + this.withKeywords = withKeywords; } public AppendInMailboxes getAppendInMailboxes() { return appendInMailboxes; } + public boolean isMarkAsSeen() { + return markAsSeen; + } + + public boolean isMarkAsImportant() { + return markAsImportant; + } + + public boolean isReject() { + return reject; + } + + public Collection<String> getWithKeywords() { + return withKeywords; + } + @Override public final boolean equals(Object o) { if (o instanceof Action) { Action action = (Action) o; - return Objects.equals(appendInMailboxes, action.appendInMailboxes); + return Objects.equals(appendInMailboxes, action.appendInMailboxes) + && Objects.equals(markAsSeen, action.markAsSeen) + && Objects.equals(markAsImportant, action.markAsImportant) + && Objects.equals(reject, action.reject) + && Objects.equals(withKeywords, action.withKeywords); } return false; } @Override public final int hashCode() { - return Objects.hash(appendInMailboxes); + return Objects.hash(appendInMailboxes, markAsImportant, markAsSeen, reject, withKeywords); } @Override public String toString() { return MoreObjects.toStringHelper(this) .add("appendInMailboxes", appendInMailboxes) + .add("markAsImportant", markAsImportant) + .add("markAsSeen", markAsSeen) + .add("reject", reject) + .add("withKeywords", withKeywords) .toString(); } } diff --git a/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/mailet/filter/ActionApplier.java b/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/mailet/filter/ActionApplier.java index e9ce7b9954..6f21a0a0cd 100644 --- a/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/mailet/filter/ActionApplier.java +++ b/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/mailet/filter/ActionApplier.java @@ -19,10 +19,12 @@ package org.apache.james.jmap.mailet.filter; +import java.util.Optional; import java.util.stream.Stream; import javax.inject.Inject; +import org.apache.james.core.MailAddress; import org.apache.james.core.Username; import org.apache.james.jmap.api.filtering.Rule; import org.apache.james.mailbox.MailboxManager; @@ -36,6 +38,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.google.common.annotations.VisibleForTesting; +import com.google.common.collect.ImmutableList; public class ActionApplier { static final String DELIVERY_PATH_PREFIX = "DeliveryPath_"; @@ -63,8 +66,8 @@ public class ActionApplier { this.mail = mail; } - public ActionApplier forUser(Username username) { - return new ActionApplier(mailboxManager, mailboxIdFactory, mail, username); + public ActionApplier forRecipient(MailAddress mailAddress, Username username) { + return new ActionApplier(mailboxManager, mailboxIdFactory, mail, mailAddress, username); } } } @@ -72,6 +75,7 @@ public class ActionApplier { private final MailboxManager mailboxManager; private final MailboxId.Factory mailboxIdFactory; private final Mail mail; + private final MailAddress mailAddress; private final Username username; @VisibleForTesting @@ -79,35 +83,55 @@ public class ActionApplier { return new Factory(mailboxManager, mailboxIdFactory); } - private ActionApplier(MailboxManager mailboxManager, MailboxId.Factory mailboxIdFactory, Mail mail, Username username) { + private ActionApplier(MailboxManager mailboxManager, MailboxId.Factory mailboxIdFactory, Mail mail, MailAddress mailAddress, Username username) { this.mailboxManager = mailboxManager; this.mailboxIdFactory = mailboxIdFactory; this.mail = mail; + this.mailAddress = mailAddress; this.username = username; } public void apply(Stream<Rule.Action> actions) { - actions.flatMap(action -> action.getAppendInMailboxes().getMailboxIds().stream()) - .map(mailboxIdFactory::fromString) - .forEach(this::addStorageDirective); + actions.forEach(this::addStorageDirective); } - private void addStorageDirective(MailboxId mailboxId) { + private void addStorageDirective(Rule.Action action) { + if (action.isReject()) { + mail.setRecipients(mail.getRecipients().stream() + .filter(recipient -> !recipient.equals(mailAddress)) + .collect(ImmutableList.toImmutableList())); + return; + } + Optional<String> targetMailbox = action.getAppendInMailboxes().getMailboxIds() + .stream() + .flatMap(this::asMailboxName) + .reduce((first, second) -> second); + + StorageDirective.Builder storageDirective = StorageDirective.builder(); + targetMailbox.ifPresent(storageDirective::targetFolder); + storageDirective + .seen(Optional.of(action.isMarkAsSeen()).filter(seen -> seen)) + .important(Optional.of(action.isMarkAsImportant()).filter(seen -> seen)) + .keywords(Optional.of(action.getWithKeywords()).filter(c -> !c.isEmpty())) + .buildOptional() + .map(a -> a.encodeAsAttributes(username)) + .orElse(Stream.of()) + .forEach(mail::setAttribute); + } + + private Stream<String> asMailboxName(String mailboxIdString) { try { + MailboxId mailboxId = mailboxIdFactory.fromString(mailboxIdString); MailboxSession mailboxSession = mailboxManager.createSystemSession(username); MessageManager messageManager = mailboxManager.getMailbox(mailboxId, mailboxSession); - String mailboxName = messageManager.getMailboxPath().getName(); - - StorageDirective.builder() - .targetFolder(mailboxName) - .build() - .encodeAsAttributes(username) - .forEach(mail::setAttribute); + return Stream.of(messageManager.getMailboxPath().getName()); } catch (MailboxNotFoundException e) { - LOGGER.info("Mailbox {} does not exist, but it was mentioned in a JMAP filtering rule", mailboxId, e); + LOGGER.info("Mailbox {} does not exist, but it was mentioned in a JMAP filtering rule", mailboxIdString, e); + return Stream.empty(); } catch (Exception e) { - LOGGER.error("Unexpected failure while resolving mailbox name for {}", mailboxId, e); + LOGGER.error("Unexpected failure while resolving mailbox name for {}", mailboxIdString, e); + return Stream.empty(); } } } diff --git a/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/mailet/filter/JMAPFiltering.java b/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/mailet/filter/JMAPFiltering.java index d7ddd315dc..e22a48336f 100644 --- a/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/mailet/filter/JMAPFiltering.java +++ b/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/mailet/filter/JMAPFiltering.java @@ -69,24 +69,21 @@ public class JMAPFiltering extends GenericMailet { @Override public void service(Mail mail) { mail.getRecipients() - .forEach(recipient -> filteringForRecipient(mail, recipient)); + .forEach(recipient -> applyFirstApplicableRule(recipient, mail)); } - private void filteringForRecipient(Mail mail, MailAddress recipient) { - Optional<Username> maybeUser = retrieveUser(recipient); - maybeUser - .ifPresent(user -> findFirstApplicableRule(user, mail)); - } - - private void findFirstApplicableRule(Username username, Mail mail) { - Rules filteringRules = Mono.from(filteringManagement.listRulesForUser(username)) - .block(); - RuleMatcher ruleMatcher = new RuleMatcher(filteringRules.getRules()); - Stream<Rule> matchingRules = ruleMatcher.findApplicableRules(mail); + private void applyFirstApplicableRule(MailAddress recipient, Mail mail) { + retrieveUser(recipient) + .ifPresent(username -> { + Rules filteringRules = Mono.from(filteringManagement.listRulesForUser(username)) + .block(); + RuleMatcher ruleMatcher = new RuleMatcher(filteringRules.getRules()); + Stream<Rule> matchingRules = ruleMatcher.findApplicableRules(mail); - actionApplierFactory.forMail(mail) - .forUser(username) - .apply(matchingRules.map(Rule::getAction)); + actionApplierFactory.forMail(mail) + .forRecipient(recipient, username) + .apply(matchingRules.map(Rule::getAction)); + }); } private Optional<Username> retrieveUser(MailAddress recipient) { diff --git a/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/mailet/filter/JMAPFilteringTest.java b/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/mailet/filter/JMAPFilteringTest.java index 4ae01a30ae..86d60a78b3 100644 --- a/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/mailet/filter/JMAPFilteringTest.java +++ b/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/mailet/filter/JMAPFilteringTest.java @@ -35,6 +35,7 @@ import static org.apache.james.jmap.mailet.filter.JMAPFilteringFixture.EMPTY; import static org.apache.james.jmap.mailet.filter.JMAPFilteringFixture.FRED_MARTIN_FULLNAME; import static org.apache.james.jmap.mailet.filter.JMAPFilteringFixture.FRED_MARTIN_FULL_SCRAMBLED_ADDRESS; import static org.apache.james.jmap.mailet.filter.JMAPFilteringFixture.GA_BOU_ZO_MEU_FULL_ADDRESS; +import static org.apache.james.jmap.mailet.filter.JMAPFilteringFixture.RECIPIENT_1; import static org.apache.james.jmap.mailet.filter.JMAPFilteringFixture.RECIPIENT_1_MAILBOX_1; import static org.apache.james.jmap.mailet.filter.JMAPFilteringFixture.RECIPIENT_1_USERNAME; import static org.apache.james.jmap.mailet.filter.JMAPFilteringFixture.SCRAMBLED_SUBJECT; @@ -57,6 +58,9 @@ import java.util.Locale; import java.util.Optional; import java.util.stream.Stream; +import javax.mail.Flags; + +import org.apache.james.core.Username; import org.apache.james.core.builder.MimeMessageBuilder; import org.apache.james.jmap.api.filtering.Rule; import org.apache.james.jmap.api.filtering.Rule.Condition.Field; @@ -66,6 +70,7 @@ import org.apache.james.util.StreamUtils; import org.apache.mailet.Attribute; import org.apache.mailet.AttributeName; import org.apache.mailet.AttributeValue; +import org.apache.mailet.StorageDirective; import org.apache.mailet.base.RFC2822Headers; import org.apache.mailet.base.test.FakeMail; import org.junit.jupiter.api.Nested; @@ -915,4 +920,117 @@ class JMAPFilteringTest { .contains(RECIPIENT_1_MAILBOX_1_ATTRIBUTE); } } + + @Test + void actionShouldSupportReject(JMAPFilteringTestSystem testSystem) throws Exception { + Mono.from(testSystem.getFilteringManagement().defineRulesForUser(RECIPIENT_1_USERNAME, + Optional.empty(), + Rule.builder() + .id(Rule.Id.of("1")) + .name("rule 1") + .condition(Rule.Condition.of(FROM, CONTAINS, FRED_MARTIN_FULLNAME)) + .action(Rule.Action.of(Rule.Action.AppendInMailboxes.withMailboxIds(), + false, false, true, ImmutableList.of())) + .build())).block(); + + FakeMail mail = testSystem.asMail(mimeMessageBuilder() + .addFrom(FRED_MARTIN_FULL_SCRAMBLED_ADDRESS)); + + testSystem.getJmapFiltering().service(mail); + + assertThat(mail.getRecipients()).isEmpty(); + } + + @Test + void actionShouldSupportSeen(JMAPFilteringTestSystem testSystem) throws Exception { + Mono.from(testSystem.getFilteringManagement().defineRulesForUser(RECIPIENT_1_USERNAME, + Optional.empty(), + Rule.builder() + .id(Rule.Id.of("1")) + .name("rule 1") + .condition(Rule.Condition.of(FROM, CONTAINS, FRED_MARTIN_FULLNAME)) + .action(Rule.Action.of(Rule.Action.AppendInMailboxes.withMailboxIds(), + true, false, false, ImmutableList.of())) + .build())).block(); + + FakeMail mail = testSystem.asMail(mimeMessageBuilder() + .addFrom(FRED_MARTIN_FULL_SCRAMBLED_ADDRESS)); + + testSystem.getJmapFiltering().service(mail); + + assertThat(StorageDirective.fromMail(Username.of("recipient1"), mail)) + .isEqualTo(StorageDirective.builder() + .seen(Optional.of(true)) + .build()); + } + + @Test + void actionShouldSupportImportant(JMAPFilteringTestSystem testSystem) throws Exception { + Mono.from(testSystem.getFilteringManagement().defineRulesForUser(RECIPIENT_1_USERNAME, + Optional.empty(), + Rule.builder() + .id(Rule.Id.of("1")) + .name("rule 1") + .condition(Rule.Condition.of(FROM, CONTAINS, FRED_MARTIN_FULLNAME)) + .action(Rule.Action.of(Rule.Action.AppendInMailboxes.withMailboxIds(), + false, true, false, ImmutableList.of())) + .build())).block(); + + FakeMail mail = testSystem.asMail(mimeMessageBuilder() + .addFrom(FRED_MARTIN_FULL_SCRAMBLED_ADDRESS)); + + testSystem.getJmapFiltering().service(mail); + + assertThat(StorageDirective.fromMail(Username.of("recipient1"), mail)) + .isEqualTo(StorageDirective.builder() + .important(Optional.of(true)) + .build()); + } + + @Test + void actionShouldSupportKeywords(JMAPFilteringTestSystem testSystem) throws Exception { + Mono.from(testSystem.getFilteringManagement().defineRulesForUser(RECIPIENT_1_USERNAME, + Optional.empty(), + Rule.builder() + .id(Rule.Id.of("1")) + .name("rule 1") + .condition(Rule.Condition.of(FROM, CONTAINS, FRED_MARTIN_FULLNAME)) + .action(Rule.Action.of(Rule.Action.AppendInMailboxes.withMailboxIds(), + false, false, false, ImmutableList.of("abc", "def"))) + .build())).block(); + + FakeMail mail = testSystem.asMail(mimeMessageBuilder() + .addFrom(FRED_MARTIN_FULL_SCRAMBLED_ADDRESS)); + + testSystem.getJmapFiltering().service(mail); + + assertThat(StorageDirective.fromMail(Username.of("recipient1"), mail).getFlags().get().getUserFlags()) + .containsOnly("abc", "def"); + } + + @Test + void actionShouldCombineFlags(JMAPFilteringTestSystem testSystem) throws Exception { + Mono.from(testSystem.getFilteringManagement().defineRulesForUser(RECIPIENT_1_USERNAME, + Optional.empty(), + Rule.builder() + .id(Rule.Id.of("1")) + .name("rule 1") + .condition(Rule.Condition.of(FROM, CONTAINS, FRED_MARTIN_FULLNAME)) + .action(Rule.Action.of(Rule.Action.AppendInMailboxes.withMailboxIds(), + true, true, false, ImmutableList.of("abc", "def"))) + .build())).block(); + + FakeMail mail = testSystem.asMail(mimeMessageBuilder() + .addFrom(FRED_MARTIN_FULL_SCRAMBLED_ADDRESS)); + + testSystem.getJmapFiltering().service(mail); + + Flags expectedFlags = new Flags(); + expectedFlags.add("abc"); + expectedFlags.add("def"); + expectedFlags.add(Flags.Flag.SEEN); + expectedFlags.add(Flags.Flag.FLAGGED); + assertThat(StorageDirective.fromMail(Username.of("recipient1"), mail).getFlags().get()) + .isEqualTo(expectedFlags); + } } \ 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