You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@james.apache.org by rc...@apache.org on 2021/01/12 11:01:59 UTC

[james-project] branch master updated (0e0f9af -> 6d899ce)

This is an automated email from the ASF dual-hosted git repository.

rcordier pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/james-project.git.


    from 0e0f9af  JAMES-2543 Migrates MPT SMTP tests to fully use Junit 5
     new b0cfc20  JAMES-3471 JPA and maildir message mappers should not register MessageId when handling FlagsUpdated events
     new 11ad4f5  JAMES-3488 Support TLS 1.3
     new 52382ef  JAMES-3472 Fix indentation in JmapRequests object
     new eaa97ab  JAMES-3472 Allows JMAPGuiceProbe fetching Email/changes state
     new c06ee0e  JAMES-3472 Update Email/changes request & response
     new 8204dc0  JAMES-3472 Email/changes method implementation & contract
     new a2be7b8  JAMES-3472 JMAP Probe method name clarification
     new 97c3f01  JAMES-3472 MemoryMailboxChangesMethodTest should generate random mailboxId
     new 9f72a00  JAMES-3473 Remove duplicated sort condition
     new f995248  JAMES-3473 Save/fetch Email State with JMAP probe
     new 2bbd5b2  JAMES-3473 Email/get should return latest state
     new 1e19c6b  JAMES-3473 New state should be ignored in irrelevant Email/get calls
     new a60a778  JAMES-3473 Dummy CassandraEmailChangeRepository should return initial state
     new 2492467  JAMES-2543 Junit 4 -> 5 migration for WebAdmin
     new d392709  JAMES-2543 Junit 4 -> 5 migration for JWT helpers
     new c51bb1b  JAMES-2543 Junit 4 -> 5 migration for server/protocols/imap
     new 192ff4e  JAMES-2543 Junit 4 -> 5 migration for server/protocols/pop3
     new dd12ea9  JAMES-2543 Junit 4 -> 5 migration for server/protocols/smtp
     new 2e0a454  JAMES-2543 Junit 4 -> 5 migration for mock SpamAssassin testing
     new 6d899ce  JAMES-2543 Junit 4 -> 5 public access modifier cleanups

The 20 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../apache/james/mailbox/model/UpdatedFlags.java   |   11 +-
 .../james/mailbox/jpa/mail/MessageUtils.java       |    1 -
 .../mailbox/jpa/mail/JpaMessageMapperTest.java     |   80 +-
 .../mailbox/maildir/mail/MaildirMessageMapper.java |    1 -
 .../store/mail/model/MessageMapperTest.java        |    3 +-
 pom.xml                                            |    2 +-
 .../apache/james/jmap/draft/JmapGuiceProbe.java    |   23 +-
 .../change/CassandraEmailChangeRepository.java     |    4 +-
 .../memory/change/MemoryEmailChangeRepository.java |    1 -
 .../james/transport/mailets/SpamAssassinTest.java  |   43 +-
 .../rfc8621/contract/BackReferenceContract.scala   |    1 +
 .../rfc8621/contract/EmailChangesContract.scala    |  173 ---
 .../contract/EmailChangesMethodContract.scala      | 1150 ++++++++++++++++++++
 .../rfc8621/contract/EmailGetMethodContract.scala  |  233 ++--
 .../rfc8621/contract/EmailSetMethodContract.scala  |  235 ++--
 .../EmailSubmissionSetMethodContract.scala         |    8 +-
 .../james/jmap/rfc8621/contract/JmapRequests.scala |   16 +-
 .../contract/MailboxChangesMethodContract.scala    |   18 +-
 .../memory/MemoryEmailChangesMethodTest.java       |   20 +-
 .../memory/MemoryMailboxChangesMethodTest.java     |    4 +-
 .../scala/org/apache/james/jmap/core/Session.scala |    4 +-
 .../james/jmap/json/EmailGetSerializer.scala       |    6 +
 .../org/apache/james/jmap/mail/EmailGet.scala      |   12 +-
 .../org/apache/james/jmap/mail/MailboxGet.scala    |    5 +-
 .../james/jmap/method/EmailChangesMethod.scala     |   48 +-
 .../apache/james/jmap/method/EmailGetMethod.scala  |   16 +-
 .../org/apache/james/jwt/JwtConfigurationTest.java |   14 +-
 .../org/apache/james/jwt/JwtTokenVerifierTest.java |   45 +-
 .../apache/james/jwt/PublicKeyProviderTest.java    |   14 +-
 .../org/apache/james/jwt/PublicKeyReaderTest.java  |   16 +-
 .../james/imapserver/netty/IMAPServerTest.java     |   13 +-
 .../apache/james/pop3server/POP3ServerTest.java    |   48 +-
 .../java/org/apache/james/smtpserver/DSNTest.java  |   30 +-
 .../smtpserver/POP3BeforeSMTPHandlerTest.java      |   12 +-
 .../apache/james/smtpserver/SMTPServerTest.java    |   16 +-
 .../apache/james/smtpserver/SPFHandlerTest.java    |    6 +-
 .../james/smtpserver/SpamAssassinHandlerTest.java  |   20 +-
 .../apache/james/smtpserver/URIRBLHandlerTest.java |   14 +-
 .../james/smtpserver/ValidRcptHandlerTest.java     |   30 +-
 .../apache/james/smtpserver/ValidRcptMXTest.java   |    6 +-
 .../james/webadmin/dto/VersionRequestTest.java     |   14 +-
 .../routes/CassandraMigrationRoutesTest.java       |   46 +-
 .../james/webadmin/FixedPortSupplierTest.java      |   16 +-
 .../james/webadmin/RandomPortSupplierTest.java     |    8 +-
 .../james/webadmin/TlsConfigurationTest.java       |   49 +-
 .../james/webadmin/WebAdminConfigurationTest.java  |   54 +-
 .../apache/james/webadmin/WebAdminServerTest.java  |   15 +-
 .../webadmin/authentication/JwtFilterTest.java     |   80 +-
 .../apache/james/webadmin/mdc/RequestIdTest.java   |    6 +-
 .../james/webadmin/routes/ErrorRoutesTest.java     |   24 +-
 .../webadmin/routes/HealthCheckRoutesTest.java     |   49 +-
 .../james/webadmin/tasks/TaskFromRequestTest.java  |    6 +-
 .../james/webadmin/utils/JsonExtractorTest.java    |   28 +-
 .../webadmin/utils/ParametersExtractorTest.java    |   34 +-
 .../webadmin/dto/UsersQuotaDetailsDTOTest.java     |   12 +-
 .../james/webadmin/dto/MailQueueDTOTest.java       |   24 +-
 .../james/webadmin/dto/MailQueueItemDTOTest.java   |   27 +-
 .../webadmin/routes/MailQueueRoutesUnitTest.java   |   19 +-
 .../routes/MailRepositoriesRoutesTest.java         |  158 +--
 .../service/MailRepositoryStoreServiceTest.java    |   32 +-
 .../webadmin/service/ReprocessingServiceTest.java  |   20 +-
 ...kSpamdTestRule.java => MockSpamdExtension.java} |   18 +-
 62 files changed, 2141 insertions(+), 1000 deletions(-)
 delete mode 100644 server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/EmailChangesContract.scala
 create mode 100644 server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/EmailChangesMethodContract.scala
 rename third-party/spamassassin/src/test/java/org/apache/james/spamassassin/mock/{MockSpamdTestRule.java => MockSpamdExtension.java} (81%)


---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@james.apache.org
For additional commands, e-mail: notifications-help@james.apache.org


[james-project] 17/20: JAMES-2543 Junit 4 -> 5 migration for server/protocols/pop3

Posted by rc...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

rcordier pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/james-project.git

commit 192ff4e0b559f4e1b43efe7986e7a1fd0385305d
Author: Benoit Tellier <bt...@linagora.com>
AuthorDate: Thu Dec 31 09:09:47 2020 +0700

    JAMES-2543 Junit 4 -> 5 migration for server/protocols/pop3
---
 .../org/apache/james/pop3server/POP3ServerTest.java    | 18 +++++++-----------
 1 file changed, 7 insertions(+), 11 deletions(-)

diff --git a/server/protocols/protocols-pop3/src/test/java/org/apache/james/pop3server/POP3ServerTest.java b/server/protocols/protocols-pop3/src/test/java/org/apache/james/pop3server/POP3ServerTest.java
index bc3b7f3..980f290 100644
--- a/server/protocols/protocols-pop3/src/test/java/org/apache/james/pop3server/POP3ServerTest.java
+++ b/server/protocols/protocols-pop3/src/test/java/org/apache/james/pop3server/POP3ServerTest.java
@@ -50,10 +50,10 @@ import org.apache.james.user.api.UsersRepository;
 import org.apache.james.user.api.UsersRepositoryException;
 import org.apache.james.user.memory.MemoryUsersRepository;
 import org.jboss.netty.util.HashedWheelTimer;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Ignore;
-import org.junit.Test;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Disabled;
+import org.junit.jupiter.api.Test;
 
 import com.google.inject.name.Names;
 
@@ -73,7 +73,7 @@ public class POP3ServerTest {
     private POP3Server pop3Server;
     private HashedWheelTimer hashedWheelTimer;
 
-    @Before
+    @BeforeEach
     public void setUp() throws Exception {
         hashedWheelTimer = new HashedWheelTimer();
         setUpServiceManager();
@@ -81,7 +81,7 @@ public class POP3ServerTest {
         pop3Configuration = new POP3TestConfiguration();
     }
 
-    @After
+    @AfterEach
     public void tearDown() throws Exception {
         try {
             if (pop3Client != null) {
@@ -422,12 +422,8 @@ public class POP3ServerTest {
 
     }
 
-    /**
-     * Test for JAMES-1202 - This was failing before as the more then one connection to the same
-     * mailbox was not handled the right way
-     */
     @Test
-    @Ignore
+    @Disabled("Test for JAMES-1202 - This was failing before as the more then one connection to the same mailbox was not handled the right way")
     public void testStatUidlListTwoConnections() throws Exception {
         finishSetUp(pop3Configuration);
 


---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@james.apache.org
For additional commands, e-mail: notifications-help@james.apache.org


[james-project] 02/20: JAMES-3488 Support TLS 1.3

Posted by rc...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

rcordier pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/james-project.git

commit 11ad4f5d5f25bf8c2876a89b73da4832681c9adb
Author: Raphael Ouazana <ra...@linagora.com>
AuthorDate: Mon Jan 11 17:39:12 2021 +0100

    JAMES-3488 Support TLS 1.3
---
 pom.xml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/pom.xml b/pom.xml
index 8ffaff4..e4f7545 100644
--- a/pom.xml
+++ b/pom.xml
@@ -643,7 +643,7 @@
         <guice.version>4.2.2</guice.version>
         <logback.version>1.2.3</logback.version>
 
-        <bouncycastle.version>1.66</bouncycastle.version>
+        <bouncycastle.version>1.68</bouncycastle.version>
 
         <scala.base>2.13</scala.base>
         <scala.version>${scala.base}.1</scala.version>


---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@james.apache.org
For additional commands, e-mail: notifications-help@james.apache.org


[james-project] 03/20: JAMES-3472 Fix indentation in JmapRequests object

Posted by rc...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

rcordier pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/james-project.git

commit 52382eff9a8e294d677233c13476ac90c54a5d92
Author: LanKhuat <dl...@linagora.com>
AuthorDate: Wed Jan 6 16:09:06 2021 +0700

    JAMES-3472 Fix indentation in JmapRequests object
---
 .../james/jmap/rfc8621/contract/JmapRequests.scala       | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/JmapRequests.scala b/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/JmapRequests.scala
index 2ac3cee..dd9cd53 100644
--- a/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/JmapRequests.scala
+++ b/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/JmapRequests.scala
@@ -73,9 +73,9 @@ object JmapRequests {
     `given`
       .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER)
       .body(request)
-      .when
+    .when
       .post
-      .`then`
+    .`then`
       .log().ifValidationFails()
       .statusCode(SC_OK)
       .contentType(JSON)
@@ -101,9 +101,9 @@ object JmapRequests {
     `given`
       .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER)
       .body(request)
-      .when
+    .when
       .post
-      .`then`
+    .`then`
       .log().ifValidationFails()
       .statusCode(SC_OK)
       .contentType(JSON)
@@ -127,9 +127,9 @@ object JmapRequests {
     `given`
       .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER)
       .body(request)
-      .when
+    .when
       .post
-      .`then`
+    .`then`
       .log().ifValidationFails()
       .statusCode(SC_OK)
       .contentType(JSON)
@@ -149,9 +149,9 @@ object JmapRequests {
     `given`
       .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER)
       .body(request)
-      .when
+    .when
       .post
-      .`then`
+    .`then`
       .log().ifValidationFails()
       .statusCode(SC_OK)
       .contentType(JSON)


---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@james.apache.org
For additional commands, e-mail: notifications-help@james.apache.org


[james-project] 14/20: JAMES-2543 Junit 4 -> 5 migration for WebAdmin

Posted by rc...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

rcordier pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/james-project.git

commit 24924675a1d3b94f16267abc52e4c46187363a11
Author: Benoit Tellier <bt...@linagora.com>
AuthorDate: Thu Dec 31 09:03:51 2020 +0700

    JAMES-2543 Junit 4 -> 5 migration for WebAdmin
---
 .../james/webadmin/dto/VersionRequestTest.java     |  14 +-
 .../routes/CassandraMigrationRoutesTest.java       |  46 +++---
 .../james/webadmin/FixedPortSupplierTest.java      |  16 +--
 .../james/webadmin/RandomPortSupplierTest.java     |   8 +-
 .../james/webadmin/TlsConfigurationTest.java       |  49 +++----
 .../james/webadmin/WebAdminConfigurationTest.java  |  54 +++----
 .../apache/james/webadmin/WebAdminServerTest.java  |  15 +-
 .../webadmin/authentication/JwtFilterTest.java     |  80 ++++-------
 .../apache/james/webadmin/mdc/RequestIdTest.java   |   6 +-
 .../james/webadmin/routes/ErrorRoutesTest.java     |  24 ++--
 .../webadmin/routes/HealthCheckRoutesTest.java     |  49 ++++---
 .../james/webadmin/tasks/TaskFromRequestTest.java  |   6 +-
 .../james/webadmin/utils/JsonExtractorTest.java    |  28 ++--
 .../webadmin/utils/ParametersExtractorTest.java    |  34 ++---
 .../webadmin/dto/UsersQuotaDetailsDTOTest.java     |  12 +-
 .../james/webadmin/dto/MailQueueDTOTest.java       |  24 ++--
 .../james/webadmin/dto/MailQueueItemDTOTest.java   |  27 ++--
 .../webadmin/routes/MailQueueRoutesUnitTest.java   |  19 ++-
 .../routes/MailRepositoriesRoutesTest.java         | 158 ++++++++++-----------
 .../service/MailRepositoryStoreServiceTest.java    |  32 ++---
 .../webadmin/service/ReprocessingServiceTest.java  |  20 +--
 21 files changed, 332 insertions(+), 389 deletions(-)

diff --git a/server/protocols/webadmin/webadmin-cassandra/src/test/java/org/apache/james/webadmin/dto/VersionRequestTest.java b/server/protocols/webadmin/webadmin-cassandra/src/test/java/org/apache/james/webadmin/dto/VersionRequestTest.java
index 228120b..2d18226 100644
--- a/server/protocols/webadmin/webadmin-cassandra/src/test/java/org/apache/james/webadmin/dto/VersionRequestTest.java
+++ b/server/protocols/webadmin/webadmin-cassandra/src/test/java/org/apache/james/webadmin/dto/VersionRequestTest.java
@@ -23,35 +23,35 @@ import static org.assertj.core.api.Assertions.assertThat;
 import static org.assertj.core.api.Assertions.assertThatThrownBy;
 
 import org.apache.james.backends.cassandra.versions.SchemaVersion;
-import org.junit.Test;
+import org.junit.jupiter.api.Test;
 
-public class VersionRequestTest {
+class VersionRequestTest {
     @Test
-    public void parseShouldThrowWhenNullVersion() throws Exception {
+    void parseShouldThrowWhenNullVersion() {
         assertThatThrownBy(() -> CassandraVersionRequest.parse(null))
             .isInstanceOf(NullPointerException.class);
     }
 
     @Test
-    public void parseShouldThrowWhenNonIntegerVersion() throws Exception {
+    void parseShouldThrowWhenNonIntegerVersion() {
         assertThatThrownBy(() -> CassandraVersionRequest.parse("NoInt"))
             .isInstanceOf(IllegalArgumentException.class);
     }
 
     @Test
-    public void parseShouldThrowWhenNegativeVersion() throws Exception {
+    void parseShouldThrowWhenNegativeVersion() {
         assertThatThrownBy(() -> CassandraVersionRequest.parse("-1"))
             .isInstanceOf(IllegalArgumentException.class);
     }
 
     @Test
-    public void parseShouldThrowWhenZeroVersion() throws Exception {
+    void parseShouldThrowWhenZeroVersion() {
         assertThatThrownBy(() -> CassandraVersionRequest.parse("0"))
             .isInstanceOf(IllegalArgumentException.class);
     }
 
     @Test
-    public void parseShouldParseTheVersionValue() throws Exception {
+    void parseShouldParseTheVersionValue() {
         CassandraVersionRequest cassandraVersionRequest = CassandraVersionRequest.parse("1");
 
         assertThat(cassandraVersionRequest.getValue()).isEqualTo(new SchemaVersion(1));
diff --git a/server/protocols/webadmin/webadmin-cassandra/src/test/java/org/apache/james/webadmin/routes/CassandraMigrationRoutesTest.java b/server/protocols/webadmin/webadmin-cassandra/src/test/java/org/apache/james/webadmin/routes/CassandraMigrationRoutesTest.java
index 8ba58a6..99fd764 100644
--- a/server/protocols/webadmin/webadmin-cassandra/src/test/java/org/apache/james/webadmin/routes/CassandraMigrationRoutesTest.java
+++ b/server/protocols/webadmin/webadmin-cassandra/src/test/java/org/apache/james/webadmin/routes/CassandraMigrationRoutesTest.java
@@ -52,10 +52,10 @@ import org.apache.james.webadmin.WebAdminUtils;
 import org.apache.james.webadmin.dto.WebAdminMigrationTaskAdditionalInformationDTO;
 import org.apache.james.webadmin.utils.JsonTransformer;
 import org.eclipse.jetty.http.HttpStatus;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Ignore;
-import org.junit.Test;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Disabled;
+import org.junit.jupiter.api.Test;
 
 import com.google.common.collect.ImmutableMap;
 
@@ -63,7 +63,7 @@ import io.restassured.RestAssured;
 import io.restassured.http.ContentType;
 import reactor.core.publisher.Mono;
 
-public class CassandraMigrationRoutesTest {
+class CassandraMigrationRoutesTest {
     private static final SchemaVersion LATEST_VERSION = new SchemaVersion(3);
     private static final SchemaVersion CURRENT_VERSION = new SchemaVersion(2);
     private static final SchemaVersion OLDER_VERSION = new SchemaVersion(1);
@@ -98,19 +98,19 @@ public class CassandraMigrationRoutesTest {
             .build();
     }
 
-    @Before
-    public void setUp() {
+    @BeforeEach
+    void setUp() {
         createServer();
     }
 
-    @After
-    public void tearDown() {
+    @AfterEach
+    void tearDown() {
         webAdminServer.destroy();
         taskManager.stop();
     }
 
     @Test
-    public void getShouldReturnTheCurrentVersion() {
+    void getShouldReturnTheCurrentVersion() {
         when(schemaVersionDAO.getCurrentSchemaVersion()).thenReturn(Mono.just(Optional.of(CURRENT_VERSION)));
 
         Integer version =
@@ -127,7 +127,7 @@ public class CassandraMigrationRoutesTest {
     }
 
     @Test
-    public void getShouldReturnTheLatestVersionWhenSetUpTheLatestVersion() {
+    void getShouldReturnTheLatestVersionWhenSetUpTheLatestVersion() {
         Integer version =
             when()
                 .get("/latest")
@@ -141,9 +141,9 @@ public class CassandraMigrationRoutesTest {
         assertThat(version).isEqualTo(LATEST_VERSION.getValue());
     }
 
-    @Ignore
+    @Disabled
     @Test
-    public void postShouldReturnConflictWhenMigrationOnRunning() {
+    void postShouldReturnConflictWhenMigrationOnRunning() {
         when()
             .post("/upgrade")
         .then()
@@ -151,7 +151,7 @@ public class CassandraMigrationRoutesTest {
     }
 
     @Test
-    public void postShouldReturnErrorCodeWhenInvalidVersion() {
+    void postShouldReturnErrorCodeWhenInvalidVersion() {
         when(schemaVersionDAO.getCurrentSchemaVersion()).thenReturn(Mono.just(Optional.of(OLDER_VERSION)));
 
         Map<String, Object> errors = given()
@@ -176,7 +176,7 @@ public class CassandraMigrationRoutesTest {
     }
 
     @Test
-    public void postShouldDoMigrationToNewVersion() {
+    void postShouldDoMigrationToNewVersion() {
         when(schemaVersionDAO.getCurrentSchemaVersion()).thenReturn(Mono.just(Optional.of(OLDER_VERSION)));
 
         String taskId = with()
@@ -198,7 +198,7 @@ public class CassandraMigrationRoutesTest {
     }
 
     @Test
-    public void postShouldCreateTaskWhenCurrentVersionIsNewerThan() {
+    void postShouldCreateTaskWhenCurrentVersionIsNewerThan() {
         when(schemaVersionDAO.getCurrentSchemaVersion()).thenReturn(Mono.just(Optional.of(CURRENT_VERSION)));
 
         String taskId =  given()
@@ -217,7 +217,7 @@ public class CassandraMigrationRoutesTest {
     }
 
     @Test
-    public void postShouldNotUpdateVersionWhenCurrentVersionIsNewerThan() {
+    void postShouldNotUpdateVersionWhenCurrentVersionIsNewerThan() {
         when(schemaVersionDAO.getCurrentSchemaVersion()).thenReturn(Mono.just(Optional.of(CURRENT_VERSION)));
 
         String taskId =  given()
@@ -236,7 +236,7 @@ public class CassandraMigrationRoutesTest {
     }
 
     @Test
-    public void postShouldPositionLocationHeader() {
+    void postShouldPositionLocationHeader() {
         when(schemaVersionDAO.getCurrentSchemaVersion()).thenReturn(Mono.just(Optional.of(CURRENT_VERSION)));
 
         given()
@@ -248,7 +248,7 @@ public class CassandraMigrationRoutesTest {
     }
 
     @Test
-    public void postShouldDoMigrationToLatestVersion() {
+    void postShouldDoMigrationToLatestVersion() {
         when(schemaVersionDAO.getCurrentSchemaVersion()).thenReturn(Mono.just(Optional.of(OLDER_VERSION)));
 
         String taskId = with()
@@ -267,7 +267,7 @@ public class CassandraMigrationRoutesTest {
     }
 
     @Test
-    public void postShouldReturnTaskIdAndLocation() {
+    void postShouldReturnTaskIdAndLocation() {
         when(schemaVersionDAO.getCurrentSchemaVersion()).thenReturn(Mono.just(Optional.of(OLDER_VERSION)));
 
         when()
@@ -278,7 +278,7 @@ public class CassandraMigrationRoutesTest {
     }
 
     @Test
-    public void createdTaskShouldHaveDetails() {
+    void createdTaskShouldHaveDetails() {
         when(schemaVersionDAO.getCurrentSchemaVersion()).thenReturn(Mono.just(Optional.of(OLDER_VERSION)));
 
         String taskId = with()
@@ -301,7 +301,7 @@ public class CassandraMigrationRoutesTest {
     }
 
     @Test
-    public void postShouldCreateTaskWhenItIsUpToDate() {
+    void postShouldCreateTaskWhenItIsUpToDate() {
         when(schemaVersionDAO.getCurrentSchemaVersion()).thenReturn(Mono.just(Optional.of(LATEST_VERSION)));
 
         String taskId = with()
@@ -318,7 +318,7 @@ public class CassandraMigrationRoutesTest {
     }
 
     @Test
-    public void postShouldNotUpdateVersionWhenItIsUpToDate() {
+    void postShouldNotUpdateVersionWhenItIsUpToDate() {
         when(schemaVersionDAO.getCurrentSchemaVersion()).thenReturn(Mono.just(Optional.of(LATEST_VERSION)));
 
         String taskId = with()
diff --git a/server/protocols/webadmin/webadmin-core/src/test/java/org/apache/james/webadmin/FixedPortSupplierTest.java b/server/protocols/webadmin/webadmin-core/src/test/java/org/apache/james/webadmin/FixedPortSupplierTest.java
index 304295d..e9633c6 100644
--- a/server/protocols/webadmin/webadmin-core/src/test/java/org/apache/james/webadmin/FixedPortSupplierTest.java
+++ b/server/protocols/webadmin/webadmin-core/src/test/java/org/apache/james/webadmin/FixedPortSupplierTest.java
@@ -22,36 +22,34 @@ package org.apache.james.webadmin;
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.assertj.core.api.Assertions.assertThatThrownBy;
 
-import org.junit.Test;
+import org.junit.jupiter.api.Test;
 
 import nl.jqno.equalsverifier.EqualsVerifier;
 
-public class FixedPortSupplierTest {
-
+class FixedPortSupplierTest {
     @Test
-    public void toIntShouldThrowOnNegativePort() {
+    void toIntShouldThrowOnNegativePort() {
         assertThatThrownBy(() -> new FixedPortSupplier(-1)).isInstanceOf(IllegalArgumentException.class);
     }
 
     @Test
-    public void toIntShouldThrowOnNullPort() {
+    void toIntShouldThrowOnNullPort() {
         assertThatThrownBy(() -> new FixedPortSupplier(0)).isInstanceOf(IllegalArgumentException.class);
     }
 
     @Test
-    public void toIntShouldThrowOnTooBigNumbers() {
+    void toIntShouldThrowOnTooBigNumbers() {
         assertThatThrownBy(() -> new FixedPortSupplier(65536)).isInstanceOf(IllegalArgumentException.class);
     }
 
     @Test
-    public void toIntShouldReturnedDesiredPort() {
+    void toIntShouldReturnedDesiredPort() {
         int expectedPort = 452;
         assertThat(new FixedPortSupplier(expectedPort).get().getValue()).isEqualTo(expectedPort);
     }
 
     @Test
-    public void shouldMatchBeanContract() {
+    void shouldMatchBeanContract() {
         EqualsVerifier.forClass(FixedPortSupplier.class).verify();
     }
-
 }
diff --git a/server/protocols/webadmin/webadmin-core/src/test/java/org/apache/james/webadmin/RandomPortSupplierTest.java b/server/protocols/webadmin/webadmin-core/src/test/java/org/apache/james/webadmin/RandomPortSupplierTest.java
index de821f1..b0311df 100644
--- a/server/protocols/webadmin/webadmin-core/src/test/java/org/apache/james/webadmin/RandomPortSupplierTest.java
+++ b/server/protocols/webadmin/webadmin-core/src/test/java/org/apache/james/webadmin/RandomPortSupplierTest.java
@@ -21,14 +21,12 @@ package org.apache.james.webadmin;
 
 import static org.assertj.core.api.Assertions.assertThat;
 
-import org.junit.Test;
-
-public class RandomPortSupplierTest {
+import org.junit.jupiter.api.Test;
 
+class RandomPortSupplierTest {
     @Test
-    public void toIntShouldReturnTwoTimeTheSameResult() {
+    void toIntShouldReturnTwoTimeTheSameResult() {
         RandomPortSupplier testee = new RandomPortSupplier();
         assertThat(testee.get().getValue()).isEqualTo(testee.get().getValue());
     }
-
 }
diff --git a/server/protocols/webadmin/webadmin-core/src/test/java/org/apache/james/webadmin/TlsConfigurationTest.java b/server/protocols/webadmin/webadmin-core/src/test/java/org/apache/james/webadmin/TlsConfigurationTest.java
index 2d93282..425051f 100644
--- a/server/protocols/webadmin/webadmin-core/src/test/java/org/apache/james/webadmin/TlsConfigurationTest.java
+++ b/server/protocols/webadmin/webadmin-core/src/test/java/org/apache/james/webadmin/TlsConfigurationTest.java
@@ -20,50 +20,41 @@
 package org.apache.james.webadmin;
 
 import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
 
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
+import org.junit.jupiter.api.Test;
 
 import nl.jqno.equalsverifier.EqualsVerifier;
 
-public class TlsConfigurationTest {
-
-    @Rule
-    public ExpectedException expectedException = ExpectedException.none();
-
+class TlsConfigurationTest {
     @Test
-    public void buildShouldThrowWhenNotEnabled() {
-        expectedException.expect(IllegalStateException.class);
-
-        TlsConfiguration.builder().build();
+    void buildShouldThrowWhenNotEnabled() {
+        assertThatThrownBy(() -> TlsConfiguration.builder().build())
+            .isInstanceOf(IllegalStateException.class);
     }
 
     @Test
-    public void buildShouldThrowWhenEnableWithoutKeystore() {
-        expectedException.expect(IllegalStateException.class);
-
-        TlsConfiguration.builder().build();
+    void buildShouldThrowWhenEnableWithoutKeystore() {
+        assertThatThrownBy(() -> TlsConfiguration.builder().build())
+            .isInstanceOf(IllegalStateException.class);
     }
 
     @Test
-    public void selfSignedShouldThrowOnNullKeyStorePath() {
-        expectedException.expect(NullPointerException.class);
-
-        TlsConfiguration.builder()
-            .selfSigned(null, "abc");
+    void selfSignedShouldThrowOnNullKeyStorePath() {
+        assertThatThrownBy(() -> TlsConfiguration.builder()
+            .selfSigned(null, "abc"))
+            .isInstanceOf(NullPointerException.class);
     }
 
     @Test
-    public void selfSignedShouldThrowOnNullKeyStorePassword() {
-        expectedException.expect(NullPointerException.class);
-
-        TlsConfiguration.builder()
-            .selfSigned("abc", null);
+    void selfSignedShouldThrowOnNullKeyStorePassword() {
+        assertThatThrownBy(() -> TlsConfiguration.builder()
+            .selfSigned("abc", null))
+            .isInstanceOf(NullPointerException.class);
     }
 
     @Test
-    public void buildShouldWorkOnSelfSignedHttps() {
+    void buildShouldWorkOnSelfSignedHttps() {
         assertThat(
             TlsConfiguration.builder()
                 .selfSigned("abcd", "efgh")
@@ -72,7 +63,7 @@ public class TlsConfigurationTest {
     }
 
     @Test
-    public void buildShouldWorkOnTrustedHttps() {
+    void buildShouldWorkOnTrustedHttps() {
         assertThat(
             TlsConfiguration.builder()
                 .raw("a", "b", "c", "d")
@@ -81,7 +72,7 @@ public class TlsConfigurationTest {
     }
 
     @Test
-    public void shouldRespectBeanContract() {
+    void shouldRespectBeanContract() {
         EqualsVerifier.forClass(TlsConfiguration.class).verify();
     }
 
diff --git a/server/protocols/webadmin/webadmin-core/src/test/java/org/apache/james/webadmin/WebAdminConfigurationTest.java b/server/protocols/webadmin/webadmin-core/src/test/java/org/apache/james/webadmin/WebAdminConfigurationTest.java
index 73d993a..3b390f2 100644
--- a/server/protocols/webadmin/webadmin-core/src/test/java/org/apache/james/webadmin/WebAdminConfigurationTest.java
+++ b/server/protocols/webadmin/webadmin-core/src/test/java/org/apache/james/webadmin/WebAdminConfigurationTest.java
@@ -20,29 +20,23 @@
 package org.apache.james.webadmin;
 
 import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
 
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
+import org.junit.jupiter.api.Test;
 
 import nl.jqno.equalsverifier.EqualsVerifier;
 
-public class WebAdminConfigurationTest {
-
-    public static final FixedPortSupplier PORT = new FixedPortSupplier(80);
-
-    @Rule
-    public ExpectedException expectedException = ExpectedException.none();
+class WebAdminConfigurationTest {
+    static final FixedPortSupplier PORT = new FixedPortSupplier(80);
 
     @Test
-    public void buildShouldThrowWhenNoPortButEnabled() {
-        expectedException.expect(IllegalStateException.class);
-
-        WebAdminConfiguration.builder().enabled().build();
+    void buildShouldThrowWhenNoPortButEnabled() {
+        assertThatThrownBy(() -> WebAdminConfiguration.builder().enabled().build())
+            .isInstanceOf(IllegalStateException.class);
     }
 
     @Test
-    public void buildShouldWorkWithoutPortWhenDisabled() {
+    void buildShouldWorkWithoutPortWhenDisabled() {
         assertThat(WebAdminConfiguration.builder()
             .disabled()
             .build())
@@ -51,14 +45,13 @@ public class WebAdminConfigurationTest {
     }
 
     @Test
-    public void buildShouldFailOnNoEnable() {
-        expectedException.expect(IllegalStateException.class);
-
-        WebAdminConfiguration.builder().port(PORT).build();
+    void buildShouldFailOnNoEnable() {
+        assertThatThrownBy(() -> WebAdminConfiguration.builder().port(PORT).build())
+            .isInstanceOf(IllegalStateException.class);
     }
 
     @Test
-    public void builderShouldBuildWithRightPort() {
+    void builderShouldBuildWithRightPort() {
         assertThat(
             WebAdminConfiguration.builder()
                 .enabled()
@@ -70,7 +63,7 @@ public class WebAdminConfigurationTest {
 
 
     @Test
-    public void builderShouldBuildWithEnable() {
+    void builderShouldBuildWithEnable() {
         assertThat(
             WebAdminConfiguration.builder()
                 .enabled()
@@ -81,7 +74,7 @@ public class WebAdminConfigurationTest {
     }
 
     @Test
-    public void builderShouldAcceptHttps() {
+    void builderShouldAcceptHttps() {
         TlsConfiguration tlsConfiguration = TlsConfiguration.builder()
             .selfSigned("abcd", "efgh")
             .build();
@@ -97,7 +90,7 @@ public class WebAdminConfigurationTest {
     }
 
     @Test
-    public void builderShouldReturnTlsEnableWhenTlsConfiguration() {
+    void builderShouldReturnTlsEnableWhenTlsConfiguration() {
         TlsConfiguration tlsConfiguration = TlsConfiguration.builder()
             .selfSigned("abcd", "efgh")
             .build();
@@ -113,7 +106,7 @@ public class WebAdminConfigurationTest {
     }
 
     @Test
-    public void builderShouldReturnTlsDisableWhenNoTlsConfiguration() {
+    void builderShouldReturnTlsDisableWhenNoTlsConfiguration() {
         assertThat(
             WebAdminConfiguration.builder()
                 .enabled()
@@ -124,7 +117,7 @@ public class WebAdminConfigurationTest {
     }
 
     @Test
-    public void builderShouldCORSEnabled() {
+    void builderShouldCORSEnabled() {
         assertThat(
             WebAdminConfiguration.builder()
                 .enabled()
@@ -136,7 +129,7 @@ public class WebAdminConfigurationTest {
     }
 
     @Test
-    public void builderShouldAcceptAllOriginsByDefault() {
+    void builderShouldAcceptAllOriginsByDefault() {
         assertThat(
             WebAdminConfiguration.builder()
                 .enabled()
@@ -148,7 +141,7 @@ public class WebAdminConfigurationTest {
     }
 
     @Test
-    public void builderShouldCORSDisabled() {
+    void builderShouldCORSDisabled() {
         assertThat(
             WebAdminConfiguration.builder()
                 .enabled()
@@ -160,7 +153,7 @@ public class WebAdminConfigurationTest {
     }
 
     @Test
-    public void builderShouldCORSWithOrigin() {
+    void builderShouldCORSWithOrigin() {
         String origin = "linagora.com";
         assertThat(
             WebAdminConfiguration.builder()
@@ -174,7 +167,7 @@ public class WebAdminConfigurationTest {
     }
 
     @Test
-    public void builderShouldDefineHostWithDefault() {
+    void builderShouldDefineHostWithDefault() {
         assertThat(
             WebAdminConfiguration.builder()
                 .enabled()
@@ -185,7 +178,7 @@ public class WebAdminConfigurationTest {
     }
 
     @Test
-    public void builderShouldDefineHostWithSetting() {
+    void builderShouldDefineHostWithSetting() {
         String host = "any.host";
         assertThat(
             WebAdminConfiguration.builder()
@@ -198,8 +191,7 @@ public class WebAdminConfigurationTest {
     }
 
     @Test
-    public void shouldMatchBeanContract() {
+    void shouldMatchBeanContract() {
         EqualsVerifier.forClass(WebAdminConfiguration.class).verify();
     }
-
 }
diff --git a/server/protocols/webadmin/webadmin-core/src/test/java/org/apache/james/webadmin/WebAdminServerTest.java b/server/protocols/webadmin/webadmin-core/src/test/java/org/apache/james/webadmin/WebAdminServerTest.java
index b1f31f9..774cac9 100644
--- a/server/protocols/webadmin/webadmin-core/src/test/java/org/apache/james/webadmin/WebAdminServerTest.java
+++ b/server/protocols/webadmin/webadmin-core/src/test/java/org/apache/james/webadmin/WebAdminServerTest.java
@@ -27,17 +27,16 @@ import org.apache.james.metrics.tests.RecordingMetricFactory;
 import org.apache.james.util.Port;
 import org.apache.james.webadmin.authentication.NoAuthenticationFilter;
 import org.apache.james.webadmin.mdc.LoggingRequestFilter;
-import org.junit.Test;
+import org.junit.jupiter.api.Test;
 
 import com.google.common.collect.ImmutableList;
 
 import io.restassured.RestAssured;
 import spark.Service;
 
-public class WebAdminServerTest {
-
+class WebAdminServerTest {
     @Test
-    public void getPortShouldThrowWhenNotConfigured() {
+    void getPortShouldThrowWhenNotConfigured() {
         WebAdminServer server = new WebAdminServer(
             WebAdminConfiguration.TEST_CONFIGURATION,
             ImmutableList.of(),
@@ -49,7 +48,7 @@ public class WebAdminServerTest {
     }
 
     @Test
-    public void getPortShouldReturnPortWhenConfigured() {
+    void getPortShouldReturnPortWhenConfigured() {
         WebAdminServer server = WebAdminUtils.createWebAdminServer().start();
 
         Port port = server.getPort();
@@ -58,7 +57,7 @@ public class WebAdminServerTest {
     }
 
     @Test
-    public void aSecondRouteWithSameEndpointShouldNotOverridePreviouslyDefinedRoutes() {
+    void aSecondRouteWithSameEndpointShouldNotOverridePreviouslyDefinedRoutes() {
         String firstAnswer = "1";
         String secondAnswer = "2";
         WebAdminServer server = WebAdminUtils.createWebAdminServer(
@@ -81,7 +80,7 @@ public class WebAdminServerTest {
     }
 
     @Test
-    public void aSecondRouteWithSameEndpointShouldNotOverridePreviouslyDefinedRoutesWhenPublic() {
+    void aSecondRouteWithSameEndpointShouldNotOverridePreviouslyDefinedRoutesWhenPublic() {
         String firstAnswer = "1";
         String secondAnswer = "2";
         WebAdminServer server = WebAdminUtils.createWebAdminServer(
@@ -104,7 +103,7 @@ public class WebAdminServerTest {
     }
 
     @Test
-    public void privateRoutesShouldBePrioritizedOverPublicRoutes() {
+    void privateRoutesShouldBePrioritizedOveroutes() {
         String firstAnswer = "1";
         String secondAnswer = "2";
         WebAdminServer server = WebAdminUtils.createWebAdminServer(
diff --git a/server/protocols/webadmin/webadmin-core/src/test/java/org/apache/james/webadmin/authentication/JwtFilterTest.java b/server/protocols/webadmin/webadmin-core/src/test/java/org/apache/james/webadmin/authentication/JwtFilterTest.java
index d2d46a4..6931493 100644
--- a/server/protocols/webadmin/webadmin-core/src/test/java/org/apache/james/webadmin/authentication/JwtFilterTest.java
+++ b/server/protocols/webadmin/webadmin-core/src/test/java/org/apache/james/webadmin/authentication/JwtFilterTest.java
@@ -19,19 +19,14 @@
 
 package org.apache.james.webadmin.authentication;
 
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.verifyZeroInteractions;
 import static org.mockito.Mockito.when;
 
 import org.apache.james.jwt.JwtTokenVerifier;
-import org.eclipse.jetty.http.HttpStatus;
-import org.hamcrest.BaseMatcher;
-import org.hamcrest.Description;
-import org.hamcrest.Matcher;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
 
 import com.google.common.collect.ImmutableSet;
 
@@ -39,38 +34,18 @@ import spark.HaltException;
 import spark.Request;
 import spark.Response;
 
-public class JwtFilterTest {
-
-    public static final Matcher<HaltException> STATUS_CODE_MATCHER_401 = new BaseMatcher<HaltException>() {
-        @Override
-        public boolean matches(Object o) {
-            if (o instanceof HaltException) {
-                HaltException haltException = (HaltException) o;
-                return haltException.statusCode() == HttpStatus.UNAUTHORIZED_401;
-            }
-            return false;
-        }
-
-        @Override
-        public void describeTo(Description description) {
-            
-        }
-    };
-
+class JwtFilterTest {
     private JwtTokenVerifier jwtTokenVerifier;
     private JwtFilter jwtFilter;
 
-    @Rule
-    public ExpectedException expectedException = ExpectedException.none();
-
-    @Before
-    public void setUp() {
+    @BeforeEach
+    void setUp() {
         jwtTokenVerifier = mock(JwtTokenVerifier.class);
         jwtFilter = new JwtFilter(() -> jwtTokenVerifier);
     }
 
     @Test
-    public void handleShouldDoNothingOnOptions() throws Exception {
+    void handleShouldDoNothingOnOptions() throws Exception {
         Request request = mock(Request.class);
         //Ensure we don't take OPTIONS string from the constant pool
         when(request.requestMethod()).thenReturn(new String("OPTIONS"));
@@ -83,58 +58,59 @@ public class JwtFilterTest {
 
 
     @Test
-    public void handleShouldRejectRequestWithHeaders() throws Exception {
+    void handleShouldRejectRequestWithHeaders() throws Exception {
         Request request = mock(Request.class);
         when(request.requestMethod()).thenReturn("GET");
         when(request.headers()).thenReturn(ImmutableSet.of());
 
-        expectedException.expect(HaltException.class);
-        expectedException.expect(STATUS_CODE_MATCHER_401);
-
-        jwtFilter.handle(request, mock(Response.class));
+        assertThatThrownBy(() -> jwtFilter.handle(request, mock(Response.class)))
+            .isInstanceOf(HaltException.class)
+            .extracting(e -> HaltException.class.cast(e).statusCode())
+            .isEqualTo(401);
     }
 
     @Test
-    public void handleShouldRejectRequestWithBearersHeaders() throws Exception {
+    void handleShouldRejectRequestWithBearersHeaders() throws Exception {
         Request request = mock(Request.class);
         when(request.requestMethod()).thenReturn("GET");
         when(request.headers(JwtFilter.AUTHORIZATION_HEADER_NAME)).thenReturn("Invalid value");
 
-        expectedException.expect(HaltException.class);
-        expectedException.expect(STATUS_CODE_MATCHER_401);
-
-        jwtFilter.handle(request, mock(Response.class));
+        assertThatThrownBy(() -> jwtFilter.handle(request, mock(Response.class)))
+            .isInstanceOf(HaltException.class)
+            .extracting(e -> HaltException.class.cast(e).statusCode())
+            .isEqualTo(401);
     }
 
     @Test
-    public void handleShouldRejectRequestWithInvalidBearerHeaders() throws Exception {
+    void handleShouldRejectRequestWithInvalidBearerHeaders() throws Exception {
         Request request = mock(Request.class);
         when(request.requestMethod()).thenReturn("GET");
         when(request.headers(JwtFilter.AUTHORIZATION_HEADER_NAME)).thenReturn("Bearer value");
         when(jwtTokenVerifier.verify("value")).thenReturn(false);
 
-        expectedException.expect(HaltException.class);
-        expectedException.expect(STATUS_CODE_MATCHER_401);
 
-        jwtFilter.handle(request, mock(Response.class));
+        assertThatThrownBy(() -> jwtFilter.handle(request, mock(Response.class)))
+            .isInstanceOf(HaltException.class)
+            .extracting(e -> HaltException.class.cast(e).statusCode())
+            .isEqualTo(401);
     }
 
     @Test
-    public void handleShouldRejectRequestWithoutAdminClaim() throws Exception {
+    void handleShouldRejectRequestWithoutAdminClaim() throws Exception {
         Request request = mock(Request.class);
         when(request.requestMethod()).thenReturn("GET");
         when(request.headers(JwtFilter.AUTHORIZATION_HEADER_NAME)).thenReturn("Bearer value");
         when(jwtTokenVerifier.verify("value")).thenReturn(true);
         when(jwtTokenVerifier.hasAttribute("admin", true, "value")).thenReturn(false);
 
-        expectedException.expect(HaltException.class);
-        expectedException.expect(STATUS_CODE_MATCHER_401);
-
-        jwtFilter.handle(request, mock(Response.class));
+        assertThatThrownBy(() -> jwtFilter.handle(request, mock(Response.class)))
+            .isInstanceOf(HaltException.class)
+            .extracting(e -> HaltException.class.cast(e).statusCode())
+            .isEqualTo(401);
     }
 
     @Test
-    public void handleShouldAcceptValidJwt() throws Exception {
+    void handleShouldAcceptValidJwt() throws Exception {
         Request request = mock(Request.class);
         when(request.requestMethod()).thenReturn("GET");
         when(request.headers(JwtFilter.AUTHORIZATION_HEADER_NAME)).thenReturn("Bearer value");
diff --git a/server/protocols/webadmin/webadmin-core/src/test/java/org/apache/james/webadmin/mdc/RequestIdTest.java b/server/protocols/webadmin/webadmin-core/src/test/java/org/apache/james/webadmin/mdc/RequestIdTest.java
index 0eaad31..df475b9 100644
--- a/server/protocols/webadmin/webadmin-core/src/test/java/org/apache/james/webadmin/mdc/RequestIdTest.java
+++ b/server/protocols/webadmin/webadmin-core/src/test/java/org/apache/james/webadmin/mdc/RequestIdTest.java
@@ -19,13 +19,13 @@
 
 package org.apache.james.webadmin.mdc;
 
-import org.junit.Test;
+import org.junit.jupiter.api.Test;
 
 import nl.jqno.equalsverifier.EqualsVerifier;
 
-public class RequestIdTest {
+class RequestIdTest {
     @Test
-    public void shouldMatchBeanContract() {
+    void shouldMatchBeanContract() {
         EqualsVerifier.forClass(RequestId.class).verify();
     }
 }
\ No newline at end of file
diff --git a/server/protocols/webadmin/webadmin-core/src/test/java/org/apache/james/webadmin/routes/ErrorRoutesTest.java b/server/protocols/webadmin/webadmin-core/src/test/java/org/apache/james/webadmin/routes/ErrorRoutesTest.java
index 65ebc70..caaa910 100644
--- a/server/protocols/webadmin/webadmin-core/src/test/java/org/apache/james/webadmin/routes/ErrorRoutesTest.java
+++ b/server/protocols/webadmin/webadmin-core/src/test/java/org/apache/james/webadmin/routes/ErrorRoutesTest.java
@@ -34,19 +34,19 @@ import static org.hamcrest.Matchers.equalTo;
 import org.apache.james.webadmin.WebAdminServer;
 import org.apache.james.webadmin.WebAdminUtils;
 import org.apache.james.webadmin.utils.ErrorResponder;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
 
 import io.restassured.RestAssured;
 
-public class ErrorRoutesTest {
+class ErrorRoutesTest {
     private static final String NOT_FOUND = "notFound";
 
     private WebAdminServer webAdminServer;
 
-    @Before
-    public void setUp() throws Exception {
+    @BeforeEach
+    void setUp() throws Exception {
         webAdminServer = WebAdminUtils.createWebAdminServer(new ErrorRoutes())
             .start();
 
@@ -56,13 +56,13 @@ public class ErrorRoutesTest {
         RestAssured.enableLoggingOfRequestAndResponseIfValidationFails();
     }
 
-    @After
-    public void tearDown() {
+    @AfterEach
+    void tearDown() {
         webAdminServer.destroy();
     }
 
     @Test
-    public void defineInternalErrorShouldReturnInternalErrorJsonFormat() {
+    void defineInternalErrorShouldReturnInternalErrorJsonFormat() {
         when()
             .get(INTERNAL_SERVER_ERROR)
         .then()
@@ -73,7 +73,7 @@ public class ErrorRoutesTest {
     }
 
     @Test
-    public void defineNotFoundShouldReturnNotFoundJsonFormat() {
+    void defineNotFoundShouldReturnNotFoundJsonFormat() {
         when()
             .get(NOT_FOUND)
         .then()
@@ -84,7 +84,7 @@ public class ErrorRoutesTest {
     }
 
     @Test
-    public void defineJsonExtractExceptionShouldReturnBadRequestJsonFormat() {
+    void defineJsonExtractExceptionShouldReturnBadRequestJsonFormat() {
         when()
             .get(JSON_EXTRACT_EXCEPTION)
         .then()
@@ -96,7 +96,7 @@ public class ErrorRoutesTest {
     }
 
     @Test
-    public void defineIllegalExceptionShouldReturnBadRequestJsonFormat() {
+    void defineIllegalExceptionShouldReturnBadRequestJsonFormat() {
         when()
             .get(INVALID_ARGUMENT_EXCEPTION)
         .then()
diff --git a/server/protocols/webadmin/webadmin-core/src/test/java/org/apache/james/webadmin/routes/HealthCheckRoutesTest.java b/server/protocols/webadmin/webadmin-core/src/test/java/org/apache/james/webadmin/routes/HealthCheckRoutesTest.java
index 939175f..aef0267 100644
--- a/server/protocols/webadmin/webadmin-core/src/test/java/org/apache/james/webadmin/routes/HealthCheckRoutesTest.java
+++ b/server/protocols/webadmin/webadmin-core/src/test/java/org/apache/james/webadmin/routes/HealthCheckRoutesTest.java
@@ -38,17 +38,16 @@ import org.apache.james.webadmin.WebAdminServer;
 import org.apache.james.webadmin.WebAdminUtils;
 import org.apache.james.webadmin.utils.JsonTransformer;
 import org.eclipse.jetty.http.HttpStatus;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
 import org.reactivestreams.Publisher;
 
 import io.restassured.RestAssured;
 import net.javacrumbs.jsonunit.core.Option;
 import reactor.core.publisher.Mono;
 
-public class HealthCheckRoutesTest {
-
+class HealthCheckRoutesTest {
     private static final String NAME_1 = "component-1";
     private static final String NAME_2 = "component-2";
     private static final String NAME_3 = "component 3";
@@ -76,8 +75,8 @@ public class HealthCheckRoutesTest {
     private WebAdminServer webAdminServer;
     private Set<HealthCheck> healthChecks;
 
-    @Before
-    public void setUp() throws Exception {
+    @BeforeEach
+    void setUp() throws Exception {
         healthChecks = new HashSet<>();
         webAdminServer = WebAdminUtils.createWebAdminServer(new HealthCheckRoutes(healthChecks, new JsonTransformer()))
             .start();
@@ -87,13 +86,13 @@ public class HealthCheckRoutesTest {
             .build();
     }
 
-    @After
-    public void tearDown() {
+    @AfterEach
+    void tearDown() {
         webAdminServer.destroy();
     }
 
     @Test
-    public void validateHealthChecksShouldReturnOkWhenNoHealthChecks() {
+    void validateHealthChecksShouldReturnOkWhenNoHealthChecks() {
         String healthCheckBody =
             "{\"status\":\"healthy\"," +
             " \"checks\":[]}";
@@ -110,7 +109,7 @@ public class HealthCheckRoutesTest {
     }
 
     @Test
-    public void validateHealthChecksShouldReturnOkWhenHealthChecksAreHealthy() {
+    void validateHealthChecksShouldReturnOkWhenHealthChecksAreHealthy() {
         healthChecks.add(healthCheck(Result.healthy(COMPONENT_NAME_1)));
         healthChecks.add(healthCheck(Result.healthy(COMPONENT_NAME_2)));
         String healthCheckBody =
@@ -142,7 +141,7 @@ public class HealthCheckRoutesTest {
     }
 
     @Test
-    public void validateHealthChecksShouldReturnInternalErrorWhenOneHealthCheckIsUnhealthy() {
+    void validateHealthChecksShouldReturnInternalErrorWhenOneHealthCheckIsUnhealthy() {
         healthChecks.add(healthCheck(Result.unhealthy(COMPONENT_NAME_1, "cause")));
         healthChecks.add(healthCheck(Result.healthy(COMPONENT_NAME_2)));
         String healthCheckBody =
@@ -174,7 +173,7 @@ public class HealthCheckRoutesTest {
     }
 
     @Test
-    public void validateHealthChecksShouldReturnInternalErrorWhenAllHealthChecksAreUnhealthy() {
+    void validateHealthChecksShouldReturnInternalErrorWhenAllHealthChecksAreUnhealthy() {
         healthChecks.add(healthCheck(Result.unhealthy(COMPONENT_NAME_1, "cause")));
         healthChecks.add(healthCheck(Result.unhealthy(COMPONENT_NAME_2, SAMPLE_CAUSE)));
         String healthCheckBody =
@@ -206,7 +205,7 @@ public class HealthCheckRoutesTest {
     }
 
     @Test
-    public void validateHealthChecksShouldReturnInternalErrorWhenOneHealthCheckIsDegraded() {
+    void validateHealthChecksShouldReturnInternalErrorWhenOneHealthCheckIsDegraded() {
         healthChecks.add(healthCheck(Result.degraded(COMPONENT_NAME_1, "cause")));
         healthChecks.add(healthCheck(Result.healthy(COMPONENT_NAME_2)));
         String healthCheckBody =
@@ -238,7 +237,7 @@ public class HealthCheckRoutesTest {
     }
 
     @Test
-    public void validateHealthChecksShouldReturnInternalErrorWhenAllHealthCheckAreDegraded() {
+    void validateHealthChecksShouldReturnInternalErrorWhenAllHealthCheckAreDegraded() {
         healthChecks.add(healthCheck(Result.degraded(COMPONENT_NAME_1, "cause")));
         healthChecks.add(healthCheck(Result.degraded(COMPONENT_NAME_2, "cause")));
         String healthCheckBody =
@@ -270,7 +269,7 @@ public class HealthCheckRoutesTest {
     }
 
     @Test
-    public void validateHealthChecksShouldReturnStatusUnHealthyWhenOneIsUnHealthyAndOtherIsDegraded() {
+    void validateHealthChecksShouldReturnStatusUnHealthyWhenOneIsUnHealthyAndOtherIsDegraded() {
         healthChecks.add(healthCheck(Result.degraded(COMPONENT_NAME_1, "cause")));
         healthChecks.add(healthCheck(Result.unhealthy(COMPONENT_NAME_2, "cause")));
         String healthCheckBody =
@@ -301,7 +300,7 @@ public class HealthCheckRoutesTest {
     }
     
     @Test
-    public void performHealthCheckShouldReturnOkWhenHealthCheckIsHealthy() {
+    void performHealthCheckShouldReturnOkWhenHealthCheckIsHealthy() {
         healthChecks.add(healthCheck(Result.healthy(COMPONENT_NAME_1)));
         
         given()
@@ -317,7 +316,7 @@ public class HealthCheckRoutesTest {
     }
     
     @Test
-    public void performHealthCheckShouldReturnNotFoundWhenComponentNameIsUnknown() {
+    void performHealthCheckShouldReturnNotFoundWhenComponentNameIsUnknown() {
         
         given()
             .pathParam("componentName", "unknown")
@@ -332,7 +331,7 @@ public class HealthCheckRoutesTest {
     }
     
     @Test
-    public void performHealthCheckShouldReturnInternalErrorWhenHealthCheckIsDegraded() {
+    void performHealthCheckShouldReturnInternalErrorWhenHealthCheckIsDegraded() {
         healthChecks.add(healthCheck(Result.degraded(COMPONENT_NAME_1, "the cause")));
         
         given()
@@ -348,7 +347,7 @@ public class HealthCheckRoutesTest {
     }
     
     @Test
-    public void performHealthCheckShouldReturnInternalErrorWhenHealthCheckIsUnhealthy() {
+    void performHealthCheckShouldReturnInternalErrorWhenHealthCheckIsUnhealthy() {
         healthChecks.add(healthCheck(Result.unhealthy(COMPONENT_NAME_1, SAMPLE_CAUSE)));
         
         given()
@@ -364,7 +363,7 @@ public class HealthCheckRoutesTest {
     }
     
     @Test
-    public void performHealthCheckShouldReturnProperlyEscapedComponentName() {
+    void performHealthCheckShouldReturnProperlyEscapedComponentName() {
         healthChecks.add(healthCheck(Result.healthy(COMPONENT_NAME_3)));
         
         given()
@@ -379,7 +378,7 @@ public class HealthCheckRoutesTest {
     }
     
     @Test
-    public void performHealthCheckShouldWorkWithEscapedPathParam() {
+    void performHealthCheckShouldWorkWithEscapedPathParam() {
         healthChecks.add(healthCheck(Result.healthy(COMPONENT_NAME_3)));
         
         // disable URL encoding
@@ -397,7 +396,7 @@ public class HealthCheckRoutesTest {
     }
 
     @Test
-    public void getHealthchecksShouldReturnEmptyWhenNoHealthChecks() {
+    void getHealthchecksShouldReturnEmptyWhenNoHealthChecks() {
         when()
            .get(HealthCheckRoutes.CHECKS)
         .then()
@@ -407,7 +406,7 @@ public class HealthCheckRoutesTest {
     }
 
     @Test
-    public void getHealthchecksShouldReturnHealthCheckWhenHealthCheckPresent() {
+    void getHealthchecksShouldReturnHealthCheckWhenHealthCheckPresent() {
         healthChecks.add(healthCheck(Result.healthy(COMPONENT_NAME_3)));
         when()
            .get(HealthCheckRoutes.CHECKS)
@@ -419,7 +418,7 @@ public class HealthCheckRoutesTest {
     }
 
     @Test
-    public void getHealthchecksShouldReturnHealthChecksWhenHealthChecksPresent() {
+    void getHealthchecksShouldReturnHealthChecksWhenHealthChecksPresent() {
         healthChecks.add(healthCheck(Result.healthy(COMPONENT_NAME_2)));
         healthChecks.add(healthCheck(Result.healthy(COMPONENT_NAME_3)));
         when()
diff --git a/server/protocols/webadmin/webadmin-core/src/test/java/org/apache/james/webadmin/tasks/TaskFromRequestTest.java b/server/protocols/webadmin/webadmin-core/src/test/java/org/apache/james/webadmin/tasks/TaskFromRequestTest.java
index 4976a5a..36cbd34 100644
--- a/server/protocols/webadmin/webadmin-core/src/test/java/org/apache/james/webadmin/tasks/TaskFromRequestTest.java
+++ b/server/protocols/webadmin/webadmin-core/src/test/java/org/apache/james/webadmin/tasks/TaskFromRequestTest.java
@@ -29,17 +29,17 @@ import org.apache.james.task.Task;
 import org.apache.james.task.TaskId;
 import org.apache.james.task.TaskManager;
 import org.eclipse.jetty.http.HttpStatus;
-import org.junit.Test;
+import org.junit.jupiter.api.Test;
 
 import spark.Request;
 import spark.Response;
 
-public class TaskFromRequestTest {
+class TaskFromRequestTest {
     static final Task TASK = mock(Task.class);
     static final String UUID_VALUE = "ce5316cb-c924-40eb-9ca0-c5828e276297";
 
     @Test
-    public void handleShouldReturnCreatedWithTaskIdHeader() throws Exception {
+    void handleShouldReturnCreatedWithTaskIdHeader() throws Exception {
         Request request = mock(Request.class);
         Response response = mock(Response.class);
 
diff --git a/server/protocols/webadmin/webadmin-core/src/test/java/org/apache/james/webadmin/utils/JsonExtractorTest.java b/server/protocols/webadmin/webadmin-core/src/test/java/org/apache/james/webadmin/utils/JsonExtractorTest.java
index ff5f2cb..17b62fb 100644
--- a/server/protocols/webadmin/webadmin-core/src/test/java/org/apache/james/webadmin/utils/JsonExtractorTest.java
+++ b/server/protocols/webadmin/webadmin-core/src/test/java/org/apache/james/webadmin/utils/JsonExtractorTest.java
@@ -22,64 +22,64 @@ package org.apache.james.webadmin.utils;
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.assertj.core.api.Assertions.assertThatThrownBy;
 
-import org.junit.Before;
-import org.junit.Test;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
 
 import com.fasterxml.jackson.annotation.JsonCreator;
 import com.fasterxml.jackson.annotation.JsonProperty;
 import com.google.common.base.Preconditions;
 
-public class JsonExtractorTest {
+class JsonExtractorTest {
 
     private JsonExtractor<Request> jsonExtractor;
 
-    @Before
-    public void setUp() {
+    @BeforeEach
+    void setUp() {
         jsonExtractor = new JsonExtractor<>(Request.class);
     }
 
     @Test
-    public void parseShouldThrowOnNullInput() throws Exception {
+    void parseShouldThrowOnNullInput() {
         assertThatThrownBy(() -> jsonExtractor.parse(null)).isInstanceOf(NullPointerException.class);
     }
 
     @Test
-    public void parseShouldThrowOnEmptyInput() throws Exception {
+    void parseShouldThrowOnEmptyInput() {
         assertThatThrownBy(() -> jsonExtractor.parse("")).isInstanceOf(JsonExtractException.class);
     }
 
     @Test
-    public void parseShouldThrowOnBrokenJson() throws Exception {
+    void parseShouldThrowOnBrokenJson() {
         assertThatThrownBy(() -> jsonExtractor.parse("{\"field1\":\"broken")).isInstanceOf(JsonExtractException.class);
     }
 
     @Test
-    public void parseShouldThrowOnEmptyJson() throws Exception {
+    void parseShouldThrowOnEmptyJson() {
         assertThatThrownBy(() -> jsonExtractor.parse("{}")).isInstanceOf(JsonExtractException.class);
     }
 
     @Test
-    public void parseShouldThrowOnMissingMandatoryField() throws Exception {
+    void parseShouldThrowOnMissingMandatoryField() {
         assertThatThrownBy(() -> jsonExtractor.parse("{\"field1\":\"any\"}")).isInstanceOf(JsonExtractException.class);
     }
 
     @Test
-    public void parseShouldThrowOnValidationProblemIllegalArgumentException() throws Exception {
+    void parseShouldThrowOnValidationProblemIllegalArgumentException() {
         assertThatThrownBy(() -> jsonExtractor.parse("{\"field1\":\"\",\"field2\":\"any\"}")).isInstanceOf(JsonExtractException.class);
     }
 
     @Test
-    public void parseShouldThrowOnValidationProblemNPE() throws Exception {
+    void parseShouldThrowOnValidationProblemNPE() {
         assertThatThrownBy(() -> jsonExtractor.parse("{\"field1\":null,\"field2\":\"any\"}")).isInstanceOf(JsonExtractException.class);
     }
 
     @Test
-    public void parseShouldThrowOnExtraFiled() throws Exception {
+    void parseShouldThrowOnExtraFiled() {
         assertThatThrownBy(() -> jsonExtractor.parse("{\"field1\":\"value\",\"field2\":\"any\",\"extra\":\"extra\"}")).isInstanceOf(JsonExtractException.class);
     }
 
     @Test
-    public void parseShouldInstantiateDestinationClass() throws Exception {
+    void parseShouldInstantiateDestinationClass() throws Exception {
         String field1 = "value1";
         String field2 = "value2";
         Request request = jsonExtractor.parse("{\"field1\":\"" + field1 + "\",\"field2\":\"" + field2 + "\"}");
diff --git a/server/protocols/webadmin/webadmin-core/src/test/java/org/apache/james/webadmin/utils/ParametersExtractorTest.java b/server/protocols/webadmin/webadmin-core/src/test/java/org/apache/james/webadmin/utils/ParametersExtractorTest.java
index e1b326c..57ec9e7 100644
--- a/server/protocols/webadmin/webadmin-core/src/test/java/org/apache/james/webadmin/utils/ParametersExtractorTest.java
+++ b/server/protocols/webadmin/webadmin-core/src/test/java/org/apache/james/webadmin/utils/ParametersExtractorTest.java
@@ -27,15 +27,15 @@ import java.util.Optional;
 
 import org.apache.james.util.streams.Limit;
 import org.apache.james.util.streams.Offset;
-import org.junit.Test;
+import org.junit.jupiter.api.Test;
 
 import spark.HaltException;
 import spark.Request;
 
-public class ParametersExtractorTest {
+class ParametersExtractorTest {
 
     @Test
-    public void extractLimitShouldReturnUnlimitedWhenNotInParameters() {
+    void extractLimitShouldReturnUnlimitedWhenNotInParameters() {
         Request request = mock(Request.class);
         when(request.queryParams("limit"))
             .thenReturn(null);
@@ -46,7 +46,7 @@ public class ParametersExtractorTest {
     }
 
     @Test
-    public void extractLimitShouldReturnUnlimitedWhenPresentInParametersButEmpty() {
+    void extractLimitShouldReturnUnlimitedWhenPresentInParametersButEmpty() {
         Request request = mock(Request.class);
         when(request.queryParams("limit"))
             .thenReturn("");
@@ -57,7 +57,7 @@ public class ParametersExtractorTest {
     }
 
     @Test
-    public void extractLimitShouldReturnTheLimitWhenPresentInParameters() {
+    void extractLimitShouldReturnTheLimitWhenPresentInParameters() {
         Request request = mock(Request.class);
         when(request.queryParams("limit"))
             .thenReturn("123");
@@ -68,7 +68,7 @@ public class ParametersExtractorTest {
     }
 
     @Test
-    public void extractLimitShouldThrowWhenNegativeLimit() {
+    void extractLimitShouldThrowWhenNegativeLimit() {
         Request request = mock(Request.class);
         when(request.queryParams("limit"))
             .thenReturn("-123");
@@ -78,7 +78,7 @@ public class ParametersExtractorTest {
     }
 
     @Test
-    public void extractLimitShouldThrowWhenZeroLimit() {
+    void extractLimitShouldThrowWhenZeroLimit() {
         Request request = mock(Request.class);
         when(request.queryParams("limit"))
             .thenReturn("0");
@@ -88,7 +88,7 @@ public class ParametersExtractorTest {
     }
 
     @Test
-    public void extractOffsetShouldReturnNoneWhenNotInParameters() {
+    void extractOffsetShouldReturnNoneWhenNotInParameters() {
         Request request = mock(Request.class);
         when(request.queryParams("offset"))
             .thenReturn(null);
@@ -99,7 +99,7 @@ public class ParametersExtractorTest {
     }
 
     @Test
-    public void extractOffsetShouldReturnNoneWhenPresentInParametersButEmpty() {
+    void extractOffsetShouldReturnNoneWhenPresentInParametersButEmpty() {
         Request request = mock(Request.class);
         when(request.queryParams("offset"))
             .thenReturn("");
@@ -110,7 +110,7 @@ public class ParametersExtractorTest {
     }
 
     @Test
-    public void extractOffsetShouldReturnTheOffsetWhenPresentInParameters() {
+    void extractOffsetShouldReturnTheOffsetWhenPresentInParameters() {
         Request request = mock(Request.class);
         when(request.queryParams("offset"))
             .thenReturn("123");
@@ -121,7 +121,7 @@ public class ParametersExtractorTest {
     }
 
     @Test
-    public void extractOffsetShouldThrowWhenNegativeOffset() {
+    void extractOffsetShouldThrowWhenNegativeOffset() {
         Request request = mock(Request.class);
         when(request.queryParams("offset"))
             .thenReturn("-123");
@@ -131,7 +131,7 @@ public class ParametersExtractorTest {
     }
 
     @Test
-    public void extractOffsetShouldReturnNoneWhenZeroLimit() {
+    void extractOffsetShouldReturnNoneWhenZeroLimit() {
         Request request = mock(Request.class);
         when(request.queryParams("offset"))
             .thenReturn("0");
@@ -144,7 +144,7 @@ public class ParametersExtractorTest {
     
 
     @Test
-    public void extractPositiveDoubleShouldReturnEmptyWhenNotInParameters() {
+    void extractPositiveDoubleShouldReturnEmptyWhenNotInParameters() {
         String parameterName = "param";
         Request request = mock(Request.class);
         when(request.queryParams(parameterName))
@@ -156,7 +156,7 @@ public class ParametersExtractorTest {
     }
 
     @Test
-    public void extractPositiveDoubleShouldReturnNoneWhenPresentInParametersButEmpty() {
+    void extractPositiveDoubleShouldReturnNoneWhenPresentInParametersButEmpty() {
         String parameterName = "param";
         Request request = mock(Request.class);
         when(request.queryParams(parameterName))
@@ -168,7 +168,7 @@ public class ParametersExtractorTest {
     }
 
     @Test
-    public void extractPositiveDoubleShouldReturnTheDoubleWhenPresentInParameters() {
+    void extractPositiveDoubleShouldReturnTheDoubleWhenPresentInParameters() {
         String parameterName = "param";
         Request request = mock(Request.class);
         when(request.queryParams(parameterName))
@@ -180,7 +180,7 @@ public class ParametersExtractorTest {
     }
 
     @Test
-    public void extractPositiveDoubleShouldThrowWhenNegativePositiveDouble() {
+    void extractPositiveDoubleShouldThrowWhenNegativePositiveDouble() {
         String parameterName = "param";
         Request request = mock(Request.class);
         when(request.queryParams(parameterName))
@@ -193,7 +193,7 @@ public class ParametersExtractorTest {
     }
 
     @Test
-    public void extractPositiveDoubleShouldReturnZeroWhenZeroLimit() {
+    void extractPositiveDoubleShouldReturnZeroWhenZeroLimit() {
         String parameterName = "param";
         Request request = mock(Request.class);
         when(request.queryParams(parameterName))
diff --git a/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/dto/UsersQuotaDetailsDTOTest.java b/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/dto/UsersQuotaDetailsDTOTest.java
index 5c3f497..86446c2 100644
--- a/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/dto/UsersQuotaDetailsDTOTest.java
+++ b/server/protocols/webadmin/webadmin-mailbox/src/test/java/org/apache/james/webadmin/dto/UsersQuotaDetailsDTOTest.java
@@ -21,26 +21,24 @@ package org.apache.james.webadmin.dto;
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.assertj.core.api.Assertions.assertThatThrownBy;
 
-import javax.mail.internet.AddressException;
-
 import org.apache.james.core.Username;
 import org.apache.james.core.quota.QuotaCountLimit;
 import org.apache.james.core.quota.QuotaCountUsage;
 import org.apache.james.core.quota.QuotaSizeLimit;
 import org.apache.james.core.quota.QuotaSizeUsage;
 import org.apache.james.mailbox.model.Quota;
-import org.junit.Test;
+import org.junit.jupiter.api.Test;
 
-public class UsersQuotaDetailsDTOTest {
+class UsersQuotaDetailsDTOTest {
 
     @Test
-    public void builderShouldThrowWhenUserIsNull() {
+    void builderShouldThrowWhenUserIsNull() {
         assertThatThrownBy(() -> UsersQuotaDetailsDTO.builder().build())
             .isInstanceOf(NullPointerException.class);
     }
 
     @Test
-    public void builderShouldThrowWhenDetailIsNull() {
+    void builderShouldThrowWhenDetailIsNull() {
         assertThatThrownBy(() -> UsersQuotaDetailsDTO.builder()
                 .user(Username.of("user@domain.org"))
                 .build())
@@ -48,7 +46,7 @@ public class UsersQuotaDetailsDTOTest {
     }
 
     @Test
-    public void builderShouldWork() throws AddressException {
+    void builderShouldWork() {
         Username username = Username.of("user@domain.org");
         QuotaDetailsDTO quotaDetailsDTO = QuotaDetailsDTO.builder()
                 .occupation(
diff --git a/server/protocols/webadmin/webadmin-mailqueue/src/test/java/org/apache/james/webadmin/dto/MailQueueDTOTest.java b/server/protocols/webadmin/webadmin-mailqueue/src/test/java/org/apache/james/webadmin/dto/MailQueueDTOTest.java
index 898b228..b41664d 100644
--- a/server/protocols/webadmin/webadmin-mailqueue/src/test/java/org/apache/james/webadmin/dto/MailQueueDTOTest.java
+++ b/server/protocols/webadmin/webadmin-mailqueue/src/test/java/org/apache/james/webadmin/dto/MailQueueDTOTest.java
@@ -20,29 +20,24 @@ package org.apache.james.webadmin.dto;
 
 import static org.assertj.core.api.Assertions.assertThatThrownBy;
 
-import org.assertj.core.api.JUnitSoftAssertions;
-import org.junit.Rule;
-import org.junit.Test;
-
-public class MailQueueDTOTest {
-
-    @Rule
-    public final JUnitSoftAssertions softly = new JUnitSoftAssertions();
+import org.assertj.core.api.SoftAssertions;
+import org.junit.jupiter.api.Test;
 
+class MailQueueDTOTest {
     @Test
-    public void buildShouldThrowWhenNameIsNull() {
+    void buildShouldThrowWhenNameIsNull() {
         assertThatThrownBy(() -> MailQueueDTO.builder().build())
             .isInstanceOf(IllegalArgumentException.class);
     }
 
     @Test
-    public void buildShouldThrowWhenNameIsEmpty() {
+    void buildShouldThrowWhenNameIsEmpty() {
         assertThatThrownBy(() -> MailQueueDTO.builder().name("").build())
             .isInstanceOf(IllegalArgumentException.class);
     }
 
     @Test
-    public void builderShouldCreateTheRightObject() {
+    void builderShouldCreateTheRightObject() {
         String name = "name";
         int size = 123;
 
@@ -50,8 +45,9 @@ public class MailQueueDTOTest {
             .name(name)
             .size(size)
             .build();
-
-        softly.assertThat(mailQueueDTO.getName()).isEqualTo(name);
-        softly.assertThat(mailQueueDTO.getSize()).isEqualTo(size);
+        SoftAssertions.assertSoftly(softly -> {
+            softly.assertThat(mailQueueDTO.getName()).isEqualTo(name);
+            softly.assertThat(mailQueueDTO.getSize()).isEqualTo(size);
+        });
     }
 }
diff --git a/server/protocols/webadmin/webadmin-mailqueue/src/test/java/org/apache/james/webadmin/dto/MailQueueItemDTOTest.java b/server/protocols/webadmin/webadmin-mailqueue/src/test/java/org/apache/james/webadmin/dto/MailQueueItemDTOTest.java
index 4b177de..19ca70e 100644
--- a/server/protocols/webadmin/webadmin-mailqueue/src/test/java/org/apache/james/webadmin/dto/MailQueueItemDTOTest.java
+++ b/server/protocols/webadmin/webadmin-mailqueue/src/test/java/org/apache/james/webadmin/dto/MailQueueItemDTOTest.java
@@ -28,31 +28,26 @@ import org.apache.james.queue.api.Mails;
 import org.apache.james.queue.api.ManageableMailQueue;
 import org.apache.james.queue.api.ManageableMailQueue.MailQueueItemView;
 import org.apache.mailet.base.test.FakeMail;
-import org.assertj.core.api.JUnitSoftAssertions;
-import org.junit.Rule;
-import org.junit.Test;
+import org.assertj.core.api.SoftAssertions;
+import org.junit.jupiter.api.Test;
 
 import com.github.steveash.guavate.Guavate;
 
-public class MailQueueItemDTOTest {
-
-    @Rule
-    public final JUnitSoftAssertions softly = new JUnitSoftAssertions();
-
+class MailQueueItemDTOTest {
     @Test
-    public void buildShouldThrowWhenNameIsNull() {
+    void buildShouldThrowWhenNameIsNull() {
         assertThatThrownBy(() -> MailQueueItemDTO.builder().build())
             .isInstanceOf(IllegalArgumentException.class);
     }
 
     @Test
-    public void buildShouldThrowWhenNameIsEmpty() {
+    void buildShouldThrowWhenNameIsEmpty() {
         assertThatThrownBy(() -> MailQueueItemDTO.builder().name("").build())
             .isInstanceOf(IllegalArgumentException.class);
     }
 
     @Test
-    public void fromShouldCreateTheRightObject() throws Exception {
+    void fromShouldCreateTheRightObject() throws Exception {
         FakeMail mail = Mails.defaultMail().name("name").build();
         ZonedDateTime date = ZonedDateTime.parse("2018-01-02T11:22:02Z");
         MailQueueItemView mailQueueItemView = new ManageableMailQueue.DefaultMailQueueItemView(mail, date);
@@ -61,9 +56,11 @@ public class MailQueueItemDTOTest {
                 .map(MailAddress::asString)
                 .collect(Guavate.toImmutableList());
 
-        softly.assertThat(mailQueueItemDTO.getName()).isEqualTo(mail.getName());
-        softly.assertThat(mailQueueItemDTO.getSender()).isEqualTo(mail.getMaybeSender().get().asString());
-        softly.assertThat(mailQueueItemDTO.getRecipients()).isEqualTo(expectedRecipients);
-        softly.assertThat(mailQueueItemDTO.getNextDelivery()).contains(date);
+        SoftAssertions.assertSoftly(softly -> {
+            softly.assertThat(mailQueueItemDTO.getName()).isEqualTo(mail.getName());
+            softly.assertThat(mailQueueItemDTO.getSender()).isEqualTo(mail.getMaybeSender().get().asString());
+            softly.assertThat(mailQueueItemDTO.getRecipients()).isEqualTo(expectedRecipients);
+            softly.assertThat(mailQueueItemDTO.getNextDelivery()).contains(date);
+        });
     }
 }
diff --git a/server/protocols/webadmin/webadmin-mailqueue/src/test/java/org/apache/james/webadmin/routes/MailQueueRoutesUnitTest.java b/server/protocols/webadmin/webadmin-mailqueue/src/test/java/org/apache/james/webadmin/routes/MailQueueRoutesUnitTest.java
index f67bc12..a03d340 100644
--- a/server/protocols/webadmin/webadmin-mailqueue/src/test/java/org/apache/james/webadmin/routes/MailQueueRoutesUnitTest.java
+++ b/server/protocols/webadmin/webadmin-mailqueue/src/test/java/org/apache/james/webadmin/routes/MailQueueRoutesUnitTest.java
@@ -28,40 +28,39 @@ import org.apache.james.queue.api.ManageableMailQueue;
 import org.apache.james.task.Hostname;
 import org.apache.james.task.MemoryTaskManager;
 import org.apache.james.webadmin.utils.JsonTransformer;
-import org.junit.Before;
-import org.junit.Test;
-
-public class MailQueueRoutesUnitTest {
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
 
+class MailQueueRoutesUnitTest {
     MailQueueRoutes testee;
 
-    @Before
-    public void setup() {
+    @BeforeEach
+    void setup() {
         MemoryTaskManager taskManager = new MemoryTaskManager(new Hostname("foo"));
         MailQueueFactory<ManageableMailQueue> mailQueueFactory = null;
         testee = new MailQueueRoutes(mailQueueFactory, new JsonTransformer(), taskManager);
     }
 
     @Test
-    public void isDelayedShouldReturnEmptyWhenNull() {
+    void isDelayedShouldReturnEmptyWhenNull() {
         Optional<Boolean> delayed = testee.isDelayed(null);
         assertThat(delayed).isEmpty();
     }
 
     @Test
-    public void isDelayedShouldBeEqualsToTrueWhenTrue() {
+    void isDelayedShouldBeEqualsToTrueWhenTrue() {
         Optional<Boolean> delayed = testee.isDelayed("true");
         assertThat(delayed).contains(true);
     }
 
     @Test
-    public void isDelayedShouldBeEqualsToFalseWhenFalse() {
+    void isDelayedShouldBeEqualsToFalseWhenFalse() {
         Optional<Boolean> delayed = testee.isDelayed("false");
         assertThat(delayed).contains(false);
     }
 
     @Test
-    public void isDelayedShouldBeEqualsToFalseWhenOtherValue() {
+    void isDelayedShouldBeEqualsToFalseWhenOtherValue() {
         Optional<Boolean> delayed = testee.isDelayed("abc");
         assertThat(delayed).contains(false);
     }
diff --git a/server/protocols/webadmin/webadmin-mailrepository/src/test/java/org/apache/james/webadmin/routes/MailRepositoriesRoutesTest.java b/server/protocols/webadmin/webadmin-mailrepository/src/test/java/org/apache/james/webadmin/routes/MailRepositoriesRoutesTest.java
index 7416bd0..2009f83 100644
--- a/server/protocols/webadmin/webadmin-mailrepository/src/test/java/org/apache/james/webadmin/routes/MailRepositoriesRoutesTest.java
+++ b/server/protocols/webadmin/webadmin-mailrepository/src/test/java/org/apache/james/webadmin/routes/MailRepositoriesRoutesTest.java
@@ -86,9 +86,9 @@ import org.apache.mailet.Mail;
 import org.apache.mailet.PerRecipientHeaders.Header;
 import org.apache.mailet.base.test.FakeMail;
 import org.eclipse.jetty.http.HttpStatus;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
 
 import com.google.common.collect.ImmutableList;
 
@@ -97,7 +97,7 @@ import io.restassured.builder.RequestSpecBuilder;
 import io.restassured.http.ContentType;
 import io.restassured.parsing.Parser;
 
-public class MailRepositoriesRoutesTest {
+class MailRepositoriesRoutesTest {
 
     private static final MailRepositoryUrl URL_MY_REPO = MailRepositoryUrl.from("memory://myRepo");
     private static final MailRepositoryUrl URL_MY_REPO_OTHER = MailRepositoryUrl.from("other://myRepo");
@@ -112,8 +112,8 @@ public class MailRepositoriesRoutesTest {
     private ManageableMailQueue spoolQueue;
     private ManageableMailQueue customQueue;
 
-    @Before
-    public void setUp() throws Exception {
+    @BeforeEach
+    void setUp() throws Exception {
         createMailRepositoryStore();
 
         MemoryTaskManager taskManager = new MemoryTaskManager(new Hostname("foo"));
@@ -141,13 +141,13 @@ public class MailRepositoriesRoutesTest {
         RestAssured.enableLoggingOfRequestAndResponseIfValidationFails();
     }
 
-    @After
-    public void tearDown() {
+    @AfterEach
+    void tearDown() {
         webAdminServer.destroy();
     }
 
     @Test
-    public void putMailRepositoryShouldReturnOkWhenRepositoryIsCreated() {
+    void putMailRepositoryShouldReturnOkWhenRepositoryIsCreated() {
         given()
             .params("protocol", "memory")
         .when()
@@ -161,7 +161,7 @@ public class MailRepositoriesRoutesTest {
     }
 
     @Test
-    public void putMailRepositoryShouldReturnOkWhenRepositoryAlreadyExists() {
+    void putMailRepositoryShouldReturnOkWhenRepositoryAlreadyExists() {
         given()
             .params("protocol", "memory")
         .when()
@@ -185,7 +185,7 @@ public class MailRepositoriesRoutesTest {
     }
 
     @Test
-    public void putMailRepositoryShouldReturnInvalidArgumentWhenProtocolIsUnsupported() {
+    void putMailRepositoryShouldReturnInvalidArgumentWhenProtocolIsUnsupported() {
         given()
             .params("protocol", "unsupported")
         .when()
@@ -201,7 +201,7 @@ public class MailRepositoriesRoutesTest {
     }
 
     @Test
-    public void getMailRepositoriesShouldReturnEmptyWhenEmpty() {
+    void getMailRepositoriesShouldReturnEmptyWhenEmpty() {
         List<Object> mailRepositories =
             when()
                 .get()
@@ -217,7 +217,7 @@ public class MailRepositoriesRoutesTest {
     }
 
     @Test
-    public void getMailRepositoriesShouldReturnRepositoryWhenOne() throws Exception {
+    void getMailRepositoriesShouldReturnRepositoryWhenOne() throws Exception {
         mailRepositoryStore.create(URL_MY_REPO);
 
         when()
@@ -230,7 +230,7 @@ public class MailRepositoriesRoutesTest {
     }
 
     @Test
-    public void getMailRepositoriesShouldDeduplicateAccordingToPath() throws Exception {
+    void getMailRepositoriesShouldDeduplicateAccordingToPath() throws Exception {
         mailRepositoryStore.create(URL_MY_REPO);
         mailRepositoryStore.create(URL_MY_REPO_OTHER);
 
@@ -244,7 +244,7 @@ public class MailRepositoriesRoutesTest {
     }
 
     @Test
-    public void getMailRepositoriesShouldReturnTwoRepositoriesWhenTwo() throws Exception {
+    void getMailRepositoriesShouldReturnTwoRepositoriesWhenTwo() throws Exception {
         mailRepositoryStore.create(URL_MY_REPO);
         mailRepositoryStore.create(MailRepositoryUrl.from("memory://mySecondRepo"));
 
@@ -264,7 +264,7 @@ public class MailRepositoriesRoutesTest {
     }
 
     @Test
-    public void listingKeysShouldReturnNotFoundWhenNoRepository() {
+    void listingKeysShouldReturnNotFoundWhenNoRepository() {
         when()
             .get(MY_REPO_MAILS)
         .then()
@@ -273,7 +273,7 @@ public class MailRepositoriesRoutesTest {
     }
 
     @Test
-    public void listingKeysShouldReturnEmptyWhenNoMail() throws Exception {
+    void listingKeysShouldReturnEmptyWhenNoMail() throws Exception {
         mailRepositoryStore.create(URL_MY_REPO);
 
         when()
@@ -284,7 +284,7 @@ public class MailRepositoriesRoutesTest {
     }
 
     @Test
-    public void listingKeysShouldReturnContainedKeys() throws Exception {
+    void listingKeysShouldReturnContainedKeys() throws Exception {
         MailRepository mailRepository = mailRepositoryStore.create(URL_MY_REPO);
 
         mailRepository.store(FakeMail.builder()
@@ -303,7 +303,7 @@ public class MailRepositoriesRoutesTest {
     }
 
     @Test
-    public void listingKeysShouldMergeRepositoryContentWhenSamePath() throws Exception {
+    void listingKeysShouldMergeRepositoryContentWhenSamePath() throws Exception {
         MailRepository mailRepository1 = mailRepositoryStore.create(URL_MY_REPO);
         MailRepository mailRepository2 = mailRepositoryStore.create(URL_MY_REPO_OTHER);
 
@@ -323,7 +323,7 @@ public class MailRepositoriesRoutesTest {
     }
 
     @Test
-    public void listingKeysShouldApplyLimitAndOffset() throws Exception {
+    void listingKeysShouldApplyLimitAndOffset() throws Exception {
         MailRepository mailRepository = mailRepositoryStore.create(URL_MY_REPO);
 
         mailRepository.store(FakeMail.builder()
@@ -348,7 +348,7 @@ public class MailRepositoriesRoutesTest {
     }
 
     @Test
-    public void listingKeysShouldApplyLimitWhenSeveralRepositories() throws Exception {
+    void listingKeysShouldApplyLimitWhenSeveralRepositories() throws Exception {
         MailRepository mailRepository1 = mailRepositoryStore.create(URL_MY_REPO);
         MailRepository mailRepository2 = mailRepositoryStore.create(URL_MY_REPO_OTHER);
 
@@ -372,7 +372,7 @@ public class MailRepositoriesRoutesTest {
     }
 
     @Test
-    public void listingKeysShouldReturnErrorOnInvalidOffset() {
+    void listingKeysShouldReturnErrorOnInvalidOffset() {
         given()
             .param("offset", "invalid")
         .when()
@@ -385,7 +385,7 @@ public class MailRepositoriesRoutesTest {
     }
 
     @Test
-    public void listingKeysShouldReturnErrorOnNegativeOffset() {
+    void listingKeysShouldReturnErrorOnNegativeOffset() {
         given()
             .param("offset", "-1")
         .when()
@@ -398,7 +398,7 @@ public class MailRepositoriesRoutesTest {
     }
 
     @Test
-    public void listingKeysShouldReturnEmptyWhenOffsetExceedsSize() throws Exception {
+    void listingKeysShouldReturnEmptyWhenOffsetExceedsSize() throws Exception {
         MailRepository mailRepository = mailRepositoryStore.create(URL_MY_REPO);
 
         mailRepository.store(FakeMail.builder()
@@ -421,7 +421,7 @@ public class MailRepositoriesRoutesTest {
     }
 
     @Test
-    public void offsetShouldBeAplliedOnTheMergedViewOfMailRepositories() throws Exception {
+    void offsetShouldBeAplliedOnTheMergedViewOfMailRepositories() throws Exception {
         MailRepository mailRepository1 = mailRepositoryStore.create(URL_MY_REPO);
         MailRepository mailRepository2 = mailRepositoryStore.create(URL_MY_REPO_OTHER);
 
@@ -448,7 +448,7 @@ public class MailRepositoriesRoutesTest {
     }
 
     @Test
-    public void listingKeysShouldReturnErrorOnInvalidLimit() {
+    void listingKeysShouldReturnErrorOnInvalidLimit() {
         given()
             .param("limit", "invalid")
         .when()
@@ -461,7 +461,7 @@ public class MailRepositoriesRoutesTest {
     }
 
     @Test
-    public void listingKeysShouldReturnErrorOnNegativeLimit() {
+    void listingKeysShouldReturnErrorOnNegativeLimit() {
         given()
             .param("limit", "-1")
         .when()
@@ -474,7 +474,7 @@ public class MailRepositoriesRoutesTest {
     }
 
     @Test
-    public void listingKeysShouldIgnoreZeroedOffset() throws Exception {
+    void listingKeysShouldIgnoreZeroedOffset() throws Exception {
         MailRepository mailRepository = mailRepositoryStore.create(URL_MY_REPO);
 
         mailRepository.store(FakeMail.builder()
@@ -495,7 +495,7 @@ public class MailRepositoriesRoutesTest {
     }
 
     @Test
-    public void zeroLimitShouldNotBeValid() {
+    void zeroLimitShouldNotBeValid() {
         given()
             .param("limit", "0")
         .when()
@@ -508,7 +508,7 @@ public class MailRepositoriesRoutesTest {
     }
 
     @Test
-    public void retrievingRepositoryShouldReturnNotFoundWhenNone() {
+    void retrievingRepositoryShouldReturnNotFoundWhenNone() {
         given()
             .get(PATH_ESCAPED_MY_REPO)
         .then()
@@ -516,7 +516,7 @@ public class MailRepositoriesRoutesTest {
     }
 
     @Test
-    public void retrievingRepositoryShouldReturnBasicInformation() throws Exception {
+    void retrievingRepositoryShouldReturnBasicInformation() throws Exception {
         mailRepositoryStore.create(URL_MY_REPO);
 
         given()
@@ -529,7 +529,7 @@ public class MailRepositoriesRoutesTest {
     }
 
     @Test
-    public void retrievingRepositorySizeShouldReturnZeroWhenEmpty() throws Exception {
+    void retrievingRepositorySizeShouldReturnZeroWhenEmpty() throws Exception {
         mailRepositoryStore.create(URL_MY_REPO);
 
         given()
@@ -541,7 +541,7 @@ public class MailRepositoriesRoutesTest {
     }
 
     @Test
-    public void retrievingRepositorySizeShouldReturnNumberOfContainedMails() throws Exception {
+    void retrievingRepositorySizeShouldReturnNumberOfContainedMails() throws Exception {
         MailRepository mailRepository = mailRepositoryStore.create(URL_MY_REPO);
 
         mailRepository.store(FakeMail.builder()
@@ -557,7 +557,7 @@ public class MailRepositoriesRoutesTest {
     }
 
     @Test
-    public void retrievingRepositorySizeShouldReturnNumberOfContainedMailsWhenSeveralRepositoryWithSamePath() throws Exception {
+    void retrievingRepositorySizeShouldReturnNumberOfContainedMailsWhenSeveralRepositoryWithSamePath() throws Exception {
         MailRepository mailRepository1 = mailRepositoryStore.create(URL_MY_REPO);
         MailRepository mailRepository2 = mailRepositoryStore.create(URL_MY_REPO_OTHER);
 
@@ -578,7 +578,7 @@ public class MailRepositoriesRoutesTest {
     }
 
     @Test
-    public void retrievingAMailShouldDisplayItsInformation() throws Exception {
+    void retrievingAMailShouldDisplayItsInformation() throws Exception {
         MailRepository mailRepository = mailRepositoryStore.create(URL_MY_REPO);
 
         String name = NAME_1;
@@ -617,7 +617,7 @@ public class MailRepositoriesRoutesTest {
     }
 
     @Test
-    public void retrievingAMailShouldDisplayAllAdditionalFieldsWhenRequested() throws Exception {
+    void retrievingAMailShouldDisplayAllAdditionalFieldsWhenRequested() throws Exception {
         MailRepository mailRepository = mailRepositoryStore.create(URL_MY_REPO);
         String name = NAME_1;
 
@@ -720,7 +720,7 @@ public class MailRepositoriesRoutesTest {
     }
 
     @Test
-    public void retrievingAMailShouldDisplayAllValidAdditionalFieldsWhenRequested() throws Exception {
+    void retrievingAMailShouldDisplayAllValidAdditionalFieldsWhenRequested() throws Exception {
         MailRepository mailRepository = mailRepositoryStore.create(URL_MY_REPO);
 
         String name = NAME_1;
@@ -751,7 +751,7 @@ public class MailRepositoriesRoutesTest {
     }
 
     @Test
-    public void retrievingAMailShouldDisplayCorrectlyEncodedHeadersInValidAdditionalFieldsWhenRequested() throws Exception {
+    void retrievingAMailShouldDisplayCorrectlyEncodedHeadersInValidAdditionalFieldsWhenRequested() throws Exception {
         MailRepository mailRepository = mailRepositoryStore.create(URL_MY_REPO);
         String name = NAME_1;
         String sender = "sender@domain";
@@ -779,7 +779,7 @@ public class MailRepositoriesRoutesTest {
     }
 
     @Test
-    public void retrievingAMailShouldDisplayAllValidAdditionalFieldsEvenTheDuplicatedOnesWhenRequested() throws Exception {
+    void retrievingAMailShouldDisplayAllValidAdditionalFieldsEvenTheDuplicatedOnesWhenRequested() throws Exception {
         MailRepository mailRepository = mailRepositoryStore.create(URL_MY_REPO);
         String name = NAME_1;
         String sender = "sender@domain";
@@ -809,7 +809,7 @@ public class MailRepositoriesRoutesTest {
     }
 
     @Test
-    public void retrievingAMailShouldFailWhenAnUnknownFieldIsRequested() throws Exception {
+    void retrievingAMailShouldFailWhenAnUnknownFieldIsRequested() throws Exception {
         MailRepository mailRepository = mailRepositoryStore.create(URL_MY_REPO);
         String name = NAME_1;
         String sender = "sender@domain";
@@ -834,7 +834,7 @@ public class MailRepositoriesRoutesTest {
     }
 
     @Test
-    public void retrievingAMailShouldNotFailWhenOnlyNameProperty() throws Exception {
+    void retrievingAMailShouldNotFailWhenOnlyNameProperty() throws Exception {
         MailRepository mailRepository = mailRepositoryStore.create(URL_MY_REPO);
 
         mailRepository.store(FakeMail.builder()
@@ -853,7 +853,7 @@ public class MailRepositoriesRoutesTest {
     }
 
     @Test
-    public void retrievingAMailShouldFailWhenUnknown() throws Exception {
+    void retrievingAMailShouldFailWhenUnknown() throws Exception {
         mailRepositoryStore.create(URL_MY_REPO);
 
         String name = "name";
@@ -867,7 +867,7 @@ public class MailRepositoriesRoutesTest {
     }
 
     @Test
-    public void downloadingAMailShouldReturnTheEml() throws Exception {
+    void downloadingAMailShouldReturnTheEml() throws Exception {
         RestAssured.requestSpecification = new RequestSpecBuilder().setPort(webAdminServer.getPort().getValue())
                 .setBasePath(MailRepositoriesRoutes.MAIL_REPOSITORIES)
                 .build();
@@ -900,7 +900,7 @@ public class MailRepositoriesRoutesTest {
     }
 
     @Test
-    public void downloadingAMailShouldFailWhenUnknown() throws Exception {
+    void downloadingAMailShouldFailWhenUnknown() throws Exception {
         mailRepositoryStore.create(URL_MY_REPO);
 
         RestAssured.requestSpecification = new RequestSpecBuilder().setPort(webAdminServer.getPort().getValue())
@@ -921,7 +921,7 @@ public class MailRepositoriesRoutesTest {
     }
 
     @Test
-    public void deletingAMailShouldRemoveIt() throws Exception {
+    void deletingAMailShouldRemoveIt() throws Exception {
         MailRepository mailRepository = mailRepositoryStore.create(URL_MY_REPO);
 
         mailRepository.store(FakeMail.builder()
@@ -943,7 +943,7 @@ public class MailRepositoriesRoutesTest {
     }
 
     @Test
-    public void deletingAMailShouldReturnOkWhenExist() throws Exception {
+    void deletingAMailShouldReturnOkWhenExist() throws Exception {
         MailRepository mailRepository = mailRepositoryStore.create(URL_MY_REPO);
 
         mailRepository.store(FakeMail.builder()
@@ -957,7 +957,7 @@ public class MailRepositoriesRoutesTest {
     }
 
     @Test
-    public void deletingAMailShouldReturnOkWhenNotExist() throws Exception {
+    void deletingAMailShouldReturnOkWhenNotExist() throws Exception {
         mailRepositoryStore.create(URL_MY_REPO);
 
         when()
@@ -967,7 +967,7 @@ public class MailRepositoriesRoutesTest {
     }
 
     @Test
-    public void deletingAllMailsShouldCreateATask() throws Exception {
+    void deletingAllMailsShouldCreateATask() throws Exception {
         mailRepositoryStore.create(URL_MY_REPO);
 
         when()
@@ -979,7 +979,7 @@ public class MailRepositoriesRoutesTest {
     }
 
     @Test
-    public void clearTaskShouldHaveDetails() throws Exception {
+    void clearTaskShouldHaveDetails() throws Exception {
         MailRepository mailRepository = mailRepositoryStore.create(URL_MY_REPO);
 
         mailRepository.store(FakeMail.builder()
@@ -1011,7 +1011,7 @@ public class MailRepositoriesRoutesTest {
     }
 
     @Test
-    public void clearTaskShouldRemoveAllTheMailsFromTheMailRepository() throws Exception {
+    void clearTaskShouldRemoveAllTheMailsFromTheMailRepository() throws Exception {
         MailRepository mailRepository = mailRepositoryStore.create(URL_MY_REPO);
 
         mailRepository.store(FakeMail.builder()
@@ -1038,7 +1038,7 @@ public class MailRepositoriesRoutesTest {
     }
 
     @Test
-    public void patchShouldReturnNotFoundWhenNoMailRepository() {
+    void patchShouldReturnNotFoundWhenNoMailRepository() {
         when()
             .delete(PATH_ESCAPED_MY_REPO + "/mails")
         .then()
@@ -1049,7 +1049,7 @@ public class MailRepositoriesRoutesTest {
     }
 
     @Test
-    public void deleteShouldReturnNotFoundWhenNoMailRepository() {
+    void deleteShouldReturnNotFoundWhenNoMailRepository() {
         when()
             .delete(PATH_ESCAPED_MY_REPO + "/mails/any")
         .then()
@@ -1060,7 +1060,7 @@ public class MailRepositoriesRoutesTest {
     }
 
     @Test
-    public void reprocessingAllTaskShouldCreateATask() throws Exception {
+    void reprocessingAllTaskShouldCreateATask() throws Exception {
         mailRepositoryStore.create(URL_MY_REPO);
 
         given()
@@ -1074,7 +1074,7 @@ public class MailRepositoriesRoutesTest {
     }
 
     @Test
-    public void reprocessingAllTaskShouldRejectInvalidActions() {
+    void reprocessingAllTaskShouldRejectInvalidActions() {
         given()
             .param("action", "invalid")
         .when()
@@ -1088,7 +1088,7 @@ public class MailRepositoriesRoutesTest {
     }
 
     @Test
-    public void reprocessingAllTaskShouldRequireAction() {
+    void reprocessingAllTaskShouldRequireAction() {
         when()
             .patch(PATH_ESCAPED_MY_REPO + "/mails")
         .then()
@@ -1100,7 +1100,7 @@ public class MailRepositoriesRoutesTest {
     }
 
     @Test
-    public void reprocessingAllTaskShouldIncludeDetailsWhenDefaultValues() throws Exception {
+    void reprocessingAllTaskShouldIncludeDetailsWhenDefaultValues() throws Exception {
         MailRepository mailRepository = mailRepositoryStore.create(URL_MY_REPO);
         mailRepository.store(FakeMail.builder()
             .name(NAME_1)
@@ -1134,7 +1134,7 @@ public class MailRepositoriesRoutesTest {
     }
 
     @Test
-    public void reprocessingAllTaskShouldIncludeDetails() throws Exception {
+    void reprocessingAllTaskShouldIncludeDetails() throws Exception {
         MailRepository mailRepository = mailRepositoryStore.create(URL_MY_REPO);
         String name1 = "name1";
         String name2 = "name2";
@@ -1173,7 +1173,7 @@ public class MailRepositoriesRoutesTest {
     }
 
     @Test
-    public void reprocessingAllTaskShouldNotFailWhenSeveralRepositoriesWithSamePath() throws Exception {
+    void reprocessingAllTaskShouldNotFailWhenSeveralRepositoriesWithSamePath() throws Exception {
         MailRepository mailRepository = mailRepositoryStore.create(URL_MY_REPO);
         mailRepositoryStore.create(URL_MY_REPO_OTHER);
         String name1 = "name1";
@@ -1203,7 +1203,7 @@ public class MailRepositoriesRoutesTest {
     }
 
     @Test
-    public void reprocessingAllTaskShouldClearMailRepository() throws Exception {
+    void reprocessingAllTaskShouldClearMailRepository() throws Exception {
         MailRepository mailRepository = mailRepositoryStore.create(URL_MY_REPO);
         String name1 = "name1";
         String name2 = "name2";
@@ -1233,7 +1233,7 @@ public class MailRepositoriesRoutesTest {
     }
 
     @Test
-    public void reprocessingAllTaskShouldClearBothMailRepositoriesWhenSamePath() throws Exception {
+    void reprocessingAllTaskShouldClearBothMailRepositoriesWhenSamePath() throws Exception {
         MailRepository mailRepository1 = mailRepositoryStore.create(URL_MY_REPO);
         MailRepository mailRepository2 = mailRepositoryStore.create(URL_MY_REPO_OTHER);
         String name1 = "name1";
@@ -1265,7 +1265,7 @@ public class MailRepositoriesRoutesTest {
     }
 
     @Test
-    public void reprocessingAllTaskShouldEnqueueMailsOnDefaultQueue() throws Exception {
+    void reprocessingAllTaskShouldEnqueueMailsOnDefaultQueue() throws Exception {
         MailRepository mailRepository = mailRepositoryStore.create(URL_MY_REPO);
         mailRepository.store(FakeMail.builder()
             .name(NAME_1)
@@ -1292,7 +1292,7 @@ public class MailRepositoriesRoutesTest {
     }
 
     @Test
-    public void reprocessingAllTaskShouldEnqueueMailsOfBothRepositoriesOnDefaultQueueWhenSamePath() throws Exception {
+    void reprocessingAllTaskShouldEnqueueMailsOfBothRepositoriesOnDefaultQueueWhenSamePath() throws Exception {
         MailRepository mailRepository1 = mailRepositoryStore.create(URL_MY_REPO);
         MailRepository mailRepository2 = mailRepositoryStore.create(URL_MY_REPO_OTHER);
         mailRepository1.store(FakeMail.builder()
@@ -1320,7 +1320,7 @@ public class MailRepositoriesRoutesTest {
     }
 
     @Test
-    public void reprocessingAllTaskShouldPreserveStateWhenProcessorIsNotSpecified() throws Exception {
+    void reprocessingAllTaskShouldPreserveStateWhenProcessorIsNotSpecified() throws Exception {
         MailRepository mailRepository = mailRepositoryStore.create(URL_MY_REPO);
         String state1 = "state1";
         String state2 = "state2";
@@ -1351,7 +1351,7 @@ public class MailRepositoriesRoutesTest {
     }
 
     @Test
-    public void reprocessingAllTaskShouldOverWriteStateWhenProcessorSpecified() throws Exception {
+    void reprocessingAllTaskShouldOverWriteStateWhenProcessorSpecified() throws Exception {
         MailRepository mailRepository = mailRepositoryStore.create(URL_MY_REPO);
         String state1 = "state1";
         String state2 = "state2";
@@ -1384,7 +1384,7 @@ public class MailRepositoriesRoutesTest {
     }
 
     @Test
-    public void reprocessingAllTaskShouldEnqueueMailsOnSpecifiedQueue() throws Exception {
+    void reprocessingAllTaskShouldEnqueueMailsOnSpecifiedQueue() throws Exception {
         MailRepository mailRepository = mailRepositoryStore.create(URL_MY_REPO);
         mailRepository.store(FakeMail.builder()
             .name(NAME_1)
@@ -1412,7 +1412,7 @@ public class MailRepositoriesRoutesTest {
     }
 
     @Test
-    public void reprocessingOneTaskShouldCreateATask() throws Exception {
+    void reprocessingOneTaskShouldCreateATask() throws Exception {
         MailRepository mailRepository = mailRepositoryStore.create(URL_MY_REPO);
         mailRepository.store(FakeMail.builder()
             .name(NAME_1)
@@ -1429,7 +1429,7 @@ public class MailRepositoriesRoutesTest {
     }
 
     @Test
-    public void reprocessingOneTaskShouldRejectInvalidActions() throws Exception {
+    void reprocessingOneTaskShouldRejectInvalidActions() throws Exception {
         MailRepository mailRepository = mailRepositoryStore.create(URL_MY_REPO);
         mailRepository.store(FakeMail.builder()
             .name(NAME_1)
@@ -1448,7 +1448,7 @@ public class MailRepositoriesRoutesTest {
     }
 
     @Test
-    public void reprocessingOneTaskShouldRequireAction() throws Exception {
+    void reprocessingOneTaskShouldRequireAction() throws Exception {
         MailRepository mailRepository = mailRepositoryStore.create(URL_MY_REPO);
         mailRepository.store(FakeMail.builder()
             .name(NAME_1)
@@ -1465,7 +1465,7 @@ public class MailRepositoriesRoutesTest {
     }
 
     @Test
-    public void reprocessingOneTaskShouldIncludeDetailsWhenDefaultValues() throws Exception {
+    void reprocessingOneTaskShouldIncludeDetailsWhenDefaultValues() throws Exception {
         MailRepository mailRepository = mailRepositoryStore.create(URL_MY_REPO);
         String name1 = "name1";
         String name2 = "name2";
@@ -1500,7 +1500,7 @@ public class MailRepositoriesRoutesTest {
     }
 
     @Test
-    public void reprocessingOneTaskShouldIncludeDetails() throws Exception {
+    void reprocessingOneTaskShouldIncludeDetails() throws Exception {
         MailRepository mailRepository = mailRepositoryStore.create(URL_MY_REPO);
         String name1 = "name1";
         String name2 = "name2";
@@ -1538,7 +1538,7 @@ public class MailRepositoriesRoutesTest {
     }
 
     @Test
-    public void reprocessingOneTaskShouldNotFailWhenSeveralRepositoryWithSamePath() throws Exception {
+    void reprocessingOneTaskShouldNotFailWhenSeveralRepositoryWithSamePath() throws Exception {
         MailRepository mailRepository = mailRepositoryStore.create(URL_MY_REPO);
         mailRepositoryStore.create(URL_MY_REPO_OTHER);
         String name1 = "name1";
@@ -1568,7 +1568,7 @@ public class MailRepositoriesRoutesTest {
     }
 
     @Test
-    public void reprocessingOneTaskShouldRemoveMailFromRepository() throws Exception {
+    void reprocessingOneTaskShouldRemoveMailFromRepository() throws Exception {
         MailRepository mailRepository = mailRepositoryStore.create(URL_MY_REPO);
         String name1 = "name1";
         String name2 = "name2";
@@ -1598,7 +1598,7 @@ public class MailRepositoriesRoutesTest {
     }
 
     @Test
-    public void reprocessingOneTaskShouldEnqueueMailsOnDefaultQueue() throws Exception {
+    void reprocessingOneTaskShouldEnqueueMailsOnDefaultQueue() throws Exception {
         MailRepository mailRepository = mailRepositoryStore.create(URL_MY_REPO);
         mailRepository.store(FakeMail.builder()
             .name(NAME_1)
@@ -1625,7 +1625,7 @@ public class MailRepositoriesRoutesTest {
     }
 
     @Test
-    public void reprocessingOneTaskShouldPreserveStateWhenProcessorIsNotSpecified() throws Exception {
+    void reprocessingOneTaskShouldPreserveStateWhenProcessorIsNotSpecified() throws Exception {
         MailRepository mailRepository = mailRepositoryStore.create(URL_MY_REPO);
         String state1 = "state1";
         String state2 = "state2";
@@ -1656,7 +1656,7 @@ public class MailRepositoriesRoutesTest {
     }
 
     @Test
-    public void reprocessingOneTaskShouldOverWriteStateWhenProcessorSpecified() throws Exception {
+    void reprocessingOneTaskShouldOverWriteStateWhenProcessorSpecified() throws Exception {
         MailRepository mailRepository = mailRepositoryStore.create(URL_MY_REPO);
         String state1 = "state1";
         String state2 = "state2";
@@ -1689,7 +1689,7 @@ public class MailRepositoriesRoutesTest {
     }
 
     @Test
-    public void reprocessingOneTaskShouldEnqueueMailsOnSpecifiedQueue() throws Exception {
+    void reprocessingOneTaskShouldEnqueueMailsOnSpecifiedQueue() throws Exception {
         MailRepository mailRepository = mailRepositoryStore.create(URL_MY_REPO);
         mailRepository.store(FakeMail.builder()
             .name(NAME_1)
@@ -1717,7 +1717,7 @@ public class MailRepositoriesRoutesTest {
     }
 
     @Test
-    public void reprocessingOneTaskShouldNotEnqueueUnknownMailKey() throws Exception {
+    void reprocessingOneTaskShouldNotEnqueueUnknownMailKey() throws Exception {
         MailRepository mailRepository = mailRepositoryStore.create(URL_MY_REPO);
         mailRepository.store(FakeMail.builder()
             .name(NAME_1)
@@ -1743,7 +1743,7 @@ public class MailRepositoriesRoutesTest {
     }
 
     @Test
-    public void reprocessingOneTaskShouldNotRemoveMailFromRepositoryWhenUnknownMailKey() throws Exception {
+    void reprocessingOneTaskShouldNotRemoveMailFromRepositoryWhenUnknownMailKey() throws Exception {
         MailRepository mailRepository = mailRepositoryStore.create(URL_MY_REPO);
         mailRepository.store(FakeMail.builder()
             .name(NAME_1)
@@ -1768,7 +1768,7 @@ public class MailRepositoriesRoutesTest {
     }
 
     @Test
-    public void reprocessingOneTaskShouldFailWhenUnknownMailKey() throws Exception {
+    void reprocessingOneTaskShouldFailWhenUnknownMailKey() throws Exception {
         MailRepository mailRepository = mailRepositoryStore.create(URL_MY_REPO);
         mailRepository.store(FakeMail.builder()
             .name(NAME_1)
diff --git a/server/protocols/webadmin/webadmin-mailrepository/src/test/java/org/apache/james/webadmin/service/MailRepositoryStoreServiceTest.java b/server/protocols/webadmin/webadmin-mailrepository/src/test/java/org/apache/james/webadmin/service/MailRepositoryStoreServiceTest.java
index 6fac837..8f449dc 100644
--- a/server/protocols/webadmin/webadmin-mailrepository/src/test/java/org/apache/james/webadmin/service/MailRepositoryStoreServiceTest.java
+++ b/server/protocols/webadmin/webadmin-mailrepository/src/test/java/org/apache/james/webadmin/service/MailRepositoryStoreServiceTest.java
@@ -41,10 +41,10 @@ import org.apache.james.util.streams.Offset;
 import org.apache.james.webadmin.dto.MailKeyDTO;
 import org.apache.james.webadmin.dto.SingleMailRepositoryResponse;
 import org.apache.mailet.base.test.FakeMail;
-import org.junit.Before;
-import org.junit.Test;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
 
-public class MailRepositoryStoreServiceTest {
+class MailRepositoryStoreServiceTest {
     private static final MailRepositoryPath FIRST_REPOSITORY_PATH = MailRepositoryPath.from("repository");
     private static final MailRepositoryPath SECOND_REPOSITORY_PATH = MailRepositoryPath.from("repository2");
     private static final MailKey NAME_1 = new MailKey("name1");
@@ -54,22 +54,22 @@ public class MailRepositoryStoreServiceTest {
     private MailRepositoryStoreService testee;
     private MemoryMailRepository repository;
 
-    @Before
-    public void setUp() {
+    @BeforeEach
+    void setUp() {
         mailRepositoryStore = mock(MailRepositoryStore.class);
         repository = new MemoryMailRepository();
         testee = new MailRepositoryStoreService(mailRepositoryStore);
     }
 
     @Test
-    public void listMailRepositoriesShouldReturnEmptyWhenEmpty() {
+    void listMailRepositoriesShouldReturnEmptyWhenEmpty() {
         when(mailRepositoryStore.getPaths()).thenReturn(Stream.empty());
 
         assertThat(testee.listMailRepositories()).isEmpty();
     }
 
     @Test
-    public void listMailRepositoriesShouldReturnOneRepositoryWhenOne() {
+    void listMailRepositoriesShouldReturnOneRepositoryWhenOne() {
         when(mailRepositoryStore.getPaths())
             .thenReturn(Stream.of(FIRST_REPOSITORY_PATH));
         assertThat(testee.listMailRepositories())
@@ -78,7 +78,7 @@ public class MailRepositoryStoreServiceTest {
     }
 
     @Test
-    public void listMailRepositoriesShouldReturnTwoRepositoriesWhentwo() {
+    void listMailRepositoriesShouldReturnTwoRepositoriesWhentwo() {
         when(mailRepositoryStore.getPaths())
             .thenReturn(Stream.of(FIRST_REPOSITORY_PATH, SECOND_REPOSITORY_PATH));
         assertThat(testee.listMailRepositories())
@@ -87,7 +87,7 @@ public class MailRepositoryStoreServiceTest {
     }
 
     @Test
-    public void listMailsShouldThrowWhenMailRepositoryStoreThrows() throws Exception {
+    void listMailsShouldThrowWhenMailRepositoryStoreThrows() throws Exception {
         when(mailRepositoryStore.getByPath(FIRST_REPOSITORY_PATH))
             .thenThrow(new MailRepositoryStore.MailRepositoryStoreException("message"));
 
@@ -96,7 +96,7 @@ public class MailRepositoryStoreServiceTest {
     }
 
     @Test
-    public void listMailsShouldReturnEmptyWhenMailRepositoryIsEmpty() throws Exception {
+    void listMailsShouldReturnEmptyWhenMailRepositoryIsEmpty() throws Exception {
         when(mailRepositoryStore.getByPath(FIRST_REPOSITORY_PATH)).thenReturn(Stream.of(repository));
 
         assertThat(testee.listMails(FIRST_REPOSITORY_PATH, Offset.none(), Limit.unlimited()).get())
@@ -104,7 +104,7 @@ public class MailRepositoryStoreServiceTest {
     }
 
     @Test
-    public void listMailsShouldReturnContainedMailKeys() throws Exception {
+    void listMailsShouldReturnContainedMailKeys() throws Exception {
         when(mailRepositoryStore.getByPath(FIRST_REPOSITORY_PATH)).thenReturn(Stream.of(repository));
 
         repository.store(FakeMail.builder()
@@ -119,7 +119,7 @@ public class MailRepositoryStoreServiceTest {
     }
 
     @Test
-    public void listMailsShouldApplyLimitAndOffset() throws Exception {
+    void listMailsShouldApplyLimitAndOffset() throws Exception {
         when(mailRepositoryStore.getByPath(FIRST_REPOSITORY_PATH)).thenReturn(Stream.of(repository));
 
         repository.store(FakeMail.builder()
@@ -137,7 +137,7 @@ public class MailRepositoryStoreServiceTest {
     }
 
     @Test
-    public void retrieveMessageShouldThrownWhenUnknownRepository() throws Exception {
+    void retrieveMessageShouldThrownWhenUnknownRepository() throws Exception {
         when(mailRepositoryStore.getByPath(FIRST_REPOSITORY_PATH)).thenReturn(Stream.of());
 
         assertThatThrownBy(() -> testee.retrieveMessage(FIRST_REPOSITORY_PATH, NAME_1))
@@ -145,7 +145,7 @@ public class MailRepositoryStoreServiceTest {
     }
 
     @Test
-    public void retrieveMessageShouldThrowWhenMailRepositoryStoreThrows() throws Exception {
+    void retrieveMessageShouldThrowWhenMailRepositoryStoreThrows() throws Exception {
         when(mailRepositoryStore.getByPath(FIRST_REPOSITORY_PATH))
             .thenThrow(new MailRepositoryStore.MailRepositoryStoreException("message"));
 
@@ -154,7 +154,7 @@ public class MailRepositoryStoreServiceTest {
     }
 
     @Test
-    public void retrieveMessageShouldReturnEmptyWhenMailNotFound() throws Exception {
+    void retrieveMessageShouldReturnEmptyWhenMailNotFound() throws Exception {
         when(mailRepositoryStore.getByPath(FIRST_REPOSITORY_PATH)).thenReturn(Stream.of(repository));
 
         assertThat(testee.retrieveMessage(FIRST_REPOSITORY_PATH, NAME_1))
@@ -162,7 +162,7 @@ public class MailRepositoryStoreServiceTest {
     }
 
     @Test
-    public void retrieveMessageShouldReturnTheMessageWhenMailExists() throws Exception {
+    void retrieveMessageShouldReturnTheMessageWhenMailExists() throws Exception {
         when(mailRepositoryStore.getByPath(FIRST_REPOSITORY_PATH)).thenReturn(Stream.of(repository));
 
         FakeMail mail = FakeMail.builder()
diff --git a/server/protocols/webadmin/webadmin-mailrepository/src/test/java/org/apache/james/webadmin/service/ReprocessingServiceTest.java b/server/protocols/webadmin/webadmin-mailrepository/src/test/java/org/apache/james/webadmin/service/ReprocessingServiceTest.java
index c191cf5..105be08 100644
--- a/server/protocols/webadmin/webadmin-mailrepository/src/test/java/org/apache/james/webadmin/service/ReprocessingServiceTest.java
+++ b/server/protocols/webadmin/webadmin-mailrepository/src/test/java/org/apache/james/webadmin/service/ReprocessingServiceTest.java
@@ -42,14 +42,14 @@ import org.apache.james.queue.api.ManageableMailQueue;
 import org.apache.james.queue.api.RawMailQueueItemDecoratorFactory;
 import org.apache.james.queue.memory.MemoryMailQueueFactory;
 import org.apache.mailet.base.test.FakeMail;
-import org.junit.Before;
-import org.junit.Test;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
 
 import com.github.fge.lambdas.Throwing;
 import com.github.fge.lambdas.consumers.ConsumerChainer;
 import com.google.common.collect.ImmutableList;
 
-public class ReprocessingServiceTest {
+class ReprocessingServiceTest {
     private static final String MEMORY_PROTOCOL = "memory";
     private static final MailRepositoryPath PATH = MailRepositoryPath.from("path");
     private static final String NAME_1 = "key-1";
@@ -69,8 +69,8 @@ public class ReprocessingServiceTest {
     private FakeMail mail2;
     private FakeMail mail3;
 
-    @Before
-    public void setUp() throws Exception {
+    @BeforeEach
+    void setUp() throws Exception {
         mailRepositoryStore = createMemoryMailRepositoryStore();
 
         queueFactory = new MemoryMailQueueFactory(new RawMailQueueItemDecoratorFactory());
@@ -94,7 +94,7 @@ public class ReprocessingServiceTest {
     }
 
     @Test
-    public void reprocessingOneShouldEnqueueMail() throws Exception {
+    void reprocessingOneShouldEnqueueMail() throws Exception {
         MailRepository repository = mailRepositoryStore.select(MailRepositoryUrl.fromPathAndProtocol(PATH, MEMORY_PROTOCOL));
         repository.store(mail1);
         repository.store(mail2);
@@ -109,7 +109,7 @@ public class ReprocessingServiceTest {
     }
 
     @Test
-    public void reprocessingOneShouldRemoveMailFromRepository() throws Exception {
+    void reprocessingOneShouldRemoveMailFromRepository() throws Exception {
         MailRepository repository = mailRepositoryStore.select(MailRepositoryUrl.fromPathAndProtocol(PATH, MEMORY_PROTOCOL));
         repository.store(mail1);
         repository.store(mail2);
@@ -122,7 +122,7 @@ public class ReprocessingServiceTest {
     }
 
     @Test
-    public void reprocessingShouldEmptyRepository() throws Exception {
+    void reprocessingShouldEmptyRepository() throws Exception {
         MailRepository repository = mailRepositoryStore.select(MailRepositoryUrl.fromPathAndProtocol(PATH, MEMORY_PROTOCOL));
         repository.store(mail1);
         repository.store(mail2);
@@ -135,7 +135,7 @@ public class ReprocessingServiceTest {
     }
 
     @Test
-    public void reprocessingShouldEnqueueAllMails() throws Exception {
+    void reprocessingShouldEnqueueAllMails() throws Exception {
         MailRepository repository = mailRepositoryStore.select(MailRepositoryUrl.fromPathAndProtocol(PATH, MEMORY_PROTOCOL));
         repository.store(mail1);
         repository.store(mail2);
@@ -150,7 +150,7 @@ public class ReprocessingServiceTest {
     }
 
     @Test
-    public void reprocessingShouldNotFailOnConcurrentDeletion() throws Exception {
+    void reprocessingShouldNotFailOnConcurrentDeletion() throws Exception {
         MailRepository repository = mailRepositoryStore.select(MailRepositoryUrl.fromPathAndProtocol(PATH, MEMORY_PROTOCOL));
         repository.store(mail1);
         repository.store(mail2);


---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@james.apache.org
For additional commands, e-mail: notifications-help@james.apache.org


[james-project] 01/20: JAMES-3471 JPA and maildir message mappers should not register MessageId when handling FlagsUpdated events

Posted by rc...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

rcordier pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/james-project.git

commit b0cfc20732f53a85b650225ce6e20dfd903f3563
Author: Rene Cordier <rc...@linagora.com>
AuthorDate: Thu Jan 7 10:44:44 2021 +0700

    JAMES-3471 JPA and maildir message mappers should not register MessageId when handling FlagsUpdated events
    
    JPA and maildir implementation do not handle MessageId, thus it was a bug that needed to be fixed.
    JpaMessageMapperTest has been adapted as well to override tests having messageId in FlagsUpdated objects.
---
 .../apache/james/mailbox/model/UpdatedFlags.java   | 11 +--
 .../james/mailbox/jpa/mail/MessageUtils.java       |  1 -
 .../mailbox/jpa/mail/JpaMessageMapperTest.java     | 80 ++++++++++++++++++++--
 .../mailbox/maildir/mail/MaildirMessageMapper.java |  1 -
 .../store/mail/model/MessageMapperTest.java        |  3 +-
 5 files changed, 82 insertions(+), 14 deletions(-)

diff --git a/mailbox/api/src/main/java/org/apache/james/mailbox/model/UpdatedFlags.java b/mailbox/api/src/main/java/org/apache/james/mailbox/model/UpdatedFlags.java
index 0649c58..d36e53f 100644
--- a/mailbox/api/src/main/java/org/apache/james/mailbox/model/UpdatedFlags.java
+++ b/mailbox/api/src/main/java/org/apache/james/mailbox/model/UpdatedFlags.java
@@ -274,10 +274,11 @@ public class UpdatedFlags {
     @Override
     public String toString() {
         return MoreObjects.toStringHelper(UpdatedFlags.class)
-                .add("uid", uid)
-                .add("oldFlags", oldFlags)
-                .add("newFlags", newFlags)
-                .add("modSeq", modSeq)
-                .toString();
+            .add("uid", uid)
+            .add("messageId", messageId)
+            .add("oldFlags", oldFlags)
+            .add("newFlags", newFlags)
+            .add("modSeq", modSeq)
+            .toString();
     }
 }
diff --git a/mailbox/jpa/src/main/java/org/apache/james/mailbox/jpa/mail/MessageUtils.java b/mailbox/jpa/src/main/java/org/apache/james/mailbox/jpa/mail/MessageUtils.java
index 1c097e7..bd5d513 100644
--- a/mailbox/jpa/src/main/java/org/apache/james/mailbox/jpa/mail/MessageUtils.java
+++ b/mailbox/jpa/src/main/java/org/apache/james/mailbox/jpa/mail/MessageUtils.java
@@ -74,7 +74,6 @@ class MessageUtils {
 
             updatedFlags.add(UpdatedFlags.builder()
                 .uid(member.getUid())
-                .messageId(member.getMessageId())
                 .modSeq(member.getModSeq())
                 .newFlags(newFlags)
                 .oldFlags(originalFlags)
diff --git a/mailbox/jpa/src/test/java/org/apache/james/mailbox/jpa/mail/JpaMessageMapperTest.java b/mailbox/jpa/src/test/java/org/apache/james/mailbox/jpa/mail/JpaMessageMapperTest.java
index 5fea0fd..1e5db35 100644
--- a/mailbox/jpa/src/test/java/org/apache/james/mailbox/jpa/mail/JpaMessageMapperTest.java
+++ b/mailbox/jpa/src/test/java/org/apache/james/mailbox/jpa/mail/JpaMessageMapperTest.java
@@ -19,13 +19,23 @@
 
 package org.apache.james.mailbox.jpa.mail;
 
+import static org.assertj.core.api.Assertions.assertThat;
+
+import java.util.Optional;
+
+import javax.mail.Flags;
+
 import org.apache.james.backends.jpa.JpaTestCluster;
+import org.apache.james.mailbox.FlagsBuilder;
+import org.apache.james.mailbox.MessageManager;
+import org.apache.james.mailbox.ModSeq;
 import org.apache.james.mailbox.exception.MailboxException;
 import org.apache.james.mailbox.jpa.JPAMailboxFixture;
+import org.apache.james.mailbox.model.UpdatedFlags;
+import org.apache.james.mailbox.store.FlagsUpdateCalculator;
 import org.apache.james.mailbox.store.mail.model.MapperProvider;
 import org.apache.james.mailbox.store.mail.model.MessageMapperTest;
 import org.junit.jupiter.api.AfterEach;
-import org.junit.jupiter.api.Disabled;
 import org.junit.jupiter.api.Test;
 
 class JpaMessageMapperTest extends MessageMapperTest {
@@ -42,33 +52,91 @@ class JpaMessageMapperTest extends MessageMapperTest {
         JPA_TEST_CLUSTER.clear(JPAMailboxFixture.MAILBOX_TABLE_NAMES);
     }
 
-    @Disabled("JAMES-3471 messageId is not supported by JPA ")
     @Test
+    @Override
     public void flagsAdditionShouldReturnAnUpdatedFlagHighlightingTheAddition() throws MailboxException {
+        saveMessages();
+        messageMapper.updateFlags(benwaInboxMailbox, message1.getUid(), new FlagsUpdateCalculator(new Flags(Flags.Flag.FLAGGED), MessageManager.FlagsUpdateMode.REPLACE));
+        ModSeq modSeq = messageMapper.getHighestModSeq(benwaInboxMailbox);
 
+        // JPA does not support MessageId
+        assertThat(messageMapper.updateFlags(benwaInboxMailbox, message1.getUid(), new FlagsUpdateCalculator(new Flags(Flags.Flag.SEEN), MessageManager.FlagsUpdateMode.ADD)))
+            .contains(UpdatedFlags.builder()
+                .uid(message1.getUid())
+                .modSeq(modSeq.next())
+                .oldFlags(new Flags(Flags.Flag.FLAGGED))
+                .newFlags(new FlagsBuilder().add(Flags.Flag.SEEN, Flags.Flag.FLAGGED).build())
+                .build());
     }
 
-    @Disabled("")
     @Test
+    @Override
     public void flagsReplacementShouldReturnAnUpdatedFlagHighlightingTheReplacement() throws MailboxException {
+        saveMessages();
+        ModSeq modSeq = messageMapper.getHighestModSeq(benwaInboxMailbox);
+        Optional<UpdatedFlags> updatedFlags = messageMapper.updateFlags(benwaInboxMailbox, message1.getUid(),
+            new FlagsUpdateCalculator(new Flags(Flags.Flag.FLAGGED), MessageManager.FlagsUpdateMode.REPLACE));
 
+        // JPA does not support MessageId
+        assertThat(updatedFlags)
+            .contains(UpdatedFlags.builder()
+                .uid(message1.getUid())
+                .modSeq(modSeq.next())
+                .oldFlags(new Flags())
+                .newFlags(new Flags(Flags.Flag.FLAGGED))
+                .build());
     }
 
-    @Disabled("")
     @Test
+    @Override
     public void flagsRemovalShouldReturnAnUpdatedFlagHighlightingTheRemoval() throws MailboxException {
+        saveMessages();
+        messageMapper.updateFlags(benwaInboxMailbox, message1.getUid(), new FlagsUpdateCalculator(new FlagsBuilder().add(Flags.Flag.FLAGGED, Flags.Flag.SEEN).build(), MessageManager.FlagsUpdateMode.REPLACE));
+        ModSeq modSeq = messageMapper.getHighestModSeq(benwaInboxMailbox);
 
+        // JPA does not support MessageId
+        assertThat(messageMapper.updateFlags(benwaInboxMailbox, message1.getUid(), new FlagsUpdateCalculator(new Flags(Flags.Flag.SEEN), MessageManager.FlagsUpdateMode.REMOVE)))
+            .contains(
+                UpdatedFlags.builder()
+                    .uid(message1.getUid())
+                    .modSeq(modSeq.next())
+                    .oldFlags(new FlagsBuilder().add(Flags.Flag.SEEN, Flags.Flag.FLAGGED).build())
+                    .newFlags(new Flags(Flags.Flag.FLAGGED))
+                    .build());
     }
 
-    @Disabled("")
     @Test
+    @Override
     public void userFlagsUpdateShouldReturnCorrectUpdatedFlags() throws MailboxException {
+        saveMessages();
+        ModSeq modSeq = messageMapper.getHighestModSeq(benwaInboxMailbox);
 
+        // JPA does not support MessageId
+        assertThat(messageMapper.updateFlags(benwaInboxMailbox, message1.getUid(), new FlagsUpdateCalculator(new Flags(USER_FLAG), MessageManager.FlagsUpdateMode.ADD)))
+            .contains(
+                UpdatedFlags.builder()
+                    .uid(message1.getUid())
+                    .modSeq(modSeq.next())
+                    .oldFlags(new Flags())
+                    .newFlags(new Flags(USER_FLAG))
+                    .build());
     }
 
-    @Disabled("")
     @Test
+    @Override
     public void userFlagsUpdateShouldReturnCorrectUpdatedFlagsWhenNoop() throws MailboxException {
+        saveMessages();
 
+        // JPA does not support MessageId
+        assertThat(
+            messageMapper.updateFlags(benwaInboxMailbox,message1.getUid(),
+                new FlagsUpdateCalculator(new Flags(USER_FLAG), MessageManager.FlagsUpdateMode.REMOVE)))
+            .contains(
+                UpdatedFlags.builder()
+                    .uid(message1.getUid())
+                    .modSeq(message1.getModSeq())
+                    .oldFlags(new Flags())
+                    .newFlags(new Flags())
+                    .build());
     }
 }
diff --git a/mailbox/maildir/src/main/java/org/apache/james/mailbox/maildir/mail/MaildirMessageMapper.java b/mailbox/maildir/src/main/java/org/apache/james/mailbox/maildir/mail/MaildirMessageMapper.java
index f8f7894..e670055 100644
--- a/mailbox/maildir/src/main/java/org/apache/james/mailbox/maildir/mail/MaildirMessageMapper.java
+++ b/mailbox/maildir/src/main/java/org/apache/james/mailbox/maildir/mail/MaildirMessageMapper.java
@@ -194,7 +194,6 @@ public class MaildirMessageMapper extends AbstractMessageMapper {
 
                     updatedFlags.add(UpdatedFlags.builder()
                         .uid(member.getUid())
-                        .messageId(member.getMessageId())
                         .modSeq(member.getModSeq())
                         .newFlags(newFlags)
                         .oldFlags(originalFlags)
diff --git a/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/MessageMapperTest.java b/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/MessageMapperTest.java
index 6f4d93d..b33bd9a 100644
--- a/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/MessageMapperTest.java
+++ b/mailbox/store/src/test/java/org/apache/james/mailbox/store/mail/model/MessageMapperTest.java
@@ -71,11 +71,12 @@ public abstract class MessageMapperTest {
     private static final int LIMIT = 10;
     private static final int BODY_START = 16;
     private static final UidValidity UID_VALIDITY = UidValidity.of(42);
-    private static final String USER_FLAG = "userFlag";
 
     private static final String CUSTOMS_USER_FLAGS_VALUE = "CustomsFlags";
     private static final Username BENWA = Username.of("benwa");
 
+    protected static final String USER_FLAG = "userFlag";
+
     private MapperProvider mapperProvider;
     protected MessageMapper messageMapper;
     private MailboxMapper mailboxMapper;


---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@james.apache.org
For additional commands, e-mail: notifications-help@james.apache.org


[james-project] 18/20: JAMES-2543 Junit 4 -> 5 migration for server/protocols/smtp

Posted by rc...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

rcordier pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/james-project.git

commit dd12ea90b025d6e152e53e887734940ccc93fd4c
Author: Benoit Tellier <bt...@linagora.com>
AuthorDate: Thu Dec 31 09:19:21 2020 +0700

    JAMES-2543 Junit 4 -> 5 migration for server/protocols/smtp
---
 .../java/org/apache/james/smtpserver/DSNTest.java  | 30 +++++++++++-----------
 .../smtpserver/POP3BeforeSMTPHandlerTest.java      | 12 ++++-----
 .../apache/james/smtpserver/SMTPServerTest.java    | 16 ++++++------
 .../apache/james/smtpserver/SPFHandlerTest.java    |  6 ++---
 .../apache/james/smtpserver/URIRBLHandlerTest.java |  2 +-
 .../james/smtpserver/ValidRcptHandlerTest.java     |  6 ++---
 .../apache/james/smtpserver/ValidRcptMXTest.java   |  6 ++---
 7 files changed, 39 insertions(+), 39 deletions(-)

diff --git a/server/protocols/protocols-smtp/src/test/java/org/apache/james/smtpserver/DSNTest.java b/server/protocols/protocols-smtp/src/test/java/org/apache/james/smtpserver/DSNTest.java
index 3c38d88..f3f13cb 100644
--- a/server/protocols/protocols-smtp/src/test/java/org/apache/james/smtpserver/DSNTest.java
+++ b/server/protocols/protocols-smtp/src/test/java/org/apache/james/smtpserver/DSNTest.java
@@ -75,14 +75,14 @@ import org.apache.mailet.DsnParameters;
 import org.apache.mailet.Mail;
 import org.assertj.core.api.SoftAssertions;
 import org.jboss.netty.util.HashedWheelTimer;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
 
 import com.google.common.collect.ImmutableList;
 import com.google.inject.TypeLiteral;
 
-public class DSNTest {
+class DSNTest {
     public static final String LOCAL_DOMAIN = "example.local";
     public static final Username BOB = Username.of("bob@localhost");
     public static final String PASSWORD = "bobpwd";
@@ -100,8 +100,8 @@ public class DSNTest {
 
     private SMTPServer smtpServer;
 
-    @Before
-    public void setUp() throws Exception {
+    @BeforeEach
+    void setUp() throws Exception {
         domainList = new MemoryDomainList(new InMemoryDNSService()
             .registerMxRecord(Domain.LOCALHOST.asString(), "127.0.0.1")
             .registerMxRecord(Domain.LOCALHOST.asString(), "127.0.0.1")
@@ -178,14 +178,14 @@ public class DSNTest {
             .build();
     }
 
-    @After
-    public void tearDown() {
+    @AfterEach
+    void tearDown() {
         smtpServer.destroy();
         hashedWheelTimer.stop();
     }
 
     @Test
-    public void ehloShouldAdvertiseDsnExtension() throws Exception {
+    void ehloShouldAdvertiseDsnExtension() throws Exception {
         smtpServer.configure(FileConfigurationProvider.getConfig(
             ClassLoader.getSystemResourceAsStream("smtpserver-dsn.xml")));
         smtpServer.init();
@@ -211,7 +211,7 @@ public class DSNTest {
     }
 
     @Test
-    public void dsnParametersShouldBeSetOnTheFinalEmail() throws Exception {
+    void dsnParametersShouldBeSetOnTheFinalEmail() throws Exception {
         smtpServer.configure(FileConfigurationProvider.getConfig(
             ClassLoader.getSystemResourceAsStream("smtpserver-dsn.xml")));
         smtpServer.init();
@@ -238,7 +238,7 @@ public class DSNTest {
     }
 
     @Test
-    public void multipleRecipientsShouldBeSupported() throws Exception {
+    void multipleRecipientsShouldBeSupported() throws Exception {
         smtpServer.configure(FileConfigurationProvider.getConfig(
             ClassLoader.getSystemResourceAsStream("smtpserver-dsn.xml")));
         smtpServer.init();
@@ -270,7 +270,7 @@ public class DSNTest {
     }
 
     @Test
-    public void notifyCanBeOmitted() throws Exception {
+    void notifyCanBeOmitted() throws Exception {
         smtpServer.configure(FileConfigurationProvider.getConfig(
             ClassLoader.getSystemResourceAsStream("smtpserver-dsn.xml")));
         smtpServer.init();
@@ -296,7 +296,7 @@ public class DSNTest {
     }
 
     @Test
-    public void orcptCanBeOmitted() throws Exception {
+    void orcptCanBeOmitted() throws Exception {
         smtpServer.configure(FileConfigurationProvider.getConfig(
             ClassLoader.getSystemResourceAsStream("smtpserver-dsn.xml")));
         smtpServer.init();
@@ -322,7 +322,7 @@ public class DSNTest {
     }
 
     @Test
-    public void retCanBeOmitted() throws Exception {
+    void retCanBeOmitted() throws Exception {
         smtpServer.configure(FileConfigurationProvider.getConfig(
             ClassLoader.getSystemResourceAsStream("smtpserver-dsn.xml")));
         smtpServer.init();
@@ -348,7 +348,7 @@ public class DSNTest {
     }
 
     @Test
-    public void envIdCanBeOmitted() throws Exception {
+    void envIdCanBeOmitted() throws Exception {
         smtpServer.configure(FileConfigurationProvider.getConfig(
             ClassLoader.getSystemResourceAsStream("smtpserver-dsn.xml")));
         smtpServer.init();
diff --git a/server/protocols/protocols-smtp/src/test/java/org/apache/james/smtpserver/POP3BeforeSMTPHandlerTest.java b/server/protocols/protocols-smtp/src/test/java/org/apache/james/smtpserver/POP3BeforeSMTPHandlerTest.java
index 66970a2..dd07d9a 100644
--- a/server/protocols/protocols-smtp/src/test/java/org/apache/james/smtpserver/POP3BeforeSMTPHandlerTest.java
+++ b/server/protocols/protocols-smtp/src/test/java/org/apache/james/smtpserver/POP3BeforeSMTPHandlerTest.java
@@ -26,9 +26,9 @@ import java.time.Duration;
 import org.apache.james.protocols.lib.POP3BeforeSMTPHelper;
 import org.apache.james.protocols.smtp.SMTPSession;
 import org.apache.james.protocols.smtp.utils.BaseFakeSMTPSession;
-import org.junit.Test;
+import org.junit.jupiter.api.Test;
 
-public class POP3BeforeSMTPHandlerTest {
+class POP3BeforeSMTPHandlerTest {
 
     private SMTPSession mockedSession;
 
@@ -59,7 +59,7 @@ public class POP3BeforeSMTPHandlerTest {
     }
 
     @Test
-    public void testAuthWorks() {
+    void testAuthWorks() {
 
         POP3BeforeSMTPHandler handler = new POP3BeforeSMTPHandler();
 
@@ -72,7 +72,7 @@ public class POP3BeforeSMTPHandlerTest {
     }
 
     @Test
-    public void testIPGetRemoved() {
+    void testIPGetRemoved() {
         long sleepTime = 100;
         POP3BeforeSMTPHandler handler = new POP3BeforeSMTPHandler();
 
@@ -92,7 +92,7 @@ public class POP3BeforeSMTPHandlerTest {
     }
 
     @Test
-    public void testThrowExceptionOnIllegalExpireTime() {
+    void testThrowExceptionOnIllegalExpireTime() {
         boolean exception = false;
         POP3BeforeSMTPHandler handler = new POP3BeforeSMTPHandler();
 
@@ -107,7 +107,7 @@ public class POP3BeforeSMTPHandlerTest {
     }
 
     @Test
-    public void testValidExpireTime() {
+    void testValidExpireTime() {
         boolean exception = false;
         POP3BeforeSMTPHandler handler = new POP3BeforeSMTPHandler();
 
diff --git a/server/protocols/protocols-smtp/src/test/java/org/apache/james/smtpserver/SMTPServerTest.java b/server/protocols/protocols-smtp/src/test/java/org/apache/james/smtpserver/SMTPServerTest.java
index 9d99f15..953068b 100644
--- a/server/protocols/protocols-smtp/src/test/java/org/apache/james/smtpserver/SMTPServerTest.java
+++ b/server/protocols/protocols-smtp/src/test/java/org/apache/james/smtpserver/SMTPServerTest.java
@@ -87,10 +87,10 @@ import org.apache.james.user.api.UsersRepository;
 import org.apache.james.user.memory.MemoryUsersRepository;
 import org.apache.mailet.Mail;
 import org.jboss.netty.util.HashedWheelTimer;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Ignore;
-import org.junit.Test;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Disabled;
+import org.junit.jupiter.api.Test;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -207,7 +207,7 @@ public class SMTPServerTest {
 
     private SMTPServer smtpServer;
 
-    @Before
+    @BeforeEach
     public void setUp() throws Exception {
 
         domainList = new MemoryDomainList(new InMemoryDNSService()
@@ -369,8 +369,8 @@ public class SMTPServerTest {
         }
     }
 
-    @After
-    public void tearDown() throws Exception {
+    @AfterEach
+    public void tearDown() {
         smtpServer.destroy();
         hashedWheelTimer.stop();
     }
@@ -640,7 +640,7 @@ public class SMTPServerTest {
     }
 
     // FIXME
-    @Ignore
+    @Disabled
     @Test
     public void testEmptyMessageReceivedHeader() throws Exception {
         init(smtpConfiguration);
diff --git a/server/protocols/protocols-smtp/src/test/java/org/apache/james/smtpserver/SPFHandlerTest.java b/server/protocols/protocols-smtp/src/test/java/org/apache/james/smtpserver/SPFHandlerTest.java
index 9349d6d..613906a 100644
--- a/server/protocols/protocols-smtp/src/test/java/org/apache/james/smtpserver/SPFHandlerTest.java
+++ b/server/protocols/protocols-smtp/src/test/java/org/apache/james/smtpserver/SPFHandlerTest.java
@@ -34,8 +34,8 @@ import org.apache.james.protocols.smtp.SMTPSession;
 import org.apache.james.protocols.smtp.hook.HookReturnCode;
 import org.apache.james.protocols.smtp.utils.BaseFakeSMTPSession;
 import org.apache.james.smtpserver.fastfail.SPFHandler;
-import org.junit.Before;
-import org.junit.Test;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
 
 import com.google.common.base.Preconditions;
 
@@ -46,7 +46,7 @@ public class SPFHandlerTest {
 
     private boolean relaying = false;
 
-    @Before
+    @BeforeEach
     public void setUp() throws Exception {
         setupMockedDnsService();
         setRelayingAllowed(false);
diff --git a/server/protocols/protocols-smtp/src/test/java/org/apache/james/smtpserver/URIRBLHandlerTest.java b/server/protocols/protocols-smtp/src/test/java/org/apache/james/smtpserver/URIRBLHandlerTest.java
index af14370..acda4bb 100644
--- a/server/protocols/protocols-smtp/src/test/java/org/apache/james/smtpserver/URIRBLHandlerTest.java
+++ b/server/protocols/protocols-smtp/src/test/java/org/apache/james/smtpserver/URIRBLHandlerTest.java
@@ -45,7 +45,7 @@ import org.apache.james.protocols.smtp.utils.BaseFakeSMTPSession;
 import org.apache.james.smtpserver.fastfail.URIRBLHandler;
 import org.apache.mailet.Mail;
 import org.apache.mailet.base.test.FakeMail;
-import org.junit.Test;
+import org.junit.jupiter.api.Test;
 
 import com.google.common.base.Preconditions;
 
diff --git a/server/protocols/protocols-smtp/src/test/java/org/apache/james/smtpserver/ValidRcptHandlerTest.java b/server/protocols/protocols-smtp/src/test/java/org/apache/james/smtpserver/ValidRcptHandlerTest.java
index 5065bc6..8bbb2a0 100644
--- a/server/protocols/protocols-smtp/src/test/java/org/apache/james/smtpserver/ValidRcptHandlerTest.java
+++ b/server/protocols/protocols-smtp/src/test/java/org/apache/james/smtpserver/ValidRcptHandlerTest.java
@@ -41,8 +41,8 @@ import org.apache.james.rrt.memory.MemoryRecipientRewriteTable;
 import org.apache.james.smtpserver.fastfail.ValidRcptHandler;
 import org.apache.james.user.api.UsersRepository;
 import org.apache.james.user.memory.MemoryUsersRepository;
-import org.junit.Before;
-import org.junit.Test;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.BeforeEach;
 
 import com.google.common.base.Preconditions;
 
@@ -62,7 +62,7 @@ public class ValidRcptHandlerTest {
     private MailAddress user1mail;
     private MailAddress invalidUserEmail;
 
-    @Before
+    @BeforeEach
     public void setUp() throws Exception {
         MemoryDomainList memoryDomainList = new MemoryDomainList(mock(DNSService.class));
         memoryDomainList.configure(DomainListConfiguration.builder()
diff --git a/server/protocols/protocols-smtp/src/test/java/org/apache/james/smtpserver/ValidRcptMXTest.java b/server/protocols/protocols-smtp/src/test/java/org/apache/james/smtpserver/ValidRcptMXTest.java
index ee29e3f..0a6da3c 100644
--- a/server/protocols/protocols-smtp/src/test/java/org/apache/james/smtpserver/ValidRcptMXTest.java
+++ b/server/protocols/protocols-smtp/src/test/java/org/apache/james/smtpserver/ValidRcptMXTest.java
@@ -31,12 +31,12 @@ import org.apache.james.protocols.smtp.SMTPSession;
 import org.apache.james.protocols.smtp.hook.HookReturnCode;
 import org.apache.james.protocols.smtp.utils.BaseFakeSMTPSession;
 import org.apache.james.smtpserver.fastfail.ValidRcptMX;
-import org.junit.Test;
+import org.junit.jupiter.api.Test;
 
 import com.google.common.base.Preconditions;
 import com.google.common.collect.ImmutableList;
 
-public class ValidRcptMXTest {
+class ValidRcptMXTest {
 
     private static final String INVALID_HOST = "invalid.host.de";
 
@@ -81,7 +81,7 @@ public class ValidRcptMXTest {
     }
 
     @Test
-    public void testRejectLoopbackMX() throws Exception {
+    void testRejectLoopbackMX() throws Exception {
         String bannedAddress = "172.53.64.2";
 
         DNSService dns = new InMemoryDNSService()


---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@james.apache.org
For additional commands, e-mail: notifications-help@james.apache.org


[james-project] 19/20: JAMES-2543 Junit 4 -> 5 migration for mock SpamAssassin testing

Posted by rc...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

rcordier pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/james-project.git

commit 2e0a45489a74f364dc12a79b7298755f624072d3
Author: Benoit Tellier <bt...@linagora.com>
AuthorDate: Thu Dec 31 09:24:18 2020 +0700

    JAMES-2543 Junit 4 -> 5 migration for mock SpamAssassin testing
---
 .../james/transport/mailets/SpamAssassinTest.java      | 10 +++++-----
 .../james/smtpserver/SpamAssassinHandlerTest.java      | 10 +++++-----
 ...{MockSpamdTestRule.java => MockSpamdExtension.java} | 18 +++++++++++-------
 3 files changed, 21 insertions(+), 17 deletions(-)

diff --git a/server/mailet/mailets/src/test/java/org/apache/james/transport/mailets/SpamAssassinTest.java b/server/mailet/mailets/src/test/java/org/apache/james/transport/mailets/SpamAssassinTest.java
index 5e8dc59..4af5557 100644
--- a/server/mailet/mailets/src/test/java/org/apache/james/transport/mailets/SpamAssassinTest.java
+++ b/server/mailet/mailets/src/test/java/org/apache/james/transport/mailets/SpamAssassinTest.java
@@ -30,23 +30,23 @@ import org.apache.james.domainlist.api.DomainList;
 import org.apache.james.metrics.tests.RecordingMetricFactory;
 import org.apache.james.spamassassin.SpamAssassinResult;
 import org.apache.james.spamassassin.mock.MockSpamd;
-import org.apache.james.spamassassin.mock.MockSpamdTestRule;
+import org.apache.james.spamassassin.mock.MockSpamdExtension;
 import org.apache.james.user.memory.MemoryUsersRepository;
 import org.apache.james.util.Port;
 import org.apache.mailet.Mail;
 import org.apache.mailet.PerRecipientHeaders;
 import org.apache.mailet.base.test.FakeMail;
 import org.apache.mailet.base.test.FakeMailetConfig;
-import org.junit.Rule;
-import org.junit.Test;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.RegisterExtension;
 
 import com.github.steveash.guavate.Guavate;
 
 public class SpamAssassinTest {
 
     public static final DomainList NO_DOMAIN_LIST = null;
-    @Rule
-    public MockSpamdTestRule spamd = new MockSpamdTestRule();
+    @RegisterExtension
+    public MockSpamdExtension spamd = new MockSpamdExtension();
 
     private SpamAssassin mailet = new SpamAssassin(new RecordingMetricFactory(), MemoryUsersRepository.withVirtualHosting(NO_DOMAIN_LIST));
 
diff --git a/server/protocols/protocols-smtp/src/test/java/org/apache/james/smtpserver/SpamAssassinHandlerTest.java b/server/protocols/protocols-smtp/src/test/java/org/apache/james/smtpserver/SpamAssassinHandlerTest.java
index 6fe930e..c727035 100644
--- a/server/protocols/protocols-smtp/src/test/java/org/apache/james/smtpserver/SpamAssassinHandlerTest.java
+++ b/server/protocols/protocols-smtp/src/test/java/org/apache/james/smtpserver/SpamAssassinHandlerTest.java
@@ -39,13 +39,13 @@ import org.apache.james.protocols.smtp.utils.BaseFakeSMTPSession;
 import org.apache.james.smtpserver.fastfail.SpamAssassinHandler;
 import org.apache.james.spamassassin.SpamAssassinResult;
 import org.apache.james.spamassassin.mock.MockSpamd;
-import org.apache.james.spamassassin.mock.MockSpamdTestRule;
+import org.apache.james.spamassassin.mock.MockSpamdExtension;
 import org.apache.mailet.Attribute;
 import org.apache.mailet.AttributeValue;
 import org.apache.mailet.Mail;
 import org.apache.mailet.base.test.FakeMail;
-import org.junit.Rule;
-import org.junit.Test;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.RegisterExtension;
 
 import com.google.common.base.Preconditions;
 
@@ -116,8 +116,8 @@ public class SpamAssassinHandlerTest {
 
     }
 
-    @Rule
-    public MockSpamdTestRule spamd = new MockSpamdTestRule();
+    @RegisterExtension
+    MockSpamdExtension spamd = new MockSpamdExtension();
 
     private Mail setupMockedMail(MimeMessage message) throws MessagingException {
         return FakeMail.builder()
diff --git a/third-party/spamassassin/src/test/java/org/apache/james/spamassassin/mock/MockSpamdTestRule.java b/third-party/spamassassin/src/test/java/org/apache/james/spamassassin/mock/MockSpamdExtension.java
similarity index 79%
rename from third-party/spamassassin/src/test/java/org/apache/james/spamassassin/mock/MockSpamdTestRule.java
rename to third-party/spamassassin/src/test/java/org/apache/james/spamassassin/mock/MockSpamdExtension.java
index 7364d86..1440a79 100644
--- a/third-party/spamassassin/src/test/java/org/apache/james/spamassassin/mock/MockSpamdTestRule.java
+++ b/third-party/spamassassin/src/test/java/org/apache/james/spamassassin/mock/MockSpamdExtension.java
@@ -23,15 +23,24 @@ import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
 
 import org.apache.james.util.concurrent.NamedThreadFactory;
+import org.junit.jupiter.api.extension.AfterEachCallback;
+import org.junit.jupiter.api.extension.BeforeAllCallback;
+import org.junit.jupiter.api.extension.BeforeEachCallback;
+import org.junit.jupiter.api.extension.ExtensionContext;
 import org.junit.rules.ExternalResource;
 
-public class MockSpamdTestRule extends ExternalResource {
+public class MockSpamdExtension implements AfterEachCallback, BeforeEachCallback {
 
     private ExecutorService executor = Executors.newSingleThreadExecutor(NamedThreadFactory.withClassName(getClass()));
     private MockSpamd spamd = new MockSpamd();
 
     @Override
-    protected void before() throws Throwable {
+    public void afterEach(ExtensionContext extensionContext) {
+        executor.shutdownNow();
+    }
+
+    @Override
+    public void beforeEach(ExtensionContext extensionContext) throws Exception {
         spamd.bind();
         executor.execute(spamd);
     }
@@ -39,9 +48,4 @@ public class MockSpamdTestRule extends ExternalResource {
     public int getPort() {
         return spamd.getPort();
     }
-
-    @Override
-    protected void after() {
-        executor.shutdownNow();
-    }
 }


---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@james.apache.org
For additional commands, e-mail: notifications-help@james.apache.org


[james-project] 05/20: JAMES-3472 Update Email/changes request & response

Posted by rc...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

rcordier pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/james-project.git

commit c06ee0e28cd7cba7bb95ec24ceb2d854590ddd9e
Author: LanKhuat <dl...@linagora.com>
AuthorDate: Wed Jan 6 16:41:14 2021 +0700

    JAMES-3472 Update Email/changes request & response
---
 .../src/main/scala/org/apache/james/jmap/core/Session.scala  |  4 +++-
 .../org/apache/james/jmap/json/EmailGetSerializer.scala      |  6 ++++++
 .../src/main/scala/org/apache/james/jmap/mail/EmailGet.scala | 12 ++++++------
 .../main/scala/org/apache/james/jmap/mail/MailboxGet.scala   |  5 +++--
 4 files changed, 18 insertions(+), 9 deletions(-)

diff --git a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/core/Session.scala b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/core/Session.scala
index 81c3f4b..bca220a 100644
--- a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/core/Session.scala
+++ b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/core/Session.scala
@@ -28,7 +28,7 @@ import eu.timepit.refined.api.Refined
 import eu.timepit.refined.refineV
 import eu.timepit.refined.string.Uuid
 import org.apache.james.core.Username
-import org.apache.james.jmap.api.change.{MailboxChanges, State => JavaState}
+import org.apache.james.jmap.api.change.{EmailChanges, MailboxChanges, State => JavaState}
 import org.apache.james.jmap.core.CapabilityIdentifier.CapabilityIdentifier
 import org.apache.james.jmap.core.Id.Id
 import org.apache.james.jmap.core.State.INSTANCE
@@ -84,6 +84,8 @@ object State {
 
   def fromMailboxChanges(mailboxChanges: MailboxChanges): State = fromJava(mailboxChanges.getNewState)
 
+  def fromEmailChanges(emailChanges: EmailChanges): State = fromJava(emailChanges.getNewState)
+
   def fromJava(javaState: JavaState): State = State(javaState.getValue)
 }
 
diff --git a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/json/EmailGetSerializer.scala b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/json/EmailGetSerializer.scala
index edc3392..4a45e02 100644
--- a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/json/EmailGetSerializer.scala
+++ b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/json/EmailGetSerializer.scala
@@ -19,6 +19,7 @@
 
 package org.apache.james.jmap.json
 
+import org.apache.james.jmap.api.change.Limit
 import org.apache.james.jmap.api.model.Preview
 import org.apache.james.jmap.core.{Properties, State}
 import org.apache.james.jmap.mail.Email.Size
@@ -109,6 +110,11 @@ object EmailGetSerializer {
   private implicit val headersWrites: Writes[EmailHeader] = Json.writes[EmailHeader]
   private implicit val bodyValueWrites: Writes[EmailBodyValue] = Json.writes[EmailBodyValue]
   private implicit val emailIdsReads: Reads[EmailIds] = Json.valueReads[EmailIds]
+  private implicit val limitReads: Reads[Limit] = {
+    case JsNumber(underlying) if underlying > 0 => JsSuccess(Limit.of(underlying.intValue))
+    case JsNumber(underlying) if underlying <= 0 => JsError("Expecting a positive integer as Limit")
+    case _ => JsError("Expecting a number as Limit")
+  }
   private implicit val emailGetRequestReads: Reads[EmailGetRequest] = Json.reads[EmailGetRequest]
 
   private implicit val emailChangesRequestReads: Reads[EmailChangesRequest] = Json.reads[EmailChangesRequest]
diff --git a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/mail/EmailGet.scala b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/mail/EmailGet.scala
index a9ff048..a3d63dc 100644
--- a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/mail/EmailGet.scala
+++ b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/mail/EmailGet.scala
@@ -25,13 +25,13 @@ import eu.timepit.refined.api.Refined
 import eu.timepit.refined.auto._
 import eu.timepit.refined.numeric.NonNegative
 import eu.timepit.refined.types.string.NonEmptyString
-import org.apache.james.jmap.core.Id.Id
-import org.apache.james.jmap.core.UnsignedInt.UnsignedInt
+import org.apache.james.jmap.api.change.Limit
 import org.apache.james.jmap.core.{AccountId, Properties, State}
 import org.apache.james.jmap.mail.Email.UnparsedEmailId
 import org.apache.james.jmap.mail.EmailGetRequest.MaxBodyValueBytes
 import org.apache.james.jmap.mail.EmailHeaders.SPECIFIC_HEADER_PREFIX
 import org.apache.james.jmap.method.WithAccountId
+import org.apache.james.mailbox.model.MessageId
 import org.apache.james.mime4j.dom.Message
 import org.apache.james.mime4j.stream.Field
 
@@ -114,13 +114,13 @@ case class SpecificHeaderRequest(property: NonEmptyString, headerName: String, p
 
 case class EmailChangesRequest(accountId: AccountId,
                                 sinceState: State,
-                                maxChanged: Option[UnsignedInt]) extends WithAccountId
+                                maxChanged: Option[Limit]) extends WithAccountId
 
 
 case class EmailChangesResponse(accountId: AccountId,
                                 oldState: State,
                                 newState: State,
                                 hasMoreChanges: HasMoreChanges,
-                                created: List[Id],
-                                updated: List[Id],
-                                destroyed: List[Id])
\ No newline at end of file
+                                created: Set[MessageId],
+                                updated: Set[MessageId],
+                                destroyed: Set[MessageId])
\ No newline at end of file
diff --git a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/mail/MailboxGet.scala b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/mail/MailboxGet.scala
index a3a33e0..7f9fd33 100644
--- a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/mail/MailboxGet.scala
+++ b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/mail/MailboxGet.scala
@@ -22,8 +22,7 @@ package org.apache.james.jmap.mail
 import eu.timepit.refined
 import eu.timepit.refined.api.Refined
 import eu.timepit.refined.collection.NonEmpty
-import org.apache.james.jmap.api.change.Limit
-import org.apache.james.jmap.api.change.MailboxChanges
+import org.apache.james.jmap.api.change.{EmailChanges, Limit, MailboxChanges}
 import org.apache.james.jmap.core.{AccountId, Properties, State}
 import org.apache.james.jmap.mail.MailboxGet.UnparsedMailboxId
 import org.apache.james.jmap.method.WithAccountId
@@ -68,6 +67,8 @@ case class MailboxGetResponse(accountId: AccountId,
 
 object HasMoreChanges {
   def fromMailboxChanges(mailboxChanges: MailboxChanges): HasMoreChanges = HasMoreChanges(mailboxChanges.hasMoreChanges)
+
+  def fromEmailChanges(emailChanges: EmailChanges): HasMoreChanges = HasMoreChanges(emailChanges.hasMoreChanges)
 }
 
 case class HasMoreChanges(value: Boolean) extends AnyVal


---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@james.apache.org
For additional commands, e-mail: notifications-help@james.apache.org


[james-project] 16/20: JAMES-2543 Junit 4 -> 5 migration for server/protocols/imap

Posted by rc...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

rcordier pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/james-project.git

commit c51bb1bb5a6c475b72d9196df70a2b7d5eb22ca4
Author: Benoit Tellier <bt...@linagora.com>
AuthorDate: Thu Dec 31 09:07:23 2020 +0700

    JAMES-2543 Junit 4 -> 5 migration for server/protocols/imap
---
 .../org/apache/james/imapserver/netty/IMAPServerTest.java     | 11 +++--------
 1 file changed, 3 insertions(+), 8 deletions(-)

diff --git a/server/protocols/protocols-imap4/src/test/java/org/apache/james/imapserver/netty/IMAPServerTest.java b/server/protocols/protocols-imap4/src/test/java/org/apache/james/imapserver/netty/IMAPServerTest.java
index 2a29157..888f9fa 100644
--- a/server/protocols/protocols-imap4/src/test/java/org/apache/james/imapserver/netty/IMAPServerTest.java
+++ b/server/protocols/protocols-imap4/src/test/java/org/apache/james/imapserver/netty/IMAPServerTest.java
@@ -27,18 +27,13 @@ import org.apache.commons.configuration2.BaseHierarchicalConfiguration;
 import org.apache.commons.configuration2.HierarchicalConfiguration;
 import org.apache.commons.configuration2.tree.ImmutableNode;
 import org.apache.james.imap.api.ImapConfiguration;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
+import org.junit.jupiter.api.Test;
 
 import com.google.common.collect.ImmutableSet;
 
 public class IMAPServerTest {
-    @Rule
-    public ExpectedException expectedException = ExpectedException.none();
-
     @Test
-    public void getImapConfigurationShouldReturnDefaultValuesWhenEmpty() throws Exception {
+    public void getImapConfigurationShouldReturnDefaultValuesWhenEmpty() {
         ImapConfiguration imapConfiguration = IMAPServer.getImapConfiguration(new BaseHierarchicalConfiguration());
 
         ImapConfiguration expectImapConfiguration = ImapConfiguration.builder()
@@ -52,7 +47,7 @@ public class IMAPServerTest {
     }
 
     @Test
-    public void getImapConfigurationShouldReturnSetValue() throws Exception {
+    public void getImapConfigurationShouldReturnSetValue() {
         HierarchicalConfiguration<ImmutableNode> configurationBuilder = new BaseHierarchicalConfiguration();
         configurationBuilder.addProperty("enableIdle", "false");
         configurationBuilder.addProperty("idleTimeInterval", "1");


---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@james.apache.org
For additional commands, e-mail: notifications-help@james.apache.org


[james-project] 04/20: JAMES-3472 Allows JMAPGuiceProbe fetching Email/changes state

Posted by rc...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

rcordier pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/james-project.git

commit eaa97ab1e7555e500f79a23596c8c06eecad747a
Author: LanKhuat <dl...@linagora.com>
AuthorDate: Wed Jan 6 16:35:31 2021 +0700

    JAMES-3472 Allows JMAPGuiceProbe fetching Email/changes state
---
 .../java/org/apache/james/jmap/draft/JmapGuiceProbe.java    | 13 ++++++++++++-
 1 file changed, 12 insertions(+), 1 deletion(-)

diff --git a/server/container/guice/protocols/jmap/src/main/java/org/apache/james/jmap/draft/JmapGuiceProbe.java b/server/container/guice/protocols/jmap/src/main/java/org/apache/james/jmap/draft/JmapGuiceProbe.java
index ca1616a..a71dff2 100644
--- a/server/container/guice/protocols/jmap/src/main/java/org/apache/james/jmap/draft/JmapGuiceProbe.java
+++ b/server/container/guice/protocols/jmap/src/main/java/org/apache/james/jmap/draft/JmapGuiceProbe.java
@@ -25,6 +25,7 @@ import javax.inject.Inject;
 
 import org.apache.james.core.Username;
 import org.apache.james.jmap.JMAPServer;
+import org.apache.james.jmap.api.change.EmailChangeRepository;
 import org.apache.james.jmap.api.change.MailboxChange;
 import org.apache.james.jmap.api.change.MailboxChangeRepository;
 import org.apache.james.jmap.api.change.State;
@@ -50,6 +51,7 @@ public class JmapGuiceProbe implements GuiceProbe {
 
     private final VacationRepository vacationRepository;
     private final MailboxChangeRepository mailboxChangeRepository;
+    private final EmailChangeRepository emailChangeRepository;
     private final JMAPServer jmapServer;
     private final MessageIdManager messageIdManager;
     private final MailboxManager mailboxManager;
@@ -57,9 +59,10 @@ public class JmapGuiceProbe implements GuiceProbe {
     private final MessageFastViewProjection messageFastViewProjection;
 
     @Inject
-    private JmapGuiceProbe(VacationRepository vacationRepository, MailboxChangeRepository mailboxChangeRepository, JMAPServer jmapServer, MessageIdManager messageIdManager, MailboxManager mailboxManager, EventBus eventBus, MessageFastViewProjection messageFastViewProjection) {
+    private JmapGuiceProbe(VacationRepository vacationRepository, MailboxChangeRepository mailboxChangeRepository, EmailChangeRepository emailChangeRepository, JMAPServer jmapServer, MessageIdManager messageIdManager, MailboxManager mailboxManager, EventBus eventBus, MessageFastViewProjection messageFastViewProjection) {
         this.vacationRepository = vacationRepository;
         this.mailboxChangeRepository = mailboxChangeRepository;
+        this.emailChangeRepository = emailChangeRepository;
         this.jmapServer = jmapServer;
         this.messageIdManager = messageIdManager;
         this.mailboxManager = mailboxManager;
@@ -103,4 +106,12 @@ public class JmapGuiceProbe implements GuiceProbe {
     public State getLastestStateWithDelegation(AccountId accountId) {
         return mailboxChangeRepository.getLatestStateWithDelegation(accountId).block();
     }
+
+    public State getLatestEmailState(AccountId accountId) {
+        return emailChangeRepository.getLatestState(accountId).block();
+    }
+
+    public State getLatestEmailStateWithDelegation(AccountId accountId) {
+        return emailChangeRepository.getLatestStateWithDelegation(accountId).block();
+    }
 }


---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@james.apache.org
For additional commands, e-mail: notifications-help@james.apache.org


[james-project] 07/20: JAMES-3472 JMAP Probe method name clarification

Posted by rc...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

rcordier pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/james-project.git

commit a2be7b819bee96e91959fa23bb2df3664ca2e44b
Author: LanKhuat <dl...@linagora.com>
AuthorDate: Thu Jan 7 10:16:35 2021 +0700

    JAMES-3472 JMAP Probe method name clarification
---
 .../java/org/apache/james/jmap/draft/JmapGuiceProbe.java |  9 ++-------
 .../rfc8621/contract/MailboxChangesMethodContract.scala  | 16 ++++++++--------
 2 files changed, 10 insertions(+), 15 deletions(-)

diff --git a/server/container/guice/protocols/jmap/src/main/java/org/apache/james/jmap/draft/JmapGuiceProbe.java b/server/container/guice/protocols/jmap/src/main/java/org/apache/james/jmap/draft/JmapGuiceProbe.java
index a71dff2..676e7f5 100644
--- a/server/container/guice/protocols/jmap/src/main/java/org/apache/james/jmap/draft/JmapGuiceProbe.java
+++ b/server/container/guice/protocols/jmap/src/main/java/org/apache/james/jmap/draft/JmapGuiceProbe.java
@@ -26,7 +26,6 @@ import javax.inject.Inject;
 import org.apache.james.core.Username;
 import org.apache.james.jmap.JMAPServer;
 import org.apache.james.jmap.api.change.EmailChangeRepository;
-import org.apache.james.jmap.api.change.MailboxChange;
 import org.apache.james.jmap.api.change.MailboxChangeRepository;
 import org.apache.james.jmap.api.change.State;
 import org.apache.james.jmap.api.model.AccountId;
@@ -95,15 +94,11 @@ public class JmapGuiceProbe implements GuiceProbe {
         Mono.from(messageFastViewProjection.clear()).block();
     }
 
-    public void saveMailboxChange(MailboxChange change) {
-        mailboxChangeRepository.save(change).block();
-    }
-
-    public State getLastestState(AccountId accountId) {
+    public State getLatestMailboxState(AccountId accountId) {
         return mailboxChangeRepository.getLatestState(accountId).block();
     }
 
-    public State getLastestStateWithDelegation(AccountId accountId) {
+    public State getLatestMailboxStateWithDelegation(AccountId accountId) {
         return mailboxChangeRepository.getLatestStateWithDelegation(accountId).block();
     }
 
diff --git a/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/MailboxChangesMethodContract.scala b/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/MailboxChangesMethodContract.scala
index 7ecf86f..1771910 100644
--- a/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/MailboxChangesMethodContract.scala
+++ b/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/MailboxChangesMethodContract.scala
@@ -1279,7 +1279,7 @@ trait MailboxChangesMethodContract {
   @Test
   def mailboxChangesShouldFailWhenAccountIdNotFound(server: GuiceJamesServer): Unit = {
     val jmapGuiceProbe:JmapGuiceProbe = server.getProbe(classOf[JmapGuiceProbe])
-    val oldState: State = jmapGuiceProbe.getLastestState(AccountId.fromUsername(BOB))
+    val oldState: State = jmapGuiceProbe.getLatestMailboxState(AccountId.fromUsername(BOB))
 
     val request =
       s"""{
@@ -1437,9 +1437,9 @@ trait MailboxChangesMethodContract {
       val response = `given`
         .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER)
         .body(request)
-        .when
+      .when
         .post
-        .`then`
+      .`then`
         .statusCode(SC_OK)
         .contentType(JSON)
         .extract
@@ -1886,17 +1886,17 @@ trait MailboxChangesMethodContract {
   private def waitForNextState(server: GuiceJamesServer, accountId: AccountId, initialState: State): State = {
     val jmapGuiceProbe: JmapGuiceProbe = server.getProbe(classOf[JmapGuiceProbe])
     awaitAtMostTenSeconds.untilAsserted {
-      () => assertThat(jmapGuiceProbe.getLastestState(accountId)).isNotEqualTo(initialState)
+      () => assertThat(jmapGuiceProbe.getLatestMailboxState(accountId)).isNotEqualTo(initialState)
     }
 
-    jmapGuiceProbe.getLastestState(accountId)
+    jmapGuiceProbe.getLatestMailboxState(accountId)
   }
 
   private def waitForNextStateWithDelegation(server: GuiceJamesServer, accountId: AccountId, initialState: State): State = {
     val jmapGuiceProbe: JmapGuiceProbe = server.getProbe(classOf[JmapGuiceProbe])
-    awaitAtMostTenSeconds.untilAsserted{ () => assertThat(jmapGuiceProbe.getLastestStateWithDelegation(accountId)).isNotEqualTo(initialState) }
+    awaitAtMostTenSeconds.untilAsserted{ () => assertThat(jmapGuiceProbe.getLatestMailboxStateWithDelegation(accountId)).isNotEqualTo(initialState) }
 
-    jmapGuiceProbe.getLastestStateWithDelegation(accountId)
+    jmapGuiceProbe.getLatestMailboxStateWithDelegation(accountId)
   }
 
   private def provisionSystemMailboxes(server: GuiceJamesServer): State = {
@@ -1959,6 +1959,6 @@ trait MailboxChangesMethodContract {
       assertThat(createdSize).isEqualTo(5)
     }
 
-    jmapGuiceProbe.getLastestState(AccountId.fromUsername(BOB))
+    jmapGuiceProbe.getLatestMailboxState(AccountId.fromUsername(BOB))
   }
 }


---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@james.apache.org
For additional commands, e-mail: notifications-help@james.apache.org


[james-project] 15/20: JAMES-2543 Junit 4 -> 5 migration for JWT helpers

Posted by rc...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

rcordier pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/james-project.git

commit d3927090c41521f096e2bcf7be93c83836de8d74
Author: Benoit Tellier <bt...@linagora.com>
AuthorDate: Thu Dec 31 09:06:22 2020 +0700

    JAMES-2543 Junit 4 -> 5 migration for JWT helpers
---
 .../java/org/apache/james/jwt/JwtConfigurationTest.java     | 12 ++++++------
 .../java/org/apache/james/jwt/JwtTokenVerifierTest.java     | 13 +++++--------
 .../java/org/apache/james/jwt/PublicKeyProviderTest.java    |  6 +++---
 .../test/java/org/apache/james/jwt/PublicKeyReaderTest.java |  6 +++---
 4 files changed, 17 insertions(+), 20 deletions(-)

diff --git a/server/protocols/jwt/src/test/java/org/apache/james/jwt/JwtConfigurationTest.java b/server/protocols/jwt/src/test/java/org/apache/james/jwt/JwtConfigurationTest.java
index 34436a9..7941c29 100644
--- a/server/protocols/jwt/src/test/java/org/apache/james/jwt/JwtConfigurationTest.java
+++ b/server/protocols/jwt/src/test/java/org/apache/james/jwt/JwtConfigurationTest.java
@@ -24,7 +24,7 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy;
 
 import java.util.Optional;
 
-import org.junit.Test;
+import org.junit.jupiter.api.Test;
 
 public class JwtConfigurationTest {
     private static final String INVALID_PUBLIC_KEY = "invalidPublicKey";
@@ -39,32 +39,32 @@ public class JwtConfigurationTest {
         "-----END PUBLIC KEY-----";
 
     @Test
-    public void getJwtPublicKeyPemShouldReturnEmptyWhenEmptyPublicKey() throws Exception {
+    public void getJwtPublicKeyPemShouldReturnEmptyWhenEmptyPublicKey() {
         JwtConfiguration jwtConfiguration = new JwtConfiguration(Optional.empty());
 
         assertThat(jwtConfiguration.getJwtPublicKeyPem()).isNotPresent();
     }
 
     @Test
-    public void constructorShouldThrowWhenNullPublicKey() throws Exception {
+    public void constructorShouldThrowWhenNullPublicKey() {
         assertThatThrownBy(() -> new JwtConfiguration(null))
             .isInstanceOf(NullPointerException.class);
     }
 
     @Test
-    public void constructorShouldThrowWhenNonePublicKey() throws Exception {
+    public void constructorShouldThrowWhenNonePublicKey() {
         assertThatThrownBy(() -> new JwtConfiguration(Optional.of("")))
             .isInstanceOf(IllegalStateException.class);
     }
 
     @Test
-    public void constructorShouldThrowWhenInvalidPublicKey() throws Exception {
+    public void constructorShouldThrowWhenInvalidPublicKey() {
         assertThatThrownBy(() -> new JwtConfiguration(Optional.of(INVALID_PUBLIC_KEY)))
             .isInstanceOf(IllegalStateException.class);
     }
 
     @Test
-    public void getJwtPublicKeyPemShouldReturnWhenValidPublicKey() throws Exception {
+    public void getJwtPublicKeyPemShouldReturnWhenValidPublicKey() {
         JwtConfiguration jwtConfiguration = new JwtConfiguration(Optional.of(VALID_PUBLIC_KEY));
 
         assertThat(jwtConfiguration.getJwtPublicKeyPem()).isPresent();
diff --git a/server/protocols/jwt/src/test/java/org/apache/james/jwt/JwtTokenVerifierTest.java b/server/protocols/jwt/src/test/java/org/apache/james/jwt/JwtTokenVerifierTest.java
index ae77048..c464a6b 100644
--- a/server/protocols/jwt/src/test/java/org/apache/james/jwt/JwtTokenVerifierTest.java
+++ b/server/protocols/jwt/src/test/java/org/apache/james/jwt/JwtTokenVerifierTest.java
@@ -26,9 +26,9 @@ import java.util.Optional;
 import org.bouncycastle.jce.provider.BouncyCastleProvider;
 import org.junit.Before;
 import org.junit.BeforeClass;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
 
 public class JwtTokenVerifierTest {
 
@@ -65,15 +65,12 @@ public class JwtTokenVerifierTest {
         "bmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.";
     private JwtTokenVerifier sut;
 
-    @Rule
-    public ExpectedException expectedException = ExpectedException.none();
-
-    @BeforeClass
+    @BeforeAll
     public static void init() {
         Security.addProvider(new BouncyCastleProvider());
     }
 
-    @Before
+    @BeforeEach
     public void setup() {
         PublicKeyProvider pubKeyProvider = new PublicKeyProvider(getJWTConfiguration(), new PublicKeyReader());
         sut = new JwtTokenVerifier(pubKeyProvider);
diff --git a/server/protocols/jwt/src/test/java/org/apache/james/jwt/PublicKeyProviderTest.java b/server/protocols/jwt/src/test/java/org/apache/james/jwt/PublicKeyProviderTest.java
index 92dcf77..ce07dce 100644
--- a/server/protocols/jwt/src/test/java/org/apache/james/jwt/PublicKeyProviderTest.java
+++ b/server/protocols/jwt/src/test/java/org/apache/james/jwt/PublicKeyProviderTest.java
@@ -26,8 +26,8 @@ import java.security.interfaces.RSAPublicKey;
 import java.util.Optional;
 
 import org.bouncycastle.jce.provider.BouncyCastleProvider;
-import org.junit.BeforeClass;
-import org.junit.Test;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
 
 public class PublicKeyProviderTest {
 
@@ -41,7 +41,7 @@ public class PublicKeyProviderTest {
             "kwIDAQAB\n" +
             "-----END PUBLIC KEY-----";
 
-    @BeforeClass
+    @BeforeAll
     public static void init() {
         Security.addProvider(new BouncyCastleProvider());
     }
diff --git a/server/protocols/jwt/src/test/java/org/apache/james/jwt/PublicKeyReaderTest.java b/server/protocols/jwt/src/test/java/org/apache/james/jwt/PublicKeyReaderTest.java
index 1b850d0..57a100e 100644
--- a/server/protocols/jwt/src/test/java/org/apache/james/jwt/PublicKeyReaderTest.java
+++ b/server/protocols/jwt/src/test/java/org/apache/james/jwt/PublicKeyReaderTest.java
@@ -25,8 +25,8 @@ import java.security.Security;
 import java.util.Optional;
 
 import org.bouncycastle.jce.provider.BouncyCastleProvider;
-import org.junit.BeforeClass;
-import org.junit.Test;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
 
 public class PublicKeyReaderTest {
 
@@ -40,7 +40,7 @@ public class PublicKeyReaderTest {
             "kwIDAQAB\n" +
             "-----END PUBLIC KEY-----";
 
-    @BeforeClass
+    @BeforeAll
     public static void init() {
         Security.addProvider(new BouncyCastleProvider());
     }


---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@james.apache.org
For additional commands, e-mail: notifications-help@james.apache.org


[james-project] 20/20: JAMES-2543 Junit 4 -> 5 public access modifier cleanups

Posted by rc...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

rcordier pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/james-project.git

commit 6d899ce0b911e832bfa9a4835cd9d201766810aa
Author: Rene Cordier <rc...@linagora.com>
AuthorDate: Thu Jan 7 11:46:17 2021 +0700

    JAMES-2543 Junit 4 -> 5 public access modifier cleanups
---
 .../james/transport/mailets/SpamAssassinTest.java  | 35 +++++++++++-----------
 .../org/apache/james/jwt/JwtConfigurationTest.java | 12 ++++----
 .../org/apache/james/jwt/JwtTokenVerifierTest.java | 32 ++++++++++----------
 .../apache/james/jwt/PublicKeyProviderTest.java    |  8 ++---
 .../org/apache/james/jwt/PublicKeyReaderTest.java  | 10 +++----
 .../james/imapserver/netty/IMAPServerTest.java     |  6 ++--
 .../apache/james/pop3server/POP3ServerTest.java    | 30 +++++++++----------
 .../james/smtpserver/SpamAssassinHandlerTest.java  | 10 +++----
 .../apache/james/smtpserver/URIRBLHandlerTest.java | 12 ++++----
 .../james/smtpserver/ValidRcptHandlerTest.java     | 24 +++++++--------
 .../spamassassin/mock/MockSpamdExtension.java      |  2 --
 11 files changed, 89 insertions(+), 92 deletions(-)

diff --git a/server/mailet/mailets/src/test/java/org/apache/james/transport/mailets/SpamAssassinTest.java b/server/mailet/mailets/src/test/java/org/apache/james/transport/mailets/SpamAssassinTest.java
index 4af5557..273bb3e 100644
--- a/server/mailet/mailets/src/test/java/org/apache/james/transport/mailets/SpamAssassinTest.java
+++ b/server/mailet/mailets/src/test/java/org/apache/james/transport/mailets/SpamAssassinTest.java
@@ -42,16 +42,17 @@ import org.junit.jupiter.api.extension.RegisterExtension;
 
 import com.github.steveash.guavate.Guavate;
 
-public class SpamAssassinTest {
+class SpamAssassinTest {
+
+    private static final DomainList NO_DOMAIN_LIST = null;
 
-    public static final DomainList NO_DOMAIN_LIST = null;
     @RegisterExtension
-    public MockSpamdExtension spamd = new MockSpamdExtension();
+    MockSpamdExtension spamd = new MockSpamdExtension();
 
     private SpamAssassin mailet = new SpamAssassin(new RecordingMetricFactory(), MemoryUsersRepository.withVirtualHosting(NO_DOMAIN_LIST));
 
     @Test
-    public void initShouldSetDefaultSpamdHostWhenNone() throws Exception {
+    void initShouldSetDefaultSpamdHostWhenNone() throws Exception {
         mailet.init(FakeMailetConfig.builder()
             .mailetName("SpamAssassin")
             .build());
@@ -60,7 +61,7 @@ public class SpamAssassinTest {
     }
 
     @Test
-    public void initShouldSetDefaultSpamdPortWhenNone() throws Exception {
+    void initShouldSetDefaultSpamdPortWhenNone() throws Exception {
         mailet.init(FakeMailetConfig.builder()
             .mailetName("SpamAssassin")
             .build());
@@ -69,7 +70,7 @@ public class SpamAssassinTest {
     }
 
     @Test
-    public void initShouldSetSpamdHostWhenPresent() throws Exception {
+    void initShouldSetSpamdHostWhenPresent() throws Exception {
         String spamdHost = "any.host";
         mailet.init(FakeMailetConfig.builder()
             .mailetName("SpamAssassin")
@@ -80,7 +81,7 @@ public class SpamAssassinTest {
     }
 
     @Test
-    public void getSpamHostShouldReturnDefaultValueWhenEmpty() throws Exception {
+    void getSpamHostShouldReturnDefaultValueWhenEmpty() throws Exception {
         mailet.init(FakeMailetConfig.builder()
             .mailetName("SpamAssassin")
             .setProperty(SpamAssassin.SPAMD_HOST, "")
@@ -90,7 +91,7 @@ public class SpamAssassinTest {
     }
 
     @Test
-    public void initShouldSetDefaultSpamdPortWhenDefault() throws Exception {
+    void initShouldSetDefaultSpamdPortWhenDefault() throws Exception {
         mailet.init(FakeMailetConfig.builder()
             .mailetName("SpamAssassin")
             .build());
@@ -99,7 +100,7 @@ public class SpamAssassinTest {
     }
 
     @Test
-    public void initShouldThrowWhenSpamdPortIsNotNumber() {
+    void initShouldThrowWhenSpamdPortIsNotNumber() {
         assertThatThrownBy(() -> mailet.init(FakeMailetConfig.builder()
             .mailetName("SpamAssassin")
             .setProperty(SpamAssassin.SPAMD_PORT, "noNumber")
@@ -107,7 +108,7 @@ public class SpamAssassinTest {
     }
 
     @Test
-    public void initShouldThrowWhenSpamdPortIsNegative() {
+    void initShouldThrowWhenSpamdPortIsNegative() {
         assertThatThrownBy(() -> mailet.init(FakeMailetConfig.builder()
             .mailetName("SpamAssassin")
             .setProperty(SpamAssassin.SPAMD_PORT, "-1")
@@ -115,7 +116,7 @@ public class SpamAssassinTest {
     }
 
     @Test
-    public void initShouldThrowWhenSpamdPortIsZero() {
+    void initShouldThrowWhenSpamdPortIsZero() {
         assertThatThrownBy(() -> mailet.init(FakeMailetConfig.builder()
             .mailetName("SpamAssassin")
             .setProperty(SpamAssassin.SPAMD_PORT, "0")
@@ -123,7 +124,7 @@ public class SpamAssassinTest {
     }
 
     @Test
-    public void initShouldThrowWhenSpamdPortTooBig() {
+    void initShouldThrowWhenSpamdPortTooBig() {
         assertThatThrownBy(() -> mailet.init(FakeMailetConfig.builder()
             .mailetName("SpamAssassin")
             .setProperty(SpamAssassin.SPAMD_PORT,
@@ -132,7 +133,7 @@ public class SpamAssassinTest {
     }
 
     @Test
-    public void initShouldSetSpamPortWhenPresent() throws Exception {
+    void initShouldSetSpamPortWhenPresent() throws Exception {
         int spamPort = 1000;
         mailet.init(FakeMailetConfig.builder()
             .mailetName("SpamAssassin")
@@ -143,7 +144,7 @@ public class SpamAssassinTest {
     }
 
     @Test
-    public void serviceShouldWriteSpamAttributeOnMail() throws Exception {
+    void serviceShouldWriteSpamAttributeOnMail() throws Exception {
         FakeMailetConfig mailetConfiguration = FakeMailetConfig.builder()
             .mailetName("SpamAssassin")
             .setProperty(SpamAssassin.SPAMD_HOST, "localhost")
@@ -177,7 +178,7 @@ public class SpamAssassinTest {
     }
 
     @Test
-    public void serviceShouldWriteMessageAsNotSpamWhenNotSpam() throws Exception {
+    void serviceShouldWriteMessageAsNotSpamWhenNotSpam() throws Exception {
         FakeMailetConfig mailetConfiguration = FakeMailetConfig.builder()
             .mailetName("SpamAssassin")
             .setProperty(SpamAssassin.SPAMD_HOST, "localhost")
@@ -213,7 +214,7 @@ public class SpamAssassinTest {
     }
 
     @Test
-    public void serviceShouldWriteMessageAsSpamWhenSpam() throws Exception {
+    void serviceShouldWriteMessageAsSpamWhenSpam() throws Exception {
         FakeMailetConfig mailetConfiguration = FakeMailetConfig.builder()
             .mailetName("SpamAssassin")
             .setProperty(SpamAssassin.SPAMD_HOST, "localhost")
@@ -249,7 +250,7 @@ public class SpamAssassinTest {
     }
 
     @Test
-    public void getMailetInfoShouldReturnSpamAssasinMailetInformation() {
+    void getMailetInfoShouldReturnSpamAssasinMailetInformation() {
         assertThat(mailet.getMailetInfo()).isEqualTo("Checks message against SpamAssassin");
     }
 
diff --git a/server/protocols/jwt/src/test/java/org/apache/james/jwt/JwtConfigurationTest.java b/server/protocols/jwt/src/test/java/org/apache/james/jwt/JwtConfigurationTest.java
index 7941c29..ee8a557 100644
--- a/server/protocols/jwt/src/test/java/org/apache/james/jwt/JwtConfigurationTest.java
+++ b/server/protocols/jwt/src/test/java/org/apache/james/jwt/JwtConfigurationTest.java
@@ -26,7 +26,7 @@ import java.util.Optional;
 
 import org.junit.jupiter.api.Test;
 
-public class JwtConfigurationTest {
+class JwtConfigurationTest {
     private static final String INVALID_PUBLIC_KEY = "invalidPublicKey";
     private static final String VALID_PUBLIC_KEY = "-----BEGIN PUBLIC KEY-----\n" +
         "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtlChO/nlVP27MpdkG0Bh\n" +
@@ -39,32 +39,32 @@ public class JwtConfigurationTest {
         "-----END PUBLIC KEY-----";
 
     @Test
-    public void getJwtPublicKeyPemShouldReturnEmptyWhenEmptyPublicKey() {
+    void getJwtPublicKeyPemShouldReturnEmptyWhenEmptyPublicKey() {
         JwtConfiguration jwtConfiguration = new JwtConfiguration(Optional.empty());
 
         assertThat(jwtConfiguration.getJwtPublicKeyPem()).isNotPresent();
     }
 
     @Test
-    public void constructorShouldThrowWhenNullPublicKey() {
+    void constructorShouldThrowWhenNullPublicKey() {
         assertThatThrownBy(() -> new JwtConfiguration(null))
             .isInstanceOf(NullPointerException.class);
     }
 
     @Test
-    public void constructorShouldThrowWhenNonePublicKey() {
+    void constructorShouldThrowWhenNonePublicKey() {
         assertThatThrownBy(() -> new JwtConfiguration(Optional.of("")))
             .isInstanceOf(IllegalStateException.class);
     }
 
     @Test
-    public void constructorShouldThrowWhenInvalidPublicKey() {
+    void constructorShouldThrowWhenInvalidPublicKey() {
         assertThatThrownBy(() -> new JwtConfiguration(Optional.of(INVALID_PUBLIC_KEY)))
             .isInstanceOf(IllegalStateException.class);
     }
 
     @Test
-    public void getJwtPublicKeyPemShouldReturnWhenValidPublicKey() {
+    void getJwtPublicKeyPemShouldReturnWhenValidPublicKey() {
         JwtConfiguration jwtConfiguration = new JwtConfiguration(Optional.of(VALID_PUBLIC_KEY));
 
         assertThat(jwtConfiguration.getJwtPublicKeyPem()).isPresent();
diff --git a/server/protocols/jwt/src/test/java/org/apache/james/jwt/JwtTokenVerifierTest.java b/server/protocols/jwt/src/test/java/org/apache/james/jwt/JwtTokenVerifierTest.java
index c464a6b..75b638a 100644
--- a/server/protocols/jwt/src/test/java/org/apache/james/jwt/JwtTokenVerifierTest.java
+++ b/server/protocols/jwt/src/test/java/org/apache/james/jwt/JwtTokenVerifierTest.java
@@ -24,13 +24,11 @@ import java.security.Security;
 import java.util.Optional;
 
 import org.bouncycastle.jce.provider.BouncyCastleProvider;
-import org.junit.Before;
-import org.junit.BeforeClass;
 import org.junit.jupiter.api.BeforeAll;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 
-public class JwtTokenVerifierTest {
+class JwtTokenVerifierTest {
 
     private static final String PUBLIC_PEM_KEY = "-----BEGIN PUBLIC KEY-----\n" +
             "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtlChO/nlVP27MpdkG0Bh\n" +
@@ -66,12 +64,12 @@ public class JwtTokenVerifierTest {
     private JwtTokenVerifier sut;
 
     @BeforeAll
-    public static void init() {
+    static void init() {
         Security.addProvider(new BouncyCastleProvider());
     }
 
     @BeforeEach
-    public void setup() {
+    void setup() {
         PublicKeyProvider pubKeyProvider = new PublicKeyProvider(getJWTConfiguration(), new PublicKeyReader());
         sut = new JwtTokenVerifier(pubKeyProvider);
     }
@@ -81,12 +79,12 @@ public class JwtTokenVerifierTest {
     }
 
     @Test
-    public void shouldReturnTrueOnValidSignature() {
+    void shouldReturnTrueOnValidSignature() {
         assertThat(sut.verify(VALID_TOKEN_WITHOUT_ADMIN)).isTrue();
     }
 
     @Test
-    public void shouldReturnFalseOnMismatchingSigningKey() {
+    void shouldReturnFalseOnMismatchingSigningKey() {
         String invalidToken = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIn0.Pd6t82" +
                 "tPL3EZdkeYxw_DV2KimE1U2FvuLHmfR_mimJ5US3JFU4J2Gd94O7rwpSTGN1B9h-_lsTebo4ua4xHsTtmczZ9xa8a_kWKaSkqFjNFa" +
                 "Fp6zcoD6ivCu03SlRqsQzSRHXo6TKbnqOt9D6Y2rNa3C4igSwoS0jUE4BgpXbc0";
@@ -95,7 +93,7 @@ public class JwtTokenVerifierTest {
     }
 
     @Test
-    public void verifyShouldReturnFalseWhenSubjectIsNull() {
+    void verifyShouldReturnFalseWhenSubjectIsNull() {
         String tokenWithNullSubject = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOm51bGwsIm5hbWUiOiJKb2huIERvZSJ9.EB" +
                 "_1grWDy_kFelXs3AQeiP13ay4eG_134dWB9XPRSeWsuPs8Mz2UY-VHDxLGD-fAqv-xKXr4QFEnS7iZkdpe0tPLNSwIjqeqkC6KqQln" +
                 "oC1okqWVWBDOcf7Acp1Jzp_cFTUhL5LkHvZDsyCdq5T9OOVVkzO4A9RrzIUsTrYPtRCBuYJ3ggR33cKpw191PulPGNH70rZqpUfDXe" +
@@ -106,7 +104,7 @@ public class JwtTokenVerifierTest {
     }
     
     @Test
-    public void verifyShouldReturnFalseWhenEmptySubject() {
+    void verifyShouldReturnFalseWhenEmptySubject() {
         String tokenWithEmptySubject = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIiLCJuYW1lIjoiSm9obiBEb2UifQ.UdY" +
                 "s2PPzFCegUYspoDCnlJR_bJm8_z1InOv4v3tq8SJETQUarOXlhb_n6y6ujVvmJiSx9dI24Hc3Czi3RGUOXbnBDj1WPfd0aVSiUSqZr" +
                 "MCHBt5vjCYqAseDaP3w4aiiFb6EV3tteJFeBLZx8XlKPYxlzRLLUADDyDSQvrFBBPxfsvCETZovKdo9ofIN64o-yx23ss63yE6oIOd" +
@@ -118,48 +116,48 @@ public class JwtTokenVerifierTest {
     }
 
     @Test
-    public void verifyShouldNotAcceptNoneAlgorithm() {
+    void verifyShouldNotAcceptNoneAlgorithm() {
         assertThat(sut.verify(TOKEN_NONE_ALGORITHM)).isFalse();
     }
 
     @Test
-    public void verifyShouldNotAcceptNoneAlgorithmWithoutSignature() {
+    void verifyShouldNotAcceptNoneAlgorithmWithoutSignature() {
         assertThat(sut.verify(TOKEN_NONE_ALGORITHM_NO_SIGNATURE)).isFalse();
     }
 
     @Test
-    public void shouldReturnUserLoginFromValidToken() {
+    void shouldReturnUserLoginFromValidToken() {
         assertThat(sut.extractLogin(VALID_TOKEN_WITHOUT_ADMIN)).isEqualTo("1234567890");
     }
 
     @Test
-    public void hasAttributeShouldReturnFalseOnNoneAlgorithm() throws Exception {
+    void hasAttributeShouldReturnFalseOnNoneAlgorithm() throws Exception {
         boolean authorized = sut.hasAttribute("admin", true, TOKEN_NONE_ALGORITHM);
 
         assertThat(authorized).isFalse();
     }
 
     @Test
-    public void hasAttributeShouldReturnFalseOnNoneAlgorithmWithoutSignature() throws Exception {
+    void hasAttributeShouldReturnFalseOnNoneAlgorithmWithoutSignature() throws Exception {
         boolean authorized = sut.hasAttribute("admin", true, TOKEN_NONE_ALGORITHM_NO_SIGNATURE);
 
         assertThat(authorized).isFalse();
     }
 
     @Test
-    public void hasAttributeShouldReturnTrueIfClaimValid() throws Exception {
+    void hasAttributeShouldReturnTrueIfClaimValid() throws Exception {
         boolean authorized = sut.hasAttribute("admin", true, VALID_TOKEN_ADMIN_TRUE);
 
         assertThat(authorized).isTrue();
     }
 
     @Test
-    public void extractLoginShouldWorkWithAdminClaim() {
+    void extractLoginShouldWorkWithAdminClaim() {
         assertThat(sut.extractLogin(VALID_TOKEN_ADMIN_TRUE)).isEqualTo("admin@open-paas.org");
     }
 
     @Test
-    public void hasAttributeShouldThrowIfClaimInvalid() throws Exception {
+    void hasAttributeShouldThrowIfClaimInvalid() throws Exception {
         boolean authorized = sut.hasAttribute("admin", true, VALID_TOKEN_ADMIN_FALSE);
 
         assertThat(authorized).isFalse();
diff --git a/server/protocols/jwt/src/test/java/org/apache/james/jwt/PublicKeyProviderTest.java b/server/protocols/jwt/src/test/java/org/apache/james/jwt/PublicKeyProviderTest.java
index ce07dce..a4771b9 100644
--- a/server/protocols/jwt/src/test/java/org/apache/james/jwt/PublicKeyProviderTest.java
+++ b/server/protocols/jwt/src/test/java/org/apache/james/jwt/PublicKeyProviderTest.java
@@ -29,7 +29,7 @@ import org.bouncycastle.jce.provider.BouncyCastleProvider;
 import org.junit.jupiter.api.BeforeAll;
 import org.junit.jupiter.api.Test;
 
-public class PublicKeyProviderTest {
+class PublicKeyProviderTest {
 
     private static final String PUBLIC_PEM_KEY = "-----BEGIN PUBLIC KEY-----\n" +
             "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtlChO/nlVP27MpdkG0Bh\n" +
@@ -42,12 +42,12 @@ public class PublicKeyProviderTest {
             "-----END PUBLIC KEY-----";
 
     @BeforeAll
-    public static void init() {
+    static void init() {
         Security.addProvider(new BouncyCastleProvider());
     }
 
     @Test
-    public void getShouldNotThrowWhenPEMKeyProvided() {
+    void getShouldNotThrowWhenPEMKeyProvided() {
 
         JwtConfiguration configWithPEMKey = new JwtConfiguration(Optional.of(PUBLIC_PEM_KEY));
 
@@ -57,7 +57,7 @@ public class PublicKeyProviderTest {
     }
 
     @Test
-    public void getShouldThrowWhenPEMKeyNotProvided() {
+    void getShouldThrowWhenPEMKeyNotProvided() {
         JwtConfiguration configWithPEMKey = new JwtConfiguration(Optional.empty());
 
         PublicKeyProvider sut = new PublicKeyProvider(configWithPEMKey, new PublicKeyReader());
diff --git a/server/protocols/jwt/src/test/java/org/apache/james/jwt/PublicKeyReaderTest.java b/server/protocols/jwt/src/test/java/org/apache/james/jwt/PublicKeyReaderTest.java
index 57a100e..655a1ab 100644
--- a/server/protocols/jwt/src/test/java/org/apache/james/jwt/PublicKeyReaderTest.java
+++ b/server/protocols/jwt/src/test/java/org/apache/james/jwt/PublicKeyReaderTest.java
@@ -28,7 +28,7 @@ import org.bouncycastle.jce.provider.BouncyCastleProvider;
 import org.junit.jupiter.api.BeforeAll;
 import org.junit.jupiter.api.Test;
 
-public class PublicKeyReaderTest {
+class PublicKeyReaderTest {
 
     private static final String PUBLIC_PEM_KEY = "-----BEGIN PUBLIC KEY-----\n" +
             "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtlChO/nlVP27MpdkG0Bh\n" +
@@ -41,22 +41,22 @@ public class PublicKeyReaderTest {
             "-----END PUBLIC KEY-----";
 
     @BeforeAll
-    public static void init() {
+    static void init() {
         Security.addProvider(new BouncyCastleProvider());
     }
 
     @Test
-    public void fromPEMShouldReturnEmptyWhenEmptyProvided() {
+    void fromPEMShouldReturnEmptyWhenEmptyProvided() {
         assertThat(new PublicKeyReader().fromPEM(Optional.empty())).isEmpty();
     }
 
     @Test
-    public void fromPEMShouldReturnEmptyWhenInvalidPEMKey() {
+    void fromPEMShouldReturnEmptyWhenInvalidPEMKey() {
         assertThat(new PublicKeyReader().fromPEM(Optional.of("blabla"))).isEmpty();
     }
 
     @Test
-    public void fromPEMShouldReturnRSAPublicKeyWhenValidPEMKey() {
+    void fromPEMShouldReturnRSAPublicKeyWhenValidPEMKey() {
         assertThat(new PublicKeyReader().fromPEM(Optional.of(PUBLIC_PEM_KEY))).isPresent();
     }
 }
diff --git a/server/protocols/protocols-imap4/src/test/java/org/apache/james/imapserver/netty/IMAPServerTest.java b/server/protocols/protocols-imap4/src/test/java/org/apache/james/imapserver/netty/IMAPServerTest.java
index 888f9fa..c4aa8c1 100644
--- a/server/protocols/protocols-imap4/src/test/java/org/apache/james/imapserver/netty/IMAPServerTest.java
+++ b/server/protocols/protocols-imap4/src/test/java/org/apache/james/imapserver/netty/IMAPServerTest.java
@@ -31,9 +31,9 @@ import org.junit.jupiter.api.Test;
 
 import com.google.common.collect.ImmutableSet;
 
-public class IMAPServerTest {
+class IMAPServerTest {
     @Test
-    public void getImapConfigurationShouldReturnDefaultValuesWhenEmpty() {
+    void getImapConfigurationShouldReturnDefaultValuesWhenEmpty() {
         ImapConfiguration imapConfiguration = IMAPServer.getImapConfiguration(new BaseHierarchicalConfiguration());
 
         ImapConfiguration expectImapConfiguration = ImapConfiguration.builder()
@@ -47,7 +47,7 @@ public class IMAPServerTest {
     }
 
     @Test
-    public void getImapConfigurationShouldReturnSetValue() {
+    void getImapConfigurationShouldReturnSetValue() {
         HierarchicalConfiguration<ImmutableNode> configurationBuilder = new BaseHierarchicalConfiguration();
         configurationBuilder.addProperty("enableIdle", "false");
         configurationBuilder.addProperty("idleTimeInterval", "1");
diff --git a/server/protocols/protocols-pop3/src/test/java/org/apache/james/pop3server/POP3ServerTest.java b/server/protocols/protocols-pop3/src/test/java/org/apache/james/pop3server/POP3ServerTest.java
index 980f290..10120fa 100644
--- a/server/protocols/protocols-pop3/src/test/java/org/apache/james/pop3server/POP3ServerTest.java
+++ b/server/protocols/protocols-pop3/src/test/java/org/apache/james/pop3server/POP3ServerTest.java
@@ -57,7 +57,7 @@ import org.junit.jupiter.api.Test;
 
 import com.google.inject.name.Names;
 
-public class POP3ServerTest {
+class POP3ServerTest {
     private static final DomainList NO_DOMAIN_LIST = null;
 
     private POP3TestConfiguration pop3Configuration;
@@ -74,7 +74,7 @@ public class POP3ServerTest {
     private HashedWheelTimer hashedWheelTimer;
 
     @BeforeEach
-    public void setUp() throws Exception {
+    void setUp() throws Exception {
         hashedWheelTimer = new HashedWheelTimer();
         setUpServiceManager();
         setUpPOP3Server();
@@ -82,7 +82,7 @@ public class POP3ServerTest {
     }
 
     @AfterEach
-    public void tearDown() throws Exception {
+    void tearDown() throws Exception {
         try {
             if (pop3Client != null) {
                 if (pop3Client.isConnected()) {
@@ -99,7 +99,7 @@ public class POP3ServerTest {
     }
 
     @Test
-    public void testAuthenticationFail() throws Exception {
+    void testAuthenticationFail() throws Exception {
         finishSetUp(pop3Configuration);
 
         pop3Client = new POP3Client();
@@ -114,7 +114,7 @@ public class POP3ServerTest {
     }
 
     @Test
-    public void testUnknownUser() throws Exception {
+    void testUnknownUser() throws Exception {
         finishSetUp(pop3Configuration);
 
         pop3Client = new POP3Client();
@@ -127,7 +127,7 @@ public class POP3ServerTest {
     }
 
     @Test
-    public void testKnownUserEmptyInbox() throws Exception {
+    void testKnownUserEmptyInbox() throws Exception {
         finishSetUp(pop3Configuration);
 
         pop3Client = new POP3Client();
@@ -176,7 +176,7 @@ public class POP3ServerTest {
      */
 
     @Test
-    public void testUnknownCommand() throws Exception {
+    void testUnknownCommand() throws Exception {
         finishSetUp(pop3Configuration);
 
         pop3Client = new POP3Client();
@@ -189,7 +189,7 @@ public class POP3ServerTest {
     }
 
     @Test
-    public void testUidlCommand() throws Exception {
+    void testUidlCommand() throws Exception {
         finishSetUp(pop3Configuration);
 
         Username username = Username.of("foo");
@@ -229,7 +229,7 @@ public class POP3ServerTest {
     }
 
     @Test
-    public void testMiscCommandsWithWithoutAuth() throws Exception {
+    void testMiscCommandsWithWithoutAuth() throws Exception {
         finishSetUp(pop3Configuration);
 
         usersRepository.addUser(Username.of("foo"), "bar");
@@ -284,7 +284,7 @@ public class POP3ServerTest {
     }
 
     @Test
-    public void testKnownUserInboxWithMessages() throws Exception {
+    void testKnownUserInboxWithMessages() throws Exception {
         finishSetUp(pop3Configuration);
 
         pop3Client = new POP3Client();
@@ -374,7 +374,7 @@ public class POP3ServerTest {
      * Test for JAMES-1202 -  Which shows that UIDL,STAT and LIST all show the same message numbers.
      */
     @Test
-    public void testStatUidlList() throws Exception {
+    void testStatUidlList() throws Exception {
         finishSetUp(pop3Configuration);
 
         pop3Client = new POP3Client();
@@ -424,7 +424,7 @@ public class POP3ServerTest {
 
     @Test
     @Disabled("Test for JAMES-1202 - This was failing before as the more then one connection to the same mailbox was not handled the right way")
-    public void testStatUidlListTwoConnections() throws Exception {
+    void testStatUidlListTwoConnections() throws Exception {
         finishSetUp(pop3Configuration);
 
         pop3Client = new POP3Client();
@@ -548,7 +548,7 @@ public class POP3ServerTest {
      */
     
     @Test
-    public void testIpStored() throws Exception {
+    void testIpStored() throws Exception {
 
         finishSetUp(pop3Configuration);
 
@@ -566,7 +566,7 @@ public class POP3ServerTest {
     }
 
     @Test
-    public void testCapa() throws Exception {
+    void testCapa() throws Exception {
         finishSetUp(pop3Configuration);
 
         pop3Client = new POP3Client();
@@ -635,7 +635,7 @@ public class POP3ServerTest {
      */
     // See JAMES-1136
     @Test
-    public void testDeadlockOnRetr() throws Exception {
+    void testDeadlockOnRetr() throws Exception {
         finishSetUp(pop3Configuration);
 
         pop3Client = new POP3Client();
diff --git a/server/protocols/protocols-smtp/src/test/java/org/apache/james/smtpserver/SpamAssassinHandlerTest.java b/server/protocols/protocols-smtp/src/test/java/org/apache/james/smtpserver/SpamAssassinHandlerTest.java
index c727035..5211426 100644
--- a/server/protocols/protocols-smtp/src/test/java/org/apache/james/smtpserver/SpamAssassinHandlerTest.java
+++ b/server/protocols/protocols-smtp/src/test/java/org/apache/james/smtpserver/SpamAssassinHandlerTest.java
@@ -49,7 +49,7 @@ import org.junit.jupiter.api.extension.RegisterExtension;
 
 import com.google.common.base.Preconditions;
 
-public class SpamAssassinHandlerTest {
+class SpamAssassinHandlerTest {
 
     private static final String SPAMD_HOST = "localhost";
     private static final Attribute FLAG_MAIL_ATTRIBUTE_NO = new Attribute(SpamAssassinResult.FLAG_MAIL, AttributeValue.of("NO"));
@@ -126,14 +126,14 @@ public class SpamAssassinHandlerTest {
             .build();
     }
 
-    public MimeMessage setupMockedMimeMessage(String text) throws MessagingException {
+    private MimeMessage setupMockedMimeMessage(String text) throws MessagingException {
         return MimeMessageBuilder.mimeMessageBuilder()
             .setText(text)
             .build();
     }
 
     @Test
-    public void testNonSpam() throws Exception {
+    void testNonSpam() throws Exception {
         SMTPSession session = setupMockedSMTPSession(setupMockedMail(setupMockedMimeMessage("test")));
 
         SpamAssassinHandler handler = new SpamAssassinHandler(new RecordingMetricFactory());
@@ -150,7 +150,7 @@ public class SpamAssassinHandlerTest {
     }
 
     @Test
-    public void testSpam() throws Exception {
+    void testSpam() throws Exception {
         SMTPSession session = setupMockedSMTPSession(setupMockedMail(setupMockedMimeMessage(MockSpamd.GTUBE)));
 
         SpamAssassinHandler handler = new SpamAssassinHandler(new RecordingMetricFactory());
@@ -166,7 +166,7 @@ public class SpamAssassinHandlerTest {
     }
 
     @Test
-    public void testSpamReject() throws Exception {
+    void testSpamReject() throws Exception {
         SMTPSession session = setupMockedSMTPSession(setupMockedMail(setupMockedMimeMessage(MockSpamd.GTUBE)));
 
         SpamAssassinHandler handler = new SpamAssassinHandler(new RecordingMetricFactory());
diff --git a/server/protocols/protocols-smtp/src/test/java/org/apache/james/smtpserver/URIRBLHandlerTest.java b/server/protocols/protocols-smtp/src/test/java/org/apache/james/smtpserver/URIRBLHandlerTest.java
index acda4bb..b207f6d 100644
--- a/server/protocols/protocols-smtp/src/test/java/org/apache/james/smtpserver/URIRBLHandlerTest.java
+++ b/server/protocols/protocols-smtp/src/test/java/org/apache/james/smtpserver/URIRBLHandlerTest.java
@@ -49,7 +49,7 @@ import org.junit.jupiter.api.Test;
 
 import com.google.common.base.Preconditions;
 
-public class URIRBLHandlerTest {
+class URIRBLHandlerTest {
 
     private static final String BAD_DOMAIN1 = "bad.domain.de";
     private static final String BAD_DOMAIN2 = "bad2.domain.de";
@@ -125,13 +125,13 @@ public class URIRBLHandlerTest {
             .build();
     }
 
-    public MimeMessage setupMockedMimeMessage(String text) throws MessagingException {
+    private MimeMessage setupMockedMimeMessage(String text) throws MessagingException {
         return MimeMessageBuilder.mimeMessageBuilder()
             .setText(text)
             .build();
     }
 
-    public MimeMessage setupMockedMimeMessageMP(String text) throws MessagingException {
+    private MimeMessage setupMockedMimeMessageMP(String text) throws MessagingException {
         return MimeMessageBuilder.mimeMessageBuilder()
             .setMultipartWithBodyParts(
                 MimeMessageBuilder.bodyPartBuilder()
@@ -175,7 +175,7 @@ public class URIRBLHandlerTest {
     }
 
     @Test
-    public void testNotBlocked() throws IOException, MessagingException {
+    void testNotBlocked() throws IOException, MessagingException {
 
         ArrayList<String> servers = new ArrayList<>();
         servers.add(URISERVER);
@@ -193,7 +193,7 @@ public class URIRBLHandlerTest {
     }
 
     @Test
-    public void testBlocked() throws IOException, MessagingException {
+    void testBlocked() throws IOException, MessagingException {
 
         ArrayList<String> servers = new ArrayList<>();
         servers.add(URISERVER);
@@ -211,7 +211,7 @@ public class URIRBLHandlerTest {
     }
 
     @Test
-    public void testBlockedMultiPart() throws IOException, MessagingException {
+    void testBlockedMultiPart() throws IOException, MessagingException {
 
         ArrayList<String> servers = new ArrayList<>();
         servers.add(URISERVER);
diff --git a/server/protocols/protocols-smtp/src/test/java/org/apache/james/smtpserver/ValidRcptHandlerTest.java b/server/protocols/protocols-smtp/src/test/java/org/apache/james/smtpserver/ValidRcptHandlerTest.java
index 8bbb2a0..21608fb 100644
--- a/server/protocols/protocols-smtp/src/test/java/org/apache/james/smtpserver/ValidRcptHandlerTest.java
+++ b/server/protocols/protocols-smtp/src/test/java/org/apache/james/smtpserver/ValidRcptHandlerTest.java
@@ -46,7 +46,7 @@ import org.junit.jupiter.api.BeforeEach;
 
 import com.google.common.base.Preconditions;
 
-public class ValidRcptHandlerTest {
+class ValidRcptHandlerTest {
     private static final Username VALID_USER = Username.of("postmaster");
     private static final String INVALID_USER = "invalid";
     private static final String USER1 = "user1";
@@ -54,7 +54,7 @@ public class ValidRcptHandlerTest {
     private static final String PASSWORD = "xxx";
     private static final boolean RELAYING_ALLOWED = true;
     private static final MaybeSender MAYBE_SENDER = MaybeSender.of(SENDER);
-    public static final Domain DOMAIN_1 = Domain.of("domain.tld");
+    private static final Domain DOMAIN_1 = Domain.of("domain.tld");
 
     private ValidRcptHandler handler;
     private MemoryRecipientRewriteTable memoryRecipientRewriteTable;
@@ -63,7 +63,7 @@ public class ValidRcptHandlerTest {
     private MailAddress invalidUserEmail;
 
     @BeforeEach
-    public void setUp() throws Exception {
+    void setUp() throws Exception {
         MemoryDomainList memoryDomainList = new MemoryDomainList(mock(DNSService.class));
         memoryDomainList.configure(DomainListConfiguration.builder()
             .defaultDomain(Domain.LOCALHOST)
@@ -128,7 +128,7 @@ public class ValidRcptHandlerTest {
     }
 
     @Test
-    public void doRcptShouldRejectNotExistingLocalUsersWhenNoRelay() {
+    void doRcptShouldRejectNotExistingLocalUsersWhenNoRelay() {
         SMTPSession session = setupMockedSMTPSession(!RELAYING_ALLOWED);
 
         HookReturnCode rCode = handler.doRcpt(session, MAYBE_SENDER, invalidUserEmail).getResult();
@@ -137,7 +137,7 @@ public class ValidRcptHandlerTest {
     }
 
     @Test
-    public void doRcptShouldDenyNotExistingLocalUsersWhenRelay() {
+    void doRcptShouldDenyNotExistingLocalUsersWhenRelay() {
         SMTPSession session = setupMockedSMTPSession(RELAYING_ALLOWED);
 
         HookReturnCode rCode = handler.doRcpt(session, MAYBE_SENDER, invalidUserEmail).getResult();
@@ -146,7 +146,7 @@ public class ValidRcptHandlerTest {
     }
 
     @Test
-    public void doRcptShouldDeclineNonLocalUsersWhenRelay() throws Exception {
+    void doRcptShouldDeclineNonLocalUsersWhenRelay() throws Exception {
         MailAddress mailAddress = new MailAddress(INVALID_USER + "@otherdomain");
         SMTPSession session = setupMockedSMTPSession(RELAYING_ALLOWED);
 
@@ -156,7 +156,7 @@ public class ValidRcptHandlerTest {
     }
 
     @Test
-    public void doRcptShouldDeclineNonLocalUsersWhenNoRelay() throws Exception {
+    void doRcptShouldDeclineNonLocalUsersWhenNoRelay() throws Exception {
         MailAddress mailAddress = new MailAddress(INVALID_USER + "@otherdomain");
         SMTPSession session = setupMockedSMTPSession(!RELAYING_ALLOWED);
 
@@ -166,7 +166,7 @@ public class ValidRcptHandlerTest {
     }
 
     @Test
-    public void doRcptShouldDeclineValidUsersWhenNoRelay() throws Exception {
+    void doRcptShouldDeclineValidUsersWhenNoRelay() throws Exception {
         SMTPSession session = setupMockedSMTPSession(!RELAYING_ALLOWED);
 
         HookReturnCode rCode = handler.doRcpt(session, MAYBE_SENDER, validUserEmail).getResult();
@@ -175,7 +175,7 @@ public class ValidRcptHandlerTest {
     }
 
     @Test
-    public void doRcptShouldDeclineValidUsersWhenRelay() throws Exception {
+    void doRcptShouldDeclineValidUsersWhenRelay() throws Exception {
         SMTPSession session = setupMockedSMTPSession(RELAYING_ALLOWED);
 
         HookReturnCode rCode = handler.doRcpt(session, MAYBE_SENDER, validUserEmail).getResult();
@@ -184,7 +184,7 @@ public class ValidRcptHandlerTest {
     }
 
     @Test
-    public void doRcptShouldDeclineWhenHasAddressMapping() throws Exception {
+    void doRcptShouldDeclineWhenHasAddressMapping() throws Exception {
         memoryRecipientRewriteTable.addAddressMapping(MappingSource.fromUser(USER1, Domain.LOCALHOST), "address");
 
         SMTPSession session = setupMockedSMTPSession(!RELAYING_ALLOWED);
@@ -195,7 +195,7 @@ public class ValidRcptHandlerTest {
     }
 
     @Test
-    public void doRcptShouldDenyWhenHasMappingLoop() throws Exception {
+    void doRcptShouldDenyWhenHasMappingLoop() throws Exception {
         memoryRecipientRewriteTable.addAddressMapping(MappingSource.fromUser(USER1, Domain.LOCALHOST), USER2 + "@domain.tld");
         memoryRecipientRewriteTable.addAddressMapping(MappingSource.fromUser(USER2, DOMAIN_1), USER1 + "@domain.tld");
         // The loop needs to be created by a domain mapping
@@ -209,7 +209,7 @@ public class ValidRcptHandlerTest {
     }
 
     @Test
-    public void doRcptShouldDeclineWhenHasErrorMapping() throws Exception {
+    void doRcptShouldDeclineWhenHasErrorMapping() throws Exception {
         memoryRecipientRewriteTable.addErrorMapping(MappingSource.fromUser(USER1, Domain.LOCALHOST), "554 BOUNCE");
 
         SMTPSession session = setupMockedSMTPSession(!RELAYING_ALLOWED);
diff --git a/third-party/spamassassin/src/test/java/org/apache/james/spamassassin/mock/MockSpamdExtension.java b/third-party/spamassassin/src/test/java/org/apache/james/spamassassin/mock/MockSpamdExtension.java
index 1440a79..c97bb51 100644
--- a/third-party/spamassassin/src/test/java/org/apache/james/spamassassin/mock/MockSpamdExtension.java
+++ b/third-party/spamassassin/src/test/java/org/apache/james/spamassassin/mock/MockSpamdExtension.java
@@ -24,10 +24,8 @@ import java.util.concurrent.Executors;
 
 import org.apache.james.util.concurrent.NamedThreadFactory;
 import org.junit.jupiter.api.extension.AfterEachCallback;
-import org.junit.jupiter.api.extension.BeforeAllCallback;
 import org.junit.jupiter.api.extension.BeforeEachCallback;
 import org.junit.jupiter.api.extension.ExtensionContext;
-import org.junit.rules.ExternalResource;
 
 public class MockSpamdExtension implements AfterEachCallback, BeforeEachCallback {
 


---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@james.apache.org
For additional commands, e-mail: notifications-help@james.apache.org


[james-project] 10/20: JAMES-3473 Save/fetch Email State with JMAP probe

Posted by rc...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

rcordier pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/james-project.git

commit f99524883e1605aa81ffe5d933181cbf8c325565
Author: LanKhuat <dl...@linagora.com>
AuthorDate: Tue Jan 5 10:38:56 2021 +0700

    JAMES-3473 Save/fetch Email State with JMAP probe
---
 .../src/main/java/org/apache/james/jmap/draft/JmapGuiceProbe.java    | 5 +++++
 .../james/jmap/rfc8621/contract/MailboxChangesMethodContract.scala   | 2 ++
 2 files changed, 7 insertions(+)

diff --git a/server/container/guice/protocols/jmap/src/main/java/org/apache/james/jmap/draft/JmapGuiceProbe.java b/server/container/guice/protocols/jmap/src/main/java/org/apache/james/jmap/draft/JmapGuiceProbe.java
index 676e7f5..f21a0a5 100644
--- a/server/container/guice/protocols/jmap/src/main/java/org/apache/james/jmap/draft/JmapGuiceProbe.java
+++ b/server/container/guice/protocols/jmap/src/main/java/org/apache/james/jmap/draft/JmapGuiceProbe.java
@@ -25,6 +25,7 @@ import javax.inject.Inject;
 
 import org.apache.james.core.Username;
 import org.apache.james.jmap.JMAPServer;
+import org.apache.james.jmap.api.change.EmailChange;
 import org.apache.james.jmap.api.change.EmailChangeRepository;
 import org.apache.james.jmap.api.change.MailboxChangeRepository;
 import org.apache.james.jmap.api.change.State;
@@ -94,6 +95,10 @@ public class JmapGuiceProbe implements GuiceProbe {
         Mono.from(messageFastViewProjection.clear()).block();
     }
 
+    public void saveEmailChange(EmailChange change) {
+        emailChangeRepository.save(change).block();
+    }
+
     public State getLatestMailboxState(AccountId accountId) {
         return mailboxChangeRepository.getLatestState(accountId).block();
     }
diff --git a/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/MailboxChangesMethodContract.scala b/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/MailboxChangesMethodContract.scala
index 1771910..216f4b9 100644
--- a/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/MailboxChangesMethodContract.scala
+++ b/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/MailboxChangesMethodContract.scala
@@ -33,6 +33,8 @@ import net.javacrumbs.jsonunit.core.internal.Options
 import org.apache.http.HttpStatus.SC_OK
 import org.apache.james.GuiceJamesServer
 import org.apache.james.jmap.api.change.State
+import org.apache.james.core.Username
+import org.apache.james.jmap.api.change.{MailboxChange, State}
 import org.apache.james.jmap.api.model.AccountId
 import org.apache.james.jmap.core.ResponseObject.SESSION_STATE
 import org.apache.james.jmap.draft.JmapGuiceProbe


---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@james.apache.org
For additional commands, e-mail: notifications-help@james.apache.org


[james-project] 09/20: JAMES-3473 Remove duplicated sort condition

Posted by rc...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

rcordier pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/james-project.git

commit 9f72a00b3c6e7ef1d23e3fec7d93eb4131f582dc
Author: LanKhuat <dl...@linagora.com>
AuthorDate: Tue Jan 5 10:35:59 2021 +0700

    JAMES-3473 Remove duplicated sort condition
---
 .../org/apache/james/jmap/memory/change/MemoryEmailChangeRepository.java | 1 -
 1 file changed, 1 deletion(-)

diff --git a/server/data/data-jmap/src/main/java/org/apache/james/jmap/memory/change/MemoryEmailChangeRepository.java b/server/data/data-jmap/src/main/java/org/apache/james/jmap/memory/change/MemoryEmailChangeRepository.java
index 994dd65..4f8ee2c 100644
--- a/server/data/data-jmap/src/main/java/org/apache/james/jmap/memory/change/MemoryEmailChangeRepository.java
+++ b/server/data/data-jmap/src/main/java/org/apache/james/jmap/memory/change/MemoryEmailChangeRepository.java
@@ -60,7 +60,6 @@ public class MemoryEmailChangeRepository implements EmailChangeRepository {
     public Mono<State> getLatestState(AccountId accountId) {
         return allChanges(accountId)
             .filter(change -> !change.isDelegated())
-            .sort(Comparator.comparing(EmailChange::getDate))
             .map(EmailChange::getState)
             .last(State.INITIAL);
     }


---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@james.apache.org
For additional commands, e-mail: notifications-help@james.apache.org


[james-project] 13/20: JAMES-3473 Dummy CassandraEmailChangeRepository should return initial state

Posted by rc...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

rcordier pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/james-project.git

commit a60a778f84eaa97ea4cd3f8a0b183f41f161faec
Author: LanKhuat <dl...@linagora.com>
AuthorDate: Thu Jan 7 16:48:18 2021 +0700

    JAMES-3473 Dummy CassandraEmailChangeRepository should return initial state
---
 .../james/jmap/cassandra/change/CassandraEmailChangeRepository.java   | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/server/data/data-jmap-cassandra/src/main/java/org/apache/james/jmap/cassandra/change/CassandraEmailChangeRepository.java b/server/data/data-jmap-cassandra/src/main/java/org/apache/james/jmap/cassandra/change/CassandraEmailChangeRepository.java
index f364fd9..1f67589 100644
--- a/server/data/data-jmap-cassandra/src/main/java/org/apache/james/jmap/cassandra/change/CassandraEmailChangeRepository.java
+++ b/server/data/data-jmap-cassandra/src/main/java/org/apache/james/jmap/cassandra/change/CassandraEmailChangeRepository.java
@@ -49,11 +49,11 @@ public class CassandraEmailChangeRepository implements EmailChangeRepository {
 
     @Override
     public Mono<State> getLatestState(AccountId accountId) {
-        return Mono.empty();
+        return Mono.just(State.INITIAL);
     }
 
     @Override
     public Mono<State> getLatestStateWithDelegation(AccountId accountId) {
-        return Mono.empty();
+        return Mono.just(State.INITIAL);
     }
 }


---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@james.apache.org
For additional commands, e-mail: notifications-help@james.apache.org


[james-project] 12/20: JAMES-3473 New state should be ignored in irrelevant Email/get calls

Posted by rc...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

rcordier pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/james-project.git

commit 1e19c6b228490afcbdf3291ac4ca85883a7e794d
Author: LanKhuat <dl...@linagora.com>
AuthorDate: Thu Jan 7 13:59:09 2021 +0700

    JAMES-3473 New state should be ignored in irrelevant Email/get calls
---
 .../rfc8621/contract/BackReferenceContract.scala   |   1 +
 .../rfc8621/contract/EmailGetMethodContract.scala  | 156 ++++++++------
 .../rfc8621/contract/EmailSetMethodContract.scala  | 235 +++++++++++----------
 .../EmailSubmissionSetMethodContract.scala         |   8 +-
 4 files changed, 219 insertions(+), 181 deletions(-)

diff --git a/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/BackReferenceContract.scala b/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/BackReferenceContract.scala
index 535bfd1..bd27d67 100644
--- a/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/BackReferenceContract.scala
+++ b/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/BackReferenceContract.scala
@@ -492,6 +492,7 @@ trait BackReferenceContract {
 
     assertThatJson(response)
       .withOptions(new Options(Option.IGNORING_ARRAY_ORDER))
+      .whenIgnoringPaths("methodResponses[2][1].state")
       .isEqualTo(
       s"""{
          |    "sessionState": "${SESSION_STATE.value}",
diff --git a/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/EmailGetMethodContract.scala b/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/EmailGetMethodContract.scala
index 7ddd52e..8dbcafe 100644
--- a/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/EmailGetMethodContract.scala
+++ b/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/EmailGetMethodContract.scala
@@ -320,14 +320,15 @@ trait EmailGetMethodContract {
       .body
       .asString
 
-    assertThatJson(response).isEqualTo(
+    assertThatJson(response)
+      .whenIgnoringPaths("methodResponses[0][1].state")
+      .isEqualTo(
       s"""{
          |    "sessionState": "${SESSION_STATE.value}",
          |    "methodResponses": [[
          |            "Email/get",
          |            {
          |                "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
-         |                "state": "${INSTANCE.value}",
          |                "list": [{
          |                        "id": "${messageId.serialize}",
          |                        "size": 85
@@ -2289,6 +2290,7 @@ trait EmailGetMethodContract {
 
     assertThatJson(response)
       .withOptions(new Options(IGNORING_ARRAY_ORDER))
+      .whenIgnoringPaths("methodResponses[0][1].state")
       .isEqualTo(
       s"""{
          |    "sessionState": "${SESSION_STATE.value}",
@@ -2296,7 +2298,6 @@ trait EmailGetMethodContract {
          |            "Email/get",
          |            {
          |                "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
-         |                "state": "${SESSION_STATE.value}",
          |                "list": [ {
          |                        "id": "${messageId.serialize}",
          |                        "size": 85
@@ -2349,14 +2350,15 @@ trait EmailGetMethodContract {
       .body
       .asString
 
-    assertThatJson(response).isEqualTo(
+    assertThatJson(response)
+      .whenIgnoringPaths("methodResponses[0][1].state")
+      .isEqualTo(
       s"""{
          |    "sessionState": "${SESSION_STATE.value}",
          |    "methodResponses": [[
          |            "Email/get",
          |            {
          |                "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
-         |                "state": "${INSTANCE.value}",
          |                "list": [
          |                    {
          |                        "id": "${messageId1.serialize()}",
@@ -2409,7 +2411,9 @@ trait EmailGetMethodContract {
       .body
       .asString
 
-    assertThatJson(response).isEqualTo(
+    assertThatJson(response)
+      .whenIgnoringPaths("methodResponses[0][1].state")
+      .isEqualTo(
       s"""{
          |    "sessionState": "${SESSION_STATE.value}",
          |    "methodResponses": [
@@ -2417,7 +2421,6 @@ trait EmailGetMethodContract {
          |            "Email/get",
          |            {
          |                "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
-         |                "state": "${INSTANCE.value}",
          |                "list": [
          |                    {
          |                        "threadId": "${messageId.serialize}",
@@ -2532,14 +2535,15 @@ trait EmailGetMethodContract {
       .body
       .asString
 
-    assertThatJson(response).isEqualTo(
+    assertThatJson(response)
+      .whenIgnoringPaths("methodResponses[0][1].state")
+      .isEqualTo(
       s"""{
          |    "sessionState": "${SESSION_STATE.value}",
          |    "methodResponses": [[
          |            "Email/get",
          |            {
          |                "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
-         |                "state": "${INSTANCE.value}",
          |                "list": [{
          |                        "id": "${messageId.serialize}",
          |                        "size": 85
@@ -2589,14 +2593,15 @@ trait EmailGetMethodContract {
       .body
       .asString
 
-    assertThatJson(response).isEqualTo(
+    assertThatJson(response)
+      .whenIgnoringPaths("methodResponses[0][1].state")
+      .isEqualTo(
       s"""{
          |    "sessionState": "${SESSION_STATE.value}",
          |    "methodResponses": [[
          |            "Email/get",
          |            {
          |                "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
-         |                "state": "${INSTANCE.value}",
          |                "list": [{
          |                        "id": "${messageId.serialize}"
          |                    }],
@@ -2645,7 +2650,9 @@ trait EmailGetMethodContract {
       .body
       .asString
 
-    assertThatJson(response).isEqualTo(
+    assertThatJson(response)
+      .whenIgnoringPaths("methodResponses[0][1].state")
+      .isEqualTo(
       s"""{
          |    "sessionState": "${SESSION_STATE.value}",
          |    "methodResponses": [[
@@ -2701,14 +2708,15 @@ trait EmailGetMethodContract {
       .body
       .asString
 
-    assertThatJson(response).isEqualTo(
+    assertThatJson(response)
+      .whenIgnoringPaths("methodResponses[0][1].state")
+      .isEqualTo(
       s"""{
          |    "sessionState": "${SESSION_STATE.value}",
          |    "methodResponses": [[
          |            "Email/get",
          |            {
          |                "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
-         |                "state": "${INSTANCE.value}",
          |                "list": [{
          |                        "id": "${messageId.serialize}",
          |                        "size": 85
@@ -3103,14 +3111,15 @@ trait EmailGetMethodContract {
       .body
       .asString
 
-    assertThatJson(response).isEqualTo(
+    assertThatJson(response)
+      .whenIgnoringPaths("methodResponses[0][1].state")
+      .isEqualTo(
       s"""{
          |    "sessionState": "${SESSION_STATE.value}",
          |    "methodResponses": [[
          |            "Email/get",
          |            {
          |                "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
-         |                "state": "${INSTANCE.value}",
          |                "list": [
          |                    {
          |                        "id": "${messageId.serialize}",
@@ -3354,7 +3363,9 @@ trait EmailGetMethodContract {
       .body
       .asString
 
-    assertThatJson(response).isEqualTo(
+    assertThatJson(response)
+      .whenIgnoringPaths("methodResponses[0][1].state")
+      .isEqualTo(
       s"""{
          |    "sessionState": "${SESSION_STATE.value}",
          |    "methodResponses": [
@@ -3362,7 +3373,6 @@ trait EmailGetMethodContract {
          |            "Email/get",
          |            {
          |                "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
-         |                "state": "${INSTANCE.value}",
          |                "list": [
          |                    {
          |                        "id": "${messageId.serialize}",
@@ -3425,14 +3435,15 @@ trait EmailGetMethodContract {
       .body
       .asString
 
-    assertThatJson(response).isEqualTo(
+    assertThatJson(response)
+      .whenIgnoringPaths("methodResponses[0][1].state")
+      .isEqualTo(
       s"""{
          |    "sessionState": "${SESSION_STATE.value}",
          |    "methodResponses": [[
          |            "Email/get",
          |            {
          |                "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
-         |                "state": "${INSTANCE.value}",
          |                "list": [
          |                    {
          |                        "id": "${messageId.serialize}",
@@ -3544,7 +3555,9 @@ trait EmailGetMethodContract {
       .body
       .asString
 
-    assertThatJson(response).isEqualTo(
+    assertThatJson(response)
+      .whenIgnoringPaths("methodResponses[0][1].state")
+      .isEqualTo(
       s"""{
          |    "sessionState": "${SESSION_STATE.value}",
          |    "methodResponses": [
@@ -3552,7 +3565,6 @@ trait EmailGetMethodContract {
          |            "Email/get",
          |            {
          |                "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
-         |                "state": "${INSTANCE.value}",
          |                "list": [
          |                    {
          |                        "id": "${messageId.serialize}",
@@ -3626,7 +3638,9 @@ trait EmailGetMethodContract {
       .asString
 
     val contentType = " multipart/mixed;\\r\\n boundary=\\\"------------64D8D789FC30153D6ED18258\\\""
-    assertThatJson(response).isEqualTo(
+    assertThatJson(response)
+      .whenIgnoringPaths("methodResponses[0][1].state")
+      .isEqualTo(
       s"""{
          |    "sessionState": "${SESSION_STATE.value}",
          |    "methodResponses": [
@@ -3634,7 +3648,6 @@ trait EmailGetMethodContract {
          |            "Email/get",
          |            {
          |                "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
-         |                "state": "${INSTANCE.value}",
          |                "list": [
          |                    {
          |                        "id": "${messageId.serialize}",
@@ -3816,7 +3829,9 @@ trait EmailGetMethodContract {
       .body
       .asString
 
-    assertThatJson(response).isEqualTo(
+    assertThatJson(response)
+      .whenIgnoringPaths("methodResponses[0][1].state")
+      .isEqualTo(
       s"""{
          |    "sessionState": "${SESSION_STATE.value}",
          |    "methodResponses": [
@@ -3824,7 +3839,6 @@ trait EmailGetMethodContract {
          |            "Email/get",
          |            {
          |                "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
-         |                "state": "${INSTANCE.value}",
          |                "list": [
          |                    {
          |                        "id": "${messageId.serialize}",
@@ -3999,14 +4013,15 @@ trait EmailGetMethodContract {
       .body
       .asString
 
-    assertThatJson(response).isEqualTo(
+    assertThatJson(response)
+      .whenIgnoringPaths("methodResponses[0][1].state")
+      .isEqualTo(
       s"""{
          |    "sessionState": "${SESSION_STATE.value}",
          |    "methodResponses": [[
          |            "Email/get",
          |            {
          |                "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
-         |                "state": "${INSTANCE.value}",
          |                "list": [
          |                    {
          |                        "id": "${messageId.serialize}",
@@ -4063,14 +4078,15 @@ trait EmailGetMethodContract {
       .body
       .asString
 
-    assertThatJson(response).isEqualTo(
+    assertThatJson(response)
+      .whenIgnoringPaths("methodResponses[0][1].state")
+      .isEqualTo(
       s"""{
          |    "sessionState": "${SESSION_STATE.value}",
          |    "methodResponses": [[
          |            "Email/get",
          |            {
          |                "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
-         |                "state": "${INSTANCE.value}",
          |                "list": [
          |                    {
          |                        "id": "${messageId.serialize}",
@@ -4127,14 +4143,15 @@ trait EmailGetMethodContract {
       .body
       .asString
 
-    assertThatJson(response).isEqualTo(
+    assertThatJson(response)
+      .whenIgnoringPaths("methodResponses[0][1].state")
+      .isEqualTo(
       s"""{
          |    "sessionState": "${SESSION_STATE.value}",
          |    "methodResponses": [[
          |            "Email/get",
          |            {
          |                "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
-         |                "state": "${INSTANCE.value}",
          |                "list": [
          |                    {
          |                        "id": "${messageId.serialize}",
@@ -4192,14 +4209,15 @@ trait EmailGetMethodContract {
       .body
       .asString
 
-    assertThatJson(response).isEqualTo(
+    assertThatJson(response)
+      .whenIgnoringPaths("methodResponses[0][1].state")
+      .isEqualTo(
       s"""{
          |    "sessionState": "${SESSION_STATE.value}",
          |    "methodResponses": [[
          |            "Email/get",
          |            {
          |                "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
-         |                "state": "${INSTANCE.value}",
          |                "list": [
          |                    {
          |                        "id": "${messageId.serialize}",
@@ -4255,14 +4273,15 @@ trait EmailGetMethodContract {
       .body
       .asString
 
-    assertThatJson(response).isEqualTo(
+    assertThatJson(response)
+      .whenIgnoringPaths("methodResponses[0][1].state")
+      .isEqualTo(
       s"""{
          |    "sessionState": "${SESSION_STATE.value}",
          |    "methodResponses": [[
          |            "Email/get",
          |            {
          |                "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
-         |                "state": "${INSTANCE.value}",
          |                "list": [
          |                    {
          |                        "id": "${messageId.serialize}",
@@ -4318,7 +4337,9 @@ trait EmailGetMethodContract {
       .body
       .asString
 
-    assertThatJson(response).isEqualTo(
+    assertThatJson(response)
+      .whenIgnoringPaths("methodResponses[0][1].state")
+      .isEqualTo(
       s"""{
          |    "sessionState": "${SESSION_STATE.value}",
          |    "methodResponses": [
@@ -4329,7 +4350,6 @@ trait EmailGetMethodContract {
          |                "notFound": [
          |
          |                ],
-         |                "state": "${INSTANCE.value}",
          |                "list": [
          |                    {
          |                        "id": "1",
@@ -4385,14 +4405,15 @@ trait EmailGetMethodContract {
       .body
       .asString
 
-    assertThatJson(response).isEqualTo(
+    assertThatJson(response)
+      .whenIgnoringPaths("methodResponses[0][1].state")
+      .isEqualTo(
       s"""{
          |    "sessionState": "${SESSION_STATE.value}",
          |    "methodResponses": [[
          |            "Email/get",
          |            {
          |                "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
-         |                "state": "${INSTANCE.value}",
          |                "list": [
          |                    {
          |                        "id": "${messageId.serialize}",
@@ -4448,14 +4469,15 @@ trait EmailGetMethodContract {
       .body
       .asString
 
-    assertThatJson(response).isEqualTo(
+    assertThatJson(response)
+      .whenIgnoringPaths("methodResponses[0][1].state")
+      .isEqualTo(
       s"""{
          |    "sessionState": "${SESSION_STATE.value}",
          |    "methodResponses": [[
          |            "Email/get",
          |            {
          |                "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
-         |                "state": "${INSTANCE.value}",
          |                "list": [
          |                    {
          |                        "id": "${messageId.serialize}",
@@ -4512,7 +4534,9 @@ trait EmailGetMethodContract {
       .body
       .asString
 
-    assertThatJson(response).isEqualTo(
+    assertThatJson(response)
+      .whenIgnoringPaths("methodResponses[0][1].state")
+      .isEqualTo(
       s"""{
          |    "sessionState": "${SESSION_STATE.value}",
          |    "methodResponses": [
@@ -4520,7 +4544,6 @@ trait EmailGetMethodContract {
          |            "Email/get",
          |            {
          |                "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
-         |                "state": "${INSTANCE.value}",
          |                "list": [
          |                    {
          |                        "id": "${messageId.serialize}",
@@ -4583,14 +4606,15 @@ trait EmailGetMethodContract {
       .body
       .asString
 
-    assertThatJson(response).isEqualTo(
+    assertThatJson(response)
+      .whenIgnoringPaths("methodResponses[0][1].state")
+      .isEqualTo(
       s"""{
          |    "sessionState": "${SESSION_STATE.value}",
          |    "methodResponses": [[
          |            "Email/get",
          |            {
          |                "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
-         |                "state": "${INSTANCE.value}",
          |                "list": [
          |                    {
          |                        "id": "${messageId.serialize}",
@@ -4646,7 +4670,9 @@ trait EmailGetMethodContract {
       .body
       .asString
 
-    assertThatJson(response).isEqualTo(
+    assertThatJson(response)
+      .whenIgnoringPaths("methodResponses[0][1].state")
+      .isEqualTo(
       s"""{
          |    "sessionState": "${SESSION_STATE.value}",
          |    "methodResponses": [
@@ -4654,7 +4680,6 @@ trait EmailGetMethodContract {
          |            "Email/get",
          |            {
          |                "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
-         |                "state": "${INSTANCE.value}",
          |                "list": [
          |                    {
          |                        "id": "${messageId.serialize}",
@@ -4720,14 +4745,15 @@ trait EmailGetMethodContract {
       .body
       .asString
 
-    assertThatJson(response).isEqualTo(
+    assertThatJson(response)
+      .whenIgnoringPaths("methodResponses[0][1].state")
+      .isEqualTo(
       s"""{
          |    "sessionState": "${SESSION_STATE.value}",
          |    "methodResponses": [[
          |            "Email/get",
          |            {
          |                "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
-         |                "state": "${INSTANCE.value}",
          |                "list": [
          |                    {
          |                        "id": "${messageId.serialize}",
@@ -4784,7 +4810,9 @@ trait EmailGetMethodContract {
       .body
       .asString
 
-    assertThatJson(response).isEqualTo(
+    assertThatJson(response)
+      .whenIgnoringPaths("methodResponses[0][1].state")
+      .isEqualTo(
       s"""{
          |    "sessionState": "${SESSION_STATE.value}",
          |    "methodResponses": [
@@ -4792,7 +4820,6 @@ trait EmailGetMethodContract {
          |            "Email/get",
          |            {
          |                "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
-         |                "state": "${INSTANCE.value}",
          |                "list": [
          |                    {
          |                        "id": "${messageId.serialize}",
@@ -4858,14 +4885,15 @@ trait EmailGetMethodContract {
       .body
       .asString
 
-    assertThatJson(response).isEqualTo(
+    assertThatJson(response)
+      .whenIgnoringPaths("methodResponses[0][1].state")
+      .isEqualTo(
       s"""{
          |    "sessionState": "${SESSION_STATE.value}",
          |    "methodResponses": [[
          |            "Email/get",
          |            {
          |                "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
-         |                "state": "${INSTANCE.value}",
          |                "list": [
          |                    {
          |                        "id": "${messageId.serialize}",
@@ -4930,14 +4958,15 @@ trait EmailGetMethodContract {
       .body
       .asString
 
-    assertThatJson(response).isEqualTo(
+    assertThatJson(response)
+      .whenIgnoringPaths("methodResponses[0][1].state")
+      .isEqualTo(
       s"""{
          |    "sessionState": "${SESSION_STATE.value}",
          |    "methodResponses": [[
          |            "Email/get",
          |            {
          |                "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
-         |                "state": "${INSTANCE.value}",
          |                "list": [
          |                    {
          |                        "id": "${messageId.serialize}",
@@ -4986,14 +5015,15 @@ trait EmailGetMethodContract {
       .body
       .asString
 
-    assertThatJson(response).isEqualTo(
+    assertThatJson(response)
+      .whenIgnoringPaths("methodResponses[0][1].state")
+      .isEqualTo(
       s"""{
          |    "sessionState": "${SESSION_STATE.value}",
          |    "methodResponses": [[
          |            "Email/get",
          |            {
          |                "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
-         |                "state": "${INSTANCE.value}",
          |                "list": [
          |                    {
          |                        "id": "${messageId.serialize}",
@@ -5070,14 +5100,15 @@ trait EmailGetMethodContract {
       .body
       .asString
 
-    assertThatJson(response).isEqualTo(
+    assertThatJson(response)
+      .whenIgnoringPaths("methodResponses[0][1].state")
+      .isEqualTo(
       s"""{
          |    "sessionState": "${SESSION_STATE.value}",
          |    "methodResponses": [[
          |            "Email/get",
          |            {
          |                "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
-         |                "state": "${INSTANCE.value}",
          |                "list": [
          |                    {
          |                        "id": "${messageId.serialize}",
@@ -5465,14 +5496,15 @@ trait EmailGetMethodContract {
       .body
       .asString
 
-    assertThatJson(response).isEqualTo(
+    assertThatJson(response)
+      .whenIgnoringPaths("methodResponses[0][1].state")
+      .isEqualTo(
       s"""{
          |    "sessionState": "${SESSION_STATE.value}",
          |    "methodResponses": [[
          |            "Email/get",
          |            {
          |                "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
-         |                "state": "${INSTANCE.value}",
          |                "list": [{
          |                    "id": "${messageId.serialize}",
          |                    "headers": [
diff --git a/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/EmailSetMethodContract.scala b/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/EmailSetMethodContract.scala
index ac44738..57285ac 100644
--- a/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/EmailSetMethodContract.scala
+++ b/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/EmailSetMethodContract.scala
@@ -3021,6 +3021,7 @@ trait EmailSetMethodContract {
            |}""".stripMargin)
 
     assertThatJson(response)
+      .whenIgnoringPaths("methodResponses[1][1].state")
       .isEqualTo(
         s"""{
            |  "sessionState": "${SESSION_STATE.value}",
@@ -3039,7 +3040,6 @@ trait EmailSetMethodContract {
            |    }, "c1"],
            |    ["Email/get", {
            |      "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
-           |      "state": "${INSTANCE.value}",
            |      "list": [
            |        {
            |          "id": "$messageId",
@@ -3133,6 +3133,7 @@ trait EmailSetMethodContract {
       .get.asInstanceOf[JsNumber].value
 
     assertThatJson(response)
+      .whenIgnoringPaths("methodResponses[1][1].state")
       .isEqualTo(
         s"""{
            |  "sessionState": "${SESSION_STATE.value}",
@@ -3151,7 +3152,6 @@ trait EmailSetMethodContract {
            |    }, "c1"],
            |    ["Email/get", {
            |      "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
-           |      "state": "${INSTANCE.value}",
            |      "list": [
            |        {
            |          "id": "$messageId",
@@ -4647,23 +4647,25 @@ trait EmailSetMethodContract {
       .body
       .asString
 
-    assertThatJson(response).isEqualTo(
-      s"""{
-         |    "sessionState": "${SESSION_STATE.value}",
-         |    "methodResponses": [
-         |      ["Email/set", {
-         |        "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
-         |        "newState": "${INSTANCE.value}",
-         |        "destroyed": ["${messageId.serialize}"]
-         |      }, "c1"],
-         |      ["Email/get", {
-         |        "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
-         |        "state": "${INSTANCE.value}",
-         |        "list": [],
-         |        "notFound": ["${messageId.serialize}"]
-         |      }, "c2"]
-         |    ]
-         |}""".stripMargin)
+    assertThatJson(response)
+      .whenIgnoringPaths("methodResponses[1][1].state")
+      .isEqualTo(
+        s"""{
+           |    "sessionState": "${SESSION_STATE.value}",
+           |    "methodResponses": [
+           |      ["Email/set", {
+           |        "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
+           |        "newState": "${INSTANCE.value}",
+           |        "destroyed": ["${messageId.serialize}"]
+           |      }, "c1"],
+           |      ["Email/get", {
+           |        "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
+           |        "state": "${INSTANCE.value}",
+           |        "list": [],
+           |        "notFound": ["${messageId.serialize}"]
+           |      }, "c2"]
+           |    ]
+           |}""".stripMargin)
   }
 
   @Test
@@ -4912,23 +4914,24 @@ trait EmailSetMethodContract {
       .body
       .asString
 
-    assertThatJson(response).isEqualTo(
-      s"""{
-         |    "sessionState": "${SESSION_STATE.value}",
-         |    "methodResponses": [
-         |      ["Email/set", {
-         |        "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
-         |        "newState": "${INSTANCE.value}",
-         |        "destroyed": ["${messageId.serialize}"]
-         |      }, "c1"],
-         |      ["Email/get", {
-         |        "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
-         |        "state": "${INSTANCE.value}",
-         |        "list": [],
-         |        "notFound": ["${messageId.serialize}"]
-         |      }, "c2"]
-         |    ]
-         |}""".stripMargin)
+    assertThatJson(response)
+      .whenIgnoringPaths("methodResponses[1][1].state")
+      .isEqualTo(
+        s"""{
+           |    "sessionState": "${SESSION_STATE.value}",
+           |    "methodResponses": [
+           |      ["Email/set", {
+           |        "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
+           |        "newState": "${INSTANCE.value}",
+           |        "destroyed": ["${messageId.serialize}"]
+           |      }, "c1"],
+           |      ["Email/get", {
+           |        "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
+           |        "list": [],
+           |        "notFound": ["${messageId.serialize}"]
+           |      }, "c2"]
+           |    ]
+           |}""".stripMargin)
   }
 
   @Test
@@ -4982,23 +4985,24 @@ trait EmailSetMethodContract {
       .body
       .asString
 
-    assertThatJson(response).isEqualTo(
-      s"""{
-         |    "sessionState": "${SESSION_STATE.value}",
-         |    "methodResponses": [
-         |      ["Email/set", {
-         |        "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
-         |        "newState": "${INSTANCE.value}",
-         |        "destroyed": ["${messageId.serialize}"]
-         |      }, "c1"],
-         |      ["Email/get", {
-         |        "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
-         |        "state": "${INSTANCE.value}",
-         |        "list": [],
-         |        "notFound": ["${messageId.serialize}"]
-         |      }, "c2"]
-         |    ]
-         |}""".stripMargin)
+    assertThatJson(response)
+      .whenIgnoringPaths("methodResponses[1][1].state")
+      .isEqualTo(
+        s"""{
+           |    "sessionState": "${SESSION_STATE.value}",
+           |    "methodResponses": [
+           |      ["Email/set", {
+           |        "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
+           |        "newState": "${INSTANCE.value}",
+           |        "destroyed": ["${messageId.serialize}"]
+           |      }, "c1"],
+           |      ["Email/get", {
+           |        "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
+           |        "list": [],
+           |        "notFound": ["${messageId.serialize}"]
+           |      }, "c2"]
+           |    ]
+           |}""".stripMargin)
   }
 
   @Test
@@ -5374,33 +5378,34 @@ trait EmailSetMethodContract {
       .body
       .asString
 
-    assertThatJson(response).isEqualTo(
-      s"""{
-         |    "sessionState": "${SESSION_STATE.value}",
-         |    "methodResponses": [
-         |      ["Email/set", {
-         |        "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
-         |        "newState": "${INSTANCE.value}",
-         |        "updated": {
-         |          "${messageId.serialize}": null
-         |        }
-         |      }, "c1"],
-         |      ["Email/get",{
-         |        "accountId":"29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
-         |        "state":"${INSTANCE.value}",
-         |        "list":[
-         |          {
-         |            "id":"${messageId.serialize}",
-         |            "mailboxIds":{
-         |              "${mailboxId2.serialize}":true,
-         |              "${mailboxId3.serialize}":true
-         |            }
-         |          }
-         |        ],
-         |        "notFound":[]
-         |        },"c2"]
-         |    ]
-         |}""".stripMargin)
+    assertThatJson(response)
+      .whenIgnoringPaths("methodResponses[1][1].state")
+      .isEqualTo(
+        s"""{
+           |    "sessionState": "${SESSION_STATE.value}",
+           |    "methodResponses": [
+           |      ["Email/set", {
+           |        "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
+           |        "newState": "${INSTANCE.value}",
+           |        "updated": {
+           |          "${messageId.serialize}": null
+           |        }
+           |      }, "c1"],
+           |      ["Email/get",{
+           |        "accountId":"29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
+           |        "list":[
+           |          {
+           |            "id":"${messageId.serialize}",
+           |            "mailboxIds":{
+           |              "${mailboxId2.serialize}":true,
+           |              "${mailboxId3.serialize}":true
+           |            }
+           |          }
+           |        ],
+           |        "notFound":[]
+           |        },"c2"]
+           |    ]
+           |}""".stripMargin)
   }
 
   @Test
@@ -5463,39 +5468,39 @@ trait EmailSetMethodContract {
       .asString
 
     assertThatJson(response)
+      .whenIgnoringPaths("methodResponses[1][1].state")
       .isEqualTo(
-      s"""{
-         |    "sessionState": "${SESSION_STATE.value}",
-         |    "methodResponses": [
-         |      ["Email/set", {
-         |        "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
-         |        "newState": "${INSTANCE.value}",
-         |        "updated": {
-         |          "${messageId1.serialize}": null,
-         |          "${messageId2.serialize}": null
-         |        }
-         |      }, "c1"],
-         |      ["Email/get", {
-         |        "accountId":"29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
-         |        "state":"${INSTANCE.value}",
-         |        "list":[
-         |          {
-         |            "id":"${messageId1.serialize}",
-         |            "mailboxIds": {
-         |              "${mailboxId2.serialize}":true
-         |            }
-         |          },
-         |          {
-         |            "id":"${messageId2.serialize}",
-         |            "mailboxIds":{
-         |              "${mailboxId2.serialize}":true
-         |            }
-         |          }
-         |        ],
-         |        "notFound":[]
-         |        },"c2"]
-         |    ]
-         |}""".stripMargin)
+        s"""{
+           |    "sessionState": "${SESSION_STATE.value}",
+           |    "methodResponses": [
+           |      ["Email/set", {
+           |        "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
+           |        "newState": "${INSTANCE.value}",
+           |        "updated": {
+           |          "${messageId1.serialize}": null,
+           |          "${messageId2.serialize}": null
+           |        }
+           |      }, "c1"],
+           |      ["Email/get", {
+           |        "accountId":"29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
+           |        "list":[
+           |          {
+           |            "id":"${messageId1.serialize}",
+           |            "mailboxIds": {
+           |              "${mailboxId2.serialize}":true
+           |            }
+           |          },
+           |          {
+           |            "id":"${messageId2.serialize}",
+           |            "mailboxIds":{
+           |              "${mailboxId2.serialize}":true
+           |            }
+           |          }
+           |        ],
+           |        "notFound":[]
+           |        },"c2"]
+           |    ]
+           |}""".stripMargin)
   }
 
   @Test
@@ -5615,6 +5620,7 @@ trait EmailSetMethodContract {
       .asString
 
     assertThatJson(response)
+      .whenIgnoringPaths("methodResponses[1][1].state")
       .isEqualTo(
         s"""{
            |    "sessionState": "${SESSION_STATE.value}",
@@ -5631,7 +5637,6 @@ trait EmailSetMethodContract {
            |      }, "c1"],
            |      ["Email/get", {
            |        "accountId":"29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
-           |        "state":"${INSTANCE.value}",
            |        "list":[
            |          {
            |            "id":"${messageId.serialize}",
@@ -5786,6 +5791,7 @@ trait EmailSetMethodContract {
       .asString
 
     assertThatJson(response)
+      .whenIgnoringPaths("methodResponses[1][1].state")
       .isEqualTo(
         s"""{
            |    "sessionState": "${SESSION_STATE.value}",
@@ -5799,7 +5805,6 @@ trait EmailSetMethodContract {
            |      }, "c1"],
            |      ["Email/get", {
            |        "accountId":"29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
-           |        "state":"${INSTANCE.value}",
            |        "list":[
            |          {
            |            "id":"${messageId.serialize}",
@@ -5869,6 +5874,7 @@ trait EmailSetMethodContract {
       .asString
 
     assertThatJson(response)
+      .whenIgnoringPaths("methodResponses[1][1].state")
       .isEqualTo(
         s"""{
            |    "sessionState": "${SESSION_STATE.value}",
@@ -5882,7 +5888,6 @@ trait EmailSetMethodContract {
            |      }, "c1"],
            |      ["Email/get", {
            |        "accountId":"29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
-           |        "state":"${INSTANCE.value}",
            |        "list":[
            |          {
            |            "id":"${messageId.serialize}",
diff --git a/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/EmailSubmissionSetMethodContract.scala b/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/EmailSubmissionSetMethodContract.scala
index ddbb3bb..4ea493c 100644
--- a/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/EmailSubmissionSetMethodContract.scala
+++ b/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/EmailSubmissionSetMethodContract.scala
@@ -885,7 +885,8 @@ trait EmailSubmissionSetMethodContract {
 
     assertThatJson(response)
       // Ids are randomly generated, and not stored, let's ignore it
-      .whenIgnoringPaths("methodResponses[0][1].created.k1490")
+      .whenIgnoringPaths("methodResponses[0][1].created.k1490",
+        "methodResponses[2][1].state")
       .isEqualTo(s"""{
                    |    "sessionState": "${SESSION_STATE.value}",
                    |    "methodResponses": [
@@ -915,7 +916,6 @@ trait EmailSubmissionSetMethodContract {
                    |            "Email/get",
                    |            {
                    |                "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
-                   |                "state": "${INSTANCE.value}",
                    |                "list": [
                    |                    {
                    |                        "keywords": {"$$sent": true},
@@ -987,7 +987,8 @@ trait EmailSubmissionSetMethodContract {
 
     assertThatJson(response)
       // Ids are randomly generated, and not stored, let's ignore it
-      .whenIgnoringPaths("methodResponses[0][1].created.k1490")
+      .whenIgnoringPaths("methodResponses[0][1].created.k1490",
+        "methodResponses[2][1].state")
       .isEqualTo(s"""{
                    |    "sessionState": "${SESSION_STATE.value}",
                    |    "methodResponses": [
@@ -1015,7 +1016,6 @@ trait EmailSubmissionSetMethodContract {
                    |            "Email/get",
                    |            {
                    |                "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
-                   |                "state": "${INSTANCE.value}",
                    |                "list":[],
                    |                "notFound": ["${messageId.serialize}"]
                    |            },


---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@james.apache.org
For additional commands, e-mail: notifications-help@james.apache.org


[james-project] 11/20: JAMES-3473 Email/get should return latest state

Posted by rc...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

rcordier pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/james-project.git

commit 2bbd5b2579fa7fe44086e8c7e699a0f34736bfb4
Author: LanKhuat <dl...@linagora.com>
AuthorDate: Tue Jan 5 10:45:57 2021 +0700

    JAMES-3473 Email/get should return latest state
---
 .../rfc8621/contract/EmailGetMethodContract.scala  | 77 ++++++++++++++++++++++
 .../apache/james/jmap/method/EmailGetMethod.scala  | 16 +++--
 2 files changed, 87 insertions(+), 6 deletions(-)

diff --git a/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/EmailGetMethodContract.scala b/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/EmailGetMethodContract.scala
index 41ca8ec..7ddd52e 100644
--- a/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/EmailGetMethodContract.scala
+++ b/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/EmailGetMethodContract.scala
@@ -28,12 +28,16 @@ import io.restassured.RestAssured.{`given`, requestSpecification}
 import io.restassured.http.ContentType.JSON
 import javax.mail.Flags
 import net.javacrumbs.jsonunit.assertj.JsonAssertions.assertThatJson
+import net.javacrumbs.jsonunit.core.Option
 import net.javacrumbs.jsonunit.core.Option.IGNORING_ARRAY_ORDER
 import net.javacrumbs.jsonunit.core.internal.Options
 import org.apache.http.HttpStatus.SC_OK
 import org.apache.james.GuiceJamesServer
+import org.apache.james.jmap.api.change.{EmailChange, State}
+import org.apache.james.jmap.api.model.AccountId
 import org.apache.james.jmap.core.ResponseObject.SESSION_STATE
 import org.apache.james.jmap.core.State.INSTANCE
+import org.apache.james.jmap.draft.JmapGuiceProbe
 import org.apache.james.jmap.http.UserCredential
 import org.apache.james.jmap.rfc8621.contract.EmailGetMethodContract.createTestMessage
 import org.apache.james.jmap.rfc8621.contract.Fixture.{ACCEPT_RFC8621_VERSION_HEADER, ALICE, ANDRE, BOB, BOB_PASSWORD, DOMAIN, authScheme, baseRequestSpecBuilder}
@@ -7046,4 +7050,77 @@ trait EmailGetMethodContract {
            |    "header:List-Help:asURLs": null
            }""".stripMargin)
   }
+
+  @Test
+  def emailStateShouldBeTheLatestOne(server: GuiceJamesServer): Unit = {
+    val mailboxProbe: MailboxProbeImpl = server.getProbe(classOf[MailboxProbeImpl])
+    val accountId: AccountId = AccountId.fromUsername(BOB)
+    val path: MailboxPath = MailboxPath.inbox(BOB)
+    mailboxProbe.createMailbox(path)
+    val message: Message = Message.Builder
+      .of
+      .setSubject("test")
+      .setSender(BOB.asString())
+      .setFrom(ANDRE.asString())
+      .setBody("testmail", StandardCharsets.UTF_8)
+      .build
+    val messageId: String = server.getProbe(classOf[MailboxProbeImpl])
+      .appendMessage(BOB.asString, path, AppendCommand.from(message))
+      .getMessageId
+      .serialize()
+
+    val state: State = storeReferenceState(server, accountId)
+
+    val response = `given`
+      .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER)
+      .body(
+        s"""{
+           |  "using": ["urn:ietf:params:jmap:core", "urn:ietf:params:jmap:mail"],
+           |  "methodCalls": [[
+           |     "Email/get",
+           |     {
+           |       "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
+           |       "ids": ["$messageId"],
+           |       "properties": ["id"]
+           |     },
+           |     "c1"]
+           |  ]
+           |}""".stripMargin)
+    .when
+      .post
+    .`then`
+      .statusCode(SC_OK)
+      .extract()
+      .body()
+      .asString()
+
+    assertThatJson(response)
+      .withOptions(new Options(Option.IGNORING_ARRAY_ORDER))
+      .inPath("methodResponses[0][1]")
+      .isEqualTo(
+        s"""{
+           |  "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
+           |  "state": "${state.getValue}",
+           |  "list":[
+           |    {
+           |      "id":"$messageId"
+           |    }
+           |  ],
+           |  "notFound": []
+           |}""".stripMargin)
+  }
+
+  private def storeReferenceState(server: GuiceJamesServer, accountId: AccountId) = {
+    val jmapGuiceProbe: JmapGuiceProbe = server.getProbe(classOf[JmapGuiceProbe])
+    jmapGuiceProbe.saveEmailChange(
+      EmailChange.builder()
+        .accountId(accountId)
+        .state(State.Factory.DEFAULT.generate())
+        .date(ZonedDateTime.now())
+        .isDelegated(false)
+        .build())
+
+    val state: State = jmapGuiceProbe.getLatestEmailState(accountId)
+    state
+  }
 }
\ No newline at end of file
diff --git a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/EmailGetMethod.scala b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/EmailGetMethod.scala
index e95d711..3ee9579 100644
--- a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/EmailGetMethod.scala
+++ b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/EmailGetMethod.scala
@@ -23,10 +23,12 @@ import java.time.ZoneId
 import eu.timepit.refined.auto._
 import eu.timepit.refined.types.string.NonEmptyString
 import javax.inject.Inject
+import org.apache.james.jmap.api.change.{EmailChangeRepository, State => JavaState}
+import org.apache.james.jmap.api.model.{AccountId => JavaAccountId}
 import org.apache.james.jmap.core.CapabilityIdentifier.{CapabilityIdentifier, JMAP_CORE, JMAP_MAIL}
 import org.apache.james.jmap.core.Invocation.{Arguments, MethodName}
 import org.apache.james.jmap.core.State.INSTANCE
-import org.apache.james.jmap.core.{AccountId, ErrorCode, Invocation, Properties}
+import org.apache.james.jmap.core.{AccountId, ErrorCode, Invocation, Properties, State}
 import org.apache.james.jmap.json.{EmailGetSerializer, ResponseSerializer}
 import org.apache.james.jmap.mail.Email.UnparsedEmailId
 import org.apache.james.jmap.mail.{Email, EmailBodyPart, EmailGetRequest, EmailGetResponse, EmailIds, EmailNotFound, EmailView, EmailViewReaderFactory, SpecificHeaderRequest}
@@ -78,6 +80,7 @@ class SystemZoneIdProvider extends ZoneIdProvider {
 class EmailGetMethod @Inject() (readerFactory: EmailViewReaderFactory,
                                 messageIdFactory: MessageId.Factory,
                                 val metricFactory: MetricFactory,
+                                val emailchangeRepository: EmailChangeRepository,
                                 val sessionSupplier: SessionSupplier) extends MethodRequiringAccountId[EmailGetRequest] {
   override val methodName: MethodName = MethodName("Email/get")
   override val requiredCapabilities: Set[CapabilityIdentifier] = Set(JMAP_CORE, JMAP_MAIL)
@@ -141,11 +144,12 @@ class EmailGetMethod @Inject() (readerFactory: EmailViewReaderFactory,
     request.ids match {
       case None => SMono.raiseError(new IllegalArgumentException("ids can not be ommited for email/get"))
       case Some(ids) => getEmails(ids, mailboxSession, request)
-        .map(result => EmailGetResponse(
-          accountId = request.accountId,
-          state = INSTANCE,
-          list = result.emails.toList,
-          notFound = result.notFound))
+        .flatMap(result => SMono[JavaState](emailchangeRepository.getLatestState(JavaAccountId.fromUsername(mailboxSession.getUser)))
+          .map(state => EmailGetResponse(
+            accountId = request.accountId,
+            state = State.fromJava(state),
+            list = result.emails.toList,
+            notFound = result.notFound)))
     }
 
   private def getEmails(ids: EmailIds, mailboxSession: MailboxSession, request: EmailGetRequest): SMono[EmailGetResults] = {


---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@james.apache.org
For additional commands, e-mail: notifications-help@james.apache.org


[james-project] 06/20: JAMES-3472 Email/changes method implementation & contract

Posted by rc...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

rcordier pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/james-project.git

commit 8204dc036a3d321a40721968022b2c0a4f08cc4b
Author: LanKhuat <dl...@linagora.com>
AuthorDate: Wed Jan 6 16:44:12 2021 +0700

    JAMES-3472 Email/changes method implementation & contract
---
 .../rfc8621/contract/EmailChangesContract.scala    |  173 ---
 .../contract/EmailChangesMethodContract.scala      | 1150 ++++++++++++++++++++
 .../memory/MemoryEmailChangesMethodTest.java       |   20 +-
 .../james/jmap/method/EmailChangesMethod.scala     |   48 +-
 4 files changed, 1195 insertions(+), 196 deletions(-)

diff --git a/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/EmailChangesContract.scala b/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/EmailChangesContract.scala
deleted file mode 100644
index d4d521b..0000000
--- a/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/EmailChangesContract.scala
+++ /dev/null
@@ -1,173 +0,0 @@
-/****************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one   *
- * or more contributor license agreements.  See the NOTICE file *
- * distributed with this work for additional information        *
- * regarding copyright ownership.  The ASF licenses this file   *
- * to you under the Apache License, Version 2.0 (the            *
- * "License"); you may not use this file except in compliance   *
- * with the License.  You may obtain a copy of the License at   *
- *                                                              *
- *   http://www.apache.org/licenses/LICENSE-2.0                 *
- *                                                              *
- * Unless required by applicable law or agreed to in writing,   *
- * software distributed under the License is distributed on an  *
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
- * KIND, either express or implied.  See the License for the    *
- * specific language governing permissions and limitations      *
- * under the License.                                           *
- ****************************************************************/
-
-package org.apache.james.jmap.rfc8621.contract
-
-import io.netty.handler.codec.http.HttpHeaderNames.ACCEPT
-import io.restassured.RestAssured.{`given`, requestSpecification}
-import io.restassured.http.ContentType.JSON
-import net.javacrumbs.jsonunit.assertj.JsonAssertions.assertThatJson
-import org.apache.http.HttpStatus.SC_OK
-import org.apache.james.GuiceJamesServer
-import org.apache.james.jmap.core.ResponseObject.SESSION_STATE
-import org.apache.james.jmap.core.State.INSTANCE
-import org.apache.james.jmap.http.UserCredential
-import org.apache.james.jmap.rfc8621.contract.Fixture.{ACCEPT_RFC8621_VERSION_HEADER, BOB, BOB_PASSWORD, DOMAIN, authScheme, baseRequestSpecBuilder}
-import org.apache.james.utils.DataProbeImpl
-import org.junit.jupiter.api.{BeforeEach, Test}
-
-trait EmailChangesContract {
-  @BeforeEach
-  def setUp(server: GuiceJamesServer): Unit = {
-    server.getProbe(classOf[DataProbeImpl])
-      .fluent
-      .addDomain(DOMAIN.asString)
-      .addDomain("domain-alias.tld")
-      .addUser(BOB.asString, BOB_PASSWORD)
-
-    requestSpecification = baseRequestSpecBuilder(server)
-      .setAuth(authScheme(UserCredential(BOB, BOB_PASSWORD)))
-      .build
-  }
-
-  @Test
-  def shouldReturnCannotCalculateChanges(): Unit = {
-    val request =
-      s"""{
-         |  "using": ["urn:ietf:params:jmap:core", "urn:ietf:params:jmap:mail"],
-         |  "methodCalls": [[
-         |    "Email/changes",
-         |    {
-         |      "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
-         |      "sinceState": "2c9f1b12-b35a-43e6-9af2-0106fb53a941"
-         |    },
-         |    "c1"]]
-         |}""".stripMargin
-
-    val response =  `given`
-      .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER)
-      .body(request)
-    .when
-      .post
-    .`then`
-      .statusCode(SC_OK)
-      .contentType(JSON)
-      .extract
-      .body
-      .asString
-
-    assertThatJson(response)
-      .isEqualTo(
-        s"""{
-          |    "sessionState": "${SESSION_STATE.value}",
-          |    "methodResponses": [
-          |        [
-          |            "error",
-          |            {
-          |                "type": "cannotCalculateChanges",
-          |                "description": "Naive implementation for Email/changes"
-          |            },
-          |            "c1"
-          |        ]
-          |    ]
-          |}""".stripMargin)
-  }
-
-  @Test
-  def badAccountIdShouldBeRejected(): Unit = {
-    val request =
-      s"""{
-         |  "using": ["urn:ietf:params:jmap:core", "urn:ietf:params:jmap:mail"],
-         |  "methodCalls": [[
-         |    "Email/changes",
-         |    {
-         |      "accountId": "bad",
-         |      "sinceState": "${INSTANCE.value}"
-         |    },
-         |    "c1"]]
-         |}""".stripMargin
-
-    val response =  `given`
-      .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER)
-      .body(request)
-    .when
-      .post
-    .`then`
-      .statusCode(SC_OK)
-      .contentType(JSON)
-      .extract
-      .body
-      .asString
-
-    assertThatJson(response)
-      .isEqualTo(
-        s"""{
-          |    "sessionState": "${SESSION_STATE.value}",
-          |    "methodResponses": [
-          |        [
-          |            "error",
-          |            {
-          |                "type": "accountNotFound"
-          |            },
-          |            "c1"
-          |        ]
-          |    ]
-          |}""".stripMargin)
-  }
-
-  @Test
-  def shouldReturnEmptyWhenKnownState(): Unit = {
-    val request =
-      s"""{
-         |  "using": ["urn:ietf:params:jmap:core", "urn:ietf:params:jmap:mail"],
-         |  "methodCalls": [[
-         |    "Thread/changes",
-         |    {
-         |      "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
-         |      "sinceState": "${INSTANCE.value}"
-         |    },
-         |    "c1"]]
-         |}""".stripMargin
-
-    val response =  `given`
-      .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER)
-      .body(request)
-    .when
-      .post
-    .`then`
-      .statusCode(SC_OK)
-      .contentType(JSON)
-      .extract
-      .body
-      .asString
-
-    assertThatJson(response)
-      .inPath("methodResponses[0][1]")
-      .isEqualTo(
-        s"""{
-          |  "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
-          |  "oldState": "${INSTANCE.value}",
-          |  "newState": "${INSTANCE.value}",
-          |  "hasMoreChanges": false,
-          |  "created": [],
-          |  "updated": [],
-          |  "destroyed": []
-          |}""".stripMargin)
-  }
-}
diff --git a/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/EmailChangesMethodContract.scala b/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/EmailChangesMethodContract.scala
new file mode 100644
index 0000000..0817ebb
--- /dev/null
+++ b/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/EmailChangesMethodContract.scala
@@ -0,0 +1,1150 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ * http://www.apache.org/licenses/LICENSE-2.0                   *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ ****************************************************************/
+
+package org.apache.james.jmap.rfc8621.contract
+
+import java.nio.charset.StandardCharsets
+import java.util.concurrent.TimeUnit
+
+import io.netty.handler.codec.http.HttpHeaderNames.ACCEPT
+import io.restassured.RestAssured.{`given`, requestSpecification}
+import io.restassured.builder.ResponseSpecBuilder
+import io.restassured.http.ContentType.JSON
+import javax.mail.Flags
+import net.javacrumbs.jsonunit.assertj.JsonAssertions.assertThatJson
+import net.javacrumbs.jsonunit.core.Option.IGNORING_ARRAY_ORDER
+import net.javacrumbs.jsonunit.core.internal.Options
+import org.apache.http.HttpStatus.SC_OK
+import org.apache.james.GuiceJamesServer
+import org.apache.james.jmap.api.change.State
+import org.apache.james.jmap.api.model.AccountId
+import org.apache.james.jmap.core.ResponseObject.SESSION_STATE
+import org.apache.james.jmap.draft.JmapGuiceProbe
+import org.apache.james.jmap.http.UserCredential
+import org.apache.james.jmap.rfc8621.contract.Fixture.{ACCEPT_RFC8621_VERSION_HEADER, ANDRE, ANDRE_ACCOUNT_ID, ANDRE_PASSWORD, BOB, BOB_PASSWORD, DOMAIN, authScheme, baseRequestSpecBuilder}
+import org.apache.james.mailbox.MessageManager.AppendCommand
+import org.apache.james.mailbox.model.MailboxACL.Right
+import org.apache.james.mailbox.model.{MailboxACL, MailboxId, MailboxPath, MessageId}
+import org.apache.james.mime4j.dom.Message
+import org.apache.james.modules.{ACLProbeImpl, MailboxProbeImpl}
+import org.apache.james.utils.DataProbeImpl
+import org.assertj.core.api.Assertions.assertThat
+import org.awaitility.Awaitility
+import org.awaitility.Duration.ONE_HUNDRED_MILLISECONDS
+import org.junit.jupiter.api.{BeforeEach, Nested, Test}
+import play.api.libs.json.{JsString, Json}
+
+trait EmailChangesMethodContract {
+
+  private lazy val slowPacedPollInterval = ONE_HUNDRED_MILLISECONDS
+  private lazy val calmlyAwait = Awaitility.`with`
+    .pollInterval(slowPacedPollInterval)
+    .and.`with`.pollDelay(slowPacedPollInterval)
+    .await
+  private lazy val awaitAtMostTenSeconds = calmlyAwait.atMost(10, TimeUnit.SECONDS)
+
+  def stateFactory: State.Factory
+  def generateMailboxId: MailboxId
+
+  @BeforeEach
+  def setUp(server: GuiceJamesServer): Unit = {
+    server.getProbe(classOf[DataProbeImpl])
+      .fluent
+      .addDomain(DOMAIN.asString)
+      .addDomain("domain-alias.tld")
+      .addUser(BOB.asString, BOB_PASSWORD)
+      .addUser(ANDRE.asString, ANDRE_PASSWORD)
+
+    requestSpecification = baseRequestSpecBuilder(server)
+      .setAuth(authScheme(UserCredential(BOB, BOB_PASSWORD)))
+      .build
+  }
+
+  @Test
+  def emailChangesShouldReturnCreatedChanges(server: GuiceJamesServer): Unit = {
+    val mailboxProbe: MailboxProbeImpl = server.getProbe(classOf[MailboxProbeImpl])
+    val path: MailboxPath = MailboxPath.forUser(BOB, "mailbox1")
+
+    mailboxProbe.createMailbox(path)
+
+    val message: Message = Message.Builder
+      .of
+      .setSubject("test")
+      .setBody("testmail", StandardCharsets.UTF_8)
+      .build
+    val messageId: MessageId = mailboxProbe.appendMessage(BOB.asString(), path, AppendCommand.from(message)).getMessageId
+
+    val request =
+      s"""{
+         |  "using": ["urn:ietf:params:jmap:core", "urn:ietf:params:jmap:mail"],
+         |  "methodCalls": [[
+         |    "Email/changes",
+         |    {
+         |      "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
+         |      "sinceState": "${State.INITIAL.getValue}"
+         |    },
+         |    "c1"]]
+         |}""".stripMargin
+
+    awaitAtMostTenSeconds.untilAsserted { () =>
+      val response = `given`
+        .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER)
+        .body(request)
+      .when
+        .post
+      .`then`
+        .statusCode(SC_OK)
+        .contentType(JSON)
+        .extract
+        .body
+        .asString
+
+      assertThatJson(response)
+        .whenIgnoringPaths("methodResponses[0][1].newState")
+        .withOptions(new Options(IGNORING_ARRAY_ORDER))
+        .isEqualTo(
+          s"""{
+             |    "sessionState": "${SESSION_STATE.value}",
+             |    "methodResponses": [
+             |      [ "Email/changes", {
+             |        "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
+             |        "oldState": "${State.INITIAL.getValue}",
+             |        "hasMoreChanges": false,
+             |        "created": ["${messageId.serialize}"],
+             |        "updated": [],
+             |        "destroyed": []
+             |      }, "c1"]
+             |    ]
+             |}""".stripMargin)
+    }
+  }
+
+  @Test
+  def emailChangesShouldReturnUpdatedChangesWhenAddFlags(server: GuiceJamesServer): Unit = {
+    val mailboxProbe: MailboxProbeImpl = server.getProbe(classOf[MailboxProbeImpl])
+    val path: MailboxPath = MailboxPath.forUser(BOB, "mailbox1")
+
+    mailboxProbe.createMailbox(path)
+
+    val message: Message = Message.Builder
+      .of
+      .setSubject("test")
+      .setBody("testmail", StandardCharsets.UTF_8)
+      .build
+    val messageId: MessageId = mailboxProbe.appendMessage(BOB.asString(), path, AppendCommand.from(message)).getMessageId
+
+    val oldState: State = waitForNextState(server, AccountId.fromUsername(BOB), State.INITIAL)
+
+    JmapRequests.markEmailAsSeen(messageId)
+
+    val request =
+      s"""{
+         |  "using": ["urn:ietf:params:jmap:core", "urn:ietf:params:jmap:mail"],
+         |  "methodCalls": [[
+         |    "Email/changes",
+         |    {
+         |      "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
+         |      "sinceState": "${oldState.getValue}"
+         |    },
+         |    "c1"]]
+         |}""".stripMargin
+
+    awaitAtMostTenSeconds.untilAsserted { () =>
+      val response = `given`
+        .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER)
+        .body(request)
+      .when
+        .post
+      .`then`
+        .statusCode(SC_OK)
+        .contentType(JSON)
+        .extract
+        .body
+        .asString
+
+      assertThatJson(response)
+        .whenIgnoringPaths("methodResponses[0][1].newState")
+        .withOptions(new Options(IGNORING_ARRAY_ORDER))
+        .isEqualTo(
+          s"""{
+             |    "sessionState": "${SESSION_STATE.value}",
+             |    "methodResponses": [
+             |      [ "Email/changes", {
+             |        "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
+             |        "oldState": "${oldState.getValue}",
+             |        "hasMoreChanges": false,
+             |        "created": [],
+             |        "updated": ["${messageId.serialize()}"],
+             |        "destroyed": []
+             |      }, "c1"]
+             |    ]
+             |}""".stripMargin)
+    }
+  }
+
+  @Test
+  def emailChangesShouldReturnUpdatedChangesWhenRemoveFlags(server: GuiceJamesServer): Unit = {
+    val mailboxProbe: MailboxProbeImpl = server.getProbe(classOf[MailboxProbeImpl])
+    val path: MailboxPath = MailboxPath.forUser(BOB, "mailbox1")
+
+    mailboxProbe.createMailbox(path)
+
+    val messageId: MessageId = mailboxProbe.appendMessage(BOB.asString(), path,
+      AppendCommand.builder()
+        .withFlags(new Flags(Flags.Flag.SEEN))
+        .build("header: value\r\n\r\nbody"))
+      .getMessageId
+
+    val oldState: State = waitForNextState(server, AccountId.fromUsername(BOB), State.INITIAL)
+
+    JmapRequests.markEmailAsNotSeen(messageId)
+
+    val request =
+      s"""{
+         |  "using": ["urn:ietf:params:jmap:core", "urn:ietf:params:jmap:mail"],
+         |  "methodCalls": [[
+         |    "Email/changes",
+         |    {
+         |      "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
+         |      "sinceState": "${oldState.getValue}"
+         |    },
+         |    "c1"]]
+         |}""".stripMargin
+
+    awaitAtMostTenSeconds.untilAsserted { () =>
+      val response = `given`
+        .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER)
+        .body(request)
+      .when
+        .post
+      .`then`
+        .statusCode(SC_OK)
+        .contentType(JSON)
+        .extract
+        .body
+        .asString
+
+      assertThatJson(response)
+        .whenIgnoringPaths("methodResponses[0][1].newState")
+        .withOptions(new Options(IGNORING_ARRAY_ORDER))
+        .isEqualTo(
+          s"""{
+             |    "sessionState": "${SESSION_STATE.value}",
+             |    "methodResponses": [
+             |      [ "Email/changes", {
+             |        "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
+             |        "oldState": "${oldState.getValue}",
+             |        "hasMoreChanges": false,
+             |        "created": [],
+             |        "updated": ["${messageId.serialize()}"],
+             |        "destroyed": []
+             |      }, "c1"]
+             |    ]
+             |}""".stripMargin)
+    }
+  }
+
+  @Test
+  def emailChangesShouldReturnDestroyedChanges(server: GuiceJamesServer): Unit = {
+    val mailboxProbe: MailboxProbeImpl = server.getProbe(classOf[MailboxProbeImpl])
+    val path: MailboxPath = MailboxPath.forUser(BOB, "mailbox1")
+
+    mailboxProbe.createMailbox(path)
+
+    val message: Message = Message.Builder
+      .of
+      .setSubject("test")
+      .setBody("testmail", StandardCharsets.UTF_8)
+      .build
+    val messageId: MessageId = mailboxProbe.appendMessage(BOB.asString(), path, AppendCommand.from(message)).getMessageId
+
+    val oldState: State = waitForNextState(server, AccountId.fromUsername(BOB), State.INITIAL)
+
+    JmapRequests.destroyEmail(messageId)
+
+    val request =
+      s"""{
+         |  "using": ["urn:ietf:params:jmap:core", "urn:ietf:params:jmap:mail"],
+         |  "methodCalls": [[
+         |    "Email/changes",
+         |    {
+         |      "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
+         |      "sinceState": "${oldState.getValue}"
+         |    },
+         |    "c1"]]
+         |}""".stripMargin
+
+    awaitAtMostTenSeconds.untilAsserted { () =>
+      val response = `given`
+        .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER)
+        .body(request)
+      .when
+        .post
+      .`then`
+        .statusCode(SC_OK)
+        .contentType(JSON)
+        .extract
+        .body
+        .asString
+
+      assertThatJson(response)
+        .whenIgnoringPaths("methodResponses[0][1].newState")
+        .withOptions(new Options(IGNORING_ARRAY_ORDER))
+        .isEqualTo(
+          s"""{
+             |    "sessionState": "${SESSION_STATE.value}",
+             |    "methodResponses": [
+             |      [ "Email/changes", {
+             |        "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
+             |        "oldState": "${oldState.getValue}",
+             |        "hasMoreChanges": false,
+             |        "created": [],
+             |        "updated": [],
+             |        "destroyed": ["${messageId.serialize()}"]
+             |      }, "c1"]
+             |    ]
+             |}""".stripMargin)
+    }
+  }
+
+  @Test
+  def emailChangesShouldReturnAllTypeOfChanges(server: GuiceJamesServer): Unit = {
+    val mailboxProbe: MailboxProbeImpl = server.getProbe(classOf[MailboxProbeImpl])
+    val accountId: AccountId = AccountId.fromUsername(BOB)
+
+    val path1: MailboxPath = MailboxPath.forUser(BOB, "mailbox1")
+    mailboxProbe.createMailbox(path1)
+
+    val path2: MailboxPath = MailboxPath.forUser(BOB, "mailbox2")
+    mailboxProbe.createMailbox(path2)
+
+    val message: Message = Message.Builder
+      .of
+      .setSubject("test")
+      .setBody("testmail", StandardCharsets.UTF_8)
+      .build
+
+    val messageId1: MessageId = mailboxProbe.appendMessage(BOB.asString(), path2, AppendCommand.from(message)).getMessageId
+
+    val state1: State = waitForNextState(server, accountId, State.INITIAL)
+
+    val messageId2: MessageId = mailboxProbe.appendMessage(BOB.asString(), path2, AppendCommand.from(message)).getMessageId
+
+    val oldState: State = waitForNextState(server, accountId, state1)
+
+    val messageId3: MessageId = mailboxProbe.appendMessage(BOB.asString(), path1, AppendCommand.from(message)).getMessageId
+
+    JmapRequests.markEmailAsSeen(messageId1)
+
+    JmapRequests.destroyEmail(messageId2)
+
+    val request =
+      s"""{
+         |  "using": ["urn:ietf:params:jmap:core", "urn:ietf:params:jmap:mail"],
+         |  "methodCalls": [[
+         |    "Email/changes",
+         |    {
+         |      "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
+         |      "sinceState": "${oldState.getValue}"
+         |    },
+         |    "c1"]]
+         |}""".stripMargin
+
+    awaitAtMostTenSeconds.untilAsserted { () =>
+      val response = `given`
+        .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER)
+        .body(request)
+      .when
+        .post
+      .`then`
+        .statusCode(SC_OK)
+        .contentType(JSON)
+        .extract
+        .body
+        .asString
+
+      assertThatJson(response)
+        .whenIgnoringPaths("methodResponses[0][1].newState")
+        .withOptions(new Options(IGNORING_ARRAY_ORDER))
+        .isEqualTo(
+          s"""{
+             |    "sessionState": "${SESSION_STATE.value}",
+             |    "methodResponses": [
+             |      [ "Email/changes", {
+             |        "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
+             |        "oldState": "${oldState.getValue}",
+             |        "hasMoreChanges": false,
+             |        "created": ["${messageId3.serialize}"],
+             |        "updated": ["${messageId1.serialize}"],
+             |        "destroyed": ["${messageId2.serialize}"]
+             |      }, "c1"]
+             |    ]
+             |}""".stripMargin)
+    }
+  }
+
+  @Test
+  def emailChangesShouldNotReturnDuplicatedIdsAccrossCreatedUpdatedOrDestroyed(server: GuiceJamesServer): Unit = {
+    val mailboxProbe: MailboxProbeImpl = server.getProbe(classOf[MailboxProbeImpl])
+
+    val path = MailboxPath.forUser(BOB, "mailbox1")
+    mailboxProbe.createMailbox(path)
+
+    val message: Message = Message.Builder
+      .of
+      .setSubject("test")
+      .setBody("testmail", StandardCharsets.UTF_8)
+      .build
+    val messageId1: MessageId = mailboxProbe.appendMessage(BOB.asString(), path, AppendCommand.from(message)).getMessageId
+    val messageId2: MessageId = mailboxProbe.appendMessage(BOB.asString(), path, AppendCommand.from(message)).getMessageId
+    val messageId3: MessageId = mailboxProbe.appendMessage(BOB.asString(), path, AppendCommand.from(message)).getMessageId
+
+    JmapRequests.markEmailAsSeen(messageId2)
+
+    JmapRequests.destroyEmail(messageId3)
+
+    val request =
+      s"""{
+         |  "using": ["urn:ietf:params:jmap:core", "urn:ietf:params:jmap:mail"],
+         |  "methodCalls": [[
+         |    "Email/changes",
+         |    {
+         |      "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
+         |      "sinceState": "${State.INITIAL.getValue}"
+         |    },
+         |    "c1"]]
+         |}""".stripMargin
+
+    awaitAtMostTenSeconds.untilAsserted { () =>
+      val response = `given`
+        .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER)
+        .body(request)
+      .when
+        .post
+      .`then`
+        .statusCode(SC_OK)
+        .contentType(JSON)
+        .extract
+        .body
+        .asString
+
+      assertThatJson(response)
+        .whenIgnoringPaths("methodResponses[0][1].newState")
+        .withOptions(new Options(IGNORING_ARRAY_ORDER))
+        .isEqualTo(
+          s"""{
+             |    "sessionState": "${SESSION_STATE.value}",
+             |    "methodResponses": [
+             |      [ "Email/changes", {
+             |        "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
+             |        "oldState": "${State.INITIAL.getValue}",
+             |        "hasMoreChanges": false,
+             |        "created": ["${messageId1.serialize}", "${messageId2.serialize}"],
+             |        "updated": [],
+             |        "destroyed": []
+             |      }, "c1"]
+             |    ]
+             |}""".stripMargin)
+    }
+  }
+
+  @Nested
+  class DelegationTest {
+    @Test
+    def emailChangesShouldReturnCreatedChanges(server: GuiceJamesServer): Unit = {
+      val mailboxProbe: MailboxProbeImpl = server.getProbe(classOf[MailboxProbeImpl])
+      val path: MailboxPath = MailboxPath.forUser(BOB, "mailbox1")
+
+      mailboxProbe.createMailbox(path)
+
+      server.getProbe(classOf[ACLProbeImpl])
+        .replaceRights(path, ANDRE.asString, new MailboxACL.Rfc4314Rights(Right.Lookup, Right.Read))
+
+      val message: Message = Message.Builder
+        .of
+        .setSubject("test")
+        .setBody("testmail", StandardCharsets.UTF_8)
+        .build
+      val messageId: MessageId = mailboxProbe.appendMessage(BOB.asString(), path, AppendCommand.from(message)).getMessageId
+
+      val request =
+        s"""{
+           |  "using": ["urn:ietf:params:jmap:core", "urn:ietf:params:jmap:mail", "urn:apache:james:params:jmap:mail:shares"],
+           |  "methodCalls": [[
+           |    "Email/changes",
+           |    {
+           |      "accountId": "$ANDRE_ACCOUNT_ID",
+           |      "sinceState": "${State.INITIAL.getValue}"
+           |    },
+           |    "c1"]]
+           |}""".stripMargin
+
+      awaitAtMostTenSeconds.untilAsserted { () =>
+        val response = `given`(
+          baseRequestSpecBuilder(server)
+            .setAuth(authScheme(UserCredential(ANDRE, ANDRE_PASSWORD)))
+            .addHeader(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER)
+            .setBody(request)
+            .build, new ResponseSpecBuilder().build)
+          .post
+          .`then`
+            .statusCode(SC_OK)
+            .contentType(JSON)
+            .extract
+            .body
+            .asString
+
+        assertThatJson(response)
+          .whenIgnoringPaths("methodResponses[0][1].newState")
+          .withOptions(new Options(IGNORING_ARRAY_ORDER))
+          .isEqualTo(
+            s"""{
+               |    "sessionState": "${SESSION_STATE.value}",
+               |    "methodResponses": [
+               |      [ "Email/changes", {
+               |        "accountId": "$ANDRE_ACCOUNT_ID",
+               |        "oldState": "${State.INITIAL.getValue}",
+               |        "hasMoreChanges": false,
+               |        "created": ["${messageId.serialize}"],
+               |        "updated": [],
+               |        "destroyed": []
+               |      }, "c1"]
+               |    ]
+               |}""".stripMargin)
+      }
+    }
+
+    @Test
+    def emailChangesShouldReturnUpdatedChangesWhenAddFlags(server: GuiceJamesServer): Unit = {
+      val mailboxProbe: MailboxProbeImpl = server.getProbe(classOf[MailboxProbeImpl])
+      val path: MailboxPath = MailboxPath.forUser(BOB, "mailbox1")
+
+      mailboxProbe.createMailbox(path)
+
+      server.getProbe(classOf[ACLProbeImpl])
+        .replaceRights(path, ANDRE.asString, new MailboxACL.Rfc4314Rights(Right.Lookup, Right.Read))
+
+      val message: Message = Message.Builder
+        .of
+        .setSubject("test")
+        .setBody("testmail", StandardCharsets.UTF_8)
+        .build
+      val messageId: MessageId = mailboxProbe.appendMessage(BOB.asString(), path, AppendCommand.from(message)).getMessageId
+
+      val oldState: State = waitForNextStateWithDelegation(server, AccountId.fromUsername(ANDRE), State.INITIAL)
+
+      JmapRequests.markEmailAsSeen(messageId)
+
+      val request =
+        s"""{
+           |  "using": ["urn:ietf:params:jmap:core", "urn:ietf:params:jmap:mail", "urn:apache:james:params:jmap:mail:shares"],
+           |  "methodCalls": [[
+           |    "Email/changes",
+           |    {
+           |      "accountId": "$ANDRE_ACCOUNT_ID",
+           |      "sinceState": "${oldState.getValue}"
+           |    },
+           |    "c1"]]
+           |}""".stripMargin
+
+      awaitAtMostTenSeconds.untilAsserted { () =>
+        val response = `given`(
+          baseRequestSpecBuilder(server)
+            .setAuth(authScheme(UserCredential(ANDRE, ANDRE_PASSWORD)))
+            .addHeader(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER)
+            .setBody(request)
+            .build, new ResponseSpecBuilder().build)
+          .post
+          .`then`
+            .statusCode(SC_OK)
+            .contentType(JSON)
+            .extract
+            .body
+            .asString
+
+        assertThatJson(response)
+          .whenIgnoringPaths("methodResponses[0][1].newState")
+          .withOptions(new Options(IGNORING_ARRAY_ORDER))
+          .isEqualTo(
+            s"""{
+               |    "sessionState": "${SESSION_STATE.value}",
+               |    "methodResponses": [
+               |      [ "Email/changes", {
+               |        "accountId": "$ANDRE_ACCOUNT_ID",
+               |        "oldState": "${oldState.getValue}",
+               |        "hasMoreChanges": false,
+               |        "created": [],
+               |        "updated": ["${messageId.serialize}"],
+               |        "destroyed": []
+               |      }, "c1"]
+               |    ]
+               |}""".stripMargin)
+      }
+    }
+
+    @Test
+    def emailChangesShouldReturnUpdatedChangesWhenRemoveFlags(server: GuiceJamesServer): Unit = {
+      val mailboxProbe: MailboxProbeImpl = server.getProbe(classOf[MailboxProbeImpl])
+      val path: MailboxPath = MailboxPath.forUser(BOB, "mailbox1")
+
+      mailboxProbe.createMailbox(path)
+
+      server.getProbe(classOf[ACLProbeImpl])
+        .replaceRights(path, ANDRE.asString, new MailboxACL.Rfc4314Rights(Right.Lookup, Right.Read))
+
+      val messageId: MessageId = mailboxProbe.appendMessage(BOB.asString(), path,
+        AppendCommand.builder()
+          .withFlags(new Flags(Flags.Flag.SEEN))
+          .build("header: value\r\n\r\nbody"))
+        .getMessageId
+
+      val oldState: State = waitForNextStateWithDelegation(server, AccountId.fromUsername(ANDRE), State.INITIAL)
+
+      JmapRequests.markEmailAsNotSeen(messageId)
+
+      val request =
+        s"""{
+           |  "using": ["urn:ietf:params:jmap:core", "urn:ietf:params:jmap:mail", "urn:apache:james:params:jmap:mail:shares"],
+           |  "methodCalls": [[
+           |    "Email/changes",
+           |    {
+           |      "accountId": "$ANDRE_ACCOUNT_ID",
+           |      "sinceState": "${oldState.getValue}"
+           |    },
+           |    "c1"]]
+           |}""".stripMargin
+
+      awaitAtMostTenSeconds.untilAsserted { () =>
+        val response = `given`(
+          baseRequestSpecBuilder(server)
+            .setAuth(authScheme(UserCredential(ANDRE, ANDRE_PASSWORD)))
+            .addHeader(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER)
+            .setBody(request)
+            .build, new ResponseSpecBuilder().build)
+          .post
+          .`then`
+            .statusCode(SC_OK)
+            .contentType(JSON)
+            .extract
+            .body
+            .asString
+
+        assertThatJson(response)
+          .whenIgnoringPaths("methodResponses[0][1].newState")
+          .withOptions(new Options(IGNORING_ARRAY_ORDER))
+          .isEqualTo(
+            s"""{
+               |    "sessionState": "${SESSION_STATE.value}",
+               |    "methodResponses": [
+               |      [ "Email/changes", {
+               |        "accountId": "$ANDRE_ACCOUNT_ID",
+               |        "oldState": "${oldState.getValue}",
+               |        "hasMoreChanges": false,
+               |        "created": [],
+               |        "updated": ["${messageId.serialize}"],
+               |        "destroyed": []
+               |      }, "c1"]
+               |    ]
+               |}""".stripMargin)
+      }
+    }
+
+    @Test
+    def emailChangesShouldReturnDestroyedChanges(server: GuiceJamesServer): Unit = {
+      val mailboxProbe: MailboxProbeImpl = server.getProbe(classOf[MailboxProbeImpl])
+      val path: MailboxPath = MailboxPath.forUser(BOB, "mailbox1")
+
+      mailboxProbe.createMailbox(path)
+
+      server.getProbe(classOf[ACLProbeImpl])
+        .replaceRights(path, ANDRE.asString, new MailboxACL.Rfc4314Rights(Right.Lookup, Right.Read))
+
+      val message: Message = Message.Builder
+        .of
+        .setSubject("test")
+        .setBody("testmail", StandardCharsets.UTF_8)
+        .build
+      val messageId: MessageId = mailboxProbe.appendMessage(BOB.asString(), path, AppendCommand.from(message)).getMessageId
+
+      val oldState: State = waitForNextStateWithDelegation(server, AccountId.fromUsername(ANDRE), State.INITIAL)
+
+      JmapRequests.destroyEmail(messageId)
+
+      val request =
+        s"""{
+           |  "using": ["urn:ietf:params:jmap:core", "urn:ietf:params:jmap:mail", "urn:apache:james:params:jmap:mail:shares"],
+           |  "methodCalls": [[
+           |    "Email/changes",
+           |    {
+           |      "accountId": "$ANDRE_ACCOUNT_ID",
+           |      "sinceState": "${oldState.getValue}"
+           |    },
+           |    "c1"]]
+           |}""".stripMargin
+
+      awaitAtMostTenSeconds.untilAsserted { () =>
+        val response = `given`(
+          baseRequestSpecBuilder(server)
+            .setAuth(authScheme(UserCredential(ANDRE, ANDRE_PASSWORD)))
+            .addHeader(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER)
+            .setBody(request)
+            .build, new ResponseSpecBuilder().build)
+          .post
+          .`then`
+            .statusCode(SC_OK)
+            .contentType(JSON)
+            .extract
+            .body
+            .asString
+
+        assertThatJson(response)
+          .whenIgnoringPaths("methodResponses[0][1].newState")
+          .withOptions(new Options(IGNORING_ARRAY_ORDER))
+          .isEqualTo(
+            s"""{
+               |    "sessionState": "${SESSION_STATE.value}",
+               |    "methodResponses": [
+               |      [ "Email/changes", {
+               |        "accountId": "$ANDRE_ACCOUNT_ID",
+               |        "oldState": "${oldState.getValue}",
+               |        "hasMoreChanges": false,
+               |        "created": [],
+               |        "updated": [],
+               |        "destroyed": ["${messageId.serialize}"]
+               |      }, "c1"]
+               |    ]
+               |}""".stripMargin)
+      }
+    }
+
+    @Test
+    def emailChangesShouldNotReturnUpdatedChangesWhenMissingSharesCapability(server: GuiceJamesServer): Unit = {
+      val mailboxProbe: MailboxProbeImpl = server.getProbe(classOf[MailboxProbeImpl])
+
+      val path = MailboxPath.forUser(BOB, "mailbox1")
+      mailboxProbe.createMailbox(path)
+
+      server.getProbe(classOf[ACLProbeImpl])
+        .replaceRights(path, ANDRE.asString, new MailboxACL.Rfc4314Rights(Right.Lookup, Right.Read))
+
+      val message: Message = Message.Builder
+        .of
+        .setSubject("test")
+        .setBody("testmail", StandardCharsets.UTF_8)
+        .build
+      mailboxProbe.appendMessage(BOB.asString(), path, AppendCommand.from(message))
+
+      val request =
+        s"""{
+           |  "using": ["urn:ietf:params:jmap:core", "urn:ietf:params:jmap:mail"],
+           |  "methodCalls": [[
+           |    "Email/changes",
+           |    {
+           |      "accountId": "$ANDRE_ACCOUNT_ID",
+           |      "sinceState": "${State.INITIAL.getValue}"
+           |    },
+           |    "c1"]]
+           |}""".stripMargin
+
+      awaitAtMostTenSeconds.untilAsserted { () =>
+        val response = `given`(
+          baseRequestSpecBuilder(server)
+            .setAuth(authScheme(UserCredential(ANDRE, ANDRE_PASSWORD)))
+            .addHeader(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER)
+            .setBody(request)
+            .build, new ResponseSpecBuilder().build)
+          .post
+          .`then`
+            .statusCode(SC_OK)
+            .contentType(JSON)
+            .extract
+            .body
+            .asString
+
+        assertThatJson(response)
+          .whenIgnoringPaths("methodResponses[0][1].newState")
+          .withOptions(new Options(IGNORING_ARRAY_ORDER))
+          .isEqualTo(
+            s"""{
+               |    "sessionState": "${SESSION_STATE.value}",
+               |    "methodResponses": [
+               |      [ "Email/changes", {
+               |        "accountId": "$ANDRE_ACCOUNT_ID",
+               |        "oldState": "${State.INITIAL.getValue}",
+               |        "hasMoreChanges": false,
+               |        "created": [],
+               |        "updated": [],
+               |        "destroyed": []
+               |      }, "c1"]
+               |    ]
+               |}""".stripMargin)
+      }
+    }
+  }
+
+  @Test
+  def emailChangesShouldReturnHasMoreChangesWhenTrue(server: GuiceJamesServer): Unit = {
+    val mailboxProbe: MailboxProbeImpl = server.getProbe(classOf[MailboxProbeImpl])
+    val path: MailboxPath = MailboxPath.forUser(BOB, "mailbox1")
+
+    mailboxProbe.createMailbox(path)
+
+    val message: Message = Message.Builder
+      .of
+      .setSubject("test")
+      .setBody("testmail", StandardCharsets.UTF_8)
+      .build
+
+    val messageId1: String = mailboxProbe.appendMessage(BOB.asString(), path, AppendCommand.from(message)).getMessageId.serialize
+    val messageId2: String = mailboxProbe.appendMessage(BOB.asString(), path, AppendCommand.from(message)).getMessageId.serialize
+    val messageId3: String = mailboxProbe.appendMessage(BOB.asString(), path, AppendCommand.from(message)).getMessageId.serialize
+    val messageId4: String = mailboxProbe.appendMessage(BOB.asString(), path, AppendCommand.from(message)).getMessageId.serialize
+    val messageId5: String = mailboxProbe.appendMessage(BOB.asString(), path, AppendCommand.from(message)).getMessageId.serialize
+    mailboxProbe.appendMessage(BOB.asString(), path, AppendCommand.from(message))
+
+    val request =
+      s"""{
+         |  "using": ["urn:ietf:params:jmap:core", "urn:ietf:params:jmap:mail"],
+         |  "methodCalls": [[
+         |    "Email/changes",
+         |    {
+         |      "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
+         |      "sinceState": "${State.INITIAL.getValue}"
+         |    },
+         |    "c1"]]
+         |}""".stripMargin
+
+    awaitAtMostTenSeconds.untilAsserted { () =>
+      val response = `given`
+        .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER)
+        .body(request)
+      .when
+        .post
+      .`then`
+        .statusCode(SC_OK)
+        .contentType(JSON)
+        .extract
+        .body
+        .asString
+
+      assertThatJson(response)
+        .whenIgnoringPaths("methodResponses[0][1].newState")
+        .withOptions(new Options(IGNORING_ARRAY_ORDER))
+        .isEqualTo(
+          s"""{
+             |    "sessionState": "${SESSION_STATE.value}",
+             |    "methodResponses": [
+             |      [ "Email/changes", {
+             |        "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
+             |        "oldState": "${State.INITIAL.getValue}",
+             |        "hasMoreChanges": true,
+             |        "created": ["$messageId1", "$messageId2", "$messageId3", "$messageId4", "$messageId5"],
+             |        "updated": [],
+             |        "destroyed": []
+             |      }, "c1"]
+             |    ]
+             |}""".stripMargin)
+    }
+  }
+
+  @Test
+  def emailChangesShouldReturnNoChangesWhenNoNewerState(server: GuiceJamesServer): Unit = {
+    val request =
+      s"""{
+         |  "using": ["urn:ietf:params:jmap:core", "urn:ietf:params:jmap:mail"],
+         |  "methodCalls": [[
+         |    "Email/changes",
+         |    {
+         |      "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
+         |      "sinceState": "${State.INITIAL.getValue}"
+         |    },
+         |    "c1"]]
+         |}""".stripMargin
+
+    awaitAtMostTenSeconds.untilAsserted { () =>
+      val response = `given`
+        .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER)
+        .body(request)
+      .when
+        .post
+      .`then`
+        .statusCode(SC_OK)
+        .contentType(JSON)
+        .extract
+        .body
+        .asString
+
+      assertThatJson(response)
+        .withOptions(new Options(IGNORING_ARRAY_ORDER))
+        .isEqualTo(
+          s"""{
+             |    "sessionState": "${SESSION_STATE.value}",
+             |    "methodResponses": [
+             |      [ "Email/changes", {
+             |        "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
+             |        "oldState": "${State.INITIAL.getValue}",
+             |        "newState": "${State.INITIAL.getValue}",
+             |        "hasMoreChanges": false,
+             |        "created": [],
+             |        "updated": [],
+             |        "destroyed": []
+             |      }, "c1"]
+             |    ]
+             |}""".stripMargin)
+    }
+  }
+
+  @Test
+  def emailChangesShouldReturnDifferentStateThanOldState(server: GuiceJamesServer): Unit = {
+    val mailboxProbe: MailboxProbeImpl = server.getProbe(classOf[MailboxProbeImpl])
+    val path: MailboxPath = MailboxPath.forUser(BOB, "mailbox1")
+
+    mailboxProbe.createMailbox(path)
+
+    val message: Message = Message.Builder
+      .of
+      .setSubject("test")
+      .setBody("testmail", StandardCharsets.UTF_8)
+      .build
+    mailboxProbe.appendMessage(BOB.asString(), path, AppendCommand.from(message))
+
+    val request =
+      s"""{
+         |  "using": ["urn:ietf:params:jmap:core", "urn:ietf:params:jmap:mail"],
+         |  "methodCalls": [[
+         |    "Email/changes",
+         |    {
+         |      "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
+         |      "sinceState": "${State.INITIAL.getValue}"
+         |    },
+         |    "c1"]]
+         |}""".stripMargin
+
+    awaitAtMostTenSeconds.untilAsserted { () =>
+      val response = `given`
+        .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER)
+        .body(request)
+      .when
+        .post
+      .`then`
+        .statusCode(SC_OK)
+        .contentType(JSON)
+        .extract
+        .body
+        .asString
+
+      val newState = Json.parse(response)
+        .\("methodResponses")
+        .\(0).\(1)
+        .\("newState")
+        .get.asInstanceOf[JsString].value
+
+      assertThat(State.INITIAL.getValue.toString).isNotEqualTo(newState)
+    }
+  }
+
+  @Test
+  def emailChangesShouldEventuallyReturnNoChanges(server: GuiceJamesServer): Unit = {
+    val mailboxProbe: MailboxProbeImpl = server.getProbe(classOf[MailboxProbeImpl])
+    val path = MailboxPath.forUser(BOB, "mailbox1")
+    mailboxProbe.createMailbox(path)
+
+    val message: Message = Message.Builder
+      .of
+      .setSubject("test")
+      .setBody("testmail", StandardCharsets.UTF_8)
+      .build
+    mailboxProbe.appendMessage(BOB.asString(), path, AppendCommand.from(message))
+
+    val request1 =
+      s"""{
+         |  "using": ["urn:ietf:params:jmap:core", "urn:ietf:params:jmap:mail"],
+         |  "methodCalls": [[
+         |    "Email/changes",
+         |    {
+         |      "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
+         |      "sinceState": "${State.INITIAL.getValue}"
+         |    },
+         |    "c1"]]
+         |}""".stripMargin
+
+    val response1 = `given`
+      .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER)
+      .body(request1)
+    .when
+      .post
+    .`then`
+      .statusCode(SC_OK)
+      .contentType(JSON)
+      .extract
+      .body
+      .asString
+
+    val newState = Json.parse(response1)
+      .\("methodResponses")
+      .\(0).\(1)
+      .\("newState")
+      .get.asInstanceOf[JsString].value
+
+    val request2 =
+      s"""{
+         |  "using": ["urn:ietf:params:jmap:core", "urn:ietf:params:jmap:mail"],
+         |  "methodCalls": [[
+         |    "Email/changes",
+         |    {
+         |      "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
+         |      "sinceState": "$newState"
+         |    },
+         |    "c1"]]
+         |}""".stripMargin
+
+    val response2 = `given`
+      .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER)
+      .body(request2)
+    .when
+      .post
+    .`then`
+      .statusCode(SC_OK)
+      .contentType(JSON)
+      .extract
+      .body
+      .asString
+
+    assertThatJson(response2)
+      .withOptions(new Options(IGNORING_ARRAY_ORDER))
+      .isEqualTo(
+        s"""{
+           |    "sessionState": "${SESSION_STATE.value}",
+           |    "methodResponses": [
+           |      [ "Email/changes", {
+           |        "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
+           |        "oldState": "$newState",
+           |        "newState": "$newState",
+           |        "hasMoreChanges": false,
+           |        "created": [],
+           |        "updated": [],
+           |        "destroyed": []
+           |      }, "c1"]
+           |    ]
+           |}""".stripMargin)
+  }
+
+  @Test
+  def emailChangesShouldFailWhenAccountIdNotFound(): Unit = {
+    val request =
+      s"""{
+         |  "using": ["urn:ietf:params:jmap:core", "urn:ietf:params:jmap:mail"],
+         |  "methodCalls": [[
+         |    "Email/changes",
+         |    {
+         |      "accountId": "bad",
+         |      "sinceState": "${State.INITIAL.getValue}"
+         |    },
+         |    "c1"]]
+         |}""".stripMargin
+
+    val response =  `given`
+      .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER)
+      .body(request)
+    .when
+      .post
+    .`then`
+      .statusCode(SC_OK)
+      .contentType(JSON)
+      .extract
+      .body
+      .asString
+
+    assertThatJson(response)
+      .isEqualTo(
+        s"""{
+           |    "sessionState": "${SESSION_STATE.value}",
+           |    "methodResponses": [
+           |        [
+           |            "error",
+           |            {
+           |                "type": "accountNotFound"
+           |            },
+           |            "c1"
+           |        ]
+           |    ]
+           |}""".stripMargin)
+  }
+
+  @Test
+  def emailChangesShouldFailWhenStateNotFound(server: GuiceJamesServer): Unit = {
+    val state: String = stateFactory.generate().getValue.toString
+
+    val request =
+      s"""{
+         |  "using": ["urn:ietf:params:jmap:core", "urn:ietf:params:jmap:mail"],
+         |  "methodCalls": [[
+         |    "Email/changes",
+         |    {
+         |      "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
+         |      "sinceState": "$state"
+         |    },
+         |    "c1"]]
+         |}""".stripMargin
+
+    val response = `given`
+      .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER)
+      .body(request)
+    .when
+      .post
+    .`then`
+      .statusCode(SC_OK)
+      .contentType(JSON)
+      .extract
+      .body
+      .asString
+
+    assertThatJson(response)
+      .whenIgnoringPaths("methodResponses[0][1].newState")
+      .withOptions(new Options(IGNORING_ARRAY_ORDER))
+      .isEqualTo(
+        s"""{
+           |  "sessionState": "${SESSION_STATE.value}",
+           |  "methodResponses": [[
+           |    "error", {
+           |      "type": "cannotCalculateChanges",
+           |      "description": "State '$state' could not be found"
+           |    }, "c1"]
+           |  ]
+           |}""".stripMargin)
+  }
+
+  private def waitForNextState(server: GuiceJamesServer, accountId: AccountId, initialState: State): State = {
+    val jmapGuiceProbe: JmapGuiceProbe = server.getProbe(classOf[JmapGuiceProbe])
+    awaitAtMostTenSeconds.untilAsserted {
+      () => assertThat(jmapGuiceProbe.getLatestEmailState(accountId)).isNotEqualTo(initialState)
+    }
+
+    jmapGuiceProbe.getLatestEmailState(accountId)
+  }
+
+  private def waitForNextStateWithDelegation(server: GuiceJamesServer, accountId: AccountId, initialState: State): State = {
+    val jmapGuiceProbe: JmapGuiceProbe = server.getProbe(classOf[JmapGuiceProbe])
+    awaitAtMostTenSeconds.untilAsserted {
+      () => assertThat(jmapGuiceProbe.getLatestEmailStateWithDelegation(accountId)).isNotEqualTo(initialState)
+    }
+
+    jmapGuiceProbe.getLatestEmailStateWithDelegation(accountId)
+  }
+}
diff --git a/server/protocols/jmap-rfc-8621-integration-tests/memory-jmap-rfc-8621-integration-tests/src/test/java/org/apache/james/jmap/rfc8621/memory/MemoryEmailChangesMethodTest.java b/server/protocols/jmap-rfc-8621-integration-tests/memory-jmap-rfc-8621-integration-tests/src/test/java/org/apache/james/jmap/rfc8621/memory/MemoryEmailChangesMethodTest.java
index e6887ed..a0ce35a 100644
--- a/server/protocols/jmap-rfc-8621-integration-tests/memory-jmap-rfc-8621-integration-tests/src/test/java/org/apache/james/jmap/rfc8621/memory/MemoryEmailChangesMethodTest.java
+++ b/server/protocols/jmap-rfc-8621-integration-tests/memory-jmap-rfc-8621-integration-tests/src/test/java/org/apache/james/jmap/rfc8621/memory/MemoryEmailChangesMethodTest.java
@@ -21,19 +21,33 @@ package org.apache.james.jmap.rfc8621.memory;
 
 import static org.apache.james.MemoryJamesServerMain.IN_MEMORY_SERVER_AGGREGATE_MODULE;
 
+import java.util.concurrent.ThreadLocalRandom;
+
 import org.apache.james.GuiceJamesServer;
 import org.apache.james.JamesServerBuilder;
 import org.apache.james.JamesServerExtension;
-import org.apache.james.jmap.rfc8621.contract.EmailChangesContract;
-import org.apache.james.jmap.rfc8621.contract.ThreadChangesContract;
+import org.apache.james.jmap.api.change.State;
+import org.apache.james.jmap.rfc8621.contract.EmailChangesMethodContract;
+import org.apache.james.mailbox.inmemory.InMemoryId;
+import org.apache.james.mailbox.model.MailboxId;
 import org.apache.james.modules.TestJMAPServerModule;
 import org.junit.jupiter.api.extension.RegisterExtension;
 
-public class MemoryEmailChangesMethodTest implements EmailChangesContract {
+public class MemoryEmailChangesMethodTest implements EmailChangesMethodContract {
     @RegisterExtension
     static JamesServerExtension testExtension = new JamesServerBuilder<>(JamesServerBuilder.defaultConfigurationProvider())
         .server(configuration -> GuiceJamesServer.forConfiguration(configuration)
             .combineWith(IN_MEMORY_SERVER_AGGREGATE_MODULE)
             .overrideWith(new TestJMAPServerModule()))
         .build();
+
+    @Override
+    public State.Factory stateFactory() {
+        return State.Factory.DEFAULT;
+    }
+
+    @Override
+    public MailboxId generateMailboxId() {
+        return InMemoryId.of(ThreadLocalRandom.current().nextInt());
+    }
 }
diff --git a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/EmailChangesMethod.scala b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/EmailChangesMethod.scala
index 821e323..8f67520 100644
--- a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/EmailChangesMethod.scala
+++ b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/EmailChangesMethod.scala
@@ -21,9 +21,11 @@ package org.apache.james.jmap.method
 
 import eu.timepit.refined.auto._
 import javax.inject.Inject
-import org.apache.james.jmap.core.CapabilityIdentifier.{CapabilityIdentifier, JMAP_MAIL}
+import org.apache.james.jmap.api.change.{EmailChangeRepository, EmailChanges, State => JavaState}
+import org.apache.james.jmap.api.model.{AccountId => JavaAccountId}
+import org.apache.james.jmap.core.CapabilityIdentifier.{CapabilityIdentifier, JAMES_SHARES, JMAP_MAIL}
 import org.apache.james.jmap.core.Invocation.{Arguments, MethodName}
-import org.apache.james.jmap.core.{ErrorCode, Invocation, State}
+import org.apache.james.jmap.core.{Invocation, State}
 import org.apache.james.jmap.json.{EmailGetSerializer, ResponseSerializer}
 import org.apache.james.jmap.mail.{EmailChangesRequest, EmailChangesResponse, HasMoreChanges}
 import org.apache.james.jmap.routes.SessionSupplier
@@ -32,32 +34,38 @@ import org.apache.james.metrics.api.MetricFactory
 import play.api.libs.json.{JsError, JsSuccess}
 import reactor.core.scala.publisher.SMono
 
+import scala.jdk.CollectionConverters._
+import scala.jdk.OptionConverters._
+
 class EmailChangesMethod @Inject()(val metricFactory: MetricFactory,
+                                   val emailChangeRepository: EmailChangeRepository,
                                    val sessionSupplier: SessionSupplier) extends MethodRequiringAccountId[EmailChangesRequest] {
   override val methodName: MethodName = MethodName("Email/changes")
   override val requiredCapabilities: Set[CapabilityIdentifier] = Set(JMAP_MAIL)
 
   override def doProcess(capabilities: Set[CapabilityIdentifier], invocation: InvocationWithContext, mailboxSession: MailboxSession, request: EmailChangesRequest): SMono[InvocationWithContext] =
-    if (request.sinceState.equals(State.INSTANCE)) {
-      val response: EmailChangesResponse = EmailChangesResponse(
+    SMono({
+      val accountId: JavaAccountId = JavaAccountId.fromUsername(mailboxSession.getUser)
+      if (capabilities.contains(JAMES_SHARES)) {
+        SMono[EmailChanges](emailChangeRepository.getSinceStateWithDelegation(accountId, JavaState.of(request.sinceState.value), request.maxChanged.toJava))
+      } else {
+        SMono[EmailChanges](emailChangeRepository.getSinceState(accountId, JavaState.of(request.sinceState.value), request.maxChanged.toJava))
+      }
+    })
+      .map(emailChanges => EmailChangesResponse(
         accountId = request.accountId,
-        oldState = State.INSTANCE,
-        newState = State.INSTANCE,
-        hasMoreChanges = HasMoreChanges(false),
-        created = List(),
-        updated = List(),
-        destroyed = List())
-      SMono.just(InvocationWithContext(invocation = Invocation(
-        methodName = methodName,
-        arguments = Arguments(EmailGetSerializer.serializeChanges(response)),
-        methodCallId = invocation.invocation.methodCallId
-      ), processingContext = invocation.processingContext))
-    } else {
-      SMono.just(InvocationWithContext(invocation = Invocation.error(ErrorCode.CannotCalculateChanges,
-        "Naive implementation for Email/changes",
-        invocation.invocation.methodCallId),
+        oldState = request.sinceState,
+        newState = State.fromEmailChanges(emailChanges),
+        hasMoreChanges = HasMoreChanges.fromEmailChanges(emailChanges),
+        created = emailChanges.getCreated.asScala.toSet,
+        updated = emailChanges.getUpdated.asScala.toSet,
+        destroyed = emailChanges.getDestroyed.asScala.toSet))
+      .map(response => InvocationWithContext(
+        invocation = Invocation(
+          methodName = methodName,
+          arguments = Arguments(EmailGetSerializer.serializeChanges(response)),
+          methodCallId = invocation.invocation.methodCallId),
         processingContext = invocation.processingContext))
-    }
 
   override def getRequest(mailboxSession: MailboxSession, invocation: Invocation): Either[IllegalArgumentException, EmailChangesRequest] =
     EmailGetSerializer.deserializeEmailChangesRequest(invocation.arguments.value) match {


---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@james.apache.org
For additional commands, e-mail: notifications-help@james.apache.org


[james-project] 08/20: JAMES-3472 MemoryMailboxChangesMethodTest should generate random mailboxId

Posted by rc...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

rcordier pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/james-project.git

commit 97c3f010aa7cc7e9703e8a0e0b27e11cb1810280
Author: LanKhuat <dl...@linagora.com>
AuthorDate: Thu Jan 7 10:32:43 2021 +0700

    JAMES-3472 MemoryMailboxChangesMethodTest should generate random mailboxId
---
 .../james/jmap/rfc8621/memory/MemoryMailboxChangesMethodTest.java     | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/server/protocols/jmap-rfc-8621-integration-tests/memory-jmap-rfc-8621-integration-tests/src/test/java/org/apache/james/jmap/rfc8621/memory/MemoryMailboxChangesMethodTest.java b/server/protocols/jmap-rfc-8621-integration-tests/memory-jmap-rfc-8621-integration-tests/src/test/java/org/apache/james/jmap/rfc8621/memory/MemoryMailboxChangesMethodTest.java
index df68a52..e0cce3f 100644
--- a/server/protocols/jmap-rfc-8621-integration-tests/memory-jmap-rfc-8621-integration-tests/src/test/java/org/apache/james/jmap/rfc8621/memory/MemoryMailboxChangesMethodTest.java
+++ b/server/protocols/jmap-rfc-8621-integration-tests/memory-jmap-rfc-8621-integration-tests/src/test/java/org/apache/james/jmap/rfc8621/memory/MemoryMailboxChangesMethodTest.java
@@ -21,6 +21,8 @@ package org.apache.james.jmap.rfc8621.memory;
 
 import static org.apache.james.MemoryJamesServerMain.IN_MEMORY_SERVER_AGGREGATE_MODULE;
 
+import java.util.concurrent.ThreadLocalRandom;
+
 import org.apache.james.GuiceJamesServer;
 import org.apache.james.JamesServerBuilder;
 import org.apache.james.JamesServerExtension;
@@ -47,6 +49,6 @@ public class MemoryMailboxChangesMethodTest implements MailboxChangesMethodContr
 
     @Override
     public MailboxId generateMailboxId() {
-        return InMemoryId.of(0);
+        return InMemoryId.of(ThreadLocalRandom.current().nextInt());
     }
 }
\ No newline at end of file


---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@james.apache.org
For additional commands, e-mail: notifications-help@james.apache.org