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 2023/03/20 02:22:30 UTC

[james-project] branch master updated: JAMES-3895 Automatically provision default (IMAP) mailboxes (#1476)

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


The following commit(s) were added to refs/heads/master by this push:
     new 47d4938a54 JAMES-3895 Automatically provision default (IMAP) mailboxes (#1476)
47d4938a54 is described below

commit 47d4938a54bef154f353c43394ea6723d6a78768
Author: Wojtek <wo...@users.noreply.github.com>
AuthorDate: Mon Mar 20 03:22:23 2023 +0100

    JAMES-3895 Automatically provision default (IMAP) mailboxes (#1476)
---
 .../org/apache/james/mailbox/DefaultMailboxes.java |  2 +-
 .../apache/james/mpt/host/JamesImapHostSystem.java |  1 +
 .../james/mpt/imapmailbox/suite/Condstore.java     |  8 +++--
 .../apache/james/imap/api/ImapConfiguration.java   | 21 ++++++++++--
 .../imap/processor/AbstractAuthProcessor.java      | 40 ++++++++++++++++++----
 .../james/imap/processor/CapabilityProcessor.java  |  9 ++---
 .../james/imap/api/ImapConfigurationTest.java      | 25 ++++++++++++++
 .../imap/processor/CapabilityProcessorTest.java    |  9 +++++
 .../org/apache/james/jmap/ProvisioningTest.java    |  2 +-
 .../integration/GetMailboxesMethodTest.java        |  6 ++--
 .../rfc8621/contract/BackReferenceContract.scala   | 25 ++++++++++----
 .../contract/MailboxGetMethodContract.scala        |  6 ++--
 .../rfc8621/contract/ProvisioningContract.scala    |  2 +-
 .../apache/james/imapserver/netty/IMAPServer.java  |  1 +
 .../netty/IMAPServerConfigurationTest.java         |  3 ++
 15 files changed, 126 insertions(+), 34 deletions(-)

diff --git a/mailbox/api/src/main/java/org/apache/james/mailbox/DefaultMailboxes.java b/mailbox/api/src/main/java/org/apache/james/mailbox/DefaultMailboxes.java
index 7b4ddbbd45..0cc0f38190 100644
--- a/mailbox/api/src/main/java/org/apache/james/mailbox/DefaultMailboxes.java
+++ b/mailbox/api/src/main/java/org/apache/james/mailbox/DefaultMailboxes.java
@@ -38,7 +38,7 @@ public interface DefaultMailboxes {
     String TEMPLATES = "Templates";
     String RESTORED_MESSAGES = "Restored-Messages";
 
-    List<String> DEFAULT_MAILBOXES = ImmutableList.of(INBOX, OUTBOX, SENT, TRASH, DRAFTS, SPAM);
+    List<String> DEFAULT_MAILBOXES = ImmutableList.of(INBOX, OUTBOX, SENT, TRASH, DRAFTS, ARCHIVE, SPAM);
 
     static List<MailboxPath> defaultMailboxesAsPath(Username username) {
         return DEFAULT_MAILBOXES.stream()
diff --git a/mpt/impl/imap-mailbox/core/src/main/java/org/apache/james/mpt/host/JamesImapHostSystem.java b/mpt/impl/imap-mailbox/core/src/main/java/org/apache/james/mpt/host/JamesImapHostSystem.java
index 723629d481..eb48f6fe0c 100644
--- a/mpt/impl/imap-mailbox/core/src/main/java/org/apache/james/mpt/host/JamesImapHostSystem.java
+++ b/mpt/impl/imap-mailbox/core/src/main/java/org/apache/james/mpt/host/JamesImapHostSystem.java
@@ -80,6 +80,7 @@ public abstract class JamesImapHostSystem implements ImapHostSystem, GrantRights
         this.decoder = decoder;
         this.encoder = encoder;
         this.processor = processor;
+        configure(ImapConfiguration.builder().isProvisionDefaultMailboxes(false).build());
     }
 
     @Override
diff --git a/mpt/impl/imap-mailbox/core/src/main/java/org/apache/james/mpt/imapmailbox/suite/Condstore.java b/mpt/impl/imap-mailbox/core/src/main/java/org/apache/james/mpt/imapmailbox/suite/Condstore.java
index 3333820c2a..5d31364010 100644
--- a/mpt/impl/imap-mailbox/core/src/main/java/org/apache/james/mpt/imapmailbox/suite/Condstore.java
+++ b/mpt/impl/imap-mailbox/core/src/main/java/org/apache/james/mpt/imapmailbox/suite/Condstore.java
@@ -49,19 +49,21 @@ public abstract class Condstore implements ImapTestConstants {
 
     @Test
     public void condstoreShouldBeDisableByDefault() throws Exception {
-        system.configure(ImapConfiguration.builder().build());
+        system.configure(ImapConfiguration.builder().isProvisionDefaultMailboxes(false).build());
         simpleScriptedTestProtocol.run("CondstoreDisable");
     }
 
     @Test
     public void condstoreShouldBeDisableWhenGivenAndFalse() throws Exception {
-        system.configure(ImapConfiguration.builder().isCondstoreEnable(false).build());
+        system.configure(
+                ImapConfiguration.builder().isProvisionDefaultMailboxes(false).isCondstoreEnable(false).build());
         simpleScriptedTestProtocol.run("CondstoreDisable");
     }
 
     @Test
     public void condstoreShouldBeEnableWhenGivenAndTrue() throws Exception {
-        system.configure(ImapConfiguration.builder().isCondstoreEnable(true).build());
+        system.configure(
+                ImapConfiguration.builder().isProvisionDefaultMailboxes(false).isCondstoreEnable(true).build());
         simpleScriptedTestProtocol.run("CondstoreEnable");
     }
 }
diff --git a/protocols/imap/src/main/java/org/apache/james/imap/api/ImapConfiguration.java b/protocols/imap/src/main/java/org/apache/james/imap/api/ImapConfiguration.java
index f42a9117d8..41fc4c26b9 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/api/ImapConfiguration.java
+++ b/protocols/imap/src/main/java/org/apache/james/imap/api/ImapConfiguration.java
@@ -38,6 +38,7 @@ public class ImapConfiguration {
     public static final TimeUnit DEFAULT_HEARTBEAT_INTERVAL_UNIT = TimeUnit.SECONDS;
     public static final int DEFAULT_CONCURRENT_REQUESTS = 128;
     public static final int DEFAULT_QUEUE_SIZE = 4096;
+    public static final boolean DEFAULT_PROVISION_DEFAULT_MAILBOXES = true;
 
     public static Builder builder() {
         return new Builder();
@@ -59,6 +60,7 @@ public class ImapConfiguration {
         private Optional<Boolean> enableIdle;
         private ImmutableSet<String> disabledCaps;
         private Optional<Boolean> isCondstoreEnable;
+        private Optional<Boolean> provisionDefaultMailboxes;
         private Optional<Properties> customProperties;
 
         private Builder() {
@@ -70,6 +72,7 @@ public class ImapConfiguration {
             this.enableIdle = Optional.empty();
             this.disabledCaps = ImmutableSet.of();
             this.isCondstoreEnable = Optional.empty();
+            this.provisionDefaultMailboxes = Optional.empty();
             this.customProperties = Optional.empty();
         }
 
@@ -130,6 +133,11 @@ public class ImapConfiguration {
             return this;
         }
 
+        public Builder isProvisionDefaultMailboxes(Boolean isProvisionDefaultMailboxes) {
+            this.provisionDefaultMailboxes = Optional.of(isProvisionDefaultMailboxes);
+            return this;
+        }
+
         public Builder withCustomProperties(Properties customProperties) {
             this.customProperties = Optional.of(customProperties);
             return this;
@@ -150,6 +158,7 @@ public class ImapConfiguration {
                     idleTimeIntervalUnit.orElse(DEFAULT_HEARTBEAT_INTERVAL_UNIT),
                     normalizeDisableCaps,
                     isCondstoreEnable.orElse(DEFAULT_CONDSTORE_DISABLE),
+                    provisionDefaultMailboxes.orElse(DEFAULT_PROVISION_DEFAULT_MAILBOXES),
                     customProperties.orElseGet(Properties::new));
         }
     }
@@ -162,9 +171,10 @@ public class ImapConfiguration {
     private final ImmutableSet<Capability> disabledCaps;
     private final boolean enableIdle;
     private final boolean isCondstoreEnable;
+    private final boolean provisionDefaultMailboxes;
     private final Properties customProperties;
 
-    private ImapConfiguration(Optional<Long> appendLimit, boolean enableIdle, long idleTimeInterval, int concurrentRequests, int maxQueueSize, TimeUnit idleTimeIntervalUnit, ImmutableSet<Capability> disabledCaps, boolean isCondstoreEnable, Properties customProperties) {
+    private ImapConfiguration(Optional<Long> appendLimit, boolean enableIdle, long idleTimeInterval, int concurrentRequests, int maxQueueSize, TimeUnit idleTimeIntervalUnit, ImmutableSet<Capability> disabledCaps, boolean isCondstoreEnable, boolean provisionDefaultMailboxes, Properties customProperties) {
         this.appendLimit = appendLimit;
         this.enableIdle = enableIdle;
         this.idleTimeInterval = idleTimeInterval;
@@ -173,6 +183,7 @@ public class ImapConfiguration {
         this.idleTimeIntervalUnit = idleTimeIntervalUnit;
         this.disabledCaps = disabledCaps;
         this.isCondstoreEnable = isCondstoreEnable;
+        this.provisionDefaultMailboxes = provisionDefaultMailboxes;
         this.customProperties = customProperties;
     }
 
@@ -208,6 +219,10 @@ public class ImapConfiguration {
         return isCondstoreEnable;
     }
 
+    public boolean isProvisionDefaultMailboxes() {
+        return provisionDefaultMailboxes;
+    }
+
     public Duration idleTimeIntervalAsDuration() {
         return Duration.of(getIdleTimeInterval(), getIdleTimeIntervalUnit().toChronoUnit());
     }
@@ -227,6 +242,7 @@ public class ImapConfiguration {
                 && Objects.equal(that.getConcurrentRequests(), concurrentRequests)
                 && Objects.equal(that.getMaxQueueSize(), maxQueueSize)
                 && Objects.equal(that.getDisabledCaps(), disabledCaps)
+                && Objects.equal(that.isProvisionDefaultMailboxes(), provisionDefaultMailboxes)
                 && Objects.equal(that.getCustomProperties(), customProperties)
                 && Objects.equal(that.isCondstoreEnable(), isCondstoreEnable);
         }
@@ -236,7 +252,7 @@ public class ImapConfiguration {
     @Override
     public final int hashCode() {
         return Objects.hashCode(enableIdle, idleTimeInterval, idleTimeIntervalUnit, disabledCaps, isCondstoreEnable,
-            concurrentRequests, maxQueueSize, appendLimit, customProperties);
+            concurrentRequests, maxQueueSize, appendLimit, provisionDefaultMailboxes, customProperties);
     }
 
     @Override
@@ -250,6 +266,7 @@ public class ImapConfiguration {
                 .add("isCondstoreEnable", isCondstoreEnable)
                 .add("concurrentRequests", concurrentRequests)
                 .add("maxQueueSize", maxQueueSize)
+                .add("provisionDefaultMailboxes", provisionDefaultMailboxes)
                 .add("customProperties", customProperties)
                 .toString();
     }
diff --git a/protocols/imap/src/main/java/org/apache/james/imap/processor/AbstractAuthProcessor.java b/protocols/imap/src/main/java/org/apache/james/imap/processor/AbstractAuthProcessor.java
index 3f682363ff..1b7230ebea 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/processor/AbstractAuthProcessor.java
+++ b/protocols/imap/src/main/java/org/apache/james/imap/processor/AbstractAuthProcessor.java
@@ -21,11 +21,13 @@ package org.apache.james.imap.processor;
 import java.util.Optional;
 
 import org.apache.james.core.Username;
+import org.apache.james.imap.api.ImapConfiguration;
 import org.apache.james.imap.api.display.HumanReadableText;
 import org.apache.james.imap.api.message.request.ImapRequest;
 import org.apache.james.imap.api.message.response.StatusResponseFactory;
 import org.apache.james.imap.api.process.ImapSession;
 import org.apache.james.imap.main.PathConverter;
+import org.apache.james.mailbox.DefaultMailboxes;
 import org.apache.james.mailbox.MailboxManager;
 import org.apache.james.mailbox.MailboxSession;
 import org.apache.james.mailbox.exception.BadCredentialsException;
@@ -50,6 +52,7 @@ public abstract class AbstractAuthProcessor<R extends ImapRequest> extends Abstr
 
     // TODO: this should be configurable
     private static final int MAX_FAILURES = 3;
+    private ImapConfiguration imapConfiguration;
 
     @FunctionalInterface
     protected interface MailboxSessionAuthWithDelegationSupplier {
@@ -61,6 +64,13 @@ public abstract class AbstractAuthProcessor<R extends ImapRequest> extends Abstr
         super(acceptableClass, mailboxManager, factory, metricFactory);
     }
 
+    @Override
+    public void configure(ImapConfiguration imapConfiguration) {
+        super.configure(imapConfiguration);
+
+        this.imapConfiguration = imapConfiguration;
+    }
+
     protected void doAuth(AuthenticationAttempt authenticationAttempt, ImapSession session, ImapRequest request, Responder responder, HumanReadableText failed) {
         Preconditions.checkArgument(!authenticationAttempt.isDelegation());
         try {
@@ -137,17 +147,33 @@ public abstract class AbstractAuthProcessor<R extends ImapRequest> extends Abstr
         if (Mono.from(mailboxManager.mailboxExists(inboxPath, mailboxSession)).block()) {
             LOGGER.debug("INBOX exists. No need to create it.");
         } else {
-            try {
-                mailboxManager.createMailbox(inboxPath, MailboxManager.CreateOption.CREATE_SUBSCRIPTION, mailboxSession)
-                    .ifPresentOrElse(
-                        id -> LOGGER.info("Provisioning INBOX. {} created.", id),
-                        () -> LOGGER.warn("Provisioning INBOX successful. But no MailboxId have been returned."));
-            } catch (MailboxExistsException e) {
-                LOGGER.warn("Mailbox INBOX created by concurrent call. Safe to ignore this exception.");
+            provisionMailbox(DefaultMailboxes.INBOX, session, mailboxManager, mailboxSession);
+            if (imapConfiguration.isProvisionDefaultMailboxes()) {
+                for (String mailbox : DefaultMailboxes.DEFAULT_MAILBOXES) {
+                    provisionMailbox(mailbox, session, mailboxManager, mailboxSession);
+                }
             }
         }
     }
 
+    private void provisionMailbox(String mailbox, ImapSession session, MailboxManager mailboxManager,
+                                  MailboxSession mailboxSession) throws MailboxException {
+        var mailboxPath = PathConverter.forSession(session).buildFullPath(mailbox);
+        if (Mono.from(mailboxManager.mailboxExists(mailboxPath, mailboxSession)).block()) {
+            LOGGER.debug("{} exists. No need to create it.", mailbox);
+            return;
+        }
+        try {
+            mailboxManager.createMailbox(mailboxPath, MailboxManager.CreateOption.CREATE_SUBSCRIPTION, mailboxSession)
+                    .ifPresentOrElse(id -> LOGGER.info("Provisioning mailbox {}. {} created.", mailbox, id),
+                                     () -> LOGGER.warn(
+                                             "Provisioning mailbox {} successful. But no MailboxId have been returned.",
+                                             mailbox));
+        } catch (MailboxExistsException e) {
+            LOGGER.warn("Mailbox {} created by concurrent call. Safe to ignore this exception.", mailbox);
+        }
+    }
+
     protected void manageFailureCount(ImapSession session, ImapRequest request, Responder responder) {
         manageFailureCount(session, request, responder, HumanReadableText.AUTHENTICATION_FAILED);
     }
diff --git a/protocols/imap/src/main/java/org/apache/james/imap/processor/CapabilityProcessor.java b/protocols/imap/src/main/java/org/apache/james/imap/processor/CapabilityProcessor.java
index 3feaf5d747..70c660c645 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/processor/CapabilityProcessor.java
+++ b/protocols/imap/src/main/java/org/apache/james/imap/processor/CapabilityProcessor.java
@@ -74,7 +74,9 @@ public class CapabilityProcessor extends AbstractMailboxProcessor<CapabilityRequ
         super.configure(imapConfiguration);
 
         disabledCaps.addAll(imapConfiguration.getDisabledCaps());
-        if (shouldDisableCondstore(imapConfiguration)) {
+        if (imapConfiguration.isCondstoreEnable()) {
+            disabledCaps.remove(SUPPORTS_CONDSTORE);
+        } else {
             disabledCaps.add(SUPPORTS_CONDSTORE);
         }
         if (!getMailboxManager().getSupportedMessageCapabilities().contains(UniqueID)) {
@@ -82,11 +84,6 @@ public class CapabilityProcessor extends AbstractMailboxProcessor<CapabilityRequ
         }
     }
 
-    private boolean shouldDisableCondstore(ImapConfiguration imapConfiguration) {
-        return !imapConfiguration.isCondstoreEnable() 
-                && !disabledCaps.contains(SUPPORTS_CONDSTORE);
-    }
-
     @Override
     protected Mono<Void> processRequestReactive(CapabilityRequest request, ImapSession session, Responder responder) {
         final CapabilityResponse result = new CapabilityResponse(getSupportedCapabilities(session));        
diff --git a/protocols/imap/src/test/java/org/apache/james/imap/api/ImapConfigurationTest.java b/protocols/imap/src/test/java/org/apache/james/imap/api/ImapConfigurationTest.java
index c970230d34..54149534c3 100644
--- a/protocols/imap/src/test/java/org/apache/james/imap/api/ImapConfigurationTest.java
+++ b/protocols/imap/src/test/java/org/apache/james/imap/api/ImapConfigurationTest.java
@@ -181,5 +181,30 @@ class ImapConfigurationTest {
                 .build();
 
         assertThat(imapConfiguration.isCondstoreEnable()).isFalse();
+    }
+
+    @Test
+    void isProvisionDefaultMailboxesShouldBeTrueWhenNoSetting() {
+        ImapConfiguration imapConfiguration = ImapConfiguration.builder().build();
+
+        assertThat(imapConfiguration.isProvisionDefaultMailboxes()).isTrue();
+   }
+
+    @Test
+    void isProvisionDefaultMailboxesShouldBeTrueWhenValueIsTrue() {
+        ImapConfiguration imapConfiguration = ImapConfiguration.builder()
+                .isProvisionDefaultMailboxes(true)
+                .build();
+
+        assertThat(imapConfiguration.isProvisionDefaultMailboxes()).isTrue();
+   }
+
+    @Test
+    void isProvisionDefaultMailboxesShouldBeFalseWhenValueIsFalse() {
+        ImapConfiguration imapConfiguration = ImapConfiguration.builder()
+                .isProvisionDefaultMailboxes(false)
+                .build();
+
+        assertThat(imapConfiguration.isProvisionDefaultMailboxes()).isFalse();
    }
 }
\ No newline at end of file
diff --git a/protocols/imap/src/test/java/org/apache/james/imap/processor/CapabilityProcessorTest.java b/protocols/imap/src/test/java/org/apache/james/imap/processor/CapabilityProcessorTest.java
index d19ce5ff06..1b89404ba5 100644
--- a/protocols/imap/src/test/java/org/apache/james/imap/processor/CapabilityProcessorTest.java
+++ b/protocols/imap/src/test/java/org/apache/james/imap/processor/CapabilityProcessorTest.java
@@ -62,6 +62,15 @@ class CapabilityProcessorTest {
         assertThat(supportedCapabilities).contains(ImapConstants.SUPPORTS_CONDSTORE);
     }
 
+    @Test
+    void condstoreShouldBeSupportedWhenReconfigured() {
+        testee.configure(ImapConfiguration.builder().isCondstoreEnable(false).build());
+        testee.configure(ImapConfiguration.builder().isCondstoreEnable(true).build());
+
+        Set<Capability> supportedCapabilities = testee.getSupportedCapabilities(null);
+        assertThat(supportedCapabilities).contains(ImapConstants.SUPPORTS_CONDSTORE);
+    }
+
     @Test
     void condstoreShouldBeNotSupportedByDefault() {
         testee.configure(ImapConfiguration.builder().build());
diff --git a/server/protocols/jmap-draft-integration-testing/jmap-draft-integration-testing-common/src/test/java/org/apache/james/jmap/ProvisioningTest.java b/server/protocols/jmap-draft-integration-testing/jmap-draft-integration-testing-common/src/test/java/org/apache/james/jmap/ProvisioningTest.java
index a0aa0aa42a..2a88e78772 100644
--- a/server/protocols/jmap-draft-integration-testing/jmap-draft-integration-testing-common/src/test/java/org/apache/james/jmap/ProvisioningTest.java
+++ b/server/protocols/jmap-draft-integration-testing/jmap-draft-integration-testing-common/src/test/java/org/apache/james/jmap/ProvisioningTest.java
@@ -99,7 +99,7 @@ public abstract class ProvisioningTest {
             .header("Content-Length", notNullValue())
             .statusCode(200)
             .body(NAME, equalTo("mailboxes"))
-            .body(ARGUMENTS + ".list", hasSize(6))
+            .body(ARGUMENTS + ".list", hasSize(DefaultMailboxes.DEFAULT_MAILBOXES.size()))
             .body(ARGUMENTS + ".list.name", hasItems(DefaultMailboxes.DEFAULT_MAILBOXES.toArray()));
     }
 
diff --git a/server/protocols/jmap-draft-integration-testing/jmap-draft-integration-testing-common/src/test/java/org/apache/james/jmap/draft/methods/integration/GetMailboxesMethodTest.java b/server/protocols/jmap-draft-integration-testing/jmap-draft-integration-testing-common/src/test/java/org/apache/james/jmap/draft/methods/integration/GetMailboxesMethodTest.java
index 982c401221..1b9d35f742 100644
--- a/server/protocols/jmap-draft-integration-testing/jmap-draft-integration-testing-common/src/test/java/org/apache/james/jmap/draft/methods/integration/GetMailboxesMethodTest.java
+++ b/server/protocols/jmap-draft-integration-testing/jmap-draft-integration-testing-common/src/test/java/org/apache/james/jmap/draft/methods/integration/GetMailboxesMethodTest.java
@@ -246,7 +246,7 @@ public abstract class GetMailboxesMethodTest {
         .then()
             .statusCode(200)
             .body(NAME, equalTo("mailboxes"))
-            .body(ARGUMENTS + ".list", hasSize(8))
+            .body(ARGUMENTS + ".list", hasSize(expectedMailboxes.size()))
             .body(ARGUMENTS + ".list.name", hasItems(expectedMailboxes.toArray()));
     }
 
@@ -363,7 +363,7 @@ public abstract class GetMailboxesMethodTest {
         .then()
             .statusCode(200)
             .body(NAME, equalTo("mailboxes"))
-            .body(ARGUMENTS + ".list", hasSize(6))
+            .body(ARGUMENTS + ".list", hasSize(DefaultMailboxes.DEFAULT_MAILBOXES.size()))
             .body(ARGUMENTS + ".list.name", hasItems(DefaultMailboxes.DEFAULT_MAILBOXES.toArray()));
     }
 
@@ -634,7 +634,7 @@ public abstract class GetMailboxesMethodTest {
         .then()
             .statusCode(200)
             .body(NAME, equalTo("mailboxes"))
-            .body(ARGUMENTS + ".list", hasSize(7))
+            .body(ARGUMENTS + ".list", hasSize(expectedMailboxes.size()))
             .body(ARGUMENTS + ".list.name", hasItems(expectedMailboxes.toArray()));
     }
 
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 1094623157..c2ccd7eaf9 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
@@ -85,13 +85,14 @@ trait BackReferenceContract {
       .post
     .`then`
       .statusCode(SC_OK)
-      .header("Content-Length", "551")
+      .header("Content-Length", "573")
       .extract()
       .body()
       .asString()
 
     assertThatJson(response)
       .whenIgnoringPaths("methodResponses[0][1].state", "methodResponses[1][1].state")
+      .withOptions(new Options(Option.IGNORING_ARRAY_ORDER))
       .isEqualTo(
       s"""{
          |    "sessionState": "${SESSION_STATE.value}",
@@ -107,7 +108,8 @@ trait BackReferenceContract {
          |                    {"id": "2"},
          |                    {"id": "3"},
          |                    {"id": "4"},
-         |                    {"id": "6"}
+         |                    {"id": "6"},
+         |                    {"id": "7"}
          |                ],
          |                "notFound": []
          |            },
@@ -123,7 +125,8 @@ trait BackReferenceContract {
          |                    {"id": "2"},
          |                    {"id": "3"},
          |                    {"id": "4"},
-         |                    {"id": "6"}
+         |                    {"id": "6"},
+         |                    {"id": "7"}
          |                ],
          |                "notFound": []
          |            },
@@ -172,6 +175,7 @@ trait BackReferenceContract {
 
     assertThatJson(response)
       .whenIgnoringPaths("methodResponses[0][1].state")
+      .withOptions(new Options(Option.IGNORING_ARRAY_ORDER))
       .isEqualTo(
       s"""{
          |    "sessionState": "${SESSION_STATE.value}",
@@ -186,7 +190,8 @@ trait BackReferenceContract {
          |                    {"id": "2"},
          |                    {"id": "3"},
          |                    {"id": "4"},
-         |                    {"id": "6"}
+         |                    {"id": "6"},
+         |                    {"id": "7"}
          |                ],
          |                "notFound": []
          |            },
@@ -243,6 +248,7 @@ trait BackReferenceContract {
 
     assertThatJson(response)
       .whenIgnoringPaths("methodResponses[0][1].state")
+      .withOptions(new Options(Option.IGNORING_ARRAY_ORDER))
       .isEqualTo(
       s"""{
          |    "sessionState": "${SESSION_STATE.value}",
@@ -257,7 +263,8 @@ trait BackReferenceContract {
          |                    {"id": "2"},
          |                    {"id": "3"},
          |                    {"id": "4"},
-         |                    {"id": "6"}
+         |                    {"id": "6"},
+         |                    {"id": "7"}
          |                ],
          |                "notFound": []
          |            },
@@ -314,6 +321,7 @@ trait BackReferenceContract {
 
     assertThatJson(response)
       .whenIgnoringPaths("methodResponses[0][1].state")
+      .withOptions(new Options(Option.IGNORING_ARRAY_ORDER))
       .isEqualTo(
       s"""{
          |    "sessionState": "${SESSION_STATE.value}",
@@ -328,7 +336,8 @@ trait BackReferenceContract {
          |                    {"id": "2"},
          |                    {"id": "3"},
          |                    {"id": "4"},
-         |                    {"id": "6"}
+         |                    {"id": "6"},
+         |                    {"id": "7"}
          |                ],
          |                "notFound": []
          |            },
@@ -385,6 +394,7 @@ trait BackReferenceContract {
 
     assertThatJson(response)
       .whenIgnoringPaths("methodResponses[0][1].state")
+      .withOptions(new Options(Option.IGNORING_ARRAY_ORDER))
       .isEqualTo(
       s"""{
          |    "sessionState": "${SESSION_STATE.value}",
@@ -399,7 +409,8 @@ trait BackReferenceContract {
          |                    {"id": "2"},
          |                    {"id": "3"},
          |                    {"id": "4"},
-         |                    {"id": "6"}
+         |                    {"id": "6"},
+         |                    {"id": "7"}
          |                ],
          |                "notFound": []
          |            },
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/MailboxGetMethodContract.scala b/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/MailboxGetMethodContract.scala
index ef5d40489c..3710669720 100644
--- a/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/MailboxGetMethodContract.scala
+++ b/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/MailboxGetMethodContract.scala
@@ -752,7 +752,7 @@ trait MailboxGetMethodContract {
       .post
     .`then`
       .statusCode(SC_OK)
-      .body(s"$ARGUMENTS.list", hasSize(7))
+      .body(s"$ARGUMENTS.list", hasSize(expectedList.size))
       .body(s"$ARGUMENTS.list.name", hasItems(expectedList.toArray:_*))
   }
 
@@ -769,7 +769,7 @@ trait MailboxGetMethodContract {
       .post
     .`then`
       .statusCode(SC_OK)
-      .body(s"$ARGUMENTS.list", hasSize(6))
+      .body(s"$ARGUMENTS.list", hasSize(DefaultMailboxes.DEFAULT_MAILBOXES.size()))
       .body(s"$ARGUMENTS.list.name", hasItems(DefaultMailboxes.DEFAULT_MAILBOXES.toArray:_*))
       .body(s"$ARGUMENTS.list.name", not(hasItem(andreMailbox)))
   }
@@ -912,7 +912,7 @@ trait MailboxGetMethodContract {
     .`then`
       .statusCode(SC_OK)
       // Only system mailboxes are included
-      .body(s"$ARGUMENTS.list", hasSize(6))
+      .body(s"$ARGUMENTS.list", hasSize(DefaultMailboxes.DEFAULT_MAILBOXES.size()))
   }
 
   @Test
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/ProvisioningContract.scala b/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/ProvisioningContract.scala
index 84d3cb7901..baa67e2bb3 100644
--- a/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/ProvisioningContract.scala
+++ b/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/ProvisioningContract.scala
@@ -77,7 +77,7 @@ trait ProvisioningContract {
       .post
     .`then`
       .statusCode(SC_OK)
-      .body(s"$ARGUMENTS.list", hasSize(6))
+      .body(s"$ARGUMENTS.list", hasSize(DefaultMailboxes.DEFAULT_MAILBOXES.size()))
       .body(s"$ARGUMENTS.list.name", hasItems(DefaultMailboxes.DEFAULT_MAILBOXES.toArray:_*))
   }
 }
diff --git a/server/protocols/protocols-imap4/src/main/java/org/apache/james/imapserver/netty/IMAPServer.java b/server/protocols/protocols-imap4/src/main/java/org/apache/james/imapserver/netty/IMAPServer.java
index 0ce7dd543e..5ded55125b 100644
--- a/server/protocols/protocols-imap4/src/main/java/org/apache/james/imapserver/netty/IMAPServer.java
+++ b/server/protocols/protocols-imap4/src/main/java/org/apache/james/imapserver/netty/IMAPServer.java
@@ -202,6 +202,7 @@ public class IMAPServer extends AbstractConfigurableAsyncServer implements ImapC
                 .appendLimit(Optional.of(parseLiteralSizeLimit(configuration)).filter(i -> i > 0))
                 .maxQueueSize(configuration.getInteger("maxQueueSize", ImapConfiguration.DEFAULT_QUEUE_SIZE))
                 .concurrentRequests(configuration.getInteger("concurrentRequests", ImapConfiguration.DEFAULT_CONCURRENT_REQUESTS))
+                .isProvisionDefaultMailboxes(configuration.getBoolean("provisionDefaultMailboxes", ImapConfiguration.DEFAULT_PROVISION_DEFAULT_MAILBOXES))
                 .withCustomProperties(configuration.getProperties("customProperties"))
                 .build();
     }
diff --git a/server/protocols/protocols-imap4/src/test/java/org/apache/james/imapserver/netty/IMAPServerConfigurationTest.java b/server/protocols/protocols-imap4/src/test/java/org/apache/james/imapserver/netty/IMAPServerConfigurationTest.java
index 4a73081d1d..dfed5e559d 100644
--- a/server/protocols/protocols-imap4/src/test/java/org/apache/james/imapserver/netty/IMAPServerConfigurationTest.java
+++ b/server/protocols/protocols-imap4/src/test/java/org/apache/james/imapserver/netty/IMAPServerConfigurationTest.java
@@ -43,6 +43,7 @@ class IMAPServerConfigurationTest {
                 .idleTimeIntervalUnit(ImapConfiguration.DEFAULT_HEARTBEAT_INTERVAL_UNIT)
                 .maxQueueSize(ImapConfiguration.DEFAULT_QUEUE_SIZE)
                 .concurrentRequests(ImapConfiguration.DEFAULT_CONCURRENT_REQUESTS)
+                .isProvisionDefaultMailboxes(ImapConfiguration.DEFAULT_PROVISION_DEFAULT_MAILBOXES)
                 .disabledCaps(ImmutableSet.<String>of())
                 .build();
 
@@ -58,6 +59,7 @@ class IMAPServerConfigurationTest {
         configurationBuilder.addProperty("concurrentRequests", "42");
         configurationBuilder.addProperty("idleTimeIntervalUnit", "MINUTES");
         configurationBuilder.addProperty("disabledCaps", "ACL | MOVE");
+        configurationBuilder.addProperty("provisionDefaultMailboxes", "false");
         configurationBuilder.addProperty("customProperties", "abc=def");
         configurationBuilder.addProperty("customProperties", "ghi=jkl");
         ImapConfiguration imapConfiguration = IMAPServer.getImapConfiguration(configurationBuilder);
@@ -72,6 +74,7 @@ class IMAPServerConfigurationTest {
                 .disabledCaps(ImmutableSet.of("ACL", "MOVE"))
                 .maxQueueSize(12)
                 .concurrentRequests(42)
+                .isProvisionDefaultMailboxes(false)
                 .withCustomProperties(customProperties)
                 .build();
 


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