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 bcc355b15a JAMES-4148 Webadmin route to run filtering rule on all
users (#2835)
bcc355b15a is described below
commit bcc355b15abfa3c134ba65ee600a31325c9ffe01
Author: Rene Cordier <[email protected]>
AuthorDate: Wed Oct 15 21:56:40 2025 +0700
JAMES-4148 Webadmin route to run filtering rule on all users (#2835)
---
.../modules/servers/partials/operate/webadmin.adoc | 63 +
.../james/modules/server/JmapTasksModule.java | 7 +
.../james/modules/server/MessagesRoutesModule.java | 2 +
...dminServerTaskSerializationIntegrationTest.java | 76 +
.../james/webadmin/routes/ConditionalRoute.java} | 21 +-
...Routes.java => RunRuleOnAllMailboxesRoute.java} | 116 +-
.../data/jmap/RunRulesOnMailboxRoutes.java | 24 +-
.../james/webadmin/data/jmap/dto/UserTask.java} | 28 +-
.../data/jmap/RunRulesOnMailboxRoutesTest.java | 2185 +++++++++++---------
.../james/webadmin/routes/MessagesRoutes.java | 31 +-
.../webadmin/routes/MessageRoutesExpireTest.java | 1 +
.../james/webadmin/routes/MessageRoutesTest.java | 1 +
src/site/markdown/server/manage-webadmin.md | 63 +
13 files changed, 1573 insertions(+), 1045 deletions(-)
diff --git a/docs/modules/servers/partials/operate/webadmin.adoc
b/docs/modules/servers/partials/operate/webadmin.adoc
index ccf1fdf780..0bd32faead 100644
--- a/docs/modules/servers/partials/operate/webadmin.adoc
+++ b/docs/modules/servers/partials/operate/webadmin.adoc
@@ -1537,6 +1537,69 @@ In this case you should also add the
xref:{xref-base}/configure/mailets.adoc[mai
include::{admin-messages-extend}[]
+=== Running a filtering rule on a specific mailbox for all users
+
+....
+curl -XPOST http://ip:port/messages?action=triage&mailboxName={mailboxName} \
+-d '{
+ "id": "1",
+ "name": "rule 1",
+ "action": {
+ "moveTo": {
+ "mailboxName": "Trash"
+ }
+ },
+ "conditionGroup": {
+ "conditionCombiner": "OR",
+ "conditions": [
+ {
+ "comparator": "contains",
+ "field": "subject",
+ "value": "plop"
+ },
+ {
+ "comparator": "exactly-equals",
+ "field": "from",
+ "value": "[email protected]"
+ }
+ ]
+ }
+}'
+....
+
+Will schedule a task for each user running a filtering rule passed as query
parameter in ``mailboxName`` mailbox.
+
+Query parameter `mailboxName` should not be empty, nor contain `% *`
characters, nor starting with `#`.
+If a user does not have a mailbox with that name, it will skip that user.
+
+The action of the rule should be `moveTo` with a mailbox name defined. If
mailbox ids are defined in `appendIn` action,
+it will fail, as it makes no sense cluster scoped.
+
+Response codes:
+
+* 201: Success. Map[Username, TaskId] is returned.
+* 400: Invalid mailbox name
+* 400: Invalid JSON payload (including mailbox ids defined in the action)
+* 400: mailboxName query parameter is missing
+
+The response is a map of task id per user:
+
+....
+[
+ {
+ "username": "[email protected]", "taskId":
"5641376-02ed-47bd-bcc7-76ff6262d92a"
+ },
+ {
+ "username": "[email protected]", "taskId":
"5641376-02ed-47bd-bcc7-42cc1313f47b"
+ },
+
+ [...]
+
+]
+....
+
+link:#_running_a_filtering_rule_on_a_mailbox[More details about details
returned by running a filtering rule on a mailbox].
+
== Administrating user mailboxes
=== Creating a mailbox
diff --git
a/server/container/guice/protocols/webadmin-jmap/src/main/java/org/apache/james/modules/server/JmapTasksModule.java
b/server/container/guice/protocols/webadmin-jmap/src/main/java/org/apache/james/modules/server/JmapTasksModule.java
index 08a91c9e09..65820b1713 100644
---
a/server/container/guice/protocols/webadmin-jmap/src/main/java/org/apache/james/modules/server/JmapTasksModule.java
+++
b/server/container/guice/protocols/webadmin-jmap/src/main/java/org/apache/james/modules/server/JmapTasksModule.java
@@ -24,8 +24,11 @@ import
org.apache.james.webadmin.data.jmap.PopulateEmailQueryViewRequestToTask;
import
org.apache.james.webadmin.data.jmap.PopulateFilteringProjectionRequestToTask;
import
org.apache.james.webadmin.data.jmap.RecomputeAllFastViewProjectionItemsRequestToTask;
import
org.apache.james.webadmin.data.jmap.RecomputeUserFastViewProjectionItemsRequestToTask;
+import org.apache.james.webadmin.data.jmap.RunRuleOnAllMailboxesRoute;
import org.apache.james.webadmin.data.jmap.RunRulesOnMailboxRoutes;
+import org.apache.james.webadmin.routes.ConditionalRoute;
import org.apache.james.webadmin.routes.MailboxesRoutes;
+import org.apache.james.webadmin.routes.MessagesRoutes;
import org.apache.james.webadmin.routes.UserMailboxesRoutes;
import org.apache.james.webadmin.tasks.TaskFromRequestRegistry;
@@ -52,5 +55,9 @@ public class JmapTasksModule extends AbstractModule {
Multibinder<Routes> routesMultiBinder =
Multibinder.newSetBinder(binder(), Routes.class);
routesMultiBinder.addBinding().to(RunRulesOnMailboxRoutes.class);
+
+ Multibinder.newSetBinder(binder(), ConditionalRoute.class,
Names.named(MessagesRoutes.ALL_MESSAGES_TASKS))
+ .addBinding()
+ .to(RunRuleOnAllMailboxesRoute.class);
}
}
diff --git
a/server/container/guice/protocols/webadmin-mailbox/src/main/java/org/apache/james/modules/server/MessagesRoutesModule.java
b/server/container/guice/protocols/webadmin-mailbox/src/main/java/org/apache/james/modules/server/MessagesRoutesModule.java
index 5e0ec7a515..018511d311 100644
---
a/server/container/guice/protocols/webadmin-mailbox/src/main/java/org/apache/james/modules/server/MessagesRoutesModule.java
+++
b/server/container/guice/protocols/webadmin-mailbox/src/main/java/org/apache/james/modules/server/MessagesRoutesModule.java
@@ -22,6 +22,7 @@ package org.apache.james.modules.server;
import static
org.apache.james.webadmin.tasks.TaskFromRequestRegistry.TaskRegistration;
import org.apache.james.webadmin.Routes;
+import org.apache.james.webadmin.routes.ConditionalRoute;
import org.apache.james.webadmin.routes.MessagesRoutes;
import com.google.inject.AbstractModule;
@@ -35,5 +36,6 @@ public class MessagesRoutesModule extends AbstractModule {
routesMultibinder.addBinding().to(MessagesRoutes.class);
Multibinder.newSetBinder(binder(), TaskRegistration.class,
Names.named(MessagesRoutes.ALL_MESSAGES_TASKS));
+ Multibinder.newSetBinder(binder(), ConditionalRoute.class,
Names.named(MessagesRoutes.ALL_MESSAGES_TASKS));
}
}
diff --git
a/server/protocols/webadmin-integration-test/distributed-webadmin-integration-test/src/test/java/org/apache/james/webadmin/integration/rabbitmq/RabbitMQWebAdminServerTaskSerializationIntegrationTest.java
b/server/protocols/webadmin-integration-test/distributed-webadmin-integration-test/src/test/java/org/apache/james/webadmin/integration/rabbitmq/RabbitMQWebAdminServerTaskSerializationIntegrationTest.java
index cc5933b40d..ea01f9eb62 100644
---
a/server/protocols/webadmin-integration-test/distributed-webadmin-integration-test/src/test/java/org/apache/james/webadmin/integration/rabbitmq/RabbitMQWebAdminServerTaskSerializationIntegrationTest.java
+++
b/server/protocols/webadmin-integration-test/distributed-webadmin-integration-test/src/test/java/org/apache/james/webadmin/integration/rabbitmq/RabbitMQWebAdminServerTaskSerializationIntegrationTest.java
@@ -25,6 +25,8 @@ import static io.restassured.RestAssured.with;
import static org.apache.james.webadmin.Constants.SEPARATOR;
import static
org.apache.james.webadmin.vault.routes.DeletedMessagesVaultRoutes.MESSAGE_PATH_PARAM;
import static
org.apache.james.webadmin.vault.routes.DeletedMessagesVaultRoutes.USERS;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.eclipse.jetty.http.HttpStatus.CREATED_201;
import static org.hamcrest.CoreMatchers.notNullValue;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.nullValue;
@@ -32,6 +34,8 @@ import static
org.hamcrest.collection.IsMapWithSize.anEmptyMap;
import java.io.ByteArrayInputStream;
import java.util.Date;
+import java.util.List;
+import java.util.Map;
import java.util.stream.Stream;
import jakarta.mail.Flags;
@@ -86,6 +90,7 @@ import
org.apache.james.webadmin.vault.routes.DeletedMessagesVaultRoutes;
import org.eclipse.jetty.http.HttpStatus;
import org.hamcrest.Matchers;
import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Tag;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;
@@ -118,6 +123,7 @@ class
RabbitMQWebAdminServerTaskSerializationIntegrationTest {
private static final String DOMAIN = "domain";
private static final String USERNAME = "username@" + DOMAIN;
+ private static final String USERNAME_2 = "username2@" + DOMAIN;
private DataProbe dataProbe;
private MailboxProbe mailboxProbe;
@@ -774,6 +780,76 @@ class
RabbitMQWebAdminServerTaskSerializationIntegrationTest {
.body("additionalInformation.mailboxName",
is(MailboxConstants.INBOX));
}
+ @Disabled("JAMES-4148: Route not plugged yet")
+ @Test
+ void runRulesOnAllUsersMailboxShouldComplete(GuiceJamesServer server)
throws Exception {
+ server.getProbe(DataProbeImpl.class).addUser(USERNAME, "secret");
+ server.getProbe(DataProbeImpl.class).addUser(USERNAME_2, "secret");
+ mailboxProbe.createMailbox(MailboxConstants.USER_NAMESPACE, USERNAME,
MailboxConstants.INBOX);
+ mailboxProbe.createMailbox(MailboxConstants.USER_NAMESPACE, USERNAME,
"otherMailbox");
+ mailboxProbe.createMailbox(MailboxConstants.USER_NAMESPACE,
USERNAME_2, MailboxConstants.INBOX);
+ mailboxProbe.createMailbox(MailboxConstants.USER_NAMESPACE,
USERNAME_2, "otherMailbox");
+
+ mailboxProbe.appendMessage(
+ USERNAME,
+ MailboxPath.inbox(Username.of(USERNAME)),
+ new ByteArrayInputStream("Subject:
test\r\n\r\ntestmail".getBytes()),
+ new Date(),
+ false,
+ new Flags());
+
+ mailboxProbe.appendMessage(
+ USERNAME_2,
+ MailboxPath.inbox(Username.of(USERNAME_2)),
+ new ByteArrayInputStream("Subject:
test\r\n\r\ntestmail".getBytes()),
+ new Date(),
+ false,
+ new Flags());
+
+ List<Map<String, String>> list = given()
+ .queryParams("action", "triage", "mailboxName",
MailboxConstants.INBOX)
+ .body("""
+ {
+ "id": "1",
+ "name": "rule 1",
+ "action": {
+ "appendIn": {
+ "mailboxIds": []
+ },
+ "moveTo": {
+ "mailboxName": "otherMailbox"
+ },
+ "important": false,
+ "keyworkds": [],
+ "reject": false,
+ "seen": false
+ },
+ "conditionGroup": {
+ "conditionCombiner": "AND",
+ "conditions": [
+ {
+ "comparator": "contains",
+ "field": "subject",
+ "value": "test"
+ }
+ ]
+ }
+ }""")
+ .post("/messages")
+ .then()
+ .statusCode(CREATED_201)
+ .extract()
+ .jsonPath()
+ .getList(".");
+
+ assertThat(list)
+ .hasSize(3)
+ .first()
+ .satisfies(map -> assertThat(map).hasSize(2)
+ .containsKeys("taskId")
+ .containsEntry("username", USERNAME));
+ }
+
@Test
void cleanUploadRepositoryShouldComplete() throws Exception {
String taskId = given()
diff --git
a/server/container/guice/protocols/webadmin-mailbox/src/main/java/org/apache/james/modules/server/MessagesRoutesModule.java
b/server/protocols/webadmin/webadmin-core/src/main/java/org/apache/james/webadmin/routes/ConditionalRoute.java
similarity index 61%
copy from
server/container/guice/protocols/webadmin-mailbox/src/main/java/org/apache/james/modules/server/MessagesRoutesModule.java
copy to
server/protocols/webadmin/webadmin-core/src/main/java/org/apache/james/webadmin/routes/ConditionalRoute.java
index 5e0ec7a515..92eef046b3 100644
---
a/server/container/guice/protocols/webadmin-mailbox/src/main/java/org/apache/james/modules/server/MessagesRoutesModule.java
+++
b/server/protocols/webadmin/webadmin-core/src/main/java/org/apache/james/webadmin/routes/ConditionalRoute.java
@@ -17,23 +17,12 @@
* under the License. *
****************************************************************/
-package org.apache.james.modules.server;
+package org.apache.james.webadmin.routes;
-import static
org.apache.james.webadmin.tasks.TaskFromRequestRegistry.TaskRegistration;
+import java.util.function.Predicate;
-import org.apache.james.webadmin.Routes;
-import org.apache.james.webadmin.routes.MessagesRoutes;
+import spark.Request;
+import spark.Route;
-import com.google.inject.AbstractModule;
-import com.google.inject.multibindings.Multibinder;
-import com.google.inject.name.Names;
-
-public class MessagesRoutesModule extends AbstractModule {
- @Override
- protected void configure() {
- Multibinder<Routes> routesMultibinder =
Multibinder.newSetBinder(binder(), Routes.class);
- routesMultibinder.addBinding().to(MessagesRoutes.class);
-
- Multibinder.newSetBinder(binder(), TaskRegistration.class,
Names.named(MessagesRoutes.ALL_MESSAGES_TASKS));
- }
+public interface ConditionalRoute extends Route, Predicate<Request> {
}
diff --git
a/server/protocols/webadmin/webadmin-jmap/src/main/java/org/apache/james/webadmin/data/jmap/RunRulesOnMailboxRoutes.java
b/server/protocols/webadmin/webadmin-jmap/src/main/java/org/apache/james/webadmin/data/jmap/RunRuleOnAllMailboxesRoute.java
similarity index 55%
copy from
server/protocols/webadmin/webadmin-jmap/src/main/java/org/apache/james/webadmin/data/jmap/RunRulesOnMailboxRoutes.java
copy to
server/protocols/webadmin/webadmin-jmap/src/main/java/org/apache/james/webadmin/data/jmap/RunRuleOnAllMailboxesRoute.java
index 8d183b4597..15c01c64e8 100644
---
a/server/protocols/webadmin/webadmin-jmap/src/main/java/org/apache/james/webadmin/data/jmap/RunRulesOnMailboxRoutes.java
+++
b/server/protocols/webadmin/webadmin-jmap/src/main/java/org/apache/james/webadmin/data/jmap/RunRuleOnAllMailboxesRoute.java
@@ -19,27 +19,27 @@
package org.apache.james.webadmin.data.jmap;
-import static org.apache.james.webadmin.Constants.SEPARATOR;
+import java.util.List;
+import java.util.Optional;
import jakarta.inject.Inject;
import org.apache.james.core.Username;
+import org.apache.james.jmap.api.filtering.Rule;
import org.apache.james.jmap.api.filtering.RuleDTO;
import org.apache.james.jmap.api.filtering.Rules;
import org.apache.james.jmap.api.filtering.Version;
import org.apache.james.mailbox.MailboxManager;
import org.apache.james.mailbox.MailboxSession;
-import org.apache.james.mailbox.exception.MailboxException;
import org.apache.james.mailbox.model.MailboxPath;
import org.apache.james.task.Task;
+import org.apache.james.task.TaskId;
import org.apache.james.task.TaskManager;
import org.apache.james.user.api.UsersRepository;
-import org.apache.james.user.api.UsersRepositoryException;
-import org.apache.james.webadmin.Routes;
-import org.apache.james.webadmin.tasks.TaskFromRequestRegistry;
+import org.apache.james.webadmin.data.jmap.dto.UserTask;
+import org.apache.james.webadmin.routes.ConditionalRoute;
import org.apache.james.webadmin.tasks.TaskRegistrationKey;
import org.apache.james.webadmin.utils.ErrorResponder;
-import org.apache.james.webadmin.utils.JsonTransformer;
import org.apache.james.webadmin.validation.MailboxName;
import org.eclipse.jetty.http.HttpStatus;
import org.slf4j.Logger;
@@ -49,82 +49,66 @@ import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.guava.GuavaModule;
import com.fasterxml.jackson.datatype.jdk8.Jdk8Module;
-import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
+import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import spark.Request;
-import spark.Route;
-import spark.Service;
+import spark.Response;
-public class RunRulesOnMailboxRoutes implements Routes {
+public class RunRuleOnAllMailboxesRoute implements ConditionalRoute {
private static final Logger LOGGER =
LoggerFactory.getLogger(RunRulesOnMailboxRoutes.class);
private static final TaskRegistrationKey TRIAGE =
TaskRegistrationKey.of("triage");
- private static final String MAILBOX_NAME = ":mailboxName";
- private static final String MAILBOXES = "mailboxes";
- private static final String USER_NAME = ":userName";
- private static final String USERS_BASE = "/users";
- public static final String USER_MAILBOXES_BASE = USERS_BASE + SEPARATOR +
USER_NAME + SEPARATOR + MAILBOXES;
- public static final String SPECIFIC_MAILBOX = USER_MAILBOXES_BASE +
SEPARATOR + MAILBOX_NAME;
- public static final String MESSAGES_PATH = SPECIFIC_MAILBOX + "/messages";
+ private static final String ACTION_QUERY_PARAM = "action";
+ private static final String MAILBOX_NAME_QUERY_PARAM = "mailboxName";
private final UsersRepository usersRepository;
private final MailboxManager mailboxManager;
private final RunRulesOnMailboxService runRulesOnMailboxService;
- private final JsonTransformer jsonTransformer;
private final TaskManager taskManager;
private final ObjectMapper jsonDeserialize;
@Inject
- RunRulesOnMailboxRoutes(UsersRepository usersRepository,
- MailboxManager mailboxManager,
- TaskManager taskManager,
- JsonTransformer jsonTransformer,
- RunRulesOnMailboxService runRulesOnMailboxService)
{
+ public RunRuleOnAllMailboxesRoute(UsersRepository usersRepository,
MailboxManager mailboxManager, RunRulesOnMailboxService
runRulesOnMailboxService, TaskManager taskManager) {
this.usersRepository = usersRepository;
this.mailboxManager = mailboxManager;
- this.taskManager = taskManager;
- this.jsonTransformer = jsonTransformer;
this.runRulesOnMailboxService = runRulesOnMailboxService;
+ this.taskManager = taskManager;
+
this.jsonDeserialize = new ObjectMapper()
.registerModule(new Jdk8Module())
.registerModule(new GuavaModule());
}
@Override
- public String getBasePath() {
- return USER_MAILBOXES_BASE;
+ public boolean test(Request request) {
+ return Optional.ofNullable(request.queryParams(ACTION_QUERY_PARAM))
+ .map(TRIAGE.asString()::equalsIgnoreCase)
+ .orElse(false);
}
@Override
- public void define(Service service) {
- service.post(MESSAGES_PATH, runRulesOnMailboxRoute(), jsonTransformer);
+ public Object handle(Request request, Response response) throws Exception {
+ return runRulesOnAllUsersMailbox(request, response);
}
- public Route runRulesOnMailboxRoute() {
- return TaskFromRequestRegistry.builder()
- .parameterName("action")
- .register(TRIAGE, this::runRulesOnMailbox)
- .buildAsRoute(taskManager);
- }
-
- public Task runRulesOnMailbox(Request request) throws
UsersRepositoryException, MailboxException {
- Username username = getUsernameParam(request);
- MailboxName mailboxName = new
MailboxName(request.params(MAILBOX_NAME));
+ public List<UserTask> runRulesOnAllUsersMailbox(Request request, Response
response) {
try {
- usernamePreconditions(username);
- mailboxExistPreconditions(username, mailboxName);
+ actionPrecondition(request);
+ MailboxName mailboxName = getMailboxNameQueryParam(request);
RuleDTO ruleDTO = jsonDeserialize.readValue(request.body(),
RuleDTO.class);
Rules rules = new
Rules(RuleDTO.toRules(ImmutableList.of(ruleDTO)), Version.INITIAL);
+ rulesPrecondition(rules);
- return new RunRulesOnMailboxTask(username, mailboxName, rules,
runRulesOnMailboxService);
+ response.status(HttpStatus.CREATED_201);
+ return runRulesOnAllUsersMailbox(mailboxName, rules);
} catch (IllegalStateException e) {
- LOGGER.info("Invalid argument on user mailboxes", e);
+ LOGGER.info("Invalid argument on /messages", e);
throw ErrorResponder.builder()
.statusCode(HttpStatus.NOT_FOUND_404)
.type(ErrorResponder.ErrorType.NOT_FOUND)
- .message("Invalid argument on user mailboxes")
+ .message("Invalid argument on /messages")
.cause(e)
.haltError();
} catch (JsonProcessingException e) {
@@ -137,20 +121,44 @@ public class RunRulesOnMailboxRoutes implements Routes {
}
}
- private Username getUsernameParam(Request request) {
- return Username.of(request.params(USER_NAME));
+ private List<UserTask> runRulesOnAllUsersMailbox(MailboxName mailboxName,
Rules rules) {
+ return Flux.from(usersRepository.listReactive())
+ .filterWhen(username -> mailboxForUserExists(username,
mailboxName))
+ .map(username -> runRulesOnUserMailbox(username, mailboxName,
rules))
+ .collectList()
+ .block();
}
- private void usernamePreconditions(Username username) throws
UsersRepositoryException {
- Preconditions.checkState(usersRepository.contains(username), "User
does not exist");
+ private UserTask runRulesOnUserMailbox(Username username, MailboxName
mailboxName, Rules rules) {
+ Task task = new RunRulesOnMailboxTask(username, mailboxName, rules,
runRulesOnMailboxService);
+ TaskId taskId = taskManager.submit(task);
+ return new UserTask(username, taskId);
}
- private void mailboxExistPreconditions(Username username, MailboxName
mailboxName) throws MailboxException {
+ private void actionPrecondition(Request request) {
+ if (!test(request)) {
+ throw new IllegalArgumentException("'action' query parameter is
compulsory. Supported values are [triage]");
+ }
+ }
+
+ private MailboxName getMailboxNameQueryParam(Request request) {
+ return
Optional.ofNullable(request.queryParams(MAILBOX_NAME_QUERY_PARAM))
+ .map(MailboxName::new)
+ .orElseThrow(() -> new IllegalArgumentException("mailboxName query
param is missing"));
+ }
+
+ private Mono<Boolean> mailboxForUserExists(Username username, MailboxName
mailboxName) {
MailboxSession mailboxSession =
mailboxManager.createSystemSession(username);
- MailboxPath mailboxPath = MailboxPath.forUser(username,
mailboxName.asString())
- .assertAcceptable(mailboxSession.getPathDelimiter());
-
Preconditions.checkState(Boolean.TRUE.equals(Mono.from(mailboxManager.mailboxExists(mailboxPath,
mailboxSession)).block()),
- "Mailbox does not exist. " + mailboxPath.asString());
- mailboxManager.endProcessingRequest(mailboxSession);
+ MailboxPath mailboxPath = MailboxPath.forUser(username,
mailboxName.asString());
+ return Mono.from(mailboxManager.mailboxExists(mailboxPath,
mailboxSession));
+ }
+
+ private void rulesPrecondition(Rules rules) {
+ if (rules.getRules()
+ .stream()
+ .map(Rule::getAction)
+ .anyMatch(action ->
!action.getAppendInMailboxes().getMailboxIds().isEmpty())) {
+ throw new IllegalArgumentException("Rule payload should not have
[appendInMailboxes] action defined for runRulesOnAllUsersMailbox route");
+ }
}
}
diff --git
a/server/protocols/webadmin/webadmin-jmap/src/main/java/org/apache/james/webadmin/data/jmap/RunRulesOnMailboxRoutes.java
b/server/protocols/webadmin/webadmin-jmap/src/main/java/org/apache/james/webadmin/data/jmap/RunRulesOnMailboxRoutes.java
index 8d183b4597..084bafd78b 100644
---
a/server/protocols/webadmin/webadmin-jmap/src/main/java/org/apache/james/webadmin/data/jmap/RunRulesOnMailboxRoutes.java
+++
b/server/protocols/webadmin/webadmin-jmap/src/main/java/org/apache/james/webadmin/data/jmap/RunRulesOnMailboxRoutes.java
@@ -21,6 +21,8 @@ package org.apache.james.webadmin.data.jmap;
import static org.apache.james.webadmin.Constants.SEPARATOR;
+import java.util.Optional;
+
import jakarta.inject.Inject;
import org.apache.james.core.Username;
@@ -49,6 +51,7 @@ import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.guava.GuavaModule;
import com.fasterxml.jackson.datatype.jdk8.Jdk8Module;
+import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
@@ -61,13 +64,15 @@ public class RunRulesOnMailboxRoutes implements Routes {
private static final Logger LOGGER =
LoggerFactory.getLogger(RunRulesOnMailboxRoutes.class);
private static final TaskRegistrationKey TRIAGE =
TaskRegistrationKey.of("triage");
+ private static final String ACTION_QUERY_PARAM = "action";
private static final String MAILBOX_NAME = ":mailboxName";
private static final String MAILBOXES = "mailboxes";
private static final String USER_NAME = ":userName";
private static final String USERS_BASE = "/users";
public static final String USER_MAILBOXES_BASE = USERS_BASE + SEPARATOR +
USER_NAME + SEPARATOR + MAILBOXES;
public static final String SPECIFIC_MAILBOX = USER_MAILBOXES_BASE +
SEPARATOR + MAILBOX_NAME;
- public static final String MESSAGES_PATH = SPECIFIC_MAILBOX + "/messages";
+ public static final String MESSAGES_BASE = "/messages";
+ public static final String MESSAGES_PATH = SPECIFIC_MAILBOX +
MESSAGES_BASE;
private final UsersRepository usersRepository;
private final MailboxManager mailboxManager;
@@ -75,6 +80,7 @@ public class RunRulesOnMailboxRoutes implements Routes {
private final JsonTransformer jsonTransformer;
private final TaskManager taskManager;
private final ObjectMapper jsonDeserialize;
+ private final Optional<RunRuleOnAllMailboxesRoute> allMailboxesRoute;
@Inject
RunRulesOnMailboxRoutes(UsersRepository usersRepository,
@@ -82,6 +88,16 @@ public class RunRulesOnMailboxRoutes implements Routes {
TaskManager taskManager,
JsonTransformer jsonTransformer,
RunRulesOnMailboxService runRulesOnMailboxService)
{
+ this(usersRepository, mailboxManager, taskManager, jsonTransformer,
runRulesOnMailboxService, Optional.empty());
+ }
+
+ @VisibleForTesting
+ RunRulesOnMailboxRoutes(UsersRepository usersRepository,
+ MailboxManager mailboxManager,
+ TaskManager taskManager,
+ JsonTransformer jsonTransformer,
+ RunRulesOnMailboxService runRulesOnMailboxService,
+ Optional<RunRuleOnAllMailboxesRoute>
allMailboxesRoute) {
this.usersRepository = usersRepository;
this.mailboxManager = mailboxManager;
this.taskManager = taskManager;
@@ -90,6 +106,7 @@ public class RunRulesOnMailboxRoutes implements Routes {
this.jsonDeserialize = new ObjectMapper()
.registerModule(new Jdk8Module())
.registerModule(new GuavaModule());
+ this.allMailboxesRoute = allMailboxesRoute;
}
@Override
@@ -100,11 +117,14 @@ public class RunRulesOnMailboxRoutes implements Routes {
@Override
public void define(Service service) {
service.post(MESSAGES_PATH, runRulesOnMailboxRoute(), jsonTransformer);
+
+ // TESTING only
+ allMailboxesRoute.ifPresent(route -> service.post(MESSAGES_BASE,
route, jsonTransformer));
}
public Route runRulesOnMailboxRoute() {
return TaskFromRequestRegistry.builder()
- .parameterName("action")
+ .parameterName(ACTION_QUERY_PARAM)
.register(TRIAGE, this::runRulesOnMailbox)
.buildAsRoute(taskManager);
}
diff --git
a/server/container/guice/protocols/webadmin-mailbox/src/main/java/org/apache/james/modules/server/MessagesRoutesModule.java
b/server/protocols/webadmin/webadmin-jmap/src/main/java/org/apache/james/webadmin/data/jmap/dto/UserTask.java
similarity index 61%
copy from
server/container/guice/protocols/webadmin-mailbox/src/main/java/org/apache/james/modules/server/MessagesRoutesModule.java
copy to
server/protocols/webadmin/webadmin-jmap/src/main/java/org/apache/james/webadmin/data/jmap/dto/UserTask.java
index 5e0ec7a515..fce96f17a3 100644
---
a/server/container/guice/protocols/webadmin-mailbox/src/main/java/org/apache/james/modules/server/MessagesRoutesModule.java
+++
b/server/protocols/webadmin/webadmin-jmap/src/main/java/org/apache/james/webadmin/data/jmap/dto/UserTask.java
@@ -17,23 +17,25 @@
* under the License. *
****************************************************************/
-package org.apache.james.modules.server;
+package org.apache.james.webadmin.data.jmap.dto;
-import static
org.apache.james.webadmin.tasks.TaskFromRequestRegistry.TaskRegistration;
+import org.apache.james.core.Username;
+import org.apache.james.task.TaskId;
-import org.apache.james.webadmin.Routes;
-import org.apache.james.webadmin.routes.MessagesRoutes;
+public class UserTask {
+ private final Username username;
+ private final TaskId taskId;
-import com.google.inject.AbstractModule;
-import com.google.inject.multibindings.Multibinder;
-import com.google.inject.name.Names;
+ public UserTask(Username username, TaskId taskId) {
+ this.username = username;
+ this.taskId = taskId;
+ }
-public class MessagesRoutesModule extends AbstractModule {
- @Override
- protected void configure() {
- Multibinder<Routes> routesMultibinder =
Multibinder.newSetBinder(binder(), Routes.class);
- routesMultibinder.addBinding().to(MessagesRoutes.class);
+ public String getUsername() {
+ return username.asString();
+ }
- Multibinder.newSetBinder(binder(), TaskRegistration.class,
Names.named(MessagesRoutes.ALL_MESSAGES_TASKS));
+ public String getTaskId() {
+ return taskId.asString();
}
}
diff --git
a/server/protocols/webadmin/webadmin-jmap/src/test/java/org/apache/james/webadmin/data/jmap/RunRulesOnMailboxRoutesTest.java
b/server/protocols/webadmin/webadmin-jmap/src/test/java/org/apache/james/webadmin/data/jmap/RunRulesOnMailboxRoutesTest.java
index 1111ea9d97..71ca7a9bf3 100644
---
a/server/protocols/webadmin/webadmin-jmap/src/test/java/org/apache/james/webadmin/data/jmap/RunRulesOnMailboxRoutesTest.java
+++
b/server/protocols/webadmin/webadmin-jmap/src/test/java/org/apache/james/webadmin/data/jmap/RunRulesOnMailboxRoutesTest.java
@@ -35,7 +35,9 @@ import java.nio.charset.StandardCharsets;
import java.time.Clock;
import java.time.Duration;
import java.util.Date;
+import java.util.List;
import java.util.Map;
+import java.util.Optional;
import java.util.stream.IntStream;
import jakarta.mail.Flags;
@@ -67,14 +69,20 @@ import org.assertj.core.api.SoftAssertions;
import org.hamcrest.Matchers;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Disabled;
+import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import com.github.fge.lambdas.Throwing;
+import com.google.common.collect.ImmutableList;
import io.restassured.RestAssured;
+import reactor.core.publisher.Flux;
public class RunRulesOnMailboxRoutesTest {
private static final Username USERNAME = Username.of("username");
+ private static final Username BOB = Username.of("bob");
+ private static final Username ALICE = Username.of("alice");
private static final String MAILBOX_NAME = "myMailboxName";
private static final String OTHER_MAILBOX_NAME = "myOtherMailboxName";
private static final String MOVE_TO_MAILBOX_NAME = "moveToMailbox";
@@ -110,14 +118,46 @@ public class RunRulesOnMailboxRoutesTest {
}
}""";
+ private static final String RULE_MOVE_TO_PAYLOAD = """
+ {
+ "id": "1",
+ "name": "rule 1",
+ "action": {
+ "appendIn": {
+ "mailboxIds": []
+ },
+ "moveTo": {
+ "mailboxName": "%s"
+ },
+ "important": false,
+ "keyworkds": [],
+ "reject": false,
+ "seen": false
+ },
+ "conditionGroup": {
+ "conditionCombiner": "OR",
+ "conditions": [
+ {
+ "comparator": "contains",
+ "field": "subject",
+ "value": "plop"
+ },
+ {
+ "comparator": "exactly-equals",
+ "field": "from",
+ "value": "[email protected]"
+ }
+ ]
+ }
+ }""";
+
private WebAdminServer webAdminServer;
private UsersRepository usersRepository;
private MemoryTaskManager taskManager;
private InMemoryMailboxManager mailboxManager;
MessageIdManager messageIdManager;
- @BeforeEach
- void setUp() throws Exception {
+ private void createServer(String path) throws Exception {
InMemoryIntegrationResources resources =
InMemoryIntegrationResources.builder()
.preProvisionnedFakeAuthenticator()
.fakeAuthorizator()
@@ -137,15 +177,16 @@ public class RunRulesOnMailboxRoutesTest {
taskManager = new MemoryTaskManager(new Hostname("foo"));
+ RunRulesOnMailboxService service = new
RunRulesOnMailboxService(mailboxManager, new InMemoryId.Factory(),
messageIdManager);
webAdminServer = WebAdminUtils.createWebAdminServer(
- new RunRulesOnMailboxRoutes(usersRepository, mailboxManager,
taskManager, new JsonTransformer(),
- new RunRulesOnMailboxService(mailboxManager, new
InMemoryId.Factory(), messageIdManager)),
+ new RunRulesOnMailboxRoutes(usersRepository, mailboxManager,
taskManager, new JsonTransformer(), service,
+ Optional.of(new
RunRuleOnAllMailboxesRoute(usersRepository, mailboxManager, service,
taskManager))),
new TasksRoutes(taskManager, new JsonTransformer(),
DTOConverter.of(RunRulesOnMailboxTaskAdditionalInformationDTO.SERIALIZATION_MODULE)))
.start();
RestAssured.requestSpecification =
WebAdminUtils.buildRequestSpecification(webAdminServer)
- .setBasePath(USERS_BASE + SEPARATOR + USERNAME.asString() +
SEPARATOR + UserMailboxesRoutes.MAILBOXES)
+ .setBasePath(path)
.setUrlEncodingEnabled(false) // no further automatically encoding
by Rest Assured client. rf:
https://issues.apache.org/jira/projects/JAMES/issues/JAMES-3936
.build();
}
@@ -156,774 +197,730 @@ public class RunRulesOnMailboxRoutesTest {
taskManager.stop();
}
- @Test
- void runRulesOnMailboxShouldReturnErrorWhenUserIsNotFound() throws
UsersRepositoryException {
- when(usersRepository.contains(USERNAME)).thenReturn(false);
-
- Map<String, Object> errors = given()
- .queryParam("action", "triage")
- .body(RULE_PAYLOAD.formatted("2"))
- .post(MAILBOX_NAME + "/messages")
- .then()
- .statusCode(NOT_FOUND_404)
- .contentType(JSON)
- .extract()
- .body()
- .jsonPath()
- .getMap(".");
-
- assertThat(errors)
- .containsEntry("statusCode", NOT_FOUND_404)
- .containsEntry("type", ERROR_TYPE_NOTFOUND)
- .containsEntry("message", "Invalid argument on user mailboxes")
- .containsEntry("details", "User does not exist");
- }
-
- @Test
- void runRulesOnMailboxShouldReturnErrorWhenMailboxDoesNotExist() throws
UsersRepositoryException {
- Map<String, Object> errors = given()
- .queryParam("action", "triage")
- .body(RULE_PAYLOAD.formatted("2"))
- .post(MAILBOX_NAME + "/messages")
- .then()
- .statusCode(NOT_FOUND_404)
- .contentType(JSON)
- .extract()
- .body()
- .jsonPath()
- .getMap(".");
-
- assertThat(errors)
- .containsEntry("statusCode", NOT_FOUND_404)
- .containsEntry("type", ERROR_TYPE_NOTFOUND)
- .containsEntry("message", "Invalid argument on user mailboxes")
- .containsEntry("details", String.format("Mailbox does not exist.
#private:%s:%s", USERNAME.asString(), MAILBOX_NAME));
- }
-
- @Test
- void runRulesOnMailboxShouldReturnErrorWhenNoPayload() throws
MailboxException {
- MailboxSession systemSession =
mailboxManager.createSystemSession(USERNAME);
- MailboxPath mailboxPath = MailboxPath.forUser(USERNAME, MAILBOX_NAME);
- mailboxManager.createMailbox(mailboxPath, systemSession);
-
- Map<String, Object> errors = given()
- .queryParam("action", "triage")
- .post(MAILBOX_NAME + "/messages")
- .then()
- .statusCode(BAD_REQUEST_400)
- .contentType(JSON)
- .extract()
- .body()
- .jsonPath()
- .getMap(".");
-
- assertThat(errors)
- .containsEntry("statusCode", BAD_REQUEST_400)
- .containsEntry("type", ERROR_TYPE_INVALIDARGUMENT)
- .containsEntry("message", "JSON payload of the request is not
valid");
- }
-
- @Test
- void runRulesOnMailboxShouldReturnErrorWhenBadPayload() throws
MailboxException {
- MailboxSession systemSession =
mailboxManager.createSystemSession(USERNAME);
- MailboxPath mailboxPath = MailboxPath.forUser(USERNAME, MAILBOX_NAME);
- mailboxManager.createMailbox(mailboxPath, systemSession);
-
- Map<String, Object> errors = given()
- .queryParam("action", "triage")
- .body("""
+ @Nested
+ class RunRulesOnMailbox {
+ @BeforeEach
+ void setUp() throws Exception {
+ createServer(USERS_BASE + SEPARATOR + USERNAME.asString() +
SEPARATOR + UserMailboxesRoutes.MAILBOXES);
+ }
+
+ @Test
+ void runRulesOnMailboxShouldReturnErrorWhenUserIsNotFound() throws
UsersRepositoryException {
+ when(usersRepository.contains(USERNAME)).thenReturn(false);
+
+ Map<String, Object> errors = given()
+ .queryParam("action", "triage")
+ .body(RULE_PAYLOAD.formatted("2"))
+ .post(MAILBOX_NAME + "/messages")
+ .then()
+ .statusCode(NOT_FOUND_404)
+ .contentType(JSON)
+ .extract()
+ .body()
+ .jsonPath()
+ .getMap(".");
+
+ assertThat(errors)
+ .containsEntry("statusCode", NOT_FOUND_404)
+ .containsEntry("type", ERROR_TYPE_NOTFOUND)
+ .containsEntry("message", "Invalid argument on user mailboxes")
+ .containsEntry("details", "User does not exist");
+ }
+
+ @Test
+ void runRulesOnMailboxShouldReturnErrorWhenActionQueryParamIsMissing()
throws UsersRepositoryException {
+ Map<String, Object> errors = given()
+ .body(RULE_PAYLOAD.formatted("2"))
+ .post(MAILBOX_NAME + "/messages")
+ .then()
+ .statusCode(BAD_REQUEST_400)
+ .contentType(JSON)
+ .extract()
+ .body()
+ .jsonPath()
+ .getMap(".");
+
+ assertThat(errors)
+ .containsEntry("statusCode", BAD_REQUEST_400)
+ .containsEntry("type", ERROR_TYPE_INVALIDARGUMENT)
+ .containsEntry("message", "Invalid arguments supplied in the
user request")
+ .containsEntry("details", "'action' query parameter is
compulsory. Supported values are [triage]");
+ }
+
+ @Test
+ void runRulesOnMailboxShouldReturnErrorWhenMailboxDoesNotExist()
throws UsersRepositoryException {
+ Map<String, Object> errors = given()
+ .queryParam("action", "triage")
+ .body(RULE_PAYLOAD.formatted("2"))
+ .post(MAILBOX_NAME + "/messages")
+ .then()
+ .statusCode(NOT_FOUND_404)
+ .contentType(JSON)
+ .extract()
+ .body()
+ .jsonPath()
+ .getMap(".");
+
+ assertThat(errors)
+ .containsEntry("statusCode", NOT_FOUND_404)
+ .containsEntry("type", ERROR_TYPE_NOTFOUND)
+ .containsEntry("message", "Invalid argument on user mailboxes")
+ .containsEntry("details", String.format("Mailbox does not
exist. #private:%s:%s", USERNAME.asString(), MAILBOX_NAME));
+ }
+
+ @Test
+ void runRulesOnMailboxShouldReturnErrorWhenNoPayload() throws
MailboxException {
+ MailboxSession systemSession =
mailboxManager.createSystemSession(USERNAME);
+ MailboxPath mailboxPath = MailboxPath.forUser(USERNAME,
MAILBOX_NAME);
+ mailboxManager.createMailbox(mailboxPath, systemSession);
+
+ Map<String, Object> errors = given()
+ .queryParam("action", "triage")
+ .post(MAILBOX_NAME + "/messages")
+ .then()
+ .statusCode(BAD_REQUEST_400)
+ .contentType(JSON)
+ .extract()
+ .body()
+ .jsonPath()
+ .getMap(".");
+
+ assertThat(errors)
+ .containsEntry("statusCode", BAD_REQUEST_400)
+ .containsEntry("type", ERROR_TYPE_INVALIDARGUMENT)
+ .containsEntry("message", "JSON payload of the request is not
valid");
+ }
+
+ @Test
+ void runRulesOnMailboxShouldReturnErrorWhenBadPayload() throws
MailboxException {
+ MailboxSession systemSession =
mailboxManager.createSystemSession(USERNAME);
+ MailboxPath mailboxPath = MailboxPath.forUser(USERNAME,
MAILBOX_NAME);
+ mailboxManager.createMailbox(mailboxPath, systemSession);
+
+ Map<String, Object> errors = given()
+ .queryParam("action", "triage")
+ .body("""
{
"id": "1",
"name": "rule 1",
"condition": bad condition",
"action": "bad action"
}""")
- .post(MAILBOX_NAME + "/messages")
- .then()
- .statusCode(BAD_REQUEST_400)
- .contentType(JSON)
- .extract()
- .body()
- .jsonPath()
- .getMap(".");
-
- assertThat(errors)
- .containsEntry("statusCode", BAD_REQUEST_400)
- .containsEntry("type", ERROR_TYPE_INVALIDARGUMENT)
- .containsEntry("message", "JSON payload of the request is not
valid");
- }
-
- @Test
- void runRulesOnMailboxShouldReturnTaskId() throws MailboxException {
- MailboxSession systemSession =
mailboxManager.createSystemSession(USERNAME);
- MailboxPath mailboxPath = MailboxPath.forUser(USERNAME, MAILBOX_NAME);
- mailboxManager.createMailbox(mailboxPath, systemSession);
-
- String taskId = given()
- .queryParam("action", "triage")
- .body(RULE_PAYLOAD.formatted("2"))
- .post(MAILBOX_NAME + "/messages")
- .then()
- .statusCode(CREATED_201)
- .extract()
- .jsonPath()
- .get("taskId");
-
- assertThat(taskId)
- .isNotEmpty();
- }
-
- @Test
- void runRulesOnMailboxShouldMoveMatchingMessage() throws Exception {
- MailboxPath mailboxPath = MailboxPath.forUser(USERNAME, MAILBOX_NAME);
- MailboxPath otherMailboxPath = MailboxPath.forUser(USERNAME,
OTHER_MAILBOX_NAME);
- MailboxSession systemSession =
mailboxManager.createSystemSession(USERNAME);
-
- mailboxManager.createMailbox(mailboxPath, systemSession);
- mailboxManager.createMailbox(otherMailboxPath, systemSession);
-
- mailboxManager.getMailbox(mailboxPath, systemSession)
- .appendMessage(MessageManager.AppendCommand.builder()
- .build(Message.Builder.of()
- .setSubject("plop")
- .setFrom("[email protected]")
- .setBody("body", StandardCharsets.UTF_8)),
- systemSession);
-
- MailboxId otherMailboxId = mailboxManager.getMailbox(otherMailboxPath,
systemSession).getId();
-
- String taskId = given()
- .queryParam("action", "triage")
- .body(RULE_PAYLOAD.formatted(otherMailboxId.serialize()))
- .post(MAILBOX_NAME + "/messages")
- .then()
- .statusCode(CREATED_201)
- .extract()
- .jsonPath()
- .get("taskId");
-
- given()
- .basePath(TasksRoutes.BASE)
- .when()
- .get(taskId + "/await");
-
- SoftAssertions.assertSoftly(
- softly -> {
- softly.assertThat(Throwing.supplier(() ->
mailboxManager.getMailbox(mailboxPath,
systemSession).getMailboxCounters(systemSession).getCount()).get())
- .isEqualTo(0);
- softly.assertThat(Throwing.supplier(() ->
mailboxManager.getMailbox(otherMailboxPath,
systemSession).getMailboxCounters(systemSession).getCount()).get())
- .isEqualTo(1);
- }
- );
- }
-
- @Test
- void runRulesOnMailboxShouldSupportMoveToMailboxNameWhenMatchingMessage()
throws Exception {
- MailboxPath mailboxPath = MailboxPath.forUser(USERNAME, MAILBOX_NAME);
- MailboxPath otherMailboxPath = MailboxPath.forUser(USERNAME,
OTHER_MAILBOX_NAME);
- MailboxSession systemSession =
mailboxManager.createSystemSession(USERNAME);
-
- mailboxManager.createMailbox(mailboxPath, systemSession);
- mailboxManager.createMailbox(otherMailboxPath, systemSession);
-
- mailboxManager.getMailbox(mailboxPath, systemSession)
- .appendMessage(MessageManager.AppendCommand.builder()
- .build(Message.Builder.of()
- .setSubject("plop")
- .setFrom("[email protected]")
- .setBody("body", StandardCharsets.UTF_8)
- .addField(new RawField("X-Custom-Header", "value"))),
- systemSession);
-
- String taskId = given()
- .queryParam("action", "triage")
- .body("""
- {
- "id": "1",
- "name": "rule 1",
- "action": {
- "appendIn": {
- "mailboxIds": []
- },
- "moveTo": {
- "mailboxName": "%s"
- },
- "important": false,
- "keyworkds": [],
- "reject": false,
- "seen": false
- },
- "conditionGroup": {
- "conditionCombiner": "OR",
- "conditions": [
- {
- "comparator": "any",
- "field": "header:X-Custom-Header",
- "value": "disregarded"
+ .post(MAILBOX_NAME + "/messages")
+ .then()
+ .statusCode(BAD_REQUEST_400)
+ .contentType(JSON)
+ .extract()
+ .body()
+ .jsonPath()
+ .getMap(".");
+
+ assertThat(errors)
+ .containsEntry("statusCode", BAD_REQUEST_400)
+ .containsEntry("type", ERROR_TYPE_INVALIDARGUMENT)
+ .containsEntry("message", "JSON payload of the request is not
valid");
+ }
+
+ @Test
+ void runRulesOnMailboxShouldReturnTaskId() throws MailboxException {
+ MailboxSession systemSession =
mailboxManager.createSystemSession(USERNAME);
+ MailboxPath mailboxPath = MailboxPath.forUser(USERNAME,
MAILBOX_NAME);
+ mailboxManager.createMailbox(mailboxPath, systemSession);
+
+ String taskId = given()
+ .queryParam("action", "triage")
+ .body(RULE_PAYLOAD.formatted("2"))
+ .post(MAILBOX_NAME + "/messages")
+ .then()
+ .statusCode(CREATED_201)
+ .extract()
+ .jsonPath()
+ .get("taskId");
+
+ assertThat(taskId)
+ .isNotEmpty();
+ }
+
+ @Test
+ void runRulesOnMailboxShouldMoveMatchingMessage() throws Exception {
+ MailboxPath mailboxPath = MailboxPath.forUser(USERNAME,
MAILBOX_NAME);
+ MailboxPath otherMailboxPath = MailboxPath.forUser(USERNAME,
OTHER_MAILBOX_NAME);
+ MailboxSession systemSession =
mailboxManager.createSystemSession(USERNAME);
+
+ mailboxManager.createMailbox(mailboxPath, systemSession);
+ mailboxManager.createMailbox(otherMailboxPath, systemSession);
+
+ mailboxManager.getMailbox(mailboxPath, systemSession)
+ .appendMessage(MessageManager.AppendCommand.builder()
+ .build(Message.Builder.of()
+ .setSubject("plop")
+ .setFrom("[email protected]")
+ .setBody("body", StandardCharsets.UTF_8)),
+ systemSession);
+
+ MailboxId otherMailboxId =
mailboxManager.getMailbox(otherMailboxPath, systemSession).getId();
+
+ String taskId = given()
+ .queryParam("action", "triage")
+ .body(RULE_PAYLOAD.formatted(otherMailboxId.serialize()))
+ .post(MAILBOX_NAME + "/messages")
+ .then()
+ .statusCode(CREATED_201)
+ .extract()
+ .jsonPath()
+ .get("taskId");
+
+ given()
+ .basePath(TasksRoutes.BASE)
+ .when()
+ .get(taskId + "/await");
+
+ SoftAssertions.assertSoftly(
+ softly -> {
+ softly.assertThat(Throwing.supplier(() ->
mailboxManager.getMailbox(mailboxPath,
systemSession).getMailboxCounters(systemSession).getCount()).get())
+ .isEqualTo(0);
+ softly.assertThat(Throwing.supplier(() ->
mailboxManager.getMailbox(otherMailboxPath,
systemSession).getMailboxCounters(systemSession).getCount()).get())
+ .isEqualTo(1);
+ });
+ }
+
+ @Test
+ void
runRulesOnMailboxShouldSupportMoveToMailboxNameWhenMatchingMessage() throws
Exception {
+ MailboxPath mailboxPath = MailboxPath.forUser(USERNAME,
MAILBOX_NAME);
+ MailboxPath otherMailboxPath = MailboxPath.forUser(USERNAME,
OTHER_MAILBOX_NAME);
+ MailboxSession systemSession =
mailboxManager.createSystemSession(USERNAME);
+
+ mailboxManager.createMailbox(mailboxPath, systemSession);
+ mailboxManager.createMailbox(otherMailboxPath, systemSession);
+
+ mailboxManager.getMailbox(mailboxPath, systemSession)
+ .appendMessage(MessageManager.AppendCommand.builder()
+ .build(Message.Builder.of()
+ .setSubject("plop")
+ .setFrom("[email protected]")
+ .setBody("body", StandardCharsets.UTF_8)
+ .addField(new RawField("X-Custom-Header",
"value"))),
+ systemSession);
+
+ String taskId = given()
+ .queryParam("action", "triage")
+ .body("""
+ {
+ "id": "1",
+ "name": "rule 1",
+ "action": {
+ "appendIn": {
+ "mailboxIds": []
+ },
+ "moveTo": {
+ "mailboxName": "%s"
+ },
+ "important": false,
+ "keyworkds": [],
+ "reject": false,
+ "seen": false
+ },
+ "conditionGroup": {
+ "conditionCombiner": "OR",
+ "conditions": [
+ {
+ "comparator": "any",
+ "field": "header:X-Custom-Header",
+ "value": "disregarded"
+ }
+ ]
}
- ]
- }
- }"""
- .formatted(OTHER_MAILBOX_NAME))
- .post(MAILBOX_NAME + "/messages")
- .then()
- .statusCode(CREATED_201)
- .extract()
- .jsonPath()
- .get("taskId");
-
- given()
- .basePath(TasksRoutes.BASE)
+ }""".formatted(OTHER_MAILBOX_NAME))
+ .post(MAILBOX_NAME + "/messages")
+ .then()
+ .statusCode(CREATED_201)
+ .extract()
+ .jsonPath()
+ .get("taskId");
+
+ given()
+ .basePath(TasksRoutes.BASE)
.when()
- .get(taskId + "/await");
-
- SoftAssertions.assertSoftly(
- softly -> {
- softly.assertThat(Throwing.supplier(() ->
mailboxManager.getMailbox(mailboxPath,
systemSession).getMailboxCounters(systemSession).getCount()).get())
- .isEqualTo(0);
- softly.assertThat(Throwing.supplier(() ->
mailboxManager.getMailbox(otherMailboxPath,
systemSession).getMailboxCounters(systemSession).getCount()).get())
- .isEqualTo(1);
- }
- );
- }
-
- @Test
- void
runRulesOnMailboxShouldSupportMoveToMailboxWhenMatchingMessageAndTargetMailboxDoesNotExist()
throws Exception {
- MailboxPath mailboxPath = MailboxPath.forUser(USERNAME, MAILBOX_NAME);
- MailboxPath moveToMailboxPath = MailboxPath.forUser(USERNAME,
MOVE_TO_MAILBOX_NAME);
- MailboxSession systemSession =
mailboxManager.createSystemSession(USERNAME);
-
- mailboxManager.createMailbox(mailboxPath, systemSession);
-
- mailboxManager.getMailbox(mailboxPath, systemSession)
- .appendMessage(MessageManager.AppendCommand.builder()
- .build(Message.Builder.of()
- .setSubject("plop")
- .setFrom("[email protected]")
- .setBody("body", StandardCharsets.UTF_8)),
- systemSession);
-
- String taskId = given()
- .queryParam("action", "triage")
- .body("""
- {
- "id": "1",
- "name": "rule 1",
- "action": {
- "appendIn": {
- "mailboxIds": []
- },
- "moveTo": {
- "mailboxName": "%s"
- },
- "important": false,
- "keyworkds": [],
- "reject": false,
- "seen": false
- },
- "conditionGroup": {
- "conditionCombiner": "OR",
- "conditions": [
- {
- "comparator": "contains",
- "field": "subject",
- "value": "plop"
+ .get(taskId + "/await");
+
+ SoftAssertions.assertSoftly(
+ softly -> {
+ softly.assertThat(Throwing.supplier(() ->
mailboxManager.getMailbox(mailboxPath,
systemSession).getMailboxCounters(systemSession).getCount()).get())
+ .isEqualTo(0);
+ softly.assertThat(Throwing.supplier(() ->
mailboxManager.getMailbox(otherMailboxPath,
systemSession).getMailboxCounters(systemSession).getCount()).get())
+ .isEqualTo(1);
+ });
+ }
+
+ @Test
+ void
runRulesOnMailboxShouldSupportMoveToMailboxWhenMatchingMessageAndTargetMailboxDoesNotExist()
throws Exception {
+ MailboxPath mailboxPath = MailboxPath.forUser(USERNAME,
MAILBOX_NAME);
+ MailboxPath moveToMailboxPath = MailboxPath.forUser(USERNAME,
MOVE_TO_MAILBOX_NAME);
+ MailboxSession systemSession =
mailboxManager.createSystemSession(USERNAME);
+
+ mailboxManager.createMailbox(mailboxPath, systemSession);
+
+ mailboxManager.getMailbox(mailboxPath, systemSession)
+ .appendMessage(MessageManager.AppendCommand.builder()
+ .build(Message.Builder.of()
+ .setSubject("plop")
+ .setFrom("[email protected]")
+ .setBody("body", StandardCharsets.UTF_8)),
+ systemSession);
+
+ String taskId = given()
+ .queryParam("action", "triage")
+ .body(RULE_MOVE_TO_PAYLOAD.formatted(MOVE_TO_MAILBOX_NAME))
+ .post(MAILBOX_NAME + "/messages")
+ .then()
+ .statusCode(CREATED_201)
+ .extract()
+ .jsonPath()
+ .get("taskId");
+
+ given()
+ .basePath(TasksRoutes.BASE)
+ .when()
+ .get(taskId + "/await");
+
+ SoftAssertions.assertSoftly(
+ softly -> {
+ softly.assertThat(Throwing.supplier(() ->
mailboxManager.getMailbox(mailboxPath,
systemSession).getMailboxCounters(systemSession).getCount()).get())
+ .isEqualTo(0);
+ softly.assertThat(Throwing.supplier(() ->
mailboxManager.getMailbox(moveToMailboxPath,
systemSession).getMailboxCounters(systemSession).getCount()).get())
+ .isEqualTo(1);
+ });
+ }
+
+ @Test
+ void
runRulesOnMailboxShouldNotMoveToMailboxNameWhenNonMatchingMessage() throws
Exception {
+ MailboxPath mailboxPath = MailboxPath.forUser(USERNAME,
MAILBOX_NAME);
+ MailboxPath otherMailboxPath = MailboxPath.forUser(USERNAME,
OTHER_MAILBOX_NAME);
+ MailboxSession systemSession =
mailboxManager.createSystemSession(USERNAME);
+
+ mailboxManager.createMailbox(mailboxPath, systemSession);
+ mailboxManager.createMailbox(otherMailboxPath, systemSession);
+
+ mailboxManager.getMailbox(mailboxPath, systemSession)
+ .appendMessage(MessageManager.AppendCommand.builder()
+ .build(Message.Builder.of()
+ .setSubject("not match rules")
+ .setFrom("[email protected]")
+ .setBody("body", StandardCharsets.UTF_8)),
+ systemSession);
+
+ String taskId = given()
+ .queryParam("action", "triage")
+ .body(RULE_MOVE_TO_PAYLOAD.formatted(OTHER_MAILBOX_NAME))
+ .post(MAILBOX_NAME + "/messages")
+ .then()
+ .statusCode(CREATED_201)
+ .extract()
+ .jsonPath()
+ .get("taskId");
+
+ given()
+ .basePath(TasksRoutes.BASE)
+ .when()
+ .get(taskId + "/await");
+
+ SoftAssertions.assertSoftly(
+ softly -> {
+ softly.assertThat(Throwing.supplier(() ->
mailboxManager.getMailbox(mailboxPath,
systemSession).getMailboxCounters(systemSession).getCount()).get())
+ .isEqualTo(1);
+ softly.assertThat(Throwing.supplier(() ->
mailboxManager.getMailbox(otherMailboxPath,
systemSession).getMailboxCounters(systemSession).getCount()).get())
+ .isEqualTo(0);
+ });
+ }
+
+ @Test
+ void bothMoveToAndAppendInMailboxesShouldWork() throws Exception {
+ MailboxPath mailboxPath = MailboxPath.forUser(USERNAME,
MAILBOX_NAME);
+ MailboxPath appendIdMailboxPath = MailboxPath.forUser(USERNAME,
OTHER_MAILBOX_NAME);
+ MailboxPath moveToMailboxPath = MailboxPath.forUser(USERNAME,
MOVE_TO_MAILBOX_NAME);
+ MailboxSession systemSession =
mailboxManager.createSystemSession(USERNAME);
+
+ mailboxManager.createMailbox(mailboxPath, systemSession);
+ mailboxManager.createMailbox(appendIdMailboxPath, systemSession);
+ mailboxManager.createMailbox(moveToMailboxPath, systemSession);
+ MailboxId appendIdMailboxId =
mailboxManager.getMailbox(appendIdMailboxPath, systemSession).getId();
+
+ mailboxManager.getMailbox(mailboxPath, systemSession)
+ .appendMessage(MessageManager.AppendCommand.builder()
+ .build(Message.Builder.of()
+ .setSubject("plop")
+ .setFrom("[email protected]")
+ .setBody("body", StandardCharsets.UTF_8)),
+ systemSession);
+
+ String taskId = given()
+ .queryParam("action", "triage")
+ .body("""
+ {
+ "id": "1",
+ "name": "rule 1",
+ "action": {
+ "appendIn": {
+ "mailboxIds": ["%s"]
+ },
+ "moveTo": {
+ "mailboxName": "%s"
+ },
+ "important": false,
+ "keyworkds": [],
+ "reject": false,
+ "seen": false
},
- {
- "comparator": "exactly-equals",
- "field": "from",
- "value": "[email protected]"
+ "conditionGroup": {
+ "conditionCombiner": "OR",
+ "conditions": [
+ {
+ "comparator": "contains",
+ "field": "subject",
+ "value": "plop"
+ },
+ {
+ "comparator": "exactly-equals",
+ "field": "from",
+ "value": "[email protected]"
+ }
+ ]
}
- ]
- }
- }"""
- .formatted(MOVE_TO_MAILBOX_NAME))
- .post(MAILBOX_NAME + "/messages")
- .then()
- .statusCode(CREATED_201)
- .extract()
- .jsonPath()
- .get("taskId");
-
- given()
- .basePath(TasksRoutes.BASE)
+ }"""
+ .formatted(appendIdMailboxId.serialize(),
MOVE_TO_MAILBOX_NAME))
+ .post(MAILBOX_NAME + "/messages")
+ .then()
+ .statusCode(CREATED_201)
+ .extract()
+ .jsonPath()
+ .get("taskId");
+
+ given()
+ .basePath(TasksRoutes.BASE)
.when()
- .get(taskId + "/await");
-
- SoftAssertions.assertSoftly(
- softly -> {
- softly.assertThat(Throwing.supplier(() ->
mailboxManager.getMailbox(mailboxPath,
systemSession).getMailboxCounters(systemSession).getCount()).get())
- .isEqualTo(0);
- softly.assertThat(Throwing.supplier(() ->
mailboxManager.getMailbox(moveToMailboxPath,
systemSession).getMailboxCounters(systemSession).getCount()).get())
- .isEqualTo(1);
- }
- );
- }
-
- @Test
- void runRulesOnMailboxShouldNotMoveToMailboxNameWhenNonMatchingMessage()
throws Exception {
- MailboxPath mailboxPath = MailboxPath.forUser(USERNAME, MAILBOX_NAME);
- MailboxPath otherMailboxPath = MailboxPath.forUser(USERNAME,
OTHER_MAILBOX_NAME);
- MailboxSession systemSession =
mailboxManager.createSystemSession(USERNAME);
-
- mailboxManager.createMailbox(mailboxPath, systemSession);
- mailboxManager.createMailbox(otherMailboxPath, systemSession);
-
- mailboxManager.getMailbox(mailboxPath, systemSession)
- .appendMessage(MessageManager.AppendCommand.builder()
- .build(Message.Builder.of()
- .setSubject("not match rules")
- .setFrom("[email protected]")
- .setBody("body", StandardCharsets.UTF_8)),
- systemSession);
-
- String taskId = given()
- .queryParam("action", "triage")
- .body("""
- {
- "id": "1",
- "name": "rule 1",
- "action": {
- "appendIn": {
- "mailboxIds": []
- },
- "moveTo": {
- "mailboxName": "%s"
- },
- "important": false,
- "keyworkds": [],
- "reject": false,
- "seen": false
- },
- "conditionGroup": {
- "conditionCombiner": "OR",
- "conditions": [
- {
- "comparator": "contains",
- "field": "subject",
- "value": "plop"
+ .get(taskId + "/await");
+
+ SoftAssertions.assertSoftly(
+ softly -> {
+ softly.assertThat(Throwing.supplier(() ->
mailboxManager.getMailbox(mailboxPath,
systemSession).getMailboxCounters(systemSession).getCount()).get())
+ .isEqualTo(0);
+ softly.assertThat(Throwing.supplier(() ->
mailboxManager.getMailbox(appendIdMailboxPath,
systemSession).getMailboxCounters(systemSession).getCount()).get())
+ .isEqualTo(1);
+ softly.assertThat(Throwing.supplier(() ->
mailboxManager.getMailbox(moveToMailboxPath,
systemSession).getMailboxCounters(systemSession).getCount()).get())
+ .isEqualTo(1);
+ });
+ }
+
+ @Test
+ void
bothMoveToAndAppendInMailboxesShouldNotDuplicateMessageWhenTheSameTargetMailbox()
throws Exception {
+ MailboxPath mailboxPath = MailboxPath.forUser(USERNAME,
MAILBOX_NAME);
+ MailboxPath targetMailboxPath = MailboxPath.forUser(USERNAME,
OTHER_MAILBOX_NAME);
+ MailboxSession systemSession =
mailboxManager.createSystemSession(USERNAME);
+
+ mailboxManager.createMailbox(mailboxPath, systemSession);
+ mailboxManager.createMailbox(targetMailboxPath, systemSession);
+ MailboxId targetMailboxId =
mailboxManager.getMailbox(targetMailboxPath, systemSession).getId();
+
+ mailboxManager.getMailbox(mailboxPath, systemSession)
+ .appendMessage(MessageManager.AppendCommand.builder()
+ .build(Message.Builder.of()
+ .setSubject("plop")
+ .setFrom("[email protected]")
+ .setBody("body", StandardCharsets.UTF_8)),
+ systemSession);
+
+ String taskId = given()
+ .queryParam("action", "triage")
+ .body("""
+ {
+ "id": "1",
+ "name": "rule 1",
+ "action": {
+ "appendIn": {
+ "mailboxIds": ["%s"]
+ },
+ "moveTo": {
+ "mailboxName": "%s"
+ },
+ "important": false,
+ "keyworkds": [],
+ "reject": false,
+ "seen": false
},
- {
- "comparator": "exactly-equals",
- "field": "from",
- "value": "[email protected]"
+ "conditionGroup": {
+ "conditionCombiner": "OR",
+ "conditions": [
+ {
+ "comparator": "contains",
+ "field": "subject",
+ "value": "plop"
+ },
+ {
+ "comparator": "exactly-equals",
+ "field": "from",
+ "value": "[email protected]"
+ }
+ ]
}
- ]
- }
- }"""
- .formatted(OTHER_MAILBOX_NAME))
- .post(MAILBOX_NAME + "/messages")
- .then()
- .statusCode(CREATED_201)
- .extract()
- .jsonPath()
- .get("taskId");
-
- given()
- .basePath(TasksRoutes.BASE)
+ }"""
+ .formatted(targetMailboxId.serialize(),
OTHER_MAILBOX_NAME))
+ .post(MAILBOX_NAME + "/messages")
+ .then()
+ .statusCode(CREATED_201)
+ .extract()
+ .jsonPath()
+ .get("taskId");
+
+ given()
+ .basePath(TasksRoutes.BASE)
.when()
- .get(taskId + "/await");
-
- SoftAssertions.assertSoftly(
- softly -> {
- softly.assertThat(Throwing.supplier(() ->
mailboxManager.getMailbox(mailboxPath,
systemSession).getMailboxCounters(systemSession).getCount()).get())
- .isEqualTo(1);
- softly.assertThat(Throwing.supplier(() ->
mailboxManager.getMailbox(otherMailboxPath,
systemSession).getMailboxCounters(systemSession).getCount()).get())
- .isEqualTo(0);
- }
- );
- }
-
- @Test
- void bothMoveToAndAppendInMailboxesShouldWork() throws Exception {
- MailboxPath mailboxPath = MailboxPath.forUser(USERNAME, MAILBOX_NAME);
- MailboxPath appendIdMailboxPath = MailboxPath.forUser(USERNAME,
OTHER_MAILBOX_NAME);
- MailboxPath moveToMailboxPath = MailboxPath.forUser(USERNAME,
MOVE_TO_MAILBOX_NAME);
- MailboxSession systemSession =
mailboxManager.createSystemSession(USERNAME);
-
- mailboxManager.createMailbox(mailboxPath, systemSession);
- mailboxManager.createMailbox(appendIdMailboxPath, systemSession);
- mailboxManager.createMailbox(moveToMailboxPath, systemSession);
- MailboxId appendIdMailboxId =
mailboxManager.getMailbox(appendIdMailboxPath, systemSession).getId();
-
- mailboxManager.getMailbox(mailboxPath, systemSession)
- .appendMessage(MessageManager.AppendCommand.builder()
- .build(Message.Builder.of()
- .setSubject("plop")
- .setFrom("[email protected]")
- .setBody("body", StandardCharsets.UTF_8)),
- systemSession);
-
- String taskId = given()
- .queryParam("action", "triage")
- .body("""
- {
- "id": "1",
- "name": "rule 1",
- "action": {
- "appendIn": {
- "mailboxIds": ["%s"]
- },
- "moveTo": {
- "mailboxName": "%s"
- },
- "important": false,
- "keyworkds": [],
- "reject": false,
- "seen": false
- },
- "conditionGroup": {
- "conditionCombiner": "OR",
- "conditions": [
- {
- "comparator": "contains",
- "field": "subject",
- "value": "plop"
+ .get(taskId + "/await");
+
+ SoftAssertions.assertSoftly(
+ softly -> {
+ softly.assertThat(Throwing.supplier(() ->
mailboxManager.getMailbox(mailboxPath,
systemSession).getMailboxCounters(systemSession).getCount()).get())
+ .isEqualTo(0);
+ softly.assertThat(Throwing.supplier(() ->
mailboxManager.getMailbox(targetMailboxPath,
systemSession).getMailboxCounters(systemSession).getCount()).get())
+ .isEqualTo(1);
+ });
+ }
+
+ @Test
+ void runRulesShouldApplyDateCrieria() throws Exception {
+ MailboxPath mailboxPath = MailboxPath.forUser(USERNAME,
MAILBOX_NAME);
+ MailboxPath otherMailboxPath = MailboxPath.forUser(USERNAME,
OTHER_MAILBOX_NAME);
+ MailboxSession systemSession =
mailboxManager.createSystemSession(USERNAME);
+
+ mailboxManager.createMailbox(mailboxPath, systemSession);
+ mailboxManager.createMailbox(otherMailboxPath, systemSession);
+
+ mailboxManager.getMailbox(mailboxPath, systemSession)
+ .appendMessage(MessageManager.AppendCommand.builder()
+
.withInternalDate(Date.from(Clock.systemUTC().instant().minus(Duration.ofDays(2))))
+ .build(Message.Builder.of()
+ .setSubject("plop")
+ .setFrom("[email protected]")
+ .setBody("body", StandardCharsets.UTF_8)),
+ systemSession);
+
+ mailboxManager.getMailbox(mailboxPath, systemSession)
+ .appendMessage(MessageManager.AppendCommand.builder()
+
.withInternalDate(Date.from(Clock.systemUTC().instant().minus(Duration.ofDays(20))))
+ .build(Message.Builder.of()
+ .setSubject("plop")
+ .setFrom("[email protected]")
+ .setBody("body", StandardCharsets.UTF_8)),
+ systemSession);
+
+ MailboxId otherMailboxId =
mailboxManager.getMailbox(otherMailboxPath, systemSession).getId();
+
+ String taskId = given()
+ .queryParam("action", "triage")
+ .body("""
+ {
+ "id": "1",
+ "name": "rule 1",
+ "action": {
+ "appendIn": {
+ "mailboxIds": ["%s"]
+ },
+ "important": false,
+ "keyworkds": [],
+ "reject": false,
+ "seen": false
},
- {
- "comparator": "exactly-equals",
- "field": "from",
- "value": "[email protected]"
+ "conditionGroup": {
+ "conditionCombiner": "AND",
+ "conditions": [
+ {
+ "comparator": "contains",
+ "field": "subject",
+ "value": "plop"
+ },
+ {
+ "comparator": "isOlderThan",
+ "field": "internalDate",
+ "value": "10d"
+ }
+ ]
}
- ]
- }
- }"""
- .formatted(appendIdMailboxId.serialize(),
MOVE_TO_MAILBOX_NAME))
- .post(MAILBOX_NAME + "/messages")
- .then()
- .statusCode(CREATED_201)
- .extract()
- .jsonPath()
- .get("taskId");
-
- given()
- .basePath(TasksRoutes.BASE)
+ }""".formatted(otherMailboxId.serialize()))
+ .post(MAILBOX_NAME + "/messages")
+ .then()
+ .statusCode(CREATED_201)
+ .extract()
+ .jsonPath()
+ .get("taskId");
+
+ given()
+ .basePath(TasksRoutes.BASE)
.when()
- .get(taskId + "/await");
-
- SoftAssertions.assertSoftly(
- softly -> {
- softly.assertThat(Throwing.supplier(() ->
mailboxManager.getMailbox(mailboxPath,
systemSession).getMailboxCounters(systemSession).getCount()).get())
- .isEqualTo(0);
- softly.assertThat(Throwing.supplier(() ->
mailboxManager.getMailbox(appendIdMailboxPath,
systemSession).getMailboxCounters(systemSession).getCount()).get())
- .isEqualTo(1);
- softly.assertThat(Throwing.supplier(() ->
mailboxManager.getMailbox(moveToMailboxPath,
systemSession).getMailboxCounters(systemSession).getCount()).get())
- .isEqualTo(1);
- }
- );
- }
-
- @Test
- void
bothMoveToAndAppendInMailboxesShouldNotDuplicateMessageWhenTheSameTargetMailbox()
throws Exception {
- MailboxPath mailboxPath = MailboxPath.forUser(USERNAME, MAILBOX_NAME);
- MailboxPath targetMailboxPath = MailboxPath.forUser(USERNAME,
OTHER_MAILBOX_NAME);
- MailboxSession systemSession =
mailboxManager.createSystemSession(USERNAME);
-
- mailboxManager.createMailbox(mailboxPath, systemSession);
- mailboxManager.createMailbox(targetMailboxPath, systemSession);
- MailboxId targetMailboxId =
mailboxManager.getMailbox(targetMailboxPath, systemSession).getId();
-
- mailboxManager.getMailbox(mailboxPath, systemSession)
- .appendMessage(MessageManager.AppendCommand.builder()
+ .get(taskId + "/await");
+
+ SoftAssertions.assertSoftly(
+ softly -> {
+ softly.assertThat(Throwing.supplier(() ->
mailboxManager.getMailbox(mailboxPath,
systemSession).getMailboxCounters(systemSession).getCount()).get())
+ .isEqualTo(1);
+ softly.assertThat(Throwing.supplier(() ->
mailboxManager.getMailbox(otherMailboxPath,
systemSession).getMailboxCounters(systemSession).getCount()).get())
+ .isEqualTo(1);
+ }
+ );
+ }
+
+ @Test
+ void runRulesOnMailboxShouldNotMoveNonMatchingMessage() throws
Exception {
+ MailboxPath mailboxPath = MailboxPath.forUser(USERNAME,
MAILBOX_NAME);
+ MailboxPath otherMailboxPath = MailboxPath.forUser(USERNAME,
OTHER_MAILBOX_NAME);
+ MailboxSession systemSession =
mailboxManager.createSystemSession(USERNAME);
+
+ mailboxManager.createMailbox(mailboxPath, systemSession);
+ mailboxManager.createMailbox(otherMailboxPath, systemSession);
+
+ mailboxManager.getMailbox(mailboxPath, systemSession)
+ .appendMessage(MessageManager.AppendCommand.builder()
+ .build(Message.Builder.of()
+ .setSubject("hello")
+ .setFrom("[email protected]")
+ .setBody("body", StandardCharsets.UTF_8)),
+ systemSession);
+
+ MailboxId otherMailboxId =
mailboxManager.getMailbox(otherMailboxPath, systemSession).getId();
+
+ String taskId = given()
+ .queryParam("action", "triage")
+ .body(RULE_PAYLOAD.formatted(otherMailboxId.serialize()))
+ .post(MAILBOX_NAME + "/messages")
+ .then()
+ .statusCode(CREATED_201)
+ .extract()
+ .jsonPath()
+ .get("taskId");
+
+ given()
+ .basePath(TasksRoutes.BASE)
+ .when()
+ .get(taskId + "/await");
+
+ SoftAssertions.assertSoftly(
+ softly -> {
+ softly.assertThat(Throwing.supplier(() ->
mailboxManager.getMailbox(mailboxPath,
systemSession).getMailboxCounters(systemSession).getCount()).get())
+ .isEqualTo(1);
+ softly.assertThat(Throwing.supplier(() ->
mailboxManager.getMailbox(otherMailboxPath,
systemSession).getMailboxCounters(systemSession).getCount()).get())
+ .isEqualTo(0);
+ }
+ );
+ }
+
+ @Test
+ void runRulesOnMailboxShouldManageMixedCase() throws Exception {
+ MailboxPath mailboxPath = MailboxPath.forUser(USERNAME,
MAILBOX_NAME);
+ MailboxPath otherMailboxPath = MailboxPath.forUser(USERNAME,
OTHER_MAILBOX_NAME);
+ MailboxSession systemSession =
mailboxManager.createSystemSession(USERNAME);
+
+ mailboxManager.createMailbox(mailboxPath, systemSession);
+ mailboxManager.createMailbox(otherMailboxPath, systemSession);
+
+ MessageManager messageManager =
mailboxManager.getMailbox(mailboxPath, systemSession);
+
+ messageManager.appendMessage(
+ MessageManager.AppendCommand.builder()
.build(Message.Builder.of()
.setSubject("plop")
.setFrom("[email protected]")
.setBody("body", StandardCharsets.UTF_8)),
systemSession);
- String taskId = given()
- .queryParam("action", "triage")
- .body("""
- {
- "id": "1",
- "name": "rule 1",
- "action": {
- "appendIn": {
- "mailboxIds": ["%s"]
- },
- "moveTo": {
- "mailboxName": "%s"
- },
- "important": false,
- "keyworkds": [],
- "reject": false,
- "seen": false
- },
- "conditionGroup": {
- "conditionCombiner": "OR",
- "conditions": [
- {
- "comparator": "contains",
- "field": "subject",
- "value": "plop"
- },
- {
- "comparator": "exactly-equals",
- "field": "from",
- "value": "[email protected]"
- }
- ]
- }
- }"""
- .formatted(targetMailboxId.serialize(), OTHER_MAILBOX_NAME))
- .post(MAILBOX_NAME + "/messages")
- .then()
- .statusCode(CREATED_201)
- .extract()
- .jsonPath()
- .get("taskId");
-
- given()
- .basePath(TasksRoutes.BASE)
- .when()
- .get(taskId + "/await");
-
- SoftAssertions.assertSoftly(
- softly -> {
- softly.assertThat(Throwing.supplier(() ->
mailboxManager.getMailbox(mailboxPath,
systemSession).getMailboxCounters(systemSession).getCount()).get())
- .isEqualTo(0);
- softly.assertThat(Throwing.supplier(() ->
mailboxManager.getMailbox(targetMailboxPath,
systemSession).getMailboxCounters(systemSession).getCount()).get())
- .isEqualTo(1);
- }
- );
- }
-
- @Test
- void runRulesShouldApplyDateCrieria() throws Exception {
- MailboxPath mailboxPath = MailboxPath.forUser(USERNAME, MAILBOX_NAME);
- MailboxPath otherMailboxPath = MailboxPath.forUser(USERNAME,
OTHER_MAILBOX_NAME);
- MailboxSession systemSession =
mailboxManager.createSystemSession(USERNAME);
-
- mailboxManager.createMailbox(mailboxPath, systemSession);
- mailboxManager.createMailbox(otherMailboxPath, systemSession);
-
- mailboxManager.getMailbox(mailboxPath, systemSession)
- .appendMessage(MessageManager.AppendCommand.builder()
-
.withInternalDate(Date.from(Clock.systemUTC().instant().minus(Duration.ofDays(2))))
+ messageManager.appendMessage(
+ MessageManager.AppendCommand.builder()
.build(Message.Builder.of()
- .setSubject("plop")
+ .setSubject("hello")
.setFrom("[email protected]")
.setBody("body", StandardCharsets.UTF_8)),
systemSession);
- mailboxManager.getMailbox(mailboxPath, systemSession)
- .appendMessage(MessageManager.AppendCommand.builder()
-
.withInternalDate(Date.from(Clock.systemUTC().instant().minus(Duration.ofDays(20))))
+ messageManager.appendMessage(
+ MessageManager.AppendCommand.builder()
.build(Message.Builder.of()
- .setSubject("plop")
- .setFrom("[email protected]")
+ .setSubject("hello")
+ .setFrom("[email protected]")
.setBody("body", StandardCharsets.UTF_8)),
systemSession);
- MailboxId otherMailboxId = mailboxManager.getMailbox(otherMailboxPath,
systemSession).getId();
-
- String taskId = given()
- .queryParam("action", "triage")
- .body("""
- {
- "id": "1",
- "name": "rule 1",
- "action": {
- "appendIn": {
- "mailboxIds": ["%s"]
- },
- "important": false,
- "keyworkds": [],
- "reject": false,
- "seen": false
- },
- "conditionGroup": {
- "conditionCombiner": "AND",
- "conditions": [
- {
- "comparator": "contains",
- "field": "subject",
- "value": "plop"
- },
- {
- "comparator": "isOlderThan",
- "field": "internalDate",
- "value": "10d"
- }
- ]
- }
- }""".formatted(otherMailboxId.serialize()))
- .post(MAILBOX_NAME + "/messages")
- .then()
- .statusCode(CREATED_201)
- .extract()
- .jsonPath()
- .get("taskId");
-
- given()
- .basePath(TasksRoutes.BASE)
- .when()
- .get(taskId + "/await");
-
- SoftAssertions.assertSoftly(
- softly -> {
- softly.assertThat(Throwing.supplier(() ->
mailboxManager.getMailbox(mailboxPath,
systemSession).getMailboxCounters(systemSession).getCount()).get())
- .isEqualTo(1);
- softly.assertThat(Throwing.supplier(() ->
mailboxManager.getMailbox(otherMailboxPath,
systemSession).getMailboxCounters(systemSession).getCount()).get())
- .isEqualTo(1);
- }
- );
- }
+ MailboxId otherMailboxId =
mailboxManager.getMailbox(otherMailboxPath, systemSession).getId();
- @Test
- void runRulesOnMailboxShouldNotMoveNonMatchingMessage() throws Exception {
- MailboxPath mailboxPath = MailboxPath.forUser(USERNAME, MAILBOX_NAME);
- MailboxPath otherMailboxPath = MailboxPath.forUser(USERNAME,
OTHER_MAILBOX_NAME);
- MailboxSession systemSession =
mailboxManager.createSystemSession(USERNAME);
+ String taskId = given()
+ .queryParam("action", "triage")
+ .body(RULE_PAYLOAD.formatted(otherMailboxId.serialize()))
+ .post(MAILBOX_NAME + "/messages")
+ .then()
+ .statusCode(CREATED_201)
+ .extract()
+ .jsonPath()
+ .get("taskId");
- mailboxManager.createMailbox(mailboxPath, systemSession);
- mailboxManager.createMailbox(otherMailboxPath, systemSession);
+ given()
+ .basePath(TasksRoutes.BASE)
+ .when()
+ .get(taskId + "/await");
+
+ SoftAssertions.assertSoftly(
+ softly -> {
+ softly.assertThat(Throwing.supplier(() ->
mailboxManager.getMailbox(mailboxPath,
systemSession).getMailboxCounters(systemSession).getCount()).get())
+ .isEqualTo(1);
+ softly.assertThat(Throwing.supplier(() ->
mailboxManager.getMailbox(otherMailboxPath,
systemSession).getMailboxCounters(systemSession).getCount()).get())
+ .isEqualTo(2);
+ }
+ );
+ }
+
+ @Test
+ void runRulesOnMailboxShouldApplyFlagCriteria() throws Exception {
+ MailboxPath mailboxPath = MailboxPath.forUser(USERNAME,
MAILBOX_NAME);
+ MailboxPath otherMailboxPath = MailboxPath.forUser(USERNAME,
OTHER_MAILBOX_NAME);
+ MailboxSession systemSession =
mailboxManager.createSystemSession(USERNAME);
+
+ mailboxManager.createMailbox(mailboxPath, systemSession);
+ mailboxManager.createMailbox(otherMailboxPath, systemSession);
+
+ MessageManager messageManager =
mailboxManager.getMailbox(mailboxPath, systemSession);
+
+ messageManager.appendMessage(
+ MessageManager.AppendCommand.builder()
+ .withFlags(new FlagsBuilder().add(Flags.Flag.FLAGGED,
Flags.Flag.SEEN)
+ .build())
+ .build(Message.Builder.of()
+ .setSubject("plop")
+ .setFrom("[email protected]")
+ .setBody("body", StandardCharsets.UTF_8)),
+ systemSession).getId();
- mailboxManager.getMailbox(mailboxPath, systemSession)
- .appendMessage(MessageManager.AppendCommand.builder()
+ messageManager.appendMessage(
+ MessageManager.AppendCommand.builder()
+ .withFlags(new FlagsBuilder().add(Flags.Flag.ANSWERED)
+ .add("custom")
+ .build())
.build(Message.Builder.of()
.setSubject("hello")
.setFrom("[email protected]")
.setBody("body", StandardCharsets.UTF_8)),
- systemSession);
+ systemSession).getId();
- MailboxId otherMailboxId = mailboxManager.getMailbox(otherMailboxPath,
systemSession).getId();
-
- String taskId = given()
- .queryParam("action", "triage")
- .body(RULE_PAYLOAD.formatted(otherMailboxId.serialize()))
- .post(MAILBOX_NAME + "/messages")
- .then()
- .statusCode(CREATED_201)
- .extract()
- .jsonPath()
- .get("taskId");
-
- given()
- .basePath(TasksRoutes.BASE)
- .when()
- .get(taskId + "/await");
-
- SoftAssertions.assertSoftly(
- softly -> {
- softly.assertThat(Throwing.supplier(() ->
mailboxManager.getMailbox(mailboxPath,
systemSession).getMailboxCounters(systemSession).getCount()).get())
- .isEqualTo(1);
- softly.assertThat(Throwing.supplier(() ->
mailboxManager.getMailbox(otherMailboxPath,
systemSession).getMailboxCounters(systemSession).getCount()).get())
- .isEqualTo(0);
- }
- );
- }
+ messageManager.appendMessage(
+ MessageManager.AppendCommand.builder()
+ .withFlags(new FlagsBuilder().add(Flags.Flag.SEEN)
+ .add("custom")
+ .build())
+ .build(Message.Builder.of()
+ .setSubject("hello")
+ .setFrom("[email protected]")
+ .setBody("body", StandardCharsets.UTF_8)),
+ systemSession).getId();
- @Test
- void runRulesOnMailboxShouldManageMixedCase() throws Exception {
- MailboxPath mailboxPath = MailboxPath.forUser(USERNAME, MAILBOX_NAME);
- MailboxPath otherMailboxPath = MailboxPath.forUser(USERNAME,
OTHER_MAILBOX_NAME);
- MailboxSession systemSession =
mailboxManager.createSystemSession(USERNAME);
-
- mailboxManager.createMailbox(mailboxPath, systemSession);
- mailboxManager.createMailbox(otherMailboxPath, systemSession);
-
- MessageManager messageManager = mailboxManager.getMailbox(mailboxPath,
systemSession);
-
- messageManager.appendMessage(
- MessageManager.AppendCommand.builder()
- .build(Message.Builder.of()
- .setSubject("plop")
- .setFrom("[email protected]")
- .setBody("body", StandardCharsets.UTF_8)),
- systemSession);
-
- messageManager.appendMessage(
- MessageManager.AppendCommand.builder()
- .build(Message.Builder.of()
- .setSubject("hello")
- .setFrom("[email protected]")
- .setBody("body", StandardCharsets.UTF_8)),
- systemSession);
-
- messageManager.appendMessage(
- MessageManager.AppendCommand.builder()
- .build(Message.Builder.of()
- .setSubject("hello")
- .setFrom("[email protected]")
- .setBody("body", StandardCharsets.UTF_8)),
- systemSession);
-
- MailboxId otherMailboxId = mailboxManager.getMailbox(otherMailboxPath,
systemSession).getId();
-
- String taskId = given()
- .queryParam("action", "triage")
- .body(RULE_PAYLOAD.formatted(otherMailboxId.serialize()))
- .post(MAILBOX_NAME + "/messages")
- .then()
- .statusCode(CREATED_201)
- .extract()
- .jsonPath()
- .get("taskId");
-
- given()
- .basePath(TasksRoutes.BASE)
- .when()
- .get(taskId + "/await");
-
- SoftAssertions.assertSoftly(
- softly -> {
- softly.assertThat(Throwing.supplier(() ->
mailboxManager.getMailbox(mailboxPath,
systemSession).getMailboxCounters(systemSession).getCount()).get())
- .isEqualTo(1);
- softly.assertThat(Throwing.supplier(() ->
mailboxManager.getMailbox(otherMailboxPath,
systemSession).getMailboxCounters(systemSession).getCount()).get())
- .isEqualTo(2);
- }
- );
- }
+ MailboxId otherMailboxId =
mailboxManager.getMailbox(otherMailboxPath, systemSession).getId();
- @Test
- void runRulesOnMailboxShouldApplyFlagCriteria() throws Exception {
- MailboxPath mailboxPath = MailboxPath.forUser(USERNAME, MAILBOX_NAME);
- MailboxPath otherMailboxPath = MailboxPath.forUser(USERNAME,
OTHER_MAILBOX_NAME);
- MailboxSession systemSession =
mailboxManager.createSystemSession(USERNAME);
-
- mailboxManager.createMailbox(mailboxPath, systemSession);
- mailboxManager.createMailbox(otherMailboxPath, systemSession);
-
- MessageManager messageManager = mailboxManager.getMailbox(mailboxPath,
systemSession);
-
- messageManager.appendMessage(
- MessageManager.AppendCommand.builder()
- .withFlags(new FlagsBuilder().add(Flags.Flag.FLAGGED,
Flags.Flag.SEEN)
- .build())
- .build(Message.Builder.of()
- .setSubject("plop")
- .setFrom("[email protected]")
- .setBody("body", StandardCharsets.UTF_8)),
- systemSession).getId();
-
- messageManager.appendMessage(
- MessageManager.AppendCommand.builder()
- .withFlags(new FlagsBuilder().add(Flags.Flag.ANSWERED)
- .add("custom")
- .build())
- .build(Message.Builder.of()
- .setSubject("hello")
- .setFrom("[email protected]")
- .setBody("body", StandardCharsets.UTF_8)),
- systemSession).getId();
-
- messageManager.appendMessage(
- MessageManager.AppendCommand.builder()
- .withFlags(new FlagsBuilder().add(Flags.Flag.SEEN)
- .add("custom")
- .build())
- .build(Message.Builder.of()
- .setSubject("hello")
- .setFrom("[email protected]")
- .setBody("body", StandardCharsets.UTF_8)),
- systemSession).getId();
-
- MailboxId otherMailboxId = mailboxManager.getMailbox(otherMailboxPath,
systemSession).getId();
-
- String taskId = given()
- .queryParam("action", "triage")
- .body("""
+ String taskId = given()
+ .queryParam("action", "triage")
+ .body("""
{
"id": "1",
"name": "rule 1",
@@ -957,244 +954,528 @@ public class RunRulesOnMailboxRoutesTest {
]
}
}""".formatted(otherMailboxId.serialize()))
- .post(MAILBOX_NAME + "/messages")
- .then()
- .statusCode(CREATED_201)
- .extract()
- .jsonPath()
- .get("taskId");
-
- given()
- .basePath(TasksRoutes.BASE)
- .when()
- .get(taskId + "/await");
-
- SoftAssertions.assertSoftly(
- softly -> {
- softly.assertThat(Throwing.supplier(() ->
mailboxManager.getMailbox(mailboxPath,
systemSession).getMailboxCounters(systemSession).getCount()).get())
- .isEqualTo(2);
- softly.assertThat(Throwing.supplier(() ->
mailboxManager.getMailbox(otherMailboxPath,
systemSession).getMailboxCounters(systemSession).getCount()).get())
- .isEqualTo(1);
- }
- );
- }
-
- @Test
- void runRulesOnMailboxShouldReturnTaskDetails() throws Exception {
- MailboxPath mailboxPath = MailboxPath.forUser(USERNAME, MAILBOX_NAME);
- MailboxPath otherMailboxPath = MailboxPath.forUser(USERNAME,
OTHER_MAILBOX_NAME);
- MailboxSession systemSession =
mailboxManager.createSystemSession(USERNAME);
-
- mailboxManager.createMailbox(mailboxPath, systemSession);
- mailboxManager.createMailbox(otherMailboxPath, systemSession);
-
- MessageManager messageManager = mailboxManager.getMailbox(mailboxPath,
systemSession);
-
- messageManager.appendMessage(
- MessageManager.AppendCommand.builder()
- .build(Message.Builder.of()
- .setSubject("plop")
- .setFrom("[email protected]")
- .setBody("body", StandardCharsets.UTF_8)),
- systemSession);
-
- messageManager.appendMessage(
- MessageManager.AppendCommand.builder()
- .build(Message.Builder.of()
- .setSubject("hello")
- .setFrom("[email protected]")
- .setBody("body", StandardCharsets.UTF_8)),
- systemSession);
-
- messageManager.appendMessage(
- MessageManager.AppendCommand.builder()
- .build(Message.Builder.of()
- .setSubject("hello")
- .setFrom("[email protected]")
- .setBody("body", StandardCharsets.UTF_8)),
- systemSession);
-
- MailboxId otherMailboxId = mailboxManager.getMailbox(otherMailboxPath,
systemSession).getId();
-
- String taskId = given()
- .queryParam("action", "triage")
- .body(RULE_PAYLOAD.formatted(otherMailboxId.serialize()))
- .post(MAILBOX_NAME + "/messages")
- .then()
- .statusCode(CREATED_201)
- .extract()
- .jsonPath()
- .get("taskId");
-
- given()
- .basePath(TasksRoutes.BASE)
- .when()
- .get(taskId + "/await")
- .then()
- .body("status", Matchers.is("completed"))
- .body("taskId", Matchers.is(notNullValue()))
- .body("type",
Matchers.is(RunRulesOnMailboxTask.TASK_TYPE.asString()))
- .body("startedDate", Matchers.is(notNullValue()))
- .body("submitDate", Matchers.is(notNullValue()))
- .body("completedDate", Matchers.is(notNullValue()))
- .body("additionalInformation.username",
Matchers.is(USERNAME.asString()))
- .body("additionalInformation.mailboxName",
Matchers.is(MAILBOX_NAME))
- .body("additionalInformation.rulesOnMessagesApplySuccessfully",
Matchers.is(2))
- .body("additionalInformation.rulesOnMessagesApplyFailed",
Matchers.is(0))
- .body("additionalInformation.maximumAppliedActionExceeded",
Matchers.is(false))
- .body("additionalInformation.processedMessagesCount",
Matchers.is(3));
- }
-
- @Test
- void taskShouldStopAndCompleteWhenAppliedActionsExceedMaximumLimit()
throws Exception {
- overrideTriageRulesRouteWithActionsLimit(2);
-
- MailboxPath mailboxPath = MailboxPath.forUser(USERNAME, MAILBOX_NAME);
- MailboxPath otherMailboxPath = MailboxPath.forUser(USERNAME,
OTHER_MAILBOX_NAME);
- MailboxSession systemSession =
mailboxManager.createSystemSession(USERNAME);
-
- mailboxManager.createMailbox(mailboxPath, systemSession);
- mailboxManager.createMailbox(otherMailboxPath, systemSession);
-
- MessageManager messageManager = mailboxManager.getMailbox(mailboxPath,
systemSession);
-
- // Add 20 matching messages, which exceeds the max actions of 2
- IntStream.range(0, 20)
- .forEach(Throwing.intConsumer(i -> messageManager.appendMessage(
+ .post(MAILBOX_NAME + "/messages")
+ .then()
+ .statusCode(CREATED_201)
+ .extract()
+ .jsonPath()
+ .get("taskId");
+
+ given()
+ .basePath(TasksRoutes.BASE)
+ .when()
+ .get(taskId + "/await");
+
+ SoftAssertions.assertSoftly(
+ softly -> {
+ softly.assertThat(Throwing.supplier(() ->
mailboxManager.getMailbox(mailboxPath,
systemSession).getMailboxCounters(systemSession).getCount()).get())
+ .isEqualTo(2);
+ softly.assertThat(Throwing.supplier(() ->
mailboxManager.getMailbox(otherMailboxPath,
systemSession).getMailboxCounters(systemSession).getCount()).get())
+ .isEqualTo(1);
+ }
+ );
+ }
+
+ @Test
+ void runRulesOnMailboxShouldReturnTaskDetails() throws Exception {
+ MailboxPath mailboxPath = MailboxPath.forUser(USERNAME,
MAILBOX_NAME);
+ MailboxPath otherMailboxPath = MailboxPath.forUser(USERNAME,
OTHER_MAILBOX_NAME);
+ MailboxSession systemSession =
mailboxManager.createSystemSession(USERNAME);
+
+ mailboxManager.createMailbox(mailboxPath, systemSession);
+ mailboxManager.createMailbox(otherMailboxPath, systemSession);
+
+ MessageManager messageManager =
mailboxManager.getMailbox(mailboxPath, systemSession);
+
+ messageManager.appendMessage(
MessageManager.AppendCommand.builder()
.build(Message.Builder.of()
.setSubject("plop")
.setFrom("[email protected]")
- .setBody("matched mail", StandardCharsets.UTF_8)),
- systemSession)));
-
- MailboxId otherMailboxId = mailboxManager.getMailbox(otherMailboxPath,
systemSession).getId();
-
- String taskId = given()
- .queryParam("action", "triage")
- .body(RULE_PAYLOAD.formatted(otherMailboxId.serialize()))
- .post(MAILBOX_NAME + "/messages")
- .then()
- .statusCode(CREATED_201)
- .extract()
- .jsonPath()
- .get("taskId");
-
- given()
- .basePath(TasksRoutes.BASE)
- .when()
- .get(taskId + "/await")
- .then()
- .body("status", Matchers.is("completed"))
- .body("additionalInformation.rulesOnMessagesApplySuccessfully",
Matchers.lessThan(20))
- .body("additionalInformation.rulesOnMessagesApplyFailed",
Matchers.is(0))
- .body("additionalInformation.maximumAppliedActionExceeded",
Matchers.is(true));
- }
-
- @Test
- void taskShouldCompleteWhenAppliedActionsReachMaximumLimit() throws
Exception {
- overrideTriageRulesRouteWithActionsLimit(2);
-
- MailboxPath mailboxPath = MailboxPath.forUser(USERNAME, MAILBOX_NAME);
- MailboxPath otherMailboxPath = MailboxPath.forUser(USERNAME,
OTHER_MAILBOX_NAME);
- MailboxSession systemSession =
mailboxManager.createSystemSession(USERNAME);
-
- mailboxManager.createMailbox(mailboxPath, systemSession);
- mailboxManager.createMailbox(otherMailboxPath, systemSession);
-
- MessageManager messageManager = mailboxManager.getMailbox(mailboxPath,
systemSession);
+ .setBody("body", StandardCharsets.UTF_8)),
+ systemSession);
- // Add 2 matching messages, reach the limit of 2
- IntStream.range(0, 2)
- .forEach(Throwing.intConsumer(i -> messageManager.appendMessage(
+ messageManager.appendMessage(
MessageManager.AppendCommand.builder()
.build(Message.Builder.of()
- .setSubject("plop")
+ .setSubject("hello")
.setFrom("[email protected]")
- .setBody("matched mail", StandardCharsets.UTF_8)),
- systemSession)));
-
- MailboxId otherMailboxId = mailboxManager.getMailbox(otherMailboxPath,
systemSession).getId();
-
- String taskId = given()
- .queryParam("action", "triage")
- .body(RULE_PAYLOAD.formatted(otherMailboxId.serialize()))
- .post(MAILBOX_NAME + "/messages")
- .then()
- .statusCode(CREATED_201)
- .extract()
- .jsonPath()
- .get("taskId");
-
- given()
- .basePath(TasksRoutes.BASE)
- .when()
- .get(taskId + "/await")
- .then()
- .body("status", Matchers.is("completed"))
- .body("additionalInformation.rulesOnMessagesApplySuccessfully",
Matchers.is(2))
- .body("additionalInformation.rulesOnMessagesApplyFailed",
Matchers.is(0))
- .body("additionalInformation.maximumAppliedActionExceeded",
Matchers.is(false));
- }
+ .setBody("body", StandardCharsets.UTF_8)),
+ systemSession);
- @Test
- void taskShouldCompleteWhenAppliedActionsLessThanMaximumLimit() throws
Exception {
- overrideTriageRulesRouteWithActionsLimit(10);
+ messageManager.appendMessage(
+ MessageManager.AppendCommand.builder()
+ .build(Message.Builder.of()
+ .setSubject("hello")
+ .setFrom("[email protected]")
+ .setBody("body", StandardCharsets.UTF_8)),
+ systemSession);
- MailboxPath mailboxPath = MailboxPath.forUser(USERNAME, MAILBOX_NAME);
- MailboxPath otherMailboxPath = MailboxPath.forUser(USERNAME,
OTHER_MAILBOX_NAME);
- MailboxSession systemSession =
mailboxManager.createSystemSession(USERNAME);
+ MailboxId otherMailboxId =
mailboxManager.getMailbox(otherMailboxPath, systemSession).getId();
- mailboxManager.createMailbox(mailboxPath, systemSession);
- mailboxManager.createMailbox(otherMailboxPath, systemSession);
+ String taskId = given()
+ .queryParam("action", "triage")
+ .body(RULE_PAYLOAD.formatted(otherMailboxId.serialize()))
+ .post(MAILBOX_NAME + "/messages")
+ .then()
+ .statusCode(CREATED_201)
+ .extract()
+ .jsonPath()
+ .get("taskId");
- MessageManager messageManager = mailboxManager.getMailbox(mailboxPath,
systemSession);
+ given()
+ .basePath(TasksRoutes.BASE)
+ .when()
+ .get(taskId + "/await")
+ .then()
+ .body("status", Matchers.is("completed"))
+ .body("taskId", Matchers.is(notNullValue()))
+ .body("type",
Matchers.is(RunRulesOnMailboxTask.TASK_TYPE.asString()))
+ .body("startedDate", Matchers.is(notNullValue()))
+ .body("submitDate", Matchers.is(notNullValue()))
+ .body("completedDate", Matchers.is(notNullValue()))
+ .body("additionalInformation.username",
Matchers.is(USERNAME.asString()))
+ .body("additionalInformation.mailboxName",
Matchers.is(MAILBOX_NAME))
+
.body("additionalInformation.rulesOnMessagesApplySuccessfully", Matchers.is(2))
+ .body("additionalInformation.rulesOnMessagesApplyFailed",
Matchers.is(0));
+ }
+ }
- // Add 2 matching messages, < the limit of 10
- IntStream.range(0, 2)
- .forEach(Throwing.intConsumer(i -> messageManager.appendMessage(
- MessageManager.AppendCommand.builder()
+ @Disabled("JAMES-4148: Route not plugged yet")
+ @Nested
+ class RunRulesOnAllUsersMailbox {
+ @BeforeEach
+ void setUp() throws Exception {
+ createServer("/messages");
+
+ when(usersRepository.listReactive())
+ .thenReturn(Flux.fromIterable(ImmutableList.of(USERNAME,
ALICE, BOB)));
+ }
+
+ @Test
+ void
runRulesOnAllUsersMailboxShouldReturnErrorWhenMailboxNameQueryParamIsMissing() {
+ Map<String, Object> errors = given()
+ .queryParam("action", "triage")
+ .body(RULE_MOVE_TO_PAYLOAD.formatted("2"))
+ .post()
+ .then()
+ .statusCode(BAD_REQUEST_400)
+ .contentType(JSON)
+ .extract()
+ .body()
+ .jsonPath()
+ .getMap(".");
+
+ assertThat(errors)
+ .containsEntry("statusCode", BAD_REQUEST_400)
+ .containsEntry("type", ERROR_TYPE_INVALIDARGUMENT)
+ .containsEntry("message", "Invalid arguments supplied in the
user request")
+ .containsEntry("details", "mailboxName query param is
missing");
+ }
+
+ @Test
+ void
runRulesOnAllUsersMailboxShouldReturnErrorWhenActionQueryParamIsMissing() {
+ Map<String, Object> errors = given()
+ .queryParam("mailboxName", MAILBOX_NAME)
+ .body(RULE_MOVE_TO_PAYLOAD.formatted("2"))
+ .post()
+ .then()
+ .statusCode(BAD_REQUEST_400)
+ .contentType(JSON)
+ .extract()
+ .body()
+ .jsonPath()
+ .getMap(".");
+
+ assertThat(errors)
+ .containsEntry("statusCode", BAD_REQUEST_400)
+ .containsEntry("type", ERROR_TYPE_INVALIDARGUMENT)
+ .containsEntry("message", "Invalid arguments supplied in the
user request")
+ .containsEntry("details", "'action' query parameter is
compulsory. Supported values are [triage]");
+ }
+
+ @Test
+ void runRulesOnAllUsersMailboxShouldReturnErrorWhenNoPayload() {
+ Map<String, Object> errors = given()
+ .queryParams("action", "triage", "mailboxName", MAILBOX_NAME)
+ .post()
+ .then()
+ .statusCode(BAD_REQUEST_400)
+ .contentType(JSON)
+ .extract()
+ .body()
+ .jsonPath()
+ .getMap(".");
+
+ assertThat(errors)
+ .containsEntry("statusCode", BAD_REQUEST_400)
+ .containsEntry("type", ERROR_TYPE_INVALIDARGUMENT)
+ .containsEntry("message", "JSON payload of the request is not
valid");
+ }
+
+ @Test
+ void runRulesOnAllUsersMailboxShouldReturnErrorWhenBadPayload() {
+ Map<String, Object> errors = given()
+ .queryParams("action", "triage", "mailboxName", MAILBOX_NAME)
+ .body("""
+ {
+ "id": "1",
+ "name": "rule 1",
+ "condition": bad condition",
+ "action": "bad action"
+ }""")
+ .post()
+ .then()
+ .statusCode(BAD_REQUEST_400)
+ .contentType(JSON)
+ .extract()
+ .body()
+ .jsonPath()
+ .getMap(".");
+
+ assertThat(errors)
+ .containsEntry("statusCode", BAD_REQUEST_400)
+ .containsEntry("type", ERROR_TYPE_INVALIDARGUMENT)
+ .containsEntry("message", "JSON payload of the request is not
valid");
+ }
+
+ @Test
+ void
runRulesOnAllUsersMailboxShouldReturnErrorWhenRuleActionAppendInMailboxesIsDefined()
{
+ Map<String, Object> errors = given()
+ .queryParams("action", "triage", "mailboxName", MAILBOX_NAME)
+ .body("""
+ {
+ "id": "1",
+ "name": "rule 1",
+ "action": {
+ "appendIn": {
+ "mailboxIds": ["123"]
+ },
+ "important": false,
+ "keyworkds": [],
+ "reject": false,
+ "seen": false
+ },
+ "conditionGroup": {
+ "conditionCombiner": "OR",
+ "conditions": [
+ {
+ "comparator": "contains",
+ "field": "subject",
+ "value": "plop"
+ },
+ {
+ "comparator": "exactly-equals",
+ "field": "from",
+ "value": "[email protected]"
+ }
+ ]
+ }
+ }""")
+ .post()
+ .then()
+ .statusCode(BAD_REQUEST_400)
+ .contentType(JSON)
+ .extract()
+ .body()
+ .jsonPath()
+ .getMap(".");
+
+ assertThat(errors)
+ .containsEntry("statusCode", BAD_REQUEST_400)
+ .containsEntry("type", ERROR_TYPE_INVALIDARGUMENT)
+ .containsEntry("message", "Invalid arguments supplied in the
user request")
+ .containsEntry("details", "Rule payload should not have
[appendInMailboxes] action defined for runRulesOnAllUsersMailbox route");
+ }
+
+ @Test
+ void runRulesOnAllUsersMailboxShouldReturnListOfTaskIdPerUser() throws
MailboxException {
+ createUserMailboxes();
+
+ List<Map<String, String>> list = given()
+ .queryParams("action", "triage", "mailboxName", MAILBOX_NAME)
+ .body(RULE_MOVE_TO_PAYLOAD.formatted(MOVE_TO_MAILBOX_NAME))
+ .post()
+ .then()
+ .statusCode(CREATED_201)
+ .extract()
+ .jsonPath()
+ .getList(".");
+
+ assertThat(list)
+ .hasSize(3)
+ .first()
+ .satisfies(map -> assertThat(map).hasSize(2)
+ .containsKeys("taskId")
+ .containsEntry("username", USERNAME.asString()));
+ }
+
+ @Test
+ void runRulesOnAllUsersMailboxShouldManageMixedCase() throws Exception
{
+ createUserMailboxes();
+ createUserMessages(MailboxPath.forUser(USERNAME, MAILBOX_NAME));
+ createUserMessages(MailboxPath.forUser(ALICE, MAILBOX_NAME));
+ createUserMessages(MailboxPath.forUser(BOB, MAILBOX_NAME));
+
+ List<Map<String, String>> results = given()
+ .queryParams("action", "triage", "mailboxName", MAILBOX_NAME)
+ .body(RULE_MOVE_TO_PAYLOAD.formatted(MOVE_TO_MAILBOX_NAME))
+ .post()
+ .then()
+ .statusCode(CREATED_201)
+ .extract()
+ .jsonPath()
+ .getList(".");
+
+ results.stream()
+ .map(result -> result.get("taskId"))
+ .forEach(taskId ->
+ given()
+ .basePath(TasksRoutes.BASE)
+ .when()
+ .get(taskId + "/await"));
+
+ SoftAssertions.assertSoftly(
+ softly -> {
+ MailboxSession usernameSession =
mailboxManager.createSystemSession(USERNAME);
+ softly.assertThat(Throwing.supplier(() ->
mailboxManager.getMailbox(MailboxPath.forUser(USERNAME, MAILBOX_NAME),
usernameSession).getMailboxCounters(usernameSession).getCount()).get())
+ .isEqualTo(1);
+ softly.assertThat(Throwing.supplier(() ->
mailboxManager.getMailbox(MailboxPath.forUser(USERNAME, MOVE_TO_MAILBOX_NAME),
usernameSession).getMailboxCounters(usernameSession).getCount()).get())
+ .isEqualTo(2);
+
+ MailboxSession aliceSession =
mailboxManager.createSystemSession(ALICE);
+ softly.assertThat(Throwing.supplier(() ->
mailboxManager.getMailbox(MailboxPath.forUser(ALICE, MAILBOX_NAME),
aliceSession).getMailboxCounters(aliceSession).getCount()).get())
+ .isEqualTo(1);
+ softly.assertThat(Throwing.supplier(() ->
mailboxManager.getMailbox(MailboxPath.forUser(ALICE, MOVE_TO_MAILBOX_NAME),
aliceSession).getMailboxCounters(aliceSession).getCount()).get())
+ .isEqualTo(2);
+
+ MailboxSession bobSession =
mailboxManager.createSystemSession(BOB);
+ softly.assertThat(Throwing.supplier(() ->
mailboxManager.getMailbox(MailboxPath.forUser(BOB, MAILBOX_NAME),
bobSession).getMailboxCounters(bobSession).getCount()).get())
+ .isEqualTo(1);
+ softly.assertThat(Throwing.supplier(() ->
mailboxManager.getMailbox(MailboxPath.forUser(BOB, MOVE_TO_MAILBOX_NAME),
bobSession).getMailboxCounters(bobSession).getCount()).get())
+ .isEqualTo(2);
+ }
+ );
+ }
+
+ @Test
+ void
runRulesOnAllUsersMailboxShouldReturnNoopOnUsersWhenMailboxNameDoesNotExist()
throws Exception {
+ createUserMailboxes();
+ MailboxSession systemSession =
mailboxManager.createSystemSession(USERNAME);
+ mailboxManager.createMailbox(MailboxPath.forUser(USERNAME,
OTHER_MAILBOX_NAME), systemSession);
+
+ List<Map<String, String>> results = given()
+ .queryParams("action", "triage", "mailboxName",
OTHER_MAILBOX_NAME)
+ .body(RULE_MOVE_TO_PAYLOAD.formatted(MOVE_TO_MAILBOX_NAME))
+ .post()
+ .then()
+ .statusCode(CREATED_201)
+ .extract()
+ .jsonPath()
+ .getList(".");
+
+ assertThat(results)
+ .hasSize(1)
+ .first()
+ .satisfies(map -> assertThat(map).hasSize(2)
+ .containsKeys("taskId")
+ .containsEntry("username", USERNAME.asString()));
+ }
+
+ @Test
+ void taskShouldStopAndCompleteWhenAppliedActionsExceedMaximumLimit()
throws Exception {
+ overrideTriageRulesRouteWithActionsLimit(2);
+
+ MailboxPath mailboxPath = MailboxPath.forUser(USERNAME,
MAILBOX_NAME);
+ MailboxPath otherMailboxPath = MailboxPath.forUser(USERNAME,
OTHER_MAILBOX_NAME);
+ MailboxSession systemSession =
mailboxManager.createSystemSession(USERNAME);
+
+ mailboxManager.createMailbox(mailboxPath, systemSession);
+ mailboxManager.createMailbox(otherMailboxPath, systemSession);
+
+ MessageManager messageManager =
mailboxManager.getMailbox(mailboxPath, systemSession);
+
+ // Add 20 matching messages, which exceeds the max actions of 2
+ IntStream.range(0, 20)
+ .forEach(Throwing.intConsumer(i ->
messageManager.appendMessage(
+ MessageManager.AppendCommand.builder()
+ .build(Message.Builder.of()
+ .setSubject("plop")
+ .setFrom("[email protected]")
+ .setBody("matched mail", StandardCharsets.UTF_8)),
+ systemSession)));
+
+ MailboxId otherMailboxId =
mailboxManager.getMailbox(otherMailboxPath, systemSession).getId();
+
+ String taskId = given()
+ .queryParam("action", "triage")
+ .body(RULE_PAYLOAD.formatted(otherMailboxId.serialize()))
+ .post(MAILBOX_NAME + "/messages")
+ .then()
+ .statusCode(CREATED_201)
+ .extract()
+ .jsonPath()
+ .get("taskId");
+
+ given()
+ .basePath(TasksRoutes.BASE)
+ .when()
+ .get(taskId + "/await")
+ .then()
+ .body("status", Matchers.is("completed"))
+
.body("additionalInformation.rulesOnMessagesApplySuccessfully",
Matchers.lessThan(20))
+ .body("additionalInformation.rulesOnMessagesApplyFailed",
Matchers.is(0))
+ .body("additionalInformation.maximumAppliedActionExceeded",
Matchers.is(true));
+ }
+
+ private void createUserMessages(MailboxPath mailboxPath) throws
Exception {
+ MailboxSession systemSession =
mailboxManager.createSystemSession(mailboxPath.getUser());
+ MessageManager messageManager =
mailboxManager.getMailbox(mailboxPath, systemSession);
+
+ messageManager.appendMessage(MessageManager.AppendCommand.builder()
.build(Message.Builder.of()
.setSubject("plop")
.setFrom("[email protected]")
- .setBody("matched mail", StandardCharsets.UTF_8)),
- systemSession)));
-
- MailboxId otherMailboxId = mailboxManager.getMailbox(otherMailboxPath,
systemSession).getId();
-
- String taskId = given()
- .queryParam("action", "triage")
- .body(RULE_PAYLOAD.formatted(otherMailboxId.serialize()))
- .post(MAILBOX_NAME + "/messages")
- .then()
- .statusCode(CREATED_201)
- .extract()
- .jsonPath()
- .get("taskId");
-
- given()
- .basePath(TasksRoutes.BASE)
- .when()
- .get(taskId + "/await")
- .then()
- .body("status", Matchers.is("completed"))
- .body("additionalInformation.rulesOnMessagesApplySuccessfully",
Matchers.is(2))
- .body("additionalInformation.rulesOnMessagesApplyFailed",
Matchers.is(0))
- .body("additionalInformation.maximumAppliedActionExceeded",
Matchers.is(false));
- }
+ .setBody("body", StandardCharsets.UTF_8)),
+ systemSession);
- private void overrideTriageRulesRouteWithActionsLimit(int maxActionsLimit)
{
- webAdminServer.destroy();
- webAdminServer = WebAdminUtils.createWebAdminServer(
- new RunRulesOnMailboxRoutes(usersRepository, mailboxManager,
taskManager, new JsonTransformer(),
- new RunRulesOnMailboxService(mailboxManager, new
InMemoryId.Factory(), messageIdManager, maxActionsLimit)),
- new TasksRoutes(taskManager, new JsonTransformer(),
-
DTOConverter.of(RunRulesOnMailboxTaskAdditionalInformationDTO.SERIALIZATION_MODULE)))
- .start();
+ messageManager.appendMessage(
+ MessageManager.AppendCommand.builder()
+ .build(Message.Builder.of()
+ .setSubject("hello")
+ .setFrom("[email protected]")
+ .setBody("body", StandardCharsets.UTF_8)),
+ systemSession);
- RestAssured.requestSpecification =
WebAdminUtils.buildRequestSpecification(webAdminServer)
- .setBasePath(USERS_BASE + SEPARATOR + USERNAME.asString() +
SEPARATOR + UserMailboxesRoutes.MAILBOXES)
- .setUrlEncodingEnabled(false)
- .build();
+ messageManager.appendMessage(
+ MessageManager.AppendCommand.builder()
+ .build(Message.Builder.of()
+ .setSubject("hello")
+ .setFrom("[email protected]")
+ .setBody("body", StandardCharsets.UTF_8)),
+ systemSession);
+ }
+
+ private void createUserMailboxes() throws MailboxException {
+ MailboxSession systemSession =
mailboxManager.createSystemSession(USERNAME);
+ mailboxManager.createMailbox(MailboxPath.forUser(USERNAME,
MAILBOX_NAME), systemSession);
+ mailboxManager.createMailbox(MailboxPath.forUser(USERNAME,
MOVE_TO_MAILBOX_NAME), systemSession);
+
+ systemSession = mailboxManager.createSystemSession(ALICE);
+ mailboxManager.createMailbox(MailboxPath.forUser(ALICE,
MAILBOX_NAME), systemSession);
+ mailboxManager.createMailbox(MailboxPath.forUser(ALICE,
MOVE_TO_MAILBOX_NAME), systemSession);
+
+ systemSession = mailboxManager.createSystemSession(BOB);
+ mailboxManager.createMailbox(MailboxPath.forUser(BOB,
MAILBOX_NAME), systemSession);
+ mailboxManager.createMailbox(MailboxPath.forUser(BOB,
MOVE_TO_MAILBOX_NAME), systemSession);
+ }
+
+ @Test
+ void taskShouldCompleteWhenAppliedActionsReachMaximumLimit() throws
Exception {
+ overrideTriageRulesRouteWithActionsLimit(2);
+
+ MailboxPath mailboxPath = MailboxPath.forUser(USERNAME,
MAILBOX_NAME);
+ MailboxPath otherMailboxPath = MailboxPath.forUser(USERNAME,
OTHER_MAILBOX_NAME);
+ MailboxSession systemSession =
mailboxManager.createSystemSession(USERNAME);
+
+ mailboxManager.createMailbox(mailboxPath, systemSession);
+ mailboxManager.createMailbox(otherMailboxPath, systemSession);
+
+ MessageManager messageManager =
mailboxManager.getMailbox(mailboxPath, systemSession);
+
+ // Add 2 matching messages, reach the limit of 2
+ IntStream.range(0, 2)
+ .forEach(Throwing.intConsumer(i ->
messageManager.appendMessage(
+ MessageManager.AppendCommand.builder()
+ .build(Message.Builder.of()
+ .setSubject("plop")
+ .setFrom("[email protected]")
+ .setBody("matched mail", StandardCharsets.UTF_8)),
+ systemSession)));
+
+ MailboxId otherMailboxId =
mailboxManager.getMailbox(otherMailboxPath, systemSession).getId();
+
+ String taskId = given()
+ .queryParam("action", "triage")
+ .body(RULE_PAYLOAD.formatted(otherMailboxId.serialize()))
+ .post(MAILBOX_NAME + "/messages")
+ .then()
+ .statusCode(CREATED_201)
+ .extract()
+ .jsonPath()
+ .get("taskId");
+
+ given()
+ .basePath(TasksRoutes.BASE)
+ .when()
+ .get(taskId + "/await")
+ .then()
+ .body("status", Matchers.is("completed"))
+
.body("additionalInformation.rulesOnMessagesApplySuccessfully", Matchers.is(2))
+ .body("additionalInformation.rulesOnMessagesApplyFailed",
Matchers.is(0))
+ .body("additionalInformation.maximumAppliedActionExceeded",
Matchers.is(false));
+ }
+
+ @Test
+ void taskShouldCompleteWhenAppliedActionsLessThanMaximumLimit() throws
Exception {
+ overrideTriageRulesRouteWithActionsLimit(10);
+
+ MailboxPath mailboxPath = MailboxPath.forUser(USERNAME,
MAILBOX_NAME);
+ MailboxPath otherMailboxPath = MailboxPath.forUser(USERNAME,
OTHER_MAILBOX_NAME);
+ MailboxSession systemSession =
mailboxManager.createSystemSession(USERNAME);
+
+ mailboxManager.createMailbox(mailboxPath, systemSession);
+ mailboxManager.createMailbox(otherMailboxPath, systemSession);
+
+ MessageManager messageManager =
mailboxManager.getMailbox(mailboxPath, systemSession);
+
+ // Add 2 matching messages, < the limit of 10
+ IntStream.range(0, 2)
+ .forEach(Throwing.intConsumer(i ->
messageManager.appendMessage(
+ MessageManager.AppendCommand.builder()
+ .build(Message.Builder.of()
+ .setSubject("plop")
+ .setFrom("[email protected]")
+ .setBody("matched mail", StandardCharsets.UTF_8)),
+ systemSession)));
+
+ MailboxId otherMailboxId =
mailboxManager.getMailbox(otherMailboxPath, systemSession).getId();
+
+ String taskId = given()
+ .queryParam("action", "triage")
+ .body(RULE_PAYLOAD.formatted(otherMailboxId.serialize()))
+ .post(MAILBOX_NAME + "/messages")
+ .then()
+ .statusCode(CREATED_201)
+ .extract()
+ .jsonPath()
+ .get("taskId");
+
+ given()
+ .basePath(TasksRoutes.BASE)
+ .when()
+ .get(taskId + "/await")
+ .then()
+ .body("status", Matchers.is("completed"))
+
.body("additionalInformation.rulesOnMessagesApplySuccessfully", Matchers.is(2))
+ .body("additionalInformation.rulesOnMessagesApplyFailed",
Matchers.is(0))
+ .body("additionalInformation.maximumAppliedActionExceeded",
Matchers.is(false));
+ }
+
+ private void overrideTriageRulesRouteWithActionsLimit(int
maxActionsLimit) {
+ webAdminServer.destroy();
+ RunRulesOnMailboxService service = new
RunRulesOnMailboxService(mailboxManager, new InMemoryId.Factory(),
messageIdManager, maxActionsLimit);
+ webAdminServer = WebAdminUtils.createWebAdminServer(
+ new RunRulesOnMailboxRoutes(usersRepository,
mailboxManager, taskManager, new JsonTransformer(), service,
+ Optional.of(new
RunRuleOnAllMailboxesRoute(usersRepository, mailboxManager, service,
taskManager))),
+ new TasksRoutes(taskManager, new JsonTransformer(),
+
DTOConverter.of(RunRulesOnMailboxTaskAdditionalInformationDTO.SERIALIZATION_MODULE)))
+ .start();
+
+ RestAssured.requestSpecification =
WebAdminUtils.buildRequestSpecification(webAdminServer)
+ .setBasePath(USERS_BASE + SEPARATOR + USERNAME.asString() +
SEPARATOR + UserMailboxesRoutes.MAILBOXES)
+ .setUrlEncodingEnabled(false)
+ .build();
+ }
}
}
diff --git
a/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/routes/MessagesRoutes.java
b/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/routes/MessagesRoutes.java
index 44db76b497..5142f9c09d 100644
---
a/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/routes/MessagesRoutes.java
+++
b/server/protocols/webadmin/webadmin-mailbox/src/main/java/org/apache/james/webadmin/routes/MessagesRoutes.java
@@ -60,6 +60,7 @@ public class MessagesRoutes implements Routes {
private final ExpireMailboxService expireMailboxService;
private final JsonTransformer jsonTransformer;
private final Set<TaskFromRequestRegistry.TaskRegistration>
allMessagesTaskRegistration;
+ private final Set<ConditionalRoute> postOverrides;
private final UsersRepository usersRepository;
public static final String ALL_MESSAGES_TASKS = "allMessagesTasks";
@@ -67,13 +68,16 @@ public class MessagesRoutes implements Routes {
@Inject
MessagesRoutes(TaskManager taskManager, MessageId.Factory
messageIdFactory, MessageIdReIndexer reIndexer,
ExpireMailboxService expireMailboxService, JsonTransformer
jsonTransformer,
- @Named(ALL_MESSAGES_TASKS)
Set<TaskFromRequestRegistry.TaskRegistration> allMessagesTaskRegistration,
UsersRepository usersRepository) {
+ @Named(ALL_MESSAGES_TASKS)
Set<TaskFromRequestRegistry.TaskRegistration> allMessagesTaskRegistration,
+ @Named(ALL_MESSAGES_TASKS) Set<ConditionalRoute>
postOverrides,
+ UsersRepository usersRepository) {
this.taskManager = taskManager;
this.messageIdFactory = messageIdFactory;
this.reIndexer = reIndexer;
this.expireMailboxService = expireMailboxService;
this.jsonTransformer = jsonTransformer;
this.allMessagesTaskRegistration = allMessagesTaskRegistration;
+ this.postOverrides = postOverrides;
this.usersRepository = usersRepository;
}
@@ -87,8 +91,10 @@ public class MessagesRoutes implements Routes {
TaskFromRequest expireMailboxTaskRequest = this::expireMailbox;
service.delete(BASE_PATH,
expireMailboxTaskRequest.asRoute(taskManager), jsonTransformer);
service.post(MESSAGE_PATH, reIndexMessage(), jsonTransformer);
- allMessagesOperations()
- .ifPresent(route -> service.post(BASE_PATH, route,
jsonTransformer));
+
+ if (!postOverrides.isEmpty() &&
!allMessagesTaskRegistration.isEmpty()) {
+ service.post(BASE_PATH, allMessagesOperations(), jsonTransformer);
+ }
}
private Task expireMailbox(Request request) {
@@ -135,10 +141,19 @@ public class MessagesRoutes implements Routes {
}
}
- private Optional<Route> allMessagesOperations() {
- return TaskFromRequestRegistry.builder()
- .parameterName(TASK_PARAMETER)
- .registrations(allMessagesTaskRegistration)
- .buildAsRouteOptional(taskManager);
+ private Route allMessagesOperations() {
+ return (request, response) -> {
+ Optional<Route> override = postOverrides.stream()
+ .filter(postOverride -> postOverride.test(request))
+ .map(r -> (Route) r)
+ .findAny();
+
+ return override.or(() -> TaskFromRequestRegistry.builder()
+ .parameterName(TASK_PARAMETER)
+ .registrations(allMessagesTaskRegistration)
+ .buildAsRouteOptional(taskManager))
+ .get()
+ .handle(request, response);
+ };
}
}
diff --git
a/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/routes/MessageRoutesExpireTest.java
b/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/routes/MessageRoutesExpireTest.java
index 2926f3a272..57e5b3010a 100644
---
a/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/routes/MessageRoutesExpireTest.java
+++
b/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/routes/MessageRoutesExpireTest.java
@@ -88,6 +88,7 @@ class MessageRoutesExpireTest {
new ExpireMailboxService(usersRepository, mailboxManager,
Clock.systemUTC()),
jsonTransformer,
ImmutableSet.of(),
+ ImmutableSet.of(),
usersRepository))
.start();
diff --git
a/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/routes/MessageRoutesTest.java
b/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/routes/MessageRoutesTest.java
index 5171283246..ef86640659 100644
---
a/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/routes/MessageRoutesTest.java
+++
b/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/routes/MessageRoutesTest.java
@@ -96,6 +96,7 @@ class MessageRoutesTest {
null,
jsonTransformer,
ImmutableSet.of(),
+ ImmutableSet.of(),
null))
.start();
diff --git a/src/site/markdown/server/manage-webadmin.md
b/src/site/markdown/server/manage-webadmin.md
index de0f231a14..14f57fc1b2 100644
--- a/src/site/markdown/server/manage-webadmin.md
+++ b/src/site/markdown/server/manage-webadmin.md
@@ -1485,6 +1485,69 @@ However the source of truth will not be impacted, hence
rerunning the task will
This task could be run safely online and can be scheduled on a recurring basis
outside of peak traffic
by an admin to ensure Cassandra message consistency.
+=== Running a filtering rule on a specific mailbox for all users
+
+```
+curl -XPOST http://ip:port/messages?action=triage&mailboxName={mailboxName} \
+-d '{
+ "id": "1",
+ "name": "rule 1",
+ "action": {
+ "moveTo": {
+ "mailboxName": "Trash"
+ }
+ },
+ "conditionGroup": {
+ "conditionCombiner": "OR",
+ "conditions": [
+ {
+ "comparator": "contains",
+ "field": "subject",
+ "value": "plop"
+ },
+ {
+ "comparator": "exactly-equals",
+ "field": "from",
+ "value": "[email protected]"
+ }
+ ]
+ }
+}'
+```
+
+Will schedule a task for each user running a filtering rule passed as query
parameter in `mailboxName` mailbox.
+
+Query parameter `mailboxName` should not be empty, nor contain `% *`
characters, nor starting with `#`.
+If a user does not have a mailbox with that name, it will skip that user.
+
+The action of the rule should be `moveTo` with a mailbox name defined. If
mailbox ids are defined in `appendIn` action,
+it will fail, as it makes no sense cluster scoped.
+
+Response codes:
+
+* 201: Success. Map[Username, TaskId] is returned.
+* 400: Invalid mailbox name
+* 400: Invalid JSON payload (including mailbox ids defined in the action)
+* 400: mailboxName query parameter is missing
+
+The response is a map of task id per user:
+
+```
+[
+ {
+ "username": "[email protected]", "taskId":
"5641376-02ed-47bd-bcc7-76ff6262d92a"
+ },
+ {
+ "username": "[email protected]", "taskId":
"5641376-02ed-47bd-bcc7-42cc1313f47b"
+ },
+
+ [...]
+
+]
+```
+
+[More details about details returned by running a filtering rule on a
mailbox](#Running_a_filtering_rule_on_a_mailbox).
+
## Administrating user mailboxes
- [Creating a mailbox](#Creating_a_mailbox)
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]