You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@james.apache.org by bt...@apache.org on 2022/12/12 06:14:31 UTC

[james-project] branch master updated: JAMES-3867 Make IMAP modular (#1343)

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

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


The following commit(s) were added to refs/heads/master by this push:
     new 7ec02b7ccc JAMES-3867 Make IMAP modular (#1343)
7ec02b7ccc is described below

commit 7ec02b7ccc9ba5819475ac4e2dd598d4148da184
Author: vttran <vt...@linagora.com>
AuthorDate: Mon Dec 12 13:14:27 2022 +0700

    JAMES-3867 Make IMAP modular (#1343)
---
 examples/custom-imap/README.md                     |  59 ++++
 examples/custom-imap/docker-compose.yml            |  15 +
 examples/custom-imap/pom.xml                       | 111 +++++++
 .../sample-configuration/imapserver.xml            |  39 +++
 examples/custom-imap/sample-configuration/keystore | Bin 0 -> 2711 bytes
 .../james/examples/imap/PingCommandParser.java     |  23 +-
 .../james/examples/imap/PingImapPackages.java      |  47 +--
 .../apache/james/examples/imap/PingProcessor.java  |  32 +-
 .../james/examples/imap/PingResponseEncoder.java   |  29 +-
 .../custom-imap/src/main/resources/imapserver.xml  |  52 ++++
 .../examples/imap/ImapCustomPackagesTest.java      |  70 +++++
 .../custom-imap/src/test/resources/dnsservice.xml  |  25 ++
 .../custom-imap/src/test/resources/domainlist.xml  |  24 ++
 examples/custom-imap/src/test/resources/keystore   | Bin 0 -> 2245 bytes
 .../custom-imap/src/test/resources/listeners.xml   |  22 ++
 .../custom-imap/src/test/resources/lmtpserver.xml  |  45 +++
 .../src/test/resources/mailetcontainer.xml         | 155 ++++++++++
 .../src/test/resources/mailrepositorystore.xml     |  28 ++
 .../src/test/resources/managesieveserver.xml       |  66 ++++
 .../custom-imap/src/test/resources/pop3server.xml  |  43 +++
 .../custom-imap/src/test/resources/smtpserver.xml  | 108 +++++++
 .../src/test/resources/usersrepository.xml         |  28 ++
 examples/pom.xml                                   |   2 +
 .../imap/api/process/DefaultMailboxTyper.java      |   6 +
 .../imap/decode/parser/AppendCommandParser.java    |   2 +
 .../decode/parser/AuthenticateCommandParser.java   |   3 +
 .../decode/parser/CapabilityCommandParser.java     |   4 +
 .../imap/decode/parser/CheckCommandParser.java     |   3 +
 .../imap/decode/parser/CloseCommandParser.java     |   6 +-
 .../imap/decode/parser/CompressCommandParser.java  |   4 +
 .../imap/decode/parser/CopyCommandParser.java      |   4 +
 .../imap/decode/parser/CreateCommandParser.java    |   3 +
 .../imap/decode/parser/DeleteACLCommandParser.java |   3 +
 .../imap/decode/parser/DeleteCommandParser.java    |   3 +
 .../imap/decode/parser/EnableCommandParser.java    |   5 +-
 .../imap/decode/parser/ExamineCommandParser.java   |   3 +
 .../imap/decode/parser/ExpungeCommandParser.java   |   3 +
 .../imap/decode/parser/FetchCommandParser.java     |   3 +
 .../imap/decode/parser/GetACLCommandParser.java    |   3 +
 .../decode/parser/GetMetadataCommandParser.java    |   3 +
 .../imap/decode/parser/GetQuotaCommandParser.java  |   4 +
 .../decode/parser/GetQuotaRootCommandParser.java   |   3 +
 .../james/imap/decode/parser/IDCommandParser.java  |   4 +
 .../imap/decode/parser/IdleCommandParser.java      |   3 +
 .../imap/decode/parser/ImapParserFactory.java      |   4 +
 .../imap/decode/parser/ListCommandParser.java      |   3 +
 .../decode/parser/ListRightsCommandParser.java     |   4 +
 .../imap/decode/parser/LoginCommandParser.java     |   4 +
 .../imap/decode/parser/LogoutCommandParser.java    |   4 +
 .../imap/decode/parser/LsubCommandParser.java      |   4 +
 .../imap/decode/parser/MoveCommandParser.java      |   4 +
 .../imap/decode/parser/MyRightsCommandParser.java  |   3 +
 .../imap/decode/parser/NamespaceCommandParser.java |   4 +
 .../imap/decode/parser/NoopCommandParser.java      |   4 +
 .../imap/decode/parser/RenameCommandParser.java    |   4 +
 .../imap/decode/parser/SearchCommandParser.java    |   3 +
 .../imap/decode/parser/SelectCommandParser.java    |   4 +
 .../imap/decode/parser/SetACLCommandParser.java    |   4 +
 .../decode/parser/SetAnnotationCommandParser.java  |   4 +
 .../imap/decode/parser/SetQuotaCommandParser.java  |   4 +
 .../imap/decode/parser/StartTLSCommandParser.java  |   4 +
 .../imap/decode/parser/StatusCommandParser.java    |   3 +
 .../imap/decode/parser/StoreCommandParser.java     |   4 +-
 .../imap/decode/parser/SubscribeCommandParser.java |   4 +
 .../james/imap/decode/parser/UidCommandParser.java |   3 +
 .../imap/decode/parser/UnselectCommandParser.java  |   4 +
 .../decode/parser/UnsubscribeCommandParser.java    |   4 +
 .../imap/decode/parser/XListCommandParser.java     |   4 +
 .../imap/encode/ContinuationResponseEncoder.java   |   3 +
 .../james/imap/encode/FetchResponseEncoder.java    |   6 +
 .../james/imap/encode/StatusResponseEncoder.java   |   3 +
 .../encode/main/DefaultImapEncoderFactory.java     |   4 +-
 .../james/imap/processor/AppendProcessor.java      |   2 +
 .../imap/processor/AuthenticateProcessor.java      |   8 +
 .../james/imap/processor/CapabilityProcessor.java  |   3 +
 .../james/imap/processor/CheckProcessor.java       |   5 +-
 .../james/imap/processor/CloseProcessor.java       |   7 +-
 .../james/imap/processor/CompressProcessor.java    |   3 +
 .../apache/james/imap/processor/CopyProcessor.java |   5 +-
 .../james/imap/processor/CreateProcessor.java      |   5 +-
 .../james/imap/processor/DefaultProcessor.java     |  37 ++-
 .../james/imap/processor/DeleteACLProcessor.java   |   3 +
 .../james/imap/processor/DeleteProcessor.java      |   3 +
 .../james/imap/processor/EnableProcessor.java      |   6 +-
 .../james/imap/processor/ExamineProcessor.java     |   3 +
 .../james/imap/processor/ExpungeProcessor.java     |   3 +
 .../james/imap/processor/GetACLProcessor.java      |   5 +-
 .../james/imap/processor/GetMetadataProcessor.java |  14 +-
 .../james/imap/processor/GetQuotaProcessor.java    |   5 +-
 .../imap/processor/GetQuotaRootProcessor.java      |   5 +-
 .../apache/james/imap/processor/IdProcessor.java   |   3 +
 .../apache/james/imap/processor/IdleProcessor.java |   3 +
 .../apache/james/imap/processor/LSubProcessor.java |   5 +-
 .../apache/james/imap/processor/ListProcessor.java |   3 +
 .../james/imap/processor/ListRightsProcessor.java  |   5 +-
 .../james/imap/processor/LoginProcessor.java       |   5 +-
 .../james/imap/processor/LogoutProcessor.java      |   5 +-
 .../apache/james/imap/processor/MoveProcessor.java |   5 +-
 .../james/imap/processor/MyRightsProcessor.java    |   3 +
 .../james/imap/processor/NamespaceProcessor.java   |   5 +-
 .../apache/james/imap/processor/NoopProcessor.java |   4 +
 .../james/imap/processor/RenameProcessor.java      |   5 +-
 .../james/imap/processor/SearchProcessor.java      |   6 +-
 .../james/imap/processor/SelectProcessor.java      |   3 +
 .../james/imap/processor/SetACLProcessor.java      |   5 +-
 .../james/imap/processor/SetMetadataProcessor.java |  15 +-
 .../james/imap/processor/SetQuotaProcessor.java    |   5 +-
 .../james/imap/processor/StartTLSProcessor.java    |   3 +
 .../james/imap/processor/StatusProcessor.java      |   4 +-
 .../james/imap/processor/StoreProcessor.java       |   6 +-
 .../james/imap/processor/SubscribeProcessor.java   |   5 +-
 .../imap/processor/SystemMessageProcessor.java     |   3 +
 .../james/imap/processor/UnselectProcessor.java    |   5 +-
 .../james/imap/processor/UnsubscribeProcessor.java |   5 +-
 .../james/imap/processor/XListProcessor.java       |   8 +
 .../imap/processor/base/AbstractProcessor.java     |  10 +-
 .../james/imap/processor/fetch/FetchProcessor.java |   3 +
 .../imap/processor/GetAnnotationProcessorTest.java |   2 +
 .../imap/processor/SetMetadataProcessorTest.java   |   2 +
 .../org/apache/james/TemporaryJamesServer.java     | 106 +++++++
 server/container/guice/protocols/imap/pom.xml      |   4 +
 .../modules/protocols/DefaultImapPackage.java      |  29 +-
 .../james/modules/protocols/IMAPServerModule.java  | 155 ++++++++--
 .../james/modules/protocols/ImapPackage.java       | 335 +++++++++++++++++++++
 124 files changed, 1940 insertions(+), 157 deletions(-)

diff --git a/examples/custom-imap/README.md b/examples/custom-imap/README.md
new file mode 100644
index 0000000000..1ca468c25c
--- /dev/null
+++ b/examples/custom-imap/README.md
@@ -0,0 +1,59 @@
+# Creating your own IMAP commands
+
+James allows defining your own handler packages (logical union).
+To do that you need to define `imapPackages` in `imapserver.xml` configuration file.
+
+Eg:
+
+```xml
+<imapPackages>org.apache.james.modules.protocols.DefaultImapPackage</imapPackages>
+<imapPackages>org.apache.james.examples.imap.PingImapPackages</imapPackages>
+```
+Sample configure file: [imapserver.xml](./sample-configuration/imapserver.xml)
+
+Note that when `imapPackages` is not provided, James will implicit use
+`org.apache.James.modules.protocols.DefaultImapPackage`
+
+## Running the example
+
+Build the project:
+
+```
+mvn clean install
+```
+
+Drop the jar with dependencies in the James `extensions-jars` folder.
+
+Then start James.
+
+## Running the example with docker compose
+
+Compile:
+
+```
+mvn clean install
+```
+
+Then start James:
+
+```
+docker-compose up
+```
+
+Test with imap package: `org.apache.james.examples.imap.PingImapPackages`
+
+Command example:
+```bash
+telnet localhost 143
+Trying 127.0.0.1...
+Connected to localhost.
+Escape character is '^]'.
+* OK JAMES IMAP4rev1 Server james.local is ready.
+a01 LOGIN bob secret
+a01 NO LOGIN failed. Invalid login/password.
+a02 LOGIN bob@localhost secret
+a02 OK LOGIN completed.
+A03 PING
+* PONG
+A03 OK PING completed.
+```
diff --git a/examples/custom-imap/docker-compose.yml b/examples/custom-imap/docker-compose.yml
new file mode 100644
index 0000000000..ac56ec29aa
--- /dev/null
+++ b/examples/custom-imap/docker-compose.yml
@@ -0,0 +1,15 @@
+version: '3'
+
+services:
+
+  james:
+    image: apache/james:memory-latest
+    container_name: james
+    hostname: james.local
+    volumes:
+      - ./target/custom-imap-3.8.0-SNAPSHOT-jar-with-dependencies.jar:/root/extensions-jars/custom-imap-3.8.0-SNAPSHOT-jar-with-dependencies.jar
+      - ./sample-configuration/keystore:/root/conf/keystore
+      - ./sample-configuration/imapserver.xml:/root/conf/imapserver.xml
+    ports:
+      - "143:143"
+      - "8000:8000"
diff --git a/examples/custom-imap/pom.xml b/examples/custom-imap/pom.xml
new file mode 100644
index 0000000000..39ce1ed0d5
--- /dev/null
+++ b/examples/custom-imap/pom.xml
@@ -0,0 +1,111 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+    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.
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.apache.james.examples</groupId>
+        <artifactId>examples</artifactId>
+        <version>3.8.0-SNAPSHOT</version>
+    </parent>
+
+    <artifactId>custom-imap</artifactId>
+    <name>Apache James :: Examples :: Custom IMAP</name>
+    <description>Example of how to extend James existing IMAP implementation by adding your own commands</description>
+
+    <dependencies>
+        <dependency>
+            <groupId>${james.groupId}</groupId>
+            <artifactId>james-server-guice-imap</artifactId>
+            <version>${james.baseVersion}</version>
+        </dependency>
+        <dependency>
+            <groupId>${james.groupId}</groupId>
+            <artifactId>james-server-guice-common</artifactId>
+            <type>test-jar</type>
+            <version>${james.baseVersion}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>${james.groupId}</groupId>
+            <artifactId>james-server-memory-app</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>${james.groupId}</groupId>
+            <artifactId>testing-base</artifactId>
+            <version>${james.baseVersion}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>${james.groupId}</groupId>
+            <artifactId>james-server-testing</artifactId>
+            <version>${james.baseVersion}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>${james.protocols.groupId}</groupId>
+            <artifactId>protocols-imap</artifactId>
+            <version>${james.baseVersion}</version>
+        </dependency>
+        <dependency>
+            <groupId>com.google.inject</groupId>
+            <artifactId>guice</artifactId>
+            <version>5.1.0</version>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <configuration>
+                    <source>11</source>
+                    <target>11</target>
+                </configuration>
+            </plugin>
+            <plugin>
+                <artifactId>maven-assembly-plugin</artifactId>
+                <configuration>
+                    <archive>
+                        <manifest>
+                            <mainClass>fully.qualified.MainClass</mainClass>
+                        </manifest>
+                    </archive>
+                    <descriptorRefs>
+                        <descriptorRef>jar-with-dependencies</descriptorRef>
+                    </descriptorRefs>
+                </configuration>
+                <executions>
+                    <execution>
+                        <id>make-assembly</id>
+                        <phase>package</phase>
+                        <goals>
+                            <goal>single</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+</project>
\ No newline at end of file
diff --git a/examples/custom-imap/sample-configuration/imapserver.xml b/examples/custom-imap/sample-configuration/imapserver.xml
new file mode 100644
index 0000000000..1156e5b3c8
--- /dev/null
+++ b/examples/custom-imap/sample-configuration/imapserver.xml
@@ -0,0 +1,39 @@
+<?xml version="1.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.
+-->
+
+<imapservers>
+    <imapserver enabled="true">
+        <jmxName>imapserver</jmxName>
+        <bind>0.0.0.0:143</bind>
+        <connectionBacklog>200</connectionBacklog>
+        <tls socketTLS="false" startTLS="false">
+            <keystore>file://conf/keystore</keystore>
+            <secret>james72laBalle</secret>
+            <provider>org.bouncycastle.jce.provider.BouncyCastleProvider</provider>
+        </tls>
+        <connectionLimit>0</connectionLimit>
+        <connectionLimitPerIP>0</connectionLimitPerIP>
+        <plainAuthDisallowed>false</plainAuthDisallowed>
+        <gracefulShutdown>false</gracefulShutdown>
+    </imapserver>
+    <imapPackages>org.apache.james.modules.protocols.DefaultImapPackage</imapPackages>
+    <imapPackages>org.apache.james.examples.imap.PingImapPackages</imapPackages>
+</imapservers>
\ No newline at end of file
diff --git a/examples/custom-imap/sample-configuration/keystore b/examples/custom-imap/sample-configuration/keystore
new file mode 100644
index 0000000000..361cd01f43
Binary files /dev/null and b/examples/custom-imap/sample-configuration/keystore differ
diff --git a/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/IdleCommandParser.java b/examples/custom-imap/src/main/java/org/apache/james/examples/imap/PingCommandParser.java
similarity index 80%
copy from protocols/imap/src/main/java/org/apache/james/imap/decode/parser/IdleCommandParser.java
copy to examples/custom-imap/src/main/java/org/apache/james/examples/imap/PingCommandParser.java
index a0f1c0d5bc..1e7dd563a6 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/IdleCommandParser.java
+++ b/examples/custom-imap/src/main/java/org/apache/james/examples/imap/PingCommandParser.java
@@ -16,9 +16,11 @@
  * specific language governing permissions and limitations      *
  * under the License.                                           *
  ****************************************************************/
-package org.apache.james.imap.decode.parser;
 
-import org.apache.james.imap.api.ImapConstants;
+package org.apache.james.examples.imap;
+
+import javax.inject.Inject;
+
 import org.apache.james.imap.api.ImapMessage;
 import org.apache.james.imap.api.Tag;
 import org.apache.james.imap.api.message.response.StatusResponseFactory;
@@ -26,21 +28,16 @@ import org.apache.james.imap.api.process.ImapSession;
 import org.apache.james.imap.decode.DecodingException;
 import org.apache.james.imap.decode.ImapRequestLineReader;
 import org.apache.james.imap.decode.base.AbstractImapCommandParser;
-import org.apache.james.imap.message.request.IdleRequest;
 
-/**
- * Parses IDLE commands
- */
-public class IdleCommandParser extends AbstractImapCommandParser {
-
-    public IdleCommandParser(StatusResponseFactory statusResponseFactory) {
-        super(ImapConstants.IDLE_COMMAND, statusResponseFactory);
+public class PingCommandParser extends AbstractImapCommandParser {
+    @Inject
+    public PingCommandParser(StatusResponseFactory statusResponseFactory) {
+        super(PingImapPackages.PING_COMMAND, statusResponseFactory);
     }
 
     @Override
     protected ImapMessage decode(ImapRequestLineReader request, Tag tag, ImapSession session) throws DecodingException {
         request.eol();
-        return new IdleRequest(tag);
+        return new PingImapPackages.PingRequest(tag);
     }
-
-}
+}
\ No newline at end of file
diff --git a/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/GetQuotaRootCommandParser.java b/examples/custom-imap/src/main/java/org/apache/james/examples/imap/PingImapPackages.java
similarity index 53%
copy from protocols/imap/src/main/java/org/apache/james/imap/decode/parser/GetQuotaRootCommandParser.java
copy to examples/custom-imap/src/main/java/org/apache/james/examples/imap/PingImapPackages.java
index 533b13d55b..1ddb5a6b64 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/GetQuotaRootCommandParser.java
+++ b/examples/custom-imap/src/main/java/org/apache/james/examples/imap/PingImapPackages.java
@@ -17,32 +17,35 @@
  * under the License.                                           *
  ****************************************************************/
 
-package org.apache.james.imap.decode.parser;
+package org.apache.james.examples.imap;
 
-import org.apache.james.imap.api.ImapConstants;
-import org.apache.james.imap.api.ImapMessage;
+import javax.inject.Inject;
+
+import org.apache.james.imap.api.ImapCommand;
 import org.apache.james.imap.api.Tag;
-import org.apache.james.imap.api.message.response.StatusResponseFactory;
-import org.apache.james.imap.api.process.ImapSession;
-import org.apache.james.imap.decode.DecodingException;
-import org.apache.james.imap.decode.ImapRequestLineReader;
-import org.apache.james.imap.decode.base.AbstractImapCommandParser;
-import org.apache.james.imap.message.request.GetQuotaRootRequest;
-
-/**
- * Get Quota root command parser
- */
-public class GetQuotaRootCommandParser extends AbstractImapCommandParser {
-
-    public GetQuotaRootCommandParser(StatusResponseFactory statusResponseFactory) {
-        super(ImapConstants.GETQUOTAROOT_COMMAND, statusResponseFactory);
+import org.apache.james.imap.api.message.response.ImapResponseMessage;
+import org.apache.james.imap.message.request.AbstractImapRequest;
+import org.apache.james.modules.protocols.ImapPackage;
+import org.apache.james.utils.ClassName;
+
+import com.google.common.collect.ImmutableList;
+
+public class PingImapPackages extends ImapPackage.Impl {
+    public static class PingRequest extends AbstractImapRequest {
+        public PingRequest(Tag tag) {
+            super(tag, PING_COMMAND);
+        }
     }
 
-    @Override
-    protected ImapMessage decode(ImapRequestLineReader request, Tag tag, ImapSession session) throws DecodingException {
-        final String mailboxName = request.mailbox();
-        request.eol();
-        return new GetQuotaRootRequest(tag, mailboxName);
+    public static class PingResponse implements ImapResponseMessage {
     }
 
+    public static ImapCommand PING_COMMAND = ImapCommand.anyStateCommand("PING");
+
+    @Inject
+    public PingImapPackages() {
+        super(ImmutableList.of(new ClassName(PingProcessor.class.getCanonicalName())),
+            ImmutableList.of(new ClassName(PingCommandParser.class.getCanonicalName())),
+            ImmutableList.of(new ClassName(PingResponseEncoder.class.getCanonicalName())));
+    }
 }
diff --git a/protocols/imap/src/main/java/org/apache/james/imap/processor/CheckProcessor.java b/examples/custom-imap/src/main/java/org/apache/james/examples/imap/PingProcessor.java
similarity index 60%
copy from protocols/imap/src/main/java/org/apache/james/imap/processor/CheckProcessor.java
copy to examples/custom-imap/src/main/java/org/apache/james/examples/imap/PingProcessor.java
index cfe311e5e8..a308295870 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/processor/CheckProcessor.java
+++ b/examples/custom-imap/src/main/java/org/apache/james/examples/imap/PingProcessor.java
@@ -17,33 +17,37 @@
  * under the License.                                           *
  ****************************************************************/
 
-package org.apache.james.imap.processor;
+package org.apache.james.examples.imap;
 
+import javax.inject.Inject;
+
+import org.apache.james.imap.api.display.HumanReadableText;
 import org.apache.james.imap.api.message.response.StatusResponseFactory;
 import org.apache.james.imap.api.process.ImapSession;
-import org.apache.james.imap.message.request.CheckRequest;
-import org.apache.james.mailbox.MailboxManager;
-import org.apache.james.metrics.api.MetricFactory;
+import org.apache.james.imap.processor.base.AbstractProcessor;
 import org.apache.james.util.MDCBuilder;
 
 import reactor.core.publisher.Mono;
 
-public class CheckProcessor extends AbstractMailboxProcessor<CheckRequest> {
+public class PingProcessor extends AbstractProcessor<PingImapPackages.PingRequest> {
+
+    private final StatusResponseFactory factory;
 
-    public CheckProcessor(MailboxManager mailboxManager, StatusResponseFactory factory,
-            MetricFactory metricFactory) {
-        super(CheckRequest.class, mailboxManager, factory, metricFactory);
+    @Inject
+    public PingProcessor(StatusResponseFactory factory) {
+        super(PingImapPackages.PingRequest.class);
+        this.factory = factory;
     }
 
     @Override
-    protected Mono<Void> processRequestReactive(CheckRequest request, ImapSession session, Responder responder) {
-        return unsolicitedResponses(session, responder, false)
-            .then(Mono.fromRunnable(() -> okComplete(request, responder)));
+    protected Mono<Void> doProcess(PingImapPackages.PingRequest request, Responder responder, ImapSession session) {
+        return Mono.fromRunnable(() -> responder.respond(new PingImapPackages.PingResponse()))
+            .then(Mono.fromRunnable(() -> responder.respond(factory.taggedOk(request.getTag(), request.getCommand(), HumanReadableText.COMPLETED))));
     }
 
     @Override
-    protected MDCBuilder mdc(CheckRequest request) {
+    protected MDCBuilder mdc(PingImapPackages.PingRequest message) {
         return MDCBuilder.create()
-            .addToContext(MDCBuilder.ACTION, "CHECK");
+            .addToContext(MDCBuilder.ACTION, "PING");
     }
-}
+}
\ No newline at end of file
diff --git a/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/LsubCommandParser.java b/examples/custom-imap/src/main/java/org/apache/james/examples/imap/PingResponseEncoder.java
similarity index 63%
copy from protocols/imap/src/main/java/org/apache/james/imap/decode/parser/LsubCommandParser.java
copy to examples/custom-imap/src/main/java/org/apache/james/examples/imap/PingResponseEncoder.java
index 3d1d4ef785..31d7120cd0 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/LsubCommandParser.java
+++ b/examples/custom-imap/src/main/java/org/apache/james/examples/imap/PingResponseEncoder.java
@@ -16,24 +16,25 @@
  * specific language governing permissions and limitations      *
  * under the License.                                           *
  ****************************************************************/
-package org.apache.james.imap.decode.parser;
 
-import org.apache.james.imap.api.ImapConstants;
-import org.apache.james.imap.api.ImapMessage;
-import org.apache.james.imap.api.Tag;
-import org.apache.james.imap.api.message.response.StatusResponseFactory;
-import org.apache.james.imap.message.request.LsubRequest;
+package org.apache.james.examples.imap;
 
-/**
- * Parse LSUB commands
- */
-public class LsubCommandParser extends ListCommandParser {
-    public LsubCommandParser(StatusResponseFactory statusResponseFactory) {
-        super(ImapConstants.LSUB_COMMAND, statusResponseFactory);
+import java.io.IOException;
+
+import org.apache.james.imap.encode.ImapResponseComposer;
+import org.apache.james.imap.encode.ImapResponseEncoder;
+
+public class PingResponseEncoder implements ImapResponseEncoder<PingImapPackages.PingResponse> {
+
+    @Override
+    public Class<PingImapPackages.PingResponse> acceptableMessages() {
+        return PingImapPackages.PingResponse.class;
     }
 
     @Override
-    protected ImapMessage createMessage(String referenceName, String mailboxPattern, Tag tag) {
-        return new LsubRequest(referenceName, mailboxPattern, tag);
+    public void encode(PingImapPackages.PingResponse message, ImapResponseComposer composer) throws IOException {
+        composer.untagged();
+        composer.message("PONG");
+        composer.end();
     }
 }
diff --git a/examples/custom-imap/src/main/resources/imapserver.xml b/examples/custom-imap/src/main/resources/imapserver.xml
new file mode 100644
index 0000000000..c9eff82382
--- /dev/null
+++ b/examples/custom-imap/src/main/resources/imapserver.xml
@@ -0,0 +1,52 @@
+<?xml version="1.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.
+-->
+
+<imapservers>
+    <imapserver enabled="true">
+        <jmxName>imapserver</jmxName>
+        <bind>0.0.0.0:0</bind>
+        <connectionBacklog>200</connectionBacklog>
+        <tls socketTLS="false" startTLS="false">
+            <keystore>classpath://keystore</keystore>
+            <secret>james72laBalle</secret>
+            <provider>org.bouncycastle.jce.provider.BouncyCastleProvider</provider>
+        </tls>
+        <connectionLimit>0</connectionLimit>
+        <connectionLimitPerIP>0</connectionLimitPerIP>
+        <plainAuthDisallowed>false</plainAuthDisallowed>
+        <gracefulShutdown>false</gracefulShutdown>
+    </imapserver>
+    <imapserver enabled="true">
+        <jmxName>imapserver-ssl</jmxName>
+        <bind>0.0.0.0:0</bind>
+        <connectionBacklog>200</connectionBacklog>
+        <tls socketTLS="false" startTLS="true">
+            <keystore>classpath://keystore</keystore>
+            <secret>james72laBalle</secret>
+            <provider>org.bouncycastle.jce.provider.BouncyCastleProvider</provider>
+        </tls>
+        <connectionLimit>0</connectionLimit>
+        <connectionLimitPerIP>0</connectionLimitPerIP>
+        <gracefulShutdown>false</gracefulShutdown>
+    </imapserver>
+    <imapPackages>org.apache.james.modules.protocols.DefaultImapPackage</imapPackages>
+    <imapPackages>org.apache.james.examples.imap.PingImapPackages</imapPackages>
+</imapservers>
\ No newline at end of file
diff --git a/examples/custom-imap/src/test/java/org/apache/james/examples/imap/ImapCustomPackagesTest.java b/examples/custom-imap/src/test/java/org/apache/james/examples/imap/ImapCustomPackagesTest.java
new file mode 100644
index 0000000000..cc50e91782
--- /dev/null
+++ b/examples/custom-imap/src/test/java/org/apache/james/examples/imap/ImapCustomPackagesTest.java
@@ -0,0 +1,70 @@
+/****************************************************************
+ * 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.examples.imap;
+
+import static org.apache.james.data.UsersRepositoryModuleChooser.Implementation.DEFAULT;
+import static org.apache.james.jmap.JMAPTestingConstants.BOB;
+import static org.apache.james.jmap.JMAPTestingConstants.BOB_PASSWORD;
+import static org.apache.james.jmap.JMAPTestingConstants.DOMAIN;
+import static org.assertj.core.api.Assertions.assertThat;
+
+import java.io.IOException;
+
+import org.apache.james.GuiceJamesServer;
+import org.apache.james.JamesServerBuilder;
+import org.apache.james.JamesServerExtension;
+import org.apache.james.MemoryJamesConfiguration;
+import org.apache.james.MemoryJamesServerMain;
+import org.apache.james.modules.protocols.ImapGuiceProbe;
+import org.apache.james.utils.DataProbeImpl;
+import org.apache.james.utils.TestIMAPClient;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.RegisterExtension;
+
+public class ImapCustomPackagesTest {
+
+    @RegisterExtension
+    static JamesServerExtension jamesServerExtension = new JamesServerBuilder<MemoryJamesConfiguration>(tmpDir ->
+        MemoryJamesConfiguration.builder()
+            .workingDirectory(tmpDir)
+            .configurationFromClasspath()
+            .usersRepository(DEFAULT)
+            .build())
+        .server(MemoryJamesServerMain::createServer)
+        .lifeCycle(JamesServerExtension.Lifecycle.PER_CLASS)
+        .build();
+
+    @BeforeEach
+    void setup(GuiceJamesServer server) throws Exception {
+        server.getProbe(DataProbeImpl.class).fluent()
+            .addDomain(DOMAIN)
+            .addUser(BOB.asString(), BOB_PASSWORD);
+    }
+
+    @Test
+    void imapServerShouldSupportModularWhenProvideImapPackages(GuiceJamesServer server) throws IOException {
+        assertThat(new TestIMAPClient().connect("127.0.0.1", server.getProbe(ImapGuiceProbe.class).getImapPort())
+            .login(BOB, BOB_PASSWORD)
+            .sendCommand("PING"))
+            .contains("PONG");
+    }
+
+}
diff --git a/examples/custom-imap/src/test/resources/dnsservice.xml b/examples/custom-imap/src/test/resources/dnsservice.xml
new file mode 100644
index 0000000000..6e4fbd2efb
--- /dev/null
+++ b/examples/custom-imap/src/test/resources/dnsservice.xml
@@ -0,0 +1,25 @@
+<?xml version="1.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.                                           
+ -->
+
+<dnsservice>
+  <autodiscover>true</autodiscover>
+  <authoritative>false</authoritative>
+  <maxcachesize>50000</maxcachesize>
+</dnsservice>
diff --git a/examples/custom-imap/src/test/resources/domainlist.xml b/examples/custom-imap/src/test/resources/domainlist.xml
new file mode 100644
index 0000000000..fe17431a1e
--- /dev/null
+++ b/examples/custom-imap/src/test/resources/domainlist.xml
@@ -0,0 +1,24 @@
+<?xml version="1.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.                                           
+ -->
+
+<domainlist>
+    <autodetect>false</autodetect>
+    <autodetectIP>false</autodetectIP>
+</domainlist>
diff --git a/examples/custom-imap/src/test/resources/keystore b/examples/custom-imap/src/test/resources/keystore
new file mode 100644
index 0000000000..536a6c792b
Binary files /dev/null and b/examples/custom-imap/src/test/resources/keystore differ
diff --git a/examples/custom-imap/src/test/resources/listeners.xml b/examples/custom-imap/src/test/resources/listeners.xml
new file mode 100644
index 0000000000..ae5937f1fa
--- /dev/null
+++ b/examples/custom-imap/src/test/resources/listeners.xml
@@ -0,0 +1,22 @@
+<?xml version="1.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.                                           
+ -->
+
+<listeners>
+</listeners>
\ No newline at end of file
diff --git a/examples/custom-imap/src/test/resources/lmtpserver.xml b/examples/custom-imap/src/test/resources/lmtpserver.xml
new file mode 100644
index 0000000000..c3a2af233b
--- /dev/null
+++ b/examples/custom-imap/src/test/resources/lmtpserver.xml
@@ -0,0 +1,45 @@
+<?xml version="1.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.                                           
+ -->
+
+<lmtpservers>
+
+    <lmtpserver enabled="true">
+        <jmxName>lmtpserver</jmxName>
+        <!-- LMTP should not be reachable from outside your network so bind it to loopback-->
+        <bind>127.0.0.1:0</bind>
+        <connectionBacklog>200</connectionBacklog>
+        <connectiontimeout>1200</connectiontimeout>
+        <!-- Set the maximum simultaneous incoming connections for this service -->
+        <connectionLimit>0</connectionLimit>
+        <!-- Set the maximum simultaneous incoming connections per IP for this service -->
+        <connectionLimitPerIP>0</connectionLimitPerIP>
+        <!--  This sets the maximum allowed message size (in kilobytes) for this -->
+        <!--  LMTP service. If unspecified, the value defaults to 0, which means no limit. -->
+        <maxmessagesize>0</maxmessagesize>
+        <handlerchain coreHandlersPackage="org.apache.james.lmtpserver.MailetContainerCmdHandlerLoader">
+            <handler class="org.apache.james.lmtpserver.MailetContainerCmdHandlerLoader"/>
+            <handler class="org.apache.james.lmtpserver.MailetContainerHandler">
+                <splitExecution>true</splitExecution>
+            </handler>
+        </handlerchain>
+        <gracefulShutdown>false</gracefulShutdown>
+    </lmtpserver>
+
+</lmtpservers>
diff --git a/examples/custom-imap/src/test/resources/mailetcontainer.xml b/examples/custom-imap/src/test/resources/mailetcontainer.xml
new file mode 100644
index 0000000000..a721c7cde5
--- /dev/null
+++ b/examples/custom-imap/src/test/resources/mailetcontainer.xml
@@ -0,0 +1,155 @@
+<?xml version="1.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.
+ -->
+
+<mailetcontainer enableJmx="false">
+
+    <context>
+        <postmaster>postmaster</postmaster>
+    </context>
+
+    <spooler>
+        <threads>20</threads>
+        <errorRepository>memory://var/mail/error/</errorRepository>
+    </spooler>
+
+    <processors>
+        <processor state="root" enableJmx="false">
+            <mailet match="All" class="PostmasterAlias"/>
+            <mailet match="RelayLimit=30" class="Null"/>
+            <mailet match="All" class="ToProcessor">
+                <processor>transport</processor>
+            </mailet>
+        </processor>
+
+        <processor state="error" enableJmx="false">
+            <mailet match="All" class="Bounce">
+                <onMailetException>ignore</onMailetException>
+            </mailet>
+            <mailet match="All" class="ToRepository">
+                <repositoryPath>memory://var/mail/error/</repositoryPath>
+                <onMailetException>propagate</onMailetException>
+            </mailet>
+        </processor>
+
+
+        <processor state="transport" enableJmx="false">
+            <mailet match="SMTPAuthSuccessful" class="SetMimeHeader">
+                <name>X-UserIsAuth</name>
+                <value>true</value>
+            </mailet>
+            <mailet match="All" class="RemoveMimeHeader">
+                <name>bcc</name>
+            </mailet>
+            <mailet match="All" class="RecipientRewriteTable">
+                <errorProcessor>rrt-error</errorProcessor>
+            </mailet>
+            <mailet match="RecipientIsLocal" class="ToProcessor">
+                <processor>local-delivery</processor>
+            </mailet>
+            <mailet match="HostIsLocal" class="ToProcessor">
+                <processor>local-address-error</processor>
+                <notice>550 - Requested action not taken: no such user here</notice>
+            </mailet>
+            <mailet match="SMTPAuthSuccessful" class="SetMailAttribute">
+                <RelayAllowed>true</RelayAllowed>
+            </mailet>
+            <mailet match="SMTPIsAuthNetwork" class="SetMailAttribute">
+                <RelayAllowed>true</RelayAllowed>
+            </mailet>
+            <mailet match="SentByMailet" class="SetMailAttribute">
+                <RelayAllowed>true</RelayAllowed>
+            </mailet>
+            <mailet match="org.apache.james.jmap.mailet.SentByJmap" class="SetMailAttribute">
+                <RelayAllowed>true</RelayAllowed>
+            </mailet>
+            <mailet match="HasMailAttribute=RelayAllowed" class="RemoteDelivery">
+                <outgoingQueue>outgoing</outgoingQueue>
+                <delayTime>5000, 100000, 500000</delayTime>
+                <maxRetries>3</maxRetries>
+                <maxDnsProblemRetries>0</maxDnsProblemRetries>
+                <deliveryThreads>10</deliveryThreads>
+                <sendpartial>true</sendpartial>
+                <bounceProcessor>bounces</bounceProcessor>
+            </mailet>
+            <mailet match="All" class="ToProcessor">
+                <processor>relay-denied</processor>
+            </mailet>
+        </processor>
+
+        <processor state="local-delivery" enableJmx="true">
+            <mailet match="All" class="VacationMailet">
+                <onMailetException>ignore</onMailetException>
+            </mailet>
+            <mailet match="All" class="Sieve">
+                <onMailetException>ignore</onMailetException>
+            </mailet>
+            <mailet match="All" class="AddDeliveredToHeader"/>
+            <mailet match="All" class="org.apache.james.jmap.mailet.filter.JMAPFiltering">
+                <onMailetException>ignore</onMailetException>
+            </mailet>
+            <mailet match="All" class="LocalDelivery"/>
+        </processor>
+
+        <processor state="spam" enableJmx="false">
+            <mailet match="All" class="ToRepository">
+                <repositoryPath>memory://var/mail/spam/</repositoryPath>
+            </mailet>
+        </processor>
+
+        <processor state="local-address-error" enableJmx="false">
+            <mailet match="All" class="Bounce">
+                <attachment>none</attachment>
+            </mailet>
+            <mailet match="All" class="ToRepository">
+                <repositoryPath>memory://var/mail/address-error/</repositoryPath>
+            </mailet>
+        </processor>
+
+        <processor state="relay-denied" enableJmx="false">
+            <mailet match="All" class="Bounce">
+                <attachment>none</attachment>
+            </mailet>
+            <mailet match="All" class="ToRepository">
+                <repositoryPath>memory://var/mail/relay-denied/</repositoryPath>
+                <notice>Warning: You are sending an e-mail to a remote server. You must be authentified to perform such an operation</notice>
+            </mailet>
+        </processor>
+
+        <processor state="bounces" enableJmx="false">
+            <mailet match="All" class="DSNBounce">
+                <passThrough>false</passThrough>
+            </mailet>
+        </processor>
+
+        <processor state="rrt-error" enableJmx="false">
+            <mailet match="All" class="ToRepository">
+                <repositoryPath>memory://var/mail/rrt-error/</repositoryPath>
+                <passThrough>true</passThrough>
+            </mailet>
+            <mailet match="IsSenderInRRTLoop" class="Null"/>
+            <mailet match="All" class="Bounce"/>
+        </processor>
+
+    </processors>
+
+</mailetcontainer>
+
+
diff --git a/examples/custom-imap/src/test/resources/mailrepositorystore.xml b/examples/custom-imap/src/test/resources/mailrepositorystore.xml
new file mode 100644
index 0000000000..a607d6ccb2
--- /dev/null
+++ b/examples/custom-imap/src/test/resources/mailrepositorystore.xml
@@ -0,0 +1,28 @@
+<?xml version="1.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.
+ -->
+
+<mailrepositorystore>
+        <mailrepository class="org.apache.james.mailrepository.memory.MemoryMailRepository">
+            <protocols>
+                <protocol>memory</protocol>
+            </protocols>
+        </mailrepository>
+</mailrepositorystore>
diff --git a/examples/custom-imap/src/test/resources/managesieveserver.xml b/examples/custom-imap/src/test/resources/managesieveserver.xml
new file mode 100644
index 0000000000..b644fa4317
--- /dev/null
+++ b/examples/custom-imap/src/test/resources/managesieveserver.xml
@@ -0,0 +1,66 @@
+<?xml version="1.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.                                           
+ -->
+ 
+<!--
+   This template file can be used as example for James Server configuration
+   DO NOT USE IT AS SUCH AND ADAPT IT TO YOUR NEEDS
+-->
+ 
+<!-- See http://james.apache.org/server/3/config.html for usage -->
+
+<managesieveservers>
+
+   <managesieveserver enabled="true">
+
+     <jmxName>managesieveserver</jmxName>
+
+     <bind>0.0.0.0:0</bind>
+
+     <connectionBacklog>200</connectionBacklog>
+
+     <tls socketTLS="false" startTLS="false">
+       <!-- To create a new keystore execute:
+        keytool -genkey -alias james -keyalg RSA -keystore /path/to/james/conf/keystore
+         -->
+       <keystore>file://conf/keystore</keystore>
+       <secret>james72laBalle</secret>
+       <provider>org.bouncycastle.jce.provider.BouncyCastleProvider</provider>
+       <!-- The algorithm is optional and only needs to be specified when using something other
+        than the Sun JCE provider - You could use IbmX509 with IBM Java runtime. -->
+       <algorithm>SunX509</algorithm>
+     </tls>
+         
+        <!-- connection timeout in secconds -->
+        <connectiontimeout>360</connectiontimeout>
+
+        <!-- Set the maximum simultaneous incoming connections for this service -->
+        <connectionLimit>0</connectionLimit>
+         
+        <!-- Set the maximum simultaneous incoming connections per IP for this service -->
+        <connectionLimitPerIP>0</connectionLimitPerIP>
+        <maxmessagesize>0</maxmessagesize>
+        <addressBracketsEnforcement>true</addressBracketsEnforcement>
+        <gracefulShutdown>false</gracefulShutdown>
+  
+   </managesieveserver>
+
+</managesieveservers>
+
+
diff --git a/examples/custom-imap/src/test/resources/pop3server.xml b/examples/custom-imap/src/test/resources/pop3server.xml
new file mode 100644
index 0000000000..6e4473aae2
--- /dev/null
+++ b/examples/custom-imap/src/test/resources/pop3server.xml
@@ -0,0 +1,43 @@
+<?xml version="1.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.                                           
+ -->
+
+
+<pop3servers>
+    <pop3server enabled="true">
+        <jmxName>pop3server</jmxName>
+        <bind>0.0.0.0:0</bind>
+        <connectionBacklog>200</connectionBacklog>
+        <tls socketTLS="false" startTLS="false">
+            <!-- To create a new keystore execute:
+                  keytool -genkey -alias james -keyalg RSA -keystore /path/to/james/conf/keystore
+             -->
+            <keystore>file://conf/keystore</keystore>
+            <secret>james72laBalle</secret>
+            <provider>org.bouncycastle.jce.provider.BouncyCastleProvider</provider>
+        </tls>
+        <connectiontimeout>1200</connectiontimeout>
+        <connectionLimit>0</connectionLimit>
+        <connectionLimitPerIP>0</connectionLimitPerIP>
+        <handlerchain>
+            <handler class="org.apache.james.pop3server.core.CoreCmdHandlerLoader"/>
+        </handlerchain>
+        <gracefulShutdown>false</gracefulShutdown>
+    </pop3server>
+</pop3servers>
diff --git a/examples/custom-imap/src/test/resources/smtpserver.xml b/examples/custom-imap/src/test/resources/smtpserver.xml
new file mode 100644
index 0000000000..f981c98fd1
--- /dev/null
+++ b/examples/custom-imap/src/test/resources/smtpserver.xml
@@ -0,0 +1,108 @@
+<?xml version="1.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.
+ -->
+
+<smtpservers>
+    <smtpserver enabled="true">
+        <jmxName>smtpserver-global</jmxName>
+        <bind>0.0.0.0:0</bind>
+        <connectionBacklog>200</connectionBacklog>
+        <tls socketTLS="false" startTLS="false">
+            <keystore>file://conf/keystore</keystore>
+            <secret>james72laBalle</secret>
+            <provider>org.bouncycastle.jce.provider.BouncyCastleProvider</provider>
+            <algorithm>SunX509</algorithm>
+        </tls>
+        <connectiontimeout>360</connectiontimeout>
+        <connectionLimit>0</connectionLimit>
+        <connectionLimitPerIP>0</connectionLimitPerIP>
+        <auth>
+            <announce>never</announce>
+            <requireSSL>false</requireSSL>
+        </auth>
+        <verifyIdentity>false</verifyIdentity>
+        <maxmessagesize>0</maxmessagesize>
+        <addressBracketsEnforcement>true</addressBracketsEnforcement>
+        <smtpGreeting>Apache JAMES awesome SMTP Server</smtpGreeting>
+        <handlerchain>
+            <handler class="org.apache.james.smtpserver.fastfail.ValidRcptHandler"/>
+            <handler class="org.apache.james.smtpserver.CoreCmdHandlerLoader"/>
+        </handlerchain>
+        <gracefulShutdown>false</gracefulShutdown>
+    </smtpserver>
+    <smtpserver enabled="true">
+        <jmxName>smtpserver-TLS</jmxName>
+        <bind>0.0.0.0:0</bind>
+        <connectionBacklog>200</connectionBacklog>
+        <tls socketTLS="false" startTLS="false">
+            <keystore>file://conf/keystore</keystore>
+            <secret>james72laBalle</secret>
+            <provider>org.bouncycastle.jce.provider.BouncyCastleProvider</provider>
+            <algorithm>SunX509</algorithm>
+        </tls>
+        <connectiontimeout>360</connectiontimeout>
+        <connectionLimit>0</connectionLimit>
+        <connectionLimitPerIP>0</connectionLimitPerIP>
+        <auth>
+            <announce>forUnauthorizedAddresses</announce>
+            <requireSSL>false</requireSSL>
+        </auth>
+        <!-- Trust authenticated users -->
+        <verifyIdentity>false</verifyIdentity>
+        <maxmessagesize>0</maxmessagesize>
+        <addressBracketsEnforcement>true</addressBracketsEnforcement>
+        <smtpGreeting>Apache JAMES awesome SMTP Server</smtpGreeting>
+        <handlerchain>
+            <handler class="org.apache.james.smtpserver.fastfail.ValidRcptHandler"/>
+            <handler class="org.apache.james.smtpserver.CoreCmdHandlerLoader"/>
+        </handlerchain>
+        <gracefulShutdown>false</gracefulShutdown>
+    </smtpserver>
+    <smtpserver enabled="true">
+        <jmxName>smtpserver-authenticated</jmxName>
+        <bind>0.0.0.0:0</bind>
+        <connectionBacklog>200</connectionBacklog>
+        <tls socketTLS="false" startTLS="false">
+            <keystore>file://conf/keystore</keystore>
+            <secret>james72laBalle</secret>
+            <provider>org.bouncycastle.jce.provider.BouncyCastleProvider</provider>
+            <algorithm>SunX509</algorithm>
+        </tls>
+        <connectiontimeout>360</connectiontimeout>
+        <connectionLimit>0</connectionLimit>
+        <connectionLimitPerIP>0</connectionLimitPerIP>
+        <auth>
+            <announce>forUnauthorizedAddresses</announce>
+            <requireSSL>false</requireSSL>
+        </auth>
+        <!-- Trust authenticated users -->
+        <verifyIdentity>false</verifyIdentity>
+        <maxmessagesize>0</maxmessagesize>
+        <addressBracketsEnforcement>true</addressBracketsEnforcement>
+        <smtpGreeting>Apache JAMES awesome SMTP Server</smtpGreeting>
+        <handlerchain>
+            <handler class="org.apache.james.smtpserver.fastfail.ValidRcptHandler"/>
+            <handler class="org.apache.james.smtpserver.CoreCmdHandlerLoader"/>
+        </handlerchain>
+        <gracefulShutdown>false</gracefulShutdown>
+    </smtpserver>
+</smtpservers>
+
+
diff --git a/examples/custom-imap/src/test/resources/usersrepository.xml b/examples/custom-imap/src/test/resources/usersrepository.xml
new file mode 100644
index 0000000000..a5390d7140
--- /dev/null
+++ b/examples/custom-imap/src/test/resources/usersrepository.xml
@@ -0,0 +1,28 @@
+<?xml version="1.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.                                           
+ -->
+
+<!-- Read https://james.apache.org/server/config-users.html for further details -->
+
+<usersrepository name="LocalUsers">
+    <algorithm>PBKDF2-SHA512</algorithm>
+    <enableVirtualHosting>true</enableVirtualHosting>    
+    <enableForwarding>true</enableForwarding>
+</usersrepository>
+
diff --git a/examples/pom.xml b/examples/pom.xml
index 76130afe9c..f8a4df6932 100644
--- a/examples/pom.xml
+++ b/examples/pom.xml
@@ -35,6 +35,7 @@
   <properties>
     <james.groupId>org.apache.james</james.groupId>
     <james.baseVersion>${project.version}</james.baseVersion>
+    <james.protocols.groupId>${james.groupId}.protocols</james.protocols.groupId>
     <maven.compiler.target>1.11</maven.compiler.target>
     <maven.compiler.source>1.11</maven.compiler.source>
   </properties>
@@ -48,5 +49,6 @@
     <module>custom-webadmin-route</module>
     <module>metrics-graphite</module>
     <module>custom-healthcheck</module>
+    <module>custom-imap</module>
   </modules>
 </project>
diff --git a/protocols/imap/src/main/java/org/apache/james/imap/api/process/DefaultMailboxTyper.java b/protocols/imap/src/main/java/org/apache/james/imap/api/process/DefaultMailboxTyper.java
index 8611ff5b52..080666f92c 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/api/process/DefaultMailboxTyper.java
+++ b/protocols/imap/src/main/java/org/apache/james/imap/api/process/DefaultMailboxTyper.java
@@ -21,6 +21,8 @@ package org.apache.james.imap.api.process;
 
 import java.util.Optional;
 
+import javax.inject.Inject;
+
 import org.apache.james.mailbox.Role;
 import org.apache.james.mailbox.model.MailboxPath;
 
@@ -35,6 +37,10 @@ public class DefaultMailboxTyper implements MailboxTyper {
         Role.DRAFTS, MailboxType.DRAFTS,
         Role.TRASH, MailboxType.TRASH);
 
+    @Inject
+    public DefaultMailboxTyper() {
+    }
+
     @Override
     public MailboxType getMailboxType(ImapSession session, MailboxPath path) {
         return Role.from(path.getName())
diff --git a/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/AppendCommandParser.java b/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/AppendCommandParser.java
index aa2cd3fabe..439c06b95b 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/AppendCommandParser.java
+++ b/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/AppendCommandParser.java
@@ -26,6 +26,7 @@ import java.time.LocalDateTime;
 import java.time.ZoneId;
 import java.util.Date;
 
+import javax.inject.Inject;
 import javax.mail.Flags;
 
 import org.apache.james.imap.api.ImapConstants;
@@ -47,6 +48,7 @@ import com.google.common.annotations.VisibleForTesting;
 public class AppendCommandParser extends AbstractImapCommandParser {
     private final Clock clock;
 
+    @Inject
     public AppendCommandParser(StatusResponseFactory statusResponseFactory, Clock clock) {
         super(ImapConstants.APPEND_COMMAND, statusResponseFactory);
             this.clock = clock;
diff --git a/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/AuthenticateCommandParser.java b/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/AuthenticateCommandParser.java
index 26a9020d24..5c58d0c9ce 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/AuthenticateCommandParser.java
+++ b/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/AuthenticateCommandParser.java
@@ -18,6 +18,8 @@
  ****************************************************************/
 package org.apache.james.imap.decode.parser;
 
+import javax.inject.Inject;
+
 import org.apache.james.imap.api.ImapConstants;
 import org.apache.james.imap.api.ImapMessage;
 import org.apache.james.imap.api.Tag;
@@ -34,6 +36,7 @@ import org.apache.james.imap.message.request.IRAuthenticateRequest;
  */
 public class AuthenticateCommandParser extends AbstractImapCommandParser {
 
+    @Inject
     public AuthenticateCommandParser(StatusResponseFactory statusResponseFactory) {
         super(ImapConstants.AUTHENTICATE_COMMAND, statusResponseFactory);
     }
diff --git a/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/CapabilityCommandParser.java b/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/CapabilityCommandParser.java
index b015d874e7..0609ce31ff 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/CapabilityCommandParser.java
+++ b/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/CapabilityCommandParser.java
@@ -18,6 +18,8 @@
  ****************************************************************/
 package org.apache.james.imap.decode.parser;
 
+import javax.inject.Inject;
+
 import org.apache.james.imap.api.ImapConstants;
 import org.apache.james.imap.api.ImapMessage;
 import org.apache.james.imap.api.Tag;
@@ -32,6 +34,8 @@ import org.apache.james.imap.message.request.CapabilityRequest;
  * Parses CAPABILITY commands
  */
 public class CapabilityCommandParser extends AbstractImapCommandParser {
+
+    @Inject
     public CapabilityCommandParser(StatusResponseFactory statusResponseFactory) {
         super(ImapConstants.CAPABILITY_COMMAND, statusResponseFactory);
     }
diff --git a/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/CheckCommandParser.java b/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/CheckCommandParser.java
index 949356c218..6e9d2be1b1 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/CheckCommandParser.java
+++ b/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/CheckCommandParser.java
@@ -18,6 +18,8 @@
  ****************************************************************/
 package org.apache.james.imap.decode.parser;
 
+import javax.inject.Inject;
+
 import org.apache.james.imap.api.ImapConstants;
 import org.apache.james.imap.api.ImapMessage;
 import org.apache.james.imap.api.Tag;
@@ -33,6 +35,7 @@ import org.apache.james.imap.message.request.CheckRequest;
  */
 public class CheckCommandParser extends AbstractImapCommandParser {
 
+    @Inject
     public CheckCommandParser(StatusResponseFactory statusResponseFactory) {
         super(ImapConstants.CHECK_COMMAND, statusResponseFactory);
     }
diff --git a/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/CloseCommandParser.java b/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/CloseCommandParser.java
index b774f4d980..a2e2a55762 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/CloseCommandParser.java
+++ b/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/CloseCommandParser.java
@@ -18,6 +18,8 @@
  ****************************************************************/
 package org.apache.james.imap.decode.parser;
 
+import javax.inject.Inject;
+
 import org.apache.james.imap.api.ImapConstants;
 import org.apache.james.imap.api.ImapMessage;
 import org.apache.james.imap.api.Tag;
@@ -31,7 +33,9 @@ import org.apache.james.imap.message.request.CloseRequest;
 /**
  * Parse CLOSE commands
  */
-class CloseCommandParser extends AbstractImapCommandParser {
+public class CloseCommandParser extends AbstractImapCommandParser {
+
+    @Inject
     public CloseCommandParser(StatusResponseFactory statusResponseFactory) {
         super(ImapConstants.CLOSE_COMMAND, statusResponseFactory);
     }
diff --git a/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/CompressCommandParser.java b/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/CompressCommandParser.java
index da88b00008..b3fa9f8d03 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/CompressCommandParser.java
+++ b/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/CompressCommandParser.java
@@ -18,6 +18,8 @@
  ****************************************************************/
 package org.apache.james.imap.decode.parser;
 
+import javax.inject.Inject;
+
 import org.apache.james.imap.api.ImapConstants;
 import org.apache.james.imap.api.ImapMessage;
 import org.apache.james.imap.api.Tag;
@@ -29,6 +31,8 @@ import org.apache.james.imap.decode.base.AbstractImapCommandParser;
 import org.apache.james.imap.message.request.CompressRequest;
 
 public class CompressCommandParser extends AbstractImapCommandParser {
+
+    @Inject
     public CompressCommandParser(StatusResponseFactory statusResponseFactory) {
         super(ImapConstants.COMPRESS_COMMAND, statusResponseFactory);
     }
diff --git a/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/CopyCommandParser.java b/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/CopyCommandParser.java
index 8300bb7f0c..afb3fb1e12 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/CopyCommandParser.java
+++ b/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/CopyCommandParser.java
@@ -18,6 +18,8 @@
  ****************************************************************/
 package org.apache.james.imap.decode.parser;
 
+import javax.inject.Inject;
+
 import org.apache.james.imap.api.ImapConstants;
 import org.apache.james.imap.api.Tag;
 import org.apache.james.imap.api.message.IdRange;
@@ -28,6 +30,8 @@ import org.apache.james.imap.message.request.CopyRequest;
  * Parse COPY commands
  */
 public class CopyCommandParser extends AbstractMessageRangeCommandParser {
+
+    @Inject
     public CopyCommandParser(StatusResponseFactory statusResponseFactory) {
         super(ImapConstants.COPY_COMMAND, statusResponseFactory);
     }
diff --git a/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/CreateCommandParser.java b/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/CreateCommandParser.java
index aa912512f0..843d803510 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/CreateCommandParser.java
+++ b/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/CreateCommandParser.java
@@ -20,6 +20,8 @@ package org.apache.james.imap.decode.parser;
 
 import java.util.function.Predicate;
 
+import javax.inject.Inject;
+
 import org.apache.james.imap.api.ImapConstants;
 import org.apache.james.imap.api.ImapMessage;
 import org.apache.james.imap.api.Tag;
@@ -40,6 +42,7 @@ import com.google.common.base.Strings;
  */
 public class CreateCommandParser extends AbstractImapCommandParser {
 
+    @Inject
     public CreateCommandParser(StatusResponseFactory statusResponseFactory) {
         super(ImapConstants.CREATE_COMMAND, statusResponseFactory);
     }
diff --git a/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/DeleteACLCommandParser.java b/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/DeleteACLCommandParser.java
index df2f294bbe..c9e5996678 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/DeleteACLCommandParser.java
+++ b/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/DeleteACLCommandParser.java
@@ -19,6 +19,8 @@
 
 package org.apache.james.imap.decode.parser;
 
+import javax.inject.Inject;
+
 import org.apache.james.imap.api.ImapConstants;
 import org.apache.james.imap.api.ImapMessage;
 import org.apache.james.imap.api.Tag;
@@ -34,6 +36,7 @@ import org.apache.james.imap.message.request.DeleteACLRequest;
  */
 public class DeleteACLCommandParser extends AbstractImapCommandParser {
 
+    @Inject
     public DeleteACLCommandParser(StatusResponseFactory statusResponseFactory) {
         super(ImapConstants.DELETEACL_COMMAND, statusResponseFactory);
     }
diff --git a/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/DeleteCommandParser.java b/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/DeleteCommandParser.java
index fd5c432f97..d04cd4d7db 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/DeleteCommandParser.java
+++ b/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/DeleteCommandParser.java
@@ -18,6 +18,8 @@
  ****************************************************************/
 package org.apache.james.imap.decode.parser;
 
+import javax.inject.Inject;
+
 import org.apache.james.imap.api.ImapConstants;
 import org.apache.james.imap.api.ImapMessage;
 import org.apache.james.imap.api.Tag;
@@ -33,6 +35,7 @@ import org.apache.james.imap.message.request.DeleteRequest;
  */
 public class DeleteCommandParser extends AbstractImapCommandParser {
 
+    @Inject
     public DeleteCommandParser(StatusResponseFactory statusResponseFactory) {
         super(ImapConstants.DELETE_COMMAND, statusResponseFactory);
     }
diff --git a/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/EnableCommandParser.java b/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/EnableCommandParser.java
index e9f14eff62..9d6eb23c0d 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/EnableCommandParser.java
+++ b/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/EnableCommandParser.java
@@ -21,6 +21,8 @@ package org.apache.james.imap.decode.parser;
 import java.util.ArrayList;
 import java.util.List;
 
+import javax.inject.Inject;
+
 import org.apache.james.imap.api.ImapConstants;
 import org.apache.james.imap.api.ImapMessage;
 import org.apache.james.imap.api.Tag;
@@ -33,7 +35,8 @@ import org.apache.james.imap.decode.base.AbstractImapCommandParser;
 import org.apache.james.imap.message.request.EnableRequest;
 
 public class EnableCommandParser extends AbstractImapCommandParser {
-    
+
+    @Inject
     public EnableCommandParser(StatusResponseFactory statusResponseFactory) {
         super(ImapConstants.ENABLE_COMMAND, statusResponseFactory);
     }
diff --git a/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/ExamineCommandParser.java b/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/ExamineCommandParser.java
index e711e9d495..b7e0e1dec3 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/ExamineCommandParser.java
+++ b/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/ExamineCommandParser.java
@@ -18,6 +18,8 @@
  ****************************************************************/
 package org.apache.james.imap.decode.parser;
 
+import javax.inject.Inject;
+
 import org.apache.james.imap.api.ImapConstants;
 import org.apache.james.imap.api.Tag;
 import org.apache.james.imap.api.message.IdRange;
@@ -32,6 +34,7 @@ import org.apache.james.imap.message.request.ExamineRequest;
  */
 public class ExamineCommandParser extends AbstractSelectionCommandParser {
 
+    @Inject
     public ExamineCommandParser(StatusResponseFactory statusResponseFactory) {
         super(ImapConstants.EXAMINE_COMMAND, statusResponseFactory);
     }
diff --git a/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/ExpungeCommandParser.java b/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/ExpungeCommandParser.java
index 5216975010..eca5a173d3 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/ExpungeCommandParser.java
+++ b/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/ExpungeCommandParser.java
@@ -18,6 +18,8 @@
  ****************************************************************/
 package org.apache.james.imap.decode.parser;
 
+import javax.inject.Inject;
+
 import org.apache.james.imap.api.ImapConstants;
 import org.apache.james.imap.api.ImapMessage;
 import org.apache.james.imap.api.Tag;
@@ -33,6 +35,7 @@ import org.apache.james.imap.message.request.ExpungeRequest;
  */
 public class ExpungeCommandParser extends AbstractUidCommandParser {
 
+    @Inject
     public ExpungeCommandParser(StatusResponseFactory statusResponseFactory) {
         super(ImapConstants.EXPUNGE_COMMAND, statusResponseFactory);
     }
diff --git a/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/FetchCommandParser.java b/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/FetchCommandParser.java
index 3f11db1465..f4d36f9091 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/FetchCommandParser.java
+++ b/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/FetchCommandParser.java
@@ -32,6 +32,8 @@ import static org.apache.james.imap.api.message.FetchData.Item.UID;
 import java.util.List;
 import java.util.Locale;
 
+import javax.inject.Inject;
+
 import org.apache.james.imap.api.ImapConstants;
 import org.apache.james.imap.api.ImapMessage;
 import org.apache.james.imap.api.Tag;
@@ -59,6 +61,7 @@ public class FetchCommandParser extends AbstractUidCommandParser {
     private static final CharMatcher CLOSING_BRACKET = CharMatcher.is(']');
     private static final CharMatcher NEXT_ELEMENT_END = CharMatcher.anyOf(" [)\r\n");
 
+    @Inject
     public FetchCommandParser(StatusResponseFactory statusResponseFactory) {
         super(ImapConstants.FETCH_COMMAND, statusResponseFactory);
     }
diff --git a/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/GetACLCommandParser.java b/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/GetACLCommandParser.java
index bbcef589c0..9dbfc6fd1e 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/GetACLCommandParser.java
+++ b/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/GetACLCommandParser.java
@@ -19,6 +19,8 @@
 
 package org.apache.james.imap.decode.parser;
 
+import javax.inject.Inject;
+
 import org.apache.james.imap.api.ImapConstants;
 import org.apache.james.imap.api.ImapMessage;
 import org.apache.james.imap.api.Tag;
@@ -34,6 +36,7 @@ import org.apache.james.imap.message.request.GetACLRequest;
  */
 public class GetACLCommandParser extends AbstractImapCommandParser {
 
+    @Inject
     public GetACLCommandParser(StatusResponseFactory statusResponseFactory) {
         super(ImapConstants.GETACL_COMMAND, statusResponseFactory);
     }
diff --git a/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/GetMetadataCommandParser.java b/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/GetMetadataCommandParser.java
index c7835df6d8..4c56e0a506 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/GetMetadataCommandParser.java
+++ b/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/GetMetadataCommandParser.java
@@ -21,6 +21,8 @@ package org.apache.james.imap.decode.parser;
 
 import java.util.Optional;
 
+import javax.inject.Inject;
+
 import org.apache.james.imap.api.ImapConstants;
 import org.apache.james.imap.api.ImapMessage;
 import org.apache.james.imap.api.Tag;
@@ -44,6 +46,7 @@ public class GetMetadataCommandParser extends AbstractImapCommandParser {
     private static final String DEPTH = "DEPTH";
     private static final boolean STOP_ON_PAREN = true;
 
+    @Inject
     public GetMetadataCommandParser(StatusResponseFactory statusResponseFactory) {
         super(ImapConstants.GETMETDATA_COMMAND, statusResponseFactory);
     }
diff --git a/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/GetQuotaCommandParser.java b/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/GetQuotaCommandParser.java
index 4a21123e10..907920873a 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/GetQuotaCommandParser.java
+++ b/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/GetQuotaCommandParser.java
@@ -19,6 +19,8 @@
 
 package org.apache.james.imap.decode.parser;
 
+import javax.inject.Inject;
+
 import org.apache.james.imap.api.ImapConstants;
 import org.apache.james.imap.api.ImapMessage;
 import org.apache.james.imap.api.Tag;
@@ -33,6 +35,8 @@ import org.apache.james.imap.message.request.GetQuotaRequest;
  * GETQUOTA command parser
  */
 public class GetQuotaCommandParser extends AbstractImapCommandParser {
+
+    @Inject
     public GetQuotaCommandParser(StatusResponseFactory statusResponseFactory) {
         super(ImapConstants.GETQUOTA_COMMAND, statusResponseFactory);
     }
diff --git a/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/GetQuotaRootCommandParser.java b/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/GetQuotaRootCommandParser.java
index 533b13d55b..8e21d35b03 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/GetQuotaRootCommandParser.java
+++ b/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/GetQuotaRootCommandParser.java
@@ -19,6 +19,8 @@
 
 package org.apache.james.imap.decode.parser;
 
+import javax.inject.Inject;
+
 import org.apache.james.imap.api.ImapConstants;
 import org.apache.james.imap.api.ImapMessage;
 import org.apache.james.imap.api.Tag;
@@ -34,6 +36,7 @@ import org.apache.james.imap.message.request.GetQuotaRootRequest;
  */
 public class GetQuotaRootCommandParser extends AbstractImapCommandParser {
 
+    @Inject
     public GetQuotaRootCommandParser(StatusResponseFactory statusResponseFactory) {
         super(ImapConstants.GETQUOTAROOT_COMMAND, statusResponseFactory);
     }
diff --git a/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/IDCommandParser.java b/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/IDCommandParser.java
index cf306a43ee..79e7c84111 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/IDCommandParser.java
+++ b/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/IDCommandParser.java
@@ -20,6 +20,8 @@ package org.apache.james.imap.decode.parser;
 
 import java.util.Optional;
 
+import javax.inject.Inject;
+
 import org.apache.james.imap.api.ImapConstants;
 import org.apache.james.imap.api.ImapMessage;
 import org.apache.james.imap.api.Tag;
@@ -38,6 +40,8 @@ import com.google.common.collect.ImmutableMap;
  * CF https://www.rfc-editor.org/rfc/rfc2971.html
  */
 public class IDCommandParser extends AbstractImapCommandParser {
+
+    @Inject
     public IDCommandParser(StatusResponseFactory statusResponseFactory) {
         super(ImapConstants.ID_COMMAND, statusResponseFactory);
     }
diff --git a/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/IdleCommandParser.java b/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/IdleCommandParser.java
index a0f1c0d5bc..b7114f8af9 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/IdleCommandParser.java
+++ b/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/IdleCommandParser.java
@@ -18,6 +18,8 @@
  ****************************************************************/
 package org.apache.james.imap.decode.parser;
 
+import javax.inject.Inject;
+
 import org.apache.james.imap.api.ImapConstants;
 import org.apache.james.imap.api.ImapMessage;
 import org.apache.james.imap.api.Tag;
@@ -33,6 +35,7 @@ import org.apache.james.imap.message.request.IdleRequest;
  */
 public class IdleCommandParser extends AbstractImapCommandParser {
 
+    @Inject
     public IdleCommandParser(StatusResponseFactory statusResponseFactory) {
         super(ImapConstants.IDLE_COMMAND, statusResponseFactory);
     }
diff --git a/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/ImapParserFactory.java b/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/ImapParserFactory.java
index 2676ae4cf1..cf753daf38 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/ImapParserFactory.java
+++ b/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/ImapParserFactory.java
@@ -117,6 +117,10 @@ public class ImapParserFactory implements ImapCommandParserFactory {
                 Function.identity()));
     }
 
+    public ImapParserFactory(Map<String, ImapCommandParser> imapCommands) {
+        this.imapCommands = imapCommands;
+    }
+
     @Override
     public ImapCommandParser getParser(String commandName) {
         return imapCommands.get(commandName.toUpperCase(Locale.US));
diff --git a/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/ListCommandParser.java b/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/ListCommandParser.java
index 5909b2dbe1..3a4e42f754 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/ListCommandParser.java
+++ b/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/ListCommandParser.java
@@ -21,6 +21,8 @@ package org.apache.james.imap.decode.parser;
 import java.util.EnumSet;
 import java.util.Optional;
 
+import javax.inject.Inject;
+
 import org.apache.commons.lang3.tuple.Pair;
 import org.apache.james.imap.api.ImapCommand;
 import org.apache.james.imap.api.ImapConstants;
@@ -54,6 +56,7 @@ public class ListCommandParser extends AbstractUidCommandParser {
         }
     }
 
+    @Inject
     public ListCommandParser(StatusResponseFactory statusResponseFactory) {
         super(ImapConstants.LIST_COMMAND, statusResponseFactory);
     }
diff --git a/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/ListRightsCommandParser.java b/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/ListRightsCommandParser.java
index c7e4da0a20..20d398a018 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/ListRightsCommandParser.java
+++ b/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/ListRightsCommandParser.java
@@ -19,6 +19,8 @@
 
 package org.apache.james.imap.decode.parser;
 
+import javax.inject.Inject;
+
 import org.apache.james.imap.api.ImapConstants;
 import org.apache.james.imap.api.ImapMessage;
 import org.apache.james.imap.api.Tag;
@@ -33,6 +35,8 @@ import org.apache.james.imap.message.request.ListRightsRequest;
  * LISTRIGHTS Parser
  */
 public class ListRightsCommandParser extends AbstractImapCommandParser {
+
+    @Inject
     public ListRightsCommandParser(StatusResponseFactory statusResponseFactory) {
         super(ImapConstants.LISTRIGHTS_COMMAND, statusResponseFactory);
     }
diff --git a/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/LoginCommandParser.java b/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/LoginCommandParser.java
index 71beb18b6c..f9c033a5a2 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/LoginCommandParser.java
+++ b/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/LoginCommandParser.java
@@ -18,6 +18,8 @@
  ****************************************************************/
 package org.apache.james.imap.decode.parser;
 
+import javax.inject.Inject;
+
 import org.apache.james.core.Username;
 import org.apache.james.imap.api.ImapConstants;
 import org.apache.james.imap.api.ImapMessage;
@@ -33,6 +35,8 @@ import org.apache.james.imap.message.request.LoginRequest;
  * Parse LOGIN commands
  */
 public class LoginCommandParser extends AbstractImapCommandParser {
+
+    @Inject
     public LoginCommandParser(StatusResponseFactory statusResponseFactory) {
         super(ImapConstants.LOGIN_COMMAND, statusResponseFactory);
     }
diff --git a/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/LogoutCommandParser.java b/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/LogoutCommandParser.java
index 079362891a..1e055fc0ad 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/LogoutCommandParser.java
+++ b/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/LogoutCommandParser.java
@@ -18,6 +18,8 @@
  ****************************************************************/
 package org.apache.james.imap.decode.parser;
 
+import javax.inject.Inject;
+
 import org.apache.james.imap.api.ImapConstants;
 import org.apache.james.imap.api.ImapMessage;
 import org.apache.james.imap.api.Tag;
@@ -32,6 +34,8 @@ import org.apache.james.imap.message.request.LogoutRequest;
  * Parse LOGOUT commands
  */
 public class LogoutCommandParser extends AbstractImapCommandParser {
+
+    @Inject
     public LogoutCommandParser(StatusResponseFactory statusResponseFactory) {
         super(ImapConstants.LOGOUT_COMMAND, statusResponseFactory);
     }
diff --git a/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/LsubCommandParser.java b/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/LsubCommandParser.java
index 3d1d4ef785..c7c4a1b98c 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/LsubCommandParser.java
+++ b/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/LsubCommandParser.java
@@ -18,6 +18,8 @@
  ****************************************************************/
 package org.apache.james.imap.decode.parser;
 
+import javax.inject.Inject;
+
 import org.apache.james.imap.api.ImapConstants;
 import org.apache.james.imap.api.ImapMessage;
 import org.apache.james.imap.api.Tag;
@@ -28,6 +30,8 @@ import org.apache.james.imap.message.request.LsubRequest;
  * Parse LSUB commands
  */
 public class LsubCommandParser extends ListCommandParser {
+
+    @Inject
     public LsubCommandParser(StatusResponseFactory statusResponseFactory) {
         super(ImapConstants.LSUB_COMMAND, statusResponseFactory);
     }
diff --git a/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/MoveCommandParser.java b/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/MoveCommandParser.java
index 6df14c5fbf..8248e41a00 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/MoveCommandParser.java
+++ b/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/MoveCommandParser.java
@@ -1,5 +1,7 @@
 package org.apache.james.imap.decode.parser;
 
+import javax.inject.Inject;
+
 import org.apache.james.imap.api.ImapConstants;
 import org.apache.james.imap.api.Tag;
 import org.apache.james.imap.api.message.IdRange;
@@ -10,6 +12,8 @@ import org.apache.james.imap.message.request.MoveRequest;
  * Parse MOVE commands
  */
 public class MoveCommandParser extends AbstractMessageRangeCommandParser {
+
+    @Inject
     public MoveCommandParser(StatusResponseFactory statusResponseFactory) {
         super(ImapConstants.MOVE_COMMAND, statusResponseFactory);
     }
diff --git a/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/MyRightsCommandParser.java b/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/MyRightsCommandParser.java
index 11231305bb..432b2bb682 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/MyRightsCommandParser.java
+++ b/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/MyRightsCommandParser.java
@@ -19,6 +19,8 @@
 
 package org.apache.james.imap.decode.parser;
 
+import javax.inject.Inject;
+
 import org.apache.james.imap.api.ImapConstants;
 import org.apache.james.imap.api.ImapMessage;
 import org.apache.james.imap.api.Tag;
@@ -34,6 +36,7 @@ import org.apache.james.imap.message.request.MyRightsRequest;
  */
 public class MyRightsCommandParser extends AbstractImapCommandParser {
 
+    @Inject
     public MyRightsCommandParser(StatusResponseFactory statusResponseFactory) {
         super(ImapConstants.MYRIGHTS_COMMAND, statusResponseFactory);
     }
diff --git a/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/NamespaceCommandParser.java b/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/NamespaceCommandParser.java
index 6ecf1b67ad..7b87feab37 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/NamespaceCommandParser.java
+++ b/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/NamespaceCommandParser.java
@@ -18,6 +18,8 @@
  ****************************************************************/
 package org.apache.james.imap.decode.parser;
 
+import javax.inject.Inject;
+
 import org.apache.james.imap.api.ImapConstants;
 import org.apache.james.imap.api.ImapMessage;
 import org.apache.james.imap.api.Tag;
@@ -32,6 +34,8 @@ import org.apache.james.imap.message.request.NamespaceRequest;
  * Parse NAMESPACE commands
  */
 public class NamespaceCommandParser extends AbstractImapCommandParser {
+
+    @Inject
     public NamespaceCommandParser(StatusResponseFactory statusResponseFactory) {
         super(ImapConstants.NAMESPACE_COMMAND, statusResponseFactory);
     }
diff --git a/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/NoopCommandParser.java b/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/NoopCommandParser.java
index 22face9001..f0b1ad9f43 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/NoopCommandParser.java
+++ b/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/NoopCommandParser.java
@@ -18,6 +18,8 @@
  ****************************************************************/
 package org.apache.james.imap.decode.parser;
 
+import javax.inject.Inject;
+
 import org.apache.james.imap.api.ImapConstants;
 import org.apache.james.imap.api.ImapMessage;
 import org.apache.james.imap.api.Tag;
@@ -32,6 +34,8 @@ import org.apache.james.imap.message.request.NoopRequest;
  * Parses NOOP commands
  */
 public class NoopCommandParser extends AbstractImapCommandParser {
+
+    @Inject
     public NoopCommandParser(StatusResponseFactory statusResponseFactory) {
         super(ImapConstants.NOOP_COMMAND, statusResponseFactory);
     }
diff --git a/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/RenameCommandParser.java b/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/RenameCommandParser.java
index 8d4177c6e0..a804b6ff3c 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/RenameCommandParser.java
+++ b/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/RenameCommandParser.java
@@ -18,6 +18,8 @@
  ****************************************************************/
 package org.apache.james.imap.decode.parser;
 
+import javax.inject.Inject;
+
 import org.apache.james.imap.api.ImapConstants;
 import org.apache.james.imap.api.ImapMessage;
 import org.apache.james.imap.api.Tag;
@@ -32,6 +34,8 @@ import org.apache.james.imap.message.request.RenameRequest;
  * Parses RENAME command
  */
 public class RenameCommandParser extends AbstractImapCommandParser {
+
+    @Inject
     public RenameCommandParser(StatusResponseFactory statusResponseFactory) {
         super(ImapConstants.RENAME_COMMAND, statusResponseFactory);
     }
diff --git a/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/SearchCommandParser.java b/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/SearchCommandParser.java
index b978319011..e4e898d330 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/SearchCommandParser.java
+++ b/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/SearchCommandParser.java
@@ -26,6 +26,8 @@ import java.util.Arrays;
 import java.util.List;
 import java.util.Optional;
 
+import javax.inject.Inject;
+
 import org.apache.james.imap.api.ImapConstants;
 import org.apache.james.imap.api.ImapMessage;
 import org.apache.james.imap.api.Tag;
@@ -64,6 +66,7 @@ public class SearchCommandParser extends AbstractUidCommandParser {
 
     private static final Logger LOGGER = LoggerFactory.getLogger(SearchCommandParser.class);
 
+    @Inject
     public SearchCommandParser(StatusResponseFactory statusResponseFactory) {
         super(ImapConstants.SEARCH_COMMAND, statusResponseFactory);
     }
diff --git a/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/SelectCommandParser.java b/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/SelectCommandParser.java
index c9ad85a1e0..1d60d81a49 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/SelectCommandParser.java
+++ b/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/SelectCommandParser.java
@@ -18,6 +18,8 @@
  ****************************************************************/
 package org.apache.james.imap.decode.parser;
 
+import javax.inject.Inject;
+
 import org.apache.james.imap.api.ImapConstants;
 import org.apache.james.imap.api.Tag;
 import org.apache.james.imap.api.message.IdRange;
@@ -31,6 +33,8 @@ import org.apache.james.imap.message.request.SelectRequest;
  * Parse SELECT commands
  */
 public class SelectCommandParser extends AbstractSelectionCommandParser {
+
+    @Inject
     public SelectCommandParser(StatusResponseFactory statusResponseFactory) {
         super(ImapConstants.SELECT_COMMAND, statusResponseFactory);
     }
diff --git a/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/SetACLCommandParser.java b/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/SetACLCommandParser.java
index 981b48620c..3ea0b465a8 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/SetACLCommandParser.java
+++ b/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/SetACLCommandParser.java
@@ -19,6 +19,8 @@
 
 package org.apache.james.imap.decode.parser;
 
+import javax.inject.Inject;
+
 import org.apache.james.imap.api.ImapConstants;
 import org.apache.james.imap.api.ImapMessage;
 import org.apache.james.imap.api.Tag;
@@ -33,6 +35,8 @@ import org.apache.james.imap.message.request.SetACLRequest;
  * SETACL Parser
  */
 public class SetACLCommandParser extends AbstractImapCommandParser {
+
+    @Inject
     public SetACLCommandParser(StatusResponseFactory statusResponseFactory) {
         super(ImapConstants.SETACL_COMMAND, statusResponseFactory);
     }
diff --git a/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/SetAnnotationCommandParser.java b/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/SetAnnotationCommandParser.java
index 4bb8b82fd4..8358dc16aa 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/SetAnnotationCommandParser.java
+++ b/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/SetAnnotationCommandParser.java
@@ -22,6 +22,8 @@ package org.apache.james.imap.decode.parser;
 import java.util.Optional;
 import java.util.function.Function;
 
+import javax.inject.Inject;
+
 import org.apache.james.imap.api.ImapConstants;
 import org.apache.james.imap.api.ImapMessage;
 import org.apache.james.imap.api.Tag;
@@ -38,6 +40,8 @@ import org.apache.james.mailbox.model.MailboxAnnotationKey;
 import com.google.common.collect.ImmutableList;
 
 public class SetAnnotationCommandParser extends AbstractImapCommandParser {
+
+    @Inject
     public SetAnnotationCommandParser(StatusResponseFactory statusResponseFactory) {
         super(ImapConstants.SETMETADATA_COMMAND, statusResponseFactory);
     }
diff --git a/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/SetQuotaCommandParser.java b/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/SetQuotaCommandParser.java
index d44d3b2790..301a3549a1 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/SetQuotaCommandParser.java
+++ b/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/SetQuotaCommandParser.java
@@ -19,6 +19,8 @@
 
 package org.apache.james.imap.decode.parser;
 
+import javax.inject.Inject;
+
 import org.apache.james.imap.api.ImapConstants;
 import org.apache.james.imap.api.ImapMessage;
 import org.apache.james.imap.api.Tag;
@@ -33,6 +35,8 @@ import org.apache.james.imap.message.request.SetQuotaRequest;
  * SETQUOTA command parser
  */
 public class SetQuotaCommandParser extends AbstractImapCommandParser {
+
+    @Inject
     public SetQuotaCommandParser(StatusResponseFactory statusResponseFactory) {
         super(ImapConstants.SETQUOTA_COMMAND, statusResponseFactory);
     }
diff --git a/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/StartTLSCommandParser.java b/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/StartTLSCommandParser.java
index ea5f77b2d1..324b8a85ae 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/StartTLSCommandParser.java
+++ b/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/StartTLSCommandParser.java
@@ -18,6 +18,8 @@
  ****************************************************************/
 package org.apache.james.imap.decode.parser;
 
+import javax.inject.Inject;
+
 import org.apache.james.imap.api.ImapConstants;
 import org.apache.james.imap.api.ImapMessage;
 import org.apache.james.imap.api.Tag;
@@ -32,6 +34,8 @@ import org.apache.james.imap.message.request.StartTLSRequest;
  * Parse STARTTLS commands
  */
 public class StartTLSCommandParser extends AbstractImapCommandParser {
+
+    @Inject
     public StartTLSCommandParser(StatusResponseFactory statusResponseFactory) {
         super(ImapConstants.STARTTLS_COMMAND, statusResponseFactory);
     }
diff --git a/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/StatusCommandParser.java b/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/StatusCommandParser.java
index 9fca72d3d7..39b3306c48 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/StatusCommandParser.java
+++ b/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/StatusCommandParser.java
@@ -20,6 +20,8 @@ package org.apache.james.imap.decode.parser;
 
 import java.util.EnumSet;
 
+import javax.inject.Inject;
+
 import org.apache.james.imap.api.ImapConstants;
 import org.apache.james.imap.api.ImapMessage;
 import org.apache.james.imap.api.Tag;
@@ -37,6 +39,7 @@ import org.apache.james.imap.message.request.StatusRequest;
  */
 public class StatusCommandParser extends AbstractImapCommandParser {
 
+    @Inject
     public StatusCommandParser(StatusResponseFactory statusResponseFactory) {
         super(ImapConstants.STATUS_COMMAND, statusResponseFactory);
     }
diff --git a/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/StoreCommandParser.java b/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/StoreCommandParser.java
index f3b32e5360..b8e0a9429f 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/StoreCommandParser.java
+++ b/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/StoreCommandParser.java
@@ -20,6 +20,7 @@ package org.apache.james.imap.decode.parser;
 
 import java.util.Locale;
 
+import javax.inject.Inject;
 import javax.mail.Flags;
 
 import org.apache.james.imap.api.ImapConstants;
@@ -41,7 +42,8 @@ import org.apache.james.mailbox.MessageManager;
 public class StoreCommandParser extends AbstractUidCommandParser {
 
     private static final String UNCHANGEDSINCE = "UNCHANGEDSINCE";
-    
+
+    @Inject
     public StoreCommandParser(StatusResponseFactory statusResponseFactory) {
         super(ImapConstants.STORE_COMMAND, statusResponseFactory);
     }
diff --git a/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/SubscribeCommandParser.java b/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/SubscribeCommandParser.java
index d064bd2b14..939cd2ebd7 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/SubscribeCommandParser.java
+++ b/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/SubscribeCommandParser.java
@@ -18,6 +18,8 @@
  ****************************************************************/
 package org.apache.james.imap.decode.parser;
 
+import javax.inject.Inject;
+
 import org.apache.james.imap.api.ImapConstants;
 import org.apache.james.imap.api.ImapMessage;
 import org.apache.james.imap.api.Tag;
@@ -32,6 +34,8 @@ import org.apache.james.imap.message.request.SubscribeRequest;
  * Parse SUBSCRIBE commands
  */
 public class SubscribeCommandParser extends AbstractImapCommandParser {
+
+    @Inject
     public SubscribeCommandParser(StatusResponseFactory statusResponseFactory) {
         super(ImapConstants.SUBSCRIBE_COMMAND, statusResponseFactory);
     }
diff --git a/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/UidCommandParser.java b/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/UidCommandParser.java
index fda9287798..f04e4e2a69 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/UidCommandParser.java
+++ b/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/UidCommandParser.java
@@ -18,6 +18,8 @@
  ****************************************************************/
 package org.apache.james.imap.decode.parser;
 
+import javax.inject.Inject;
+
 import org.apache.james.imap.api.ImapConstants;
 import org.apache.james.imap.api.ImapMessage;
 import org.apache.james.imap.api.Tag;
@@ -40,6 +42,7 @@ public class UidCommandParser extends AbstractImapCommandParser {
 
     private final ImapCommandParserFactory parserFactory;
 
+    @Inject
     public UidCommandParser(ImapCommandParserFactory parserFactory, StatusResponseFactory statusResponseFactory) {
         super(ImapConstants.UID_COMMAND, statusResponseFactory);
         this.parserFactory = parserFactory;
diff --git a/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/UnselectCommandParser.java b/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/UnselectCommandParser.java
index 453df128d9..4e35a52f6b 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/UnselectCommandParser.java
+++ b/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/UnselectCommandParser.java
@@ -18,6 +18,8 @@
  ****************************************************************/
 package org.apache.james.imap.decode.parser;
 
+import javax.inject.Inject;
+
 import org.apache.james.imap.api.ImapConstants;
 import org.apache.james.imap.api.ImapMessage;
 import org.apache.james.imap.api.Tag;
@@ -34,6 +36,8 @@ import org.apache.james.imap.message.request.UnselectRequest;
  * See RFC3691
  */
 public class UnselectCommandParser extends AbstractImapCommandParser {
+
+    @Inject
     public UnselectCommandParser(StatusResponseFactory statusResponseFactory) {
         // from the RFC it seems like the command should be valid in any state.
         // At least kind of, as we will return a "BAD" response if no mailbox is
diff --git a/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/UnsubscribeCommandParser.java b/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/UnsubscribeCommandParser.java
index 80725da754..412c044e07 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/UnsubscribeCommandParser.java
+++ b/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/UnsubscribeCommandParser.java
@@ -18,6 +18,8 @@
  ****************************************************************/
 package org.apache.james.imap.decode.parser;
 
+import javax.inject.Inject;
+
 import org.apache.james.imap.api.ImapConstants;
 import org.apache.james.imap.api.ImapMessage;
 import org.apache.james.imap.api.Tag;
@@ -32,6 +34,8 @@ import org.apache.james.imap.message.request.UnsubscribeRequest;
  * Parse UNSUBSCRIBE commands
  */
 public class UnsubscribeCommandParser extends AbstractImapCommandParser {
+
+    @Inject
     public UnsubscribeCommandParser(StatusResponseFactory statusResponseFactory) {
         super(ImapConstants.UNSUBSCRIBE_COMMAND, statusResponseFactory);
     }
diff --git a/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/XListCommandParser.java b/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/XListCommandParser.java
index 15879fa45f..689831a974 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/XListCommandParser.java
+++ b/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/XListCommandParser.java
@@ -18,6 +18,8 @@
  ****************************************************************/
 package org.apache.james.imap.decode.parser;
 
+import javax.inject.Inject;
+
 import org.apache.james.imap.api.ImapConstants;
 import org.apache.james.imap.api.ImapMessage;
 import org.apache.james.imap.api.Tag;
@@ -28,6 +30,8 @@ import org.apache.james.imap.message.request.XListRequest;
  * Parse XLIST commands
  */
 public class XListCommandParser extends ListCommandParser {
+
+    @Inject
     public XListCommandParser(StatusResponseFactory statusResponseFactory) {
         super(ImapConstants.XLIST_COMMAND, statusResponseFactory);
     }
diff --git a/protocols/imap/src/main/java/org/apache/james/imap/encode/ContinuationResponseEncoder.java b/protocols/imap/src/main/java/org/apache/james/imap/encode/ContinuationResponseEncoder.java
index c46b891d15..c921357f3f 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/encode/ContinuationResponseEncoder.java
+++ b/protocols/imap/src/main/java/org/apache/james/imap/encode/ContinuationResponseEncoder.java
@@ -21,6 +21,8 @@ package org.apache.james.imap.encode;
 
 import java.io.IOException;
 
+import javax.inject.Inject;
+
 import org.apache.james.imap.api.display.HumanReadableText;
 import org.apache.james.imap.api.display.Locales;
 import org.apache.james.imap.api.display.Localizer;
@@ -30,6 +32,7 @@ public class ContinuationResponseEncoder implements ImapResponseEncoder<Continua
 
     private final Localizer localizer;
 
+    @Inject
     public ContinuationResponseEncoder(Localizer localizer) {
         this.localizer = localizer;
     }
diff --git a/protocols/imap/src/main/java/org/apache/james/imap/encode/FetchResponseEncoder.java b/protocols/imap/src/main/java/org/apache/james/imap/encode/FetchResponseEncoder.java
index 3fc4b82c23..d0f9d68bd7 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/encode/FetchResponseEncoder.java
+++ b/protocols/imap/src/main/java/org/apache/james/imap/encode/FetchResponseEncoder.java
@@ -29,6 +29,7 @@ import java.util.Map;
 import java.util.Set;
 import java.util.TreeSet;
 
+import javax.inject.Inject;
 import javax.mail.Flags;
 
 import org.apache.james.imap.api.ImapConstants;
@@ -52,6 +53,11 @@ public class FetchResponseEncoder implements ImapResponseEncoder<FetchResponse>
     /** Disables all optional BODYSTRUCTURE extensions */
     private final boolean neverAddBodyStructureExtensions;
 
+    @Inject
+    public FetchResponseEncoder() {
+        this(false);
+    }
+
     /**
      * Constructs an encoder for FETCH messages.
      *
diff --git a/protocols/imap/src/main/java/org/apache/james/imap/encode/StatusResponseEncoder.java b/protocols/imap/src/main/java/org/apache/james/imap/encode/StatusResponseEncoder.java
index 22273e2948..aa03861e64 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/encode/StatusResponseEncoder.java
+++ b/protocols/imap/src/main/java/org/apache/james/imap/encode/StatusResponseEncoder.java
@@ -22,6 +22,8 @@ package org.apache.james.imap.encode;
 import java.io.IOException;
 import java.util.Collection;
 
+import javax.inject.Inject;
+
 import org.apache.james.imap.api.ImapCommand;
 import org.apache.james.imap.api.Tag;
 import org.apache.james.imap.api.display.HumanReadableText;
@@ -35,6 +37,7 @@ import org.apache.james.imap.message.response.ImmutableStatusResponse;
 public class StatusResponseEncoder implements ImapResponseEncoder<ImmutableStatusResponse> {
     private final Localizer localizer;
 
+    @Inject
     public StatusResponseEncoder(Localizer localizer) {
         this.localizer = localizer;
     }
diff --git a/protocols/imap/src/main/java/org/apache/james/imap/encode/main/DefaultImapEncoderFactory.java b/protocols/imap/src/main/java/org/apache/james/imap/encode/main/DefaultImapEncoderFactory.java
index 9208107a5a..d368327e4f 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/encode/main/DefaultImapEncoderFactory.java
+++ b/protocols/imap/src/main/java/org/apache/james/imap/encode/main/DefaultImapEncoderFactory.java
@@ -63,11 +63,11 @@ import com.google.common.collect.ImmutableMap;
  * TODO: perhaps a POJO would be better
  */
 public class DefaultImapEncoderFactory implements ImapEncoderFactory {
-    static class DefaultImapEncoder implements ImapEncoder {
+    public static class DefaultImapEncoder implements ImapEncoder {
         private final Map<Class<? extends ImapMessage>, ImapResponseEncoder> encoders;
         private final EndImapEncoder endImapEncoder;
 
-        DefaultImapEncoder(Stream<ImapResponseEncoder> encoders, EndImapEncoder endImapEncoder) {
+        public DefaultImapEncoder(Stream<ImapResponseEncoder> encoders, EndImapEncoder endImapEncoder) {
             this.encoders = encoders
                 .collect(ImmutableMap.toImmutableMap(
                     ImapResponseEncoder::acceptableMessages,
diff --git a/protocols/imap/src/main/java/org/apache/james/imap/processor/AppendProcessor.java b/protocols/imap/src/main/java/org/apache/james/imap/processor/AppendProcessor.java
index 7837ebe79f..0017d64d0e 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/processor/AppendProcessor.java
+++ b/protocols/imap/src/main/java/org/apache/james/imap/processor/AppendProcessor.java
@@ -24,6 +24,7 @@ import static org.apache.james.util.ReactorUtils.logOnError;
 import java.util.Date;
 import java.util.List;
 
+import javax.inject.Inject;
 import javax.mail.Flags;
 
 import org.apache.james.imap.api.ImapConfiguration;
@@ -62,6 +63,7 @@ public class AppendProcessor extends AbstractMailboxProcessor<AppendRequest> imp
 
     private ImmutableList<Capability> capabilities = ImmutableList.of();
 
+    @Inject
     public AppendProcessor(MailboxManager mailboxManager, StatusResponseFactory statusResponseFactory, MetricFactory metricFactory) {
         super(AppendRequest.class, mailboxManager, statusResponseFactory, metricFactory);
     }
diff --git a/protocols/imap/src/main/java/org/apache/james/imap/processor/AuthenticateProcessor.java b/protocols/imap/src/main/java/org/apache/james/imap/processor/AuthenticateProcessor.java
index c723c204a7..64b5f9e689 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/processor/AuthenticateProcessor.java
+++ b/protocols/imap/src/main/java/org/apache/james/imap/processor/AuthenticateProcessor.java
@@ -26,6 +26,8 @@ import java.util.List;
 import java.util.Optional;
 import java.util.StringTokenizer;
 
+import javax.inject.Inject;
+
 import org.apache.commons.lang3.tuple.Pair;
 import org.apache.james.core.Username;
 import org.apache.james.imap.api.display.HumanReadableText;
@@ -63,11 +65,17 @@ public class AuthenticateProcessor extends AbstractAuthProcessor<AuthenticateReq
     private static final List<Capability> OAUTH_CAPABILITIES = ImmutableList.of(Capability.of("AUTH=" + AUTH_TYPE_OAUTHBEARER), Capability.of("AUTH=" + AUTH_TYPE_XOAUTH2));
     public static final Capability SASL_CAPABILITY = Capability.of("SASL-IR");
 
+    @Inject
     public AuthenticateProcessor(MailboxManager mailboxManager, StatusResponseFactory factory,
                                  MetricFactory metricFactory) {
         super(AuthenticateRequest.class, mailboxManager, factory, metricFactory);
     }
 
+    @Override
+    public List<Class<? extends AuthenticateRequest>> acceptableClasses() {
+        return ImmutableList.of(AuthenticateRequest.class, IRAuthenticateRequest.class);
+    }
+
     @Override
     protected void processRequest(AuthenticateRequest request, ImapSession session, final Responder responder) {
         final String authType = request.getAuthType();
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 25211a9042..690a43f3db 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
@@ -32,6 +32,8 @@ import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
 
+import javax.inject.Inject;
+
 import org.apache.james.imap.api.ImapConfiguration;
 import org.apache.james.imap.api.message.Capability;
 import org.apache.james.imap.api.message.response.StatusResponseFactory;
@@ -59,6 +61,7 @@ public class CapabilityProcessor extends AbstractMailboxProcessor<CapabilityRequ
     private final List<CapabilityImplementingProcessor> capabilities = new ArrayList<>();
     private final Set<Capability> disabledCaps = new HashSet<>();
 
+    @Inject
     public CapabilityProcessor(MailboxManager mailboxManager, StatusResponseFactory factory, MetricFactory metricFactory) {
         super(CapabilityRequest.class, mailboxManager, factory, metricFactory);
         capabilities.add(this);
diff --git a/protocols/imap/src/main/java/org/apache/james/imap/processor/CheckProcessor.java b/protocols/imap/src/main/java/org/apache/james/imap/processor/CheckProcessor.java
index cfe311e5e8..45a4a80732 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/processor/CheckProcessor.java
+++ b/protocols/imap/src/main/java/org/apache/james/imap/processor/CheckProcessor.java
@@ -19,6 +19,8 @@
 
 package org.apache.james.imap.processor;
 
+import javax.inject.Inject;
+
 import org.apache.james.imap.api.message.response.StatusResponseFactory;
 import org.apache.james.imap.api.process.ImapSession;
 import org.apache.james.imap.message.request.CheckRequest;
@@ -30,8 +32,9 @@ import reactor.core.publisher.Mono;
 
 public class CheckProcessor extends AbstractMailboxProcessor<CheckRequest> {
 
+    @Inject
     public CheckProcessor(MailboxManager mailboxManager, StatusResponseFactory factory,
-            MetricFactory metricFactory) {
+                          MetricFactory metricFactory) {
         super(CheckRequest.class, mailboxManager, factory, metricFactory);
     }
 
diff --git a/protocols/imap/src/main/java/org/apache/james/imap/processor/CloseProcessor.java b/protocols/imap/src/main/java/org/apache/james/imap/processor/CloseProcessor.java
index 0b19ba2401..819f535f42 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/processor/CloseProcessor.java
+++ b/protocols/imap/src/main/java/org/apache/james/imap/processor/CloseProcessor.java
@@ -19,6 +19,8 @@
 
 package org.apache.james.imap.processor;
 
+import javax.inject.Inject;
+
 import org.apache.james.imap.api.display.HumanReadableText;
 import org.apache.james.imap.api.message.response.StatusResponseFactory;
 import org.apache.james.imap.api.process.ImapSession;
@@ -41,9 +43,10 @@ import reactor.core.publisher.Mono;
 public class CloseProcessor extends AbstractMailboxProcessor<CloseRequest> {
     private static final Logger LOGGER = LoggerFactory.getLogger(CloseProcessor.class);
 
+    @Inject
     public CloseProcessor(MailboxManager mailboxManager, StatusResponseFactory factory,
-            MetricFactory metricFactory) {
-        super(CloseRequest.class,mailboxManager, factory, metricFactory);
+                          MetricFactory metricFactory) {
+        super(CloseRequest.class, mailboxManager, factory, metricFactory);
     }
 
     @Override
diff --git a/protocols/imap/src/main/java/org/apache/james/imap/processor/CompressProcessor.java b/protocols/imap/src/main/java/org/apache/james/imap/processor/CompressProcessor.java
index a350901647..42b774f6ad 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/processor/CompressProcessor.java
+++ b/protocols/imap/src/main/java/org/apache/james/imap/processor/CompressProcessor.java
@@ -21,6 +21,8 @@ package org.apache.james.imap.processor;
 import java.util.Collections;
 import java.util.List;
 
+import javax.inject.Inject;
+
 import org.apache.james.imap.api.ImapConstants;
 import org.apache.james.imap.api.display.HumanReadableText;
 import org.apache.james.imap.api.message.Capability;
@@ -41,6 +43,7 @@ public class CompressProcessor extends AbstractProcessor<CompressRequest> implem
     private final StatusResponseFactory factory;
     private static final String COMPRESSED = "COMPRESSED";
 
+    @Inject
     public CompressProcessor(StatusResponseFactory factory) {
         super(CompressRequest.class);
         this.factory = factory;
diff --git a/protocols/imap/src/main/java/org/apache/james/imap/processor/CopyProcessor.java b/protocols/imap/src/main/java/org/apache/james/imap/processor/CopyProcessor.java
index 7eca0f79c0..eea8169d66 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/processor/CopyProcessor.java
+++ b/protocols/imap/src/main/java/org/apache/james/imap/processor/CopyProcessor.java
@@ -19,6 +19,8 @@
 
 package org.apache.james.imap.processor;
 
+import javax.inject.Inject;
+
 import org.apache.james.imap.api.message.IdRange;
 import org.apache.james.imap.api.message.response.StatusResponseFactory;
 import org.apache.james.imap.api.process.SelectedMailbox;
@@ -34,8 +36,9 @@ import reactor.core.publisher.Flux;
 
 public class CopyProcessor extends AbstractMessageRangeProcessor<CopyRequest> {
 
+    @Inject
     public CopyProcessor(MailboxManager mailboxManager, StatusResponseFactory factory,
-            MetricFactory metricFactory) {
+                         MetricFactory metricFactory) {
         super(CopyRequest.class, mailboxManager, factory, metricFactory);
     }
 
diff --git a/protocols/imap/src/main/java/org/apache/james/imap/processor/CreateProcessor.java b/protocols/imap/src/main/java/org/apache/james/imap/processor/CreateProcessor.java
index 9e9c21272c..4eb81a25f3 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/processor/CreateProcessor.java
+++ b/protocols/imap/src/main/java/org/apache/james/imap/processor/CreateProcessor.java
@@ -19,6 +19,8 @@
 
 package org.apache.james.imap.processor;
 
+import javax.inject.Inject;
+
 import org.apache.james.imap.api.display.HumanReadableText;
 import org.apache.james.imap.api.message.response.StatusResponse;
 import org.apache.james.imap.api.message.response.StatusResponseFactory;
@@ -39,8 +41,9 @@ import reactor.core.publisher.Mono;
 public class CreateProcessor extends AbstractMailboxProcessor<CreateRequest> {
     private static final Logger LOGGER = LoggerFactory.getLogger(CreateProcessor.class);
 
+    @Inject
     public CreateProcessor(MailboxManager mailboxManager, StatusResponseFactory factory,
-            MetricFactory metricFactory) {
+                           MetricFactory metricFactory) {
         super(CreateRequest.class, mailboxManager, factory, metricFactory);
     }
 
diff --git a/protocols/imap/src/main/java/org/apache/james/imap/processor/DefaultProcessor.java b/protocols/imap/src/main/java/org/apache/james/imap/processor/DefaultProcessor.java
index 6913be379a..3a54c1ce7c 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/processor/DefaultProcessor.java
+++ b/protocols/imap/src/main/java/org/apache/james/imap/processor/DefaultProcessor.java
@@ -20,8 +20,9 @@
 package org.apache.james.imap.processor;
 
 import java.util.Map;
-import java.util.function.Function;
+import java.util.stream.Stream;
 
+import org.apache.commons.lang3.tuple.Pair;
 import org.apache.james.events.EventBus;
 import org.apache.james.imap.api.ImapConfiguration;
 import org.apache.james.imap.api.ImapMessage;
@@ -29,7 +30,6 @@ import org.apache.james.imap.api.message.response.StatusResponseFactory;
 import org.apache.james.imap.api.process.ImapProcessor;
 import org.apache.james.imap.api.process.ImapSession;
 import org.apache.james.imap.api.process.MailboxTyper;
-import org.apache.james.imap.message.request.IRAuthenticateRequest;
 import org.apache.james.imap.processor.base.AbstractProcessor;
 import org.apache.james.imap.processor.base.ImapResponseMessageProcessor;
 import org.apache.james.imap.processor.fetch.FetchProcessor;
@@ -71,8 +71,7 @@ public class DefaultProcessor implements ImapProcessor {
         builder.add(new UnsubscribeProcessor(mailboxManager, subscriptionManager, statusResponseFactory, metricFactory));
         builder.add(new SubscribeProcessor(mailboxManager, subscriptionManager, statusResponseFactory, metricFactory));
         builder.add(new CopyProcessor(mailboxManager, statusResponseFactory, metricFactory));
-        AuthenticateProcessor authenticateProcessor = new AuthenticateProcessor(mailboxManager, statusResponseFactory, metricFactory);
-        builder.add(authenticateProcessor);
+        builder.add(new AuthenticateProcessor(mailboxManager, statusResponseFactory, metricFactory));
         builder.add(new ExpungeProcessor(mailboxManager, statusResponseFactory, metricFactory));
         builder.add(new ExamineProcessor(mailboxManager, eventBus, statusResponseFactory, metricFactory));
         builder.add(new AppendProcessor(mailboxManager, statusResponseFactory, metricFactory));
@@ -85,8 +84,7 @@ public class DefaultProcessor implements ImapProcessor {
         builder.add(new XListProcessor(mailboxManager, statusResponseFactory, mailboxTyper, metricFactory, subscriptionManager));
         builder.add(new ListProcessor<>(mailboxManager, statusResponseFactory, metricFactory, subscriptionManager, statusProcessor, mailboxTyper));
         builder.add(new SearchProcessor(mailboxManager, statusResponseFactory, metricFactory));
-        SelectProcessor selectProcessor = new SelectProcessor(mailboxManager, eventBus, statusResponseFactory, metricFactory);
-        builder.add(selectProcessor);
+        builder.add(new SelectProcessor(mailboxManager, eventBus, statusResponseFactory, metricFactory));
         builder.add(new NamespaceProcessor(mailboxManager, statusResponseFactory, metricFactory));
         builder.add(new FetchProcessor(mailboxManager, statusResponseFactory, metricFactory));
         builder.add(new StartTLSProcessor(statusResponseFactory));
@@ -117,17 +115,24 @@ public class DefaultProcessor implements ImapProcessor {
             .filter(CapabilityImplementingProcessor.class::isInstance)
             .map(CapabilityImplementingProcessor.class::cast)
             .forEach(capabilityProcessor::addProcessor);
-        // add for QRESYNC
-        enableProcessor.addProcessor(selectProcessor);
-
-        ImmutableMap.Builder<Class, ImapProcessor> processorMap = ImmutableMap.<Class, ImapProcessor>builder()
-            .putAll(processors.stream()
-                .collect(ImmutableMap.toImmutableMap(
-                    AbstractProcessor::acceptableClass,
-                    Function.identity())))
-            .put(IRAuthenticateRequest.class, authenticateProcessor);
+        processors.stream()
+            .filter(PermitEnableCapabilityProcessor.class::isInstance)
+            .map(PermitEnableCapabilityProcessor.class::cast)
+            .forEach(enableProcessor::addProcessor);
+
+        ImmutableMap<Class, ImapProcessor> processorMap = processors.stream()
+            .map(AbstractProcessor.class::cast)
+            .flatMap(DefaultProcessor::asPairStream)
+            .collect(ImmutableMap.toImmutableMap(
+                Pair::getLeft,
+                Pair::getRight));
+
+        return new DefaultProcessor(processorMap, chainEndProcessor);
+    }
 
-        return new DefaultProcessor(processorMap.build(), chainEndProcessor);
+    private static Stream<Pair<Class, AbstractProcessor>> asPairStream(AbstractProcessor p) {
+        return p.acceptableClasses()
+            .stream().map(clazz -> Pair.of(clazz, p));
     }
 
     private final Map<Class, ImapProcessor> processorMap;
diff --git a/protocols/imap/src/main/java/org/apache/james/imap/processor/DeleteACLProcessor.java b/protocols/imap/src/main/java/org/apache/james/imap/processor/DeleteACLProcessor.java
index c739eb434b..20d7f1b1e7 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/processor/DeleteACLProcessor.java
+++ b/protocols/imap/src/main/java/org/apache/james/imap/processor/DeleteACLProcessor.java
@@ -21,6 +21,8 @@ package org.apache.james.imap.processor;
 
 import java.util.List;
 
+import javax.inject.Inject;
+
 import org.apache.james.imap.api.ImapConstants;
 import org.apache.james.imap.api.display.HumanReadableText;
 import org.apache.james.imap.api.message.Capability;
@@ -51,6 +53,7 @@ public class DeleteACLProcessor extends AbstractMailboxProcessor<DeleteACLReques
 
     private static final List<Capability> CAPABILITIES = ImmutableList.of(ImapConstants.SUPPORTS_ACL);
 
+    @Inject
     public DeleteACLProcessor(MailboxManager mailboxManager, StatusResponseFactory factory, MetricFactory metricFactory) {
         super(DeleteACLRequest.class, mailboxManager, factory, metricFactory);
     }
diff --git a/protocols/imap/src/main/java/org/apache/james/imap/processor/DeleteProcessor.java b/protocols/imap/src/main/java/org/apache/james/imap/processor/DeleteProcessor.java
index 4d31dc6cec..0efb95605e 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/processor/DeleteProcessor.java
+++ b/protocols/imap/src/main/java/org/apache/james/imap/processor/DeleteProcessor.java
@@ -19,6 +19,8 @@
 
 package org.apache.james.imap.processor;
 
+import javax.inject.Inject;
+
 import org.apache.james.imap.api.display.HumanReadableText;
 import org.apache.james.imap.api.message.response.StatusResponseFactory;
 import org.apache.james.imap.api.process.ImapSession;
@@ -41,6 +43,7 @@ import reactor.core.publisher.Mono;
 public class DeleteProcessor extends AbstractMailboxProcessor<DeleteRequest> {
     private static final Logger LOGGER = LoggerFactory.getLogger(DeleteProcessor.class);
 
+    @Inject
     public DeleteProcessor(MailboxManager mailboxManager, StatusResponseFactory factory, MetricFactory metricFactory) {
         super(DeleteRequest.class, mailboxManager, factory, metricFactory);
     }
diff --git a/protocols/imap/src/main/java/org/apache/james/imap/processor/EnableProcessor.java b/protocols/imap/src/main/java/org/apache/james/imap/processor/EnableProcessor.java
index 69a5b1da7e..8e88469e56 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/processor/EnableProcessor.java
+++ b/protocols/imap/src/main/java/org/apache/james/imap/processor/EnableProcessor.java
@@ -26,6 +26,8 @@ import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
 
+import javax.inject.Inject;
+
 import org.apache.james.imap.api.display.HumanReadableText;
 import org.apache.james.imap.api.message.Capability;
 import org.apache.james.imap.api.message.request.ImapRequest;
@@ -59,11 +61,11 @@ public class EnableProcessor extends AbstractMailboxProcessor<EnableRequest> imp
             MetricFactory metricFactory, CapabilityProcessor capabilityProcessor) {
         this(mailboxManager, factory, metricFactory, capabilityProcessor);
         EnableProcessor.capabilities.addAll(capabilities);
-
     }
 
+    @Inject
     public EnableProcessor(MailboxManager mailboxManager, StatusResponseFactory factory,
-            MetricFactory metricFactory, CapabilityProcessor capabilityProcessor) {
+                           MetricFactory metricFactory, CapabilityProcessor capabilityProcessor) {
         super(EnableRequest.class, mailboxManager, factory, metricFactory);
         this.capabilityProcessor = capabilityProcessor;
     }
diff --git a/protocols/imap/src/main/java/org/apache/james/imap/processor/ExamineProcessor.java b/protocols/imap/src/main/java/org/apache/james/imap/processor/ExamineProcessor.java
index 7456375115..520182fee9 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/processor/ExamineProcessor.java
+++ b/protocols/imap/src/main/java/org/apache/james/imap/processor/ExamineProcessor.java
@@ -22,6 +22,8 @@ package org.apache.james.imap.processor;
 import java.util.Objects;
 import java.util.Optional;
 
+import javax.inject.Inject;
+
 import org.apache.james.events.EventBus;
 import org.apache.james.imap.api.message.IdRange;
 import org.apache.james.imap.api.message.UidRange;
@@ -33,6 +35,7 @@ import org.apache.james.util.MDCBuilder;
 
 public class ExamineProcessor extends AbstractSelectionProcessor<ExamineRequest> {
 
+    @Inject
     public ExamineProcessor(MailboxManager mailboxManager, EventBus eventBus, StatusResponseFactory statusResponseFactory,
                             MetricFactory metricFactory) {
         super(ExamineRequest.class, mailboxManager, statusResponseFactory, true, metricFactory, eventBus);
diff --git a/protocols/imap/src/main/java/org/apache/james/imap/processor/ExpungeProcessor.java b/protocols/imap/src/main/java/org/apache/james/imap/processor/ExpungeProcessor.java
index e6d95a1fea..e39c54259f 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/processor/ExpungeProcessor.java
+++ b/protocols/imap/src/main/java/org/apache/james/imap/processor/ExpungeProcessor.java
@@ -25,6 +25,8 @@ import static org.apache.james.mailbox.MessageManager.MailboxMetaData.RecentMode
 import java.util.EnumSet;
 import java.util.List;
 
+import javax.inject.Inject;
+
 import org.apache.james.imap.api.ImapConstants;
 import org.apache.james.imap.api.display.HumanReadableText;
 import org.apache.james.imap.api.message.Capability;
@@ -58,6 +60,7 @@ public class ExpungeProcessor extends AbstractMailboxProcessor<ExpungeRequest> i
 
     private static final List<Capability> UIDPLUS = ImmutableList.of(SUPPORTS_UIDPLUS);
 
+    @Inject
     public ExpungeProcessor(MailboxManager mailboxManager, StatusResponseFactory factory, MetricFactory metricFactory) {
         super(ExpungeRequest.class, mailboxManager, factory, metricFactory);
     }
diff --git a/protocols/imap/src/main/java/org/apache/james/imap/processor/GetACLProcessor.java b/protocols/imap/src/main/java/org/apache/james/imap/processor/GetACLProcessor.java
index 345d1a5d42..c11951b094 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/processor/GetACLProcessor.java
+++ b/protocols/imap/src/main/java/org/apache/james/imap/processor/GetACLProcessor.java
@@ -24,6 +24,8 @@ import static org.apache.james.mailbox.MessageManager.MailboxMetaData.RecentMode
 import java.util.EnumSet;
 import java.util.List;
 
+import javax.inject.Inject;
+
 import org.apache.james.imap.api.ImapConstants;
 import org.apache.james.imap.api.display.HumanReadableText;
 import org.apache.james.imap.api.message.Capability;
@@ -58,8 +60,9 @@ public class GetACLProcessor extends AbstractMailboxProcessor<GetACLRequest> imp
 
     private static final List<Capability> CAPABILITIES = ImmutableList.of(ImapConstants.SUPPORTS_ACL);
 
+    @Inject
     public GetACLProcessor(MailboxManager mailboxManager, StatusResponseFactory factory,
-            MetricFactory metricFactory) {
+                           MetricFactory metricFactory) {
         super(GetACLRequest.class, mailboxManager, factory, metricFactory);
     }
 
diff --git a/protocols/imap/src/main/java/org/apache/james/imap/processor/GetMetadataProcessor.java b/protocols/imap/src/main/java/org/apache/james/imap/processor/GetMetadataProcessor.java
index 833d96110f..b563b1142c 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/processor/GetMetadataProcessor.java
+++ b/protocols/imap/src/main/java/org/apache/james/imap/processor/GetMetadataProcessor.java
@@ -25,6 +25,8 @@ import java.util.Optional;
 import java.util.Set;
 import java.util.function.Predicate;
 
+import javax.inject.Inject;
+
 import org.apache.commons.lang3.NotImplementedException;
 import org.apache.james.imap.api.ImapConstants;
 import org.apache.james.imap.api.display.HumanReadableText;
@@ -58,15 +60,25 @@ import com.google.common.collect.ImmutableSortedSet;
  */
 public class GetMetadataProcessor extends AbstractMailboxProcessor<GetMetadataRequest> implements CapabilityImplementingProcessor {
     private static final Logger LOGGER = LoggerFactory.getLogger(GetMetadataProcessor.class);
+    private final ImmutableList<Capability> capabilities;
 
+    @Inject
     public GetMetadataProcessor(MailboxManager mailboxManager, StatusResponseFactory factory,
                                 MetricFactory metricFactory) {
         super(GetMetadataRequest.class, mailboxManager, factory, metricFactory);
+        this.capabilities = computeCapabilities();
     }
 
     @Override
     public List<Capability> getImplementedCapabilities(ImapSession session) {
-        return ImmutableList.of(ImapConstants.SUPPORTS_ANNOTATION);
+        return capabilities;
+    }
+
+    private ImmutableList<Capability> computeCapabilities() {
+        return Optional.ofNullable(getMailboxManager().getSupportedMailboxCapabilities())
+            .map(capabilities -> capabilities.contains(MailboxManager.MailboxCapabilities.Annotation))
+            .map(annotationCap -> ImmutableList.of(ImapConstants.SUPPORTS_ANNOTATION))
+            .orElseGet(ImmutableList::of);
     }
 
     @Override
diff --git a/protocols/imap/src/main/java/org/apache/james/imap/processor/GetQuotaProcessor.java b/protocols/imap/src/main/java/org/apache/james/imap/processor/GetQuotaProcessor.java
index 257de7fb5c..b332df2890 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/processor/GetQuotaProcessor.java
+++ b/protocols/imap/src/main/java/org/apache/james/imap/processor/GetQuotaProcessor.java
@@ -21,6 +21,8 @@ package org.apache.james.imap.processor;
 
 import java.util.List;
 
+import javax.inject.Inject;
+
 import org.apache.james.imap.api.ImapConstants;
 import org.apache.james.imap.api.display.HumanReadableText;
 import org.apache.james.imap.api.message.Capability;
@@ -55,8 +57,9 @@ public class GetQuotaProcessor extends AbstractMailboxProcessor<GetQuotaRequest>
     private final QuotaManager quotaManager;
     private final QuotaRootResolver quotaRootResolver;
 
+    @Inject
     public GetQuotaProcessor(MailboxManager mailboxManager, StatusResponseFactory factory, QuotaManager quotaManager, QuotaRootResolver quotaRootResolver,
-            MetricFactory metricFactory) {
+                             MetricFactory metricFactory) {
         super(GetQuotaRequest.class, mailboxManager, factory, metricFactory);
         this.quotaManager = quotaManager;
         this.quotaRootResolver = quotaRootResolver;
diff --git a/protocols/imap/src/main/java/org/apache/james/imap/processor/GetQuotaRootProcessor.java b/protocols/imap/src/main/java/org/apache/james/imap/processor/GetQuotaRootProcessor.java
index d1f761061f..b036ae2747 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/processor/GetQuotaRootProcessor.java
+++ b/protocols/imap/src/main/java/org/apache/james/imap/processor/GetQuotaRootProcessor.java
@@ -21,6 +21,8 @@ package org.apache.james.imap.processor;
 
 import java.util.List;
 
+import javax.inject.Inject;
+
 import org.apache.james.core.quota.QuotaCountLimit;
 import org.apache.james.core.quota.QuotaCountUsage;
 import org.apache.james.core.quota.QuotaSizeLimit;
@@ -59,8 +61,9 @@ public class GetQuotaRootProcessor extends AbstractMailboxProcessor<GetQuotaRoot
     private final QuotaRootResolver quotaRootResolver;
     private final QuotaManager quotaManager;
 
+    @Inject
     public GetQuotaRootProcessor(MailboxManager mailboxManager, StatusResponseFactory factory, QuotaRootResolver quotaRootResolver, QuotaManager quotaManager,
-            MetricFactory metricFactory) {
+                                 MetricFactory metricFactory) {
         super(GetQuotaRootRequest.class, mailboxManager, factory, metricFactory);
         this.quotaRootResolver = quotaRootResolver;
         this.quotaManager = quotaManager;
diff --git a/protocols/imap/src/main/java/org/apache/james/imap/processor/IdProcessor.java b/protocols/imap/src/main/java/org/apache/james/imap/processor/IdProcessor.java
index 9a09c2540d..31be8fccfe 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/processor/IdProcessor.java
+++ b/protocols/imap/src/main/java/org/apache/james/imap/processor/IdProcessor.java
@@ -21,6 +21,8 @@ package org.apache.james.imap.processor;
 
 import java.util.List;
 
+import javax.inject.Inject;
+
 import org.apache.james.imap.api.message.Capability;
 import org.apache.james.imap.api.message.response.StatusResponseFactory;
 import org.apache.james.imap.api.process.ImapSession;
@@ -41,6 +43,7 @@ public class IdProcessor extends AbstractMailboxProcessor<IDRequest> implements
     private static final Logger LOGGER = LoggerFactory.getLogger(IdProcessor.class);
     private static final ImmutableList<Capability> CAPABILITIES = ImmutableList.of(Capability.of("ID"));
 
+    @Inject
     public IdProcessor(MailboxManager mailboxManager, StatusResponseFactory factory, MetricFactory metricFactory) {
         super(IDRequest.class, mailboxManager, factory, metricFactory);
     }
diff --git a/protocols/imap/src/main/java/org/apache/james/imap/processor/IdleProcessor.java b/protocols/imap/src/main/java/org/apache/james/imap/processor/IdleProcessor.java
index 29e92276b2..a8cb8d5f53 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/processor/IdleProcessor.java
+++ b/protocols/imap/src/main/java/org/apache/james/imap/processor/IdleProcessor.java
@@ -26,6 +26,8 @@ import java.util.List;
 import java.util.Locale;
 import java.util.concurrent.atomic.AtomicBoolean;
 
+import javax.inject.Inject;
+
 import org.apache.james.events.Event;
 import org.apache.james.events.EventListener;
 import org.apache.james.imap.api.ImapConfiguration;
@@ -61,6 +63,7 @@ public class IdleProcessor extends AbstractMailboxProcessor<IdleRequest> impleme
     private Duration heartbeatInterval;
     private boolean enableIdle;
 
+    @Inject
     public IdleProcessor(MailboxManager mailboxManager, StatusResponseFactory factory,
                          MetricFactory metricFactory) {
         super(IdleRequest.class, mailboxManager, factory, metricFactory);
diff --git a/protocols/imap/src/main/java/org/apache/james/imap/processor/LSubProcessor.java b/protocols/imap/src/main/java/org/apache/james/imap/processor/LSubProcessor.java
index ad87a9bb09..878f7c7eb7 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/processor/LSubProcessor.java
+++ b/protocols/imap/src/main/java/org/apache/james/imap/processor/LSubProcessor.java
@@ -23,6 +23,8 @@ import java.util.ArrayList;
 import java.util.Collection;
 import java.util.List;
 
+import javax.inject.Inject;
+
 import org.apache.james.imap.api.display.HumanReadableText;
 import org.apache.james.imap.api.display.ModifiedUtf7;
 import org.apache.james.imap.api.message.response.StatusResponseFactory;
@@ -51,8 +53,9 @@ public class LSubProcessor extends AbstractMailboxProcessor<LsubRequest> {
 
     private final SubscriptionManager subscriptionManager;
 
+    @Inject
     public LSubProcessor(MailboxManager mailboxManager, SubscriptionManager subscriptionManager, StatusResponseFactory factory,
-            MetricFactory metricFactory) {
+                         MetricFactory metricFactory) {
         super(LsubRequest.class, mailboxManager, factory, metricFactory);
         this.subscriptionManager = subscriptionManager;
     }
diff --git a/protocols/imap/src/main/java/org/apache/james/imap/processor/ListProcessor.java b/protocols/imap/src/main/java/org/apache/james/imap/processor/ListProcessor.java
index 559529b9ba..a39cd7f1af 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/processor/ListProcessor.java
+++ b/protocols/imap/src/main/java/org/apache/james/imap/processor/ListProcessor.java
@@ -32,6 +32,8 @@ import java.util.function.Function;
 import java.util.function.Predicate;
 import java.util.stream.Collectors;
 
+import javax.inject.Inject;
+
 import org.apache.commons.lang3.tuple.Pair;
 import org.apache.commons.lang3.tuple.Triple;
 import org.apache.james.imap.api.display.HumanReadableText;
@@ -86,6 +88,7 @@ public class ListProcessor<T extends ListRequest> extends AbstractMailboxProcess
     private final StatusProcessor statusProcessor;
     protected final MailboxTyper mailboxTyper;
 
+    @Inject
     public ListProcessor(MailboxManager mailboxManager, StatusResponseFactory factory,
                          MetricFactory metricFactory, SubscriptionManager subscriptionManager,
                          StatusProcessor statusProcessor, MailboxTyper mailboxTyper) {
diff --git a/protocols/imap/src/main/java/org/apache/james/imap/processor/ListRightsProcessor.java b/protocols/imap/src/main/java/org/apache/james/imap/processor/ListRightsProcessor.java
index a64e4e0558..0e039ff09e 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/processor/ListRightsProcessor.java
+++ b/protocols/imap/src/main/java/org/apache/james/imap/processor/ListRightsProcessor.java
@@ -21,6 +21,8 @@ package org.apache.james.imap.processor;
 
 import java.util.List;
 
+import javax.inject.Inject;
+
 import org.apache.james.imap.api.ImapConstants;
 import org.apache.james.imap.api.display.HumanReadableText;
 import org.apache.james.imap.api.message.Capability;
@@ -57,8 +59,9 @@ public class ListRightsProcessor extends AbstractMailboxProcessor<ListRightsRequ
 
     private static final List<Capability> CAPABILITIES = ImmutableList.of(ImapConstants.SUPPORTS_ACL);
 
+    @Inject
     public ListRightsProcessor(MailboxManager mailboxManager, StatusResponseFactory factory,
-            MetricFactory metricFactory) {
+                               MetricFactory metricFactory) {
         super(ListRightsRequest.class, mailboxManager, factory, metricFactory);
     }
 
diff --git a/protocols/imap/src/main/java/org/apache/james/imap/processor/LoginProcessor.java b/protocols/imap/src/main/java/org/apache/james/imap/processor/LoginProcessor.java
index 223e3b1d66..673d7c5a63 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/processor/LoginProcessor.java
+++ b/protocols/imap/src/main/java/org/apache/james/imap/processor/LoginProcessor.java
@@ -22,6 +22,8 @@ package org.apache.james.imap.processor;
 import java.util.Collections;
 import java.util.List;
 
+import javax.inject.Inject;
+
 import org.apache.james.imap.api.display.HumanReadableText;
 import org.apache.james.imap.api.message.Capability;
 import org.apache.james.imap.api.message.response.StatusResponseFactory;
@@ -38,7 +40,8 @@ import com.google.common.collect.ImmutableList;
  */
 public class LoginProcessor extends AbstractAuthProcessor<LoginRequest> implements CapabilityImplementingProcessor {
     private static final List<Capability> LOGINDISABLED_CAPS = ImmutableList.of(Capability.of("LOGINDISABLED"));
-    
+
+    @Inject
     public LoginProcessor(MailboxManager mailboxManager, StatusResponseFactory factory, MetricFactory metricFactory) {
         super(LoginRequest.class, mailboxManager, factory, metricFactory);
     }
diff --git a/protocols/imap/src/main/java/org/apache/james/imap/processor/LogoutProcessor.java b/protocols/imap/src/main/java/org/apache/james/imap/processor/LogoutProcessor.java
index 165301134a..547e2bfc6e 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/processor/LogoutProcessor.java
+++ b/protocols/imap/src/main/java/org/apache/james/imap/processor/LogoutProcessor.java
@@ -19,6 +19,8 @@
 
 package org.apache.james.imap.processor;
 
+import javax.inject.Inject;
+
 import org.apache.james.imap.api.message.response.StatusResponseFactory;
 import org.apache.james.imap.api.process.ImapSession;
 import org.apache.james.imap.message.request.LogoutRequest;
@@ -30,8 +32,9 @@ import org.apache.james.util.MDCBuilder;
 import reactor.core.publisher.Mono;
 
 public class LogoutProcessor extends AbstractMailboxProcessor<LogoutRequest> {
+    @Inject
     public LogoutProcessor(MailboxManager mailboxManager, StatusResponseFactory factory,
-            MetricFactory metricFactory) {
+                           MetricFactory metricFactory) {
         super(LogoutRequest.class, mailboxManager, factory, metricFactory);
     }
 
diff --git a/protocols/imap/src/main/java/org/apache/james/imap/processor/MoveProcessor.java b/protocols/imap/src/main/java/org/apache/james/imap/processor/MoveProcessor.java
index 5c01ca90b8..bdac6e4fdd 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/processor/MoveProcessor.java
+++ b/protocols/imap/src/main/java/org/apache/james/imap/processor/MoveProcessor.java
@@ -21,6 +21,8 @@ package org.apache.james.imap.processor;
 
 import java.util.List;
 
+import javax.inject.Inject;
+
 import org.apache.james.imap.api.ImapConstants;
 import org.apache.james.imap.api.message.Capability;
 import org.apache.james.imap.api.message.IdRange;
@@ -43,8 +45,9 @@ public class MoveProcessor extends AbstractMessageRangeProcessor<MoveRequest> im
 
     private final boolean moveCapabilitySupported;
 
+    @Inject
     public MoveProcessor(MailboxManager mailboxManager, StatusResponseFactory factory,
-            MetricFactory metricFactory) {
+                         MetricFactory metricFactory) {
         super(MoveRequest.class, mailboxManager, factory, metricFactory);
         moveCapabilitySupported = mailboxManager.hasCapability(MailboxManager.MailboxCapabilities.Move);
     }
diff --git a/protocols/imap/src/main/java/org/apache/james/imap/processor/MyRightsProcessor.java b/protocols/imap/src/main/java/org/apache/james/imap/processor/MyRightsProcessor.java
index f113f8a778..d588c90caa 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/processor/MyRightsProcessor.java
+++ b/protocols/imap/src/main/java/org/apache/james/imap/processor/MyRightsProcessor.java
@@ -22,6 +22,8 @@ package org.apache.james.imap.processor;
 import java.util.Collections;
 import java.util.List;
 
+import javax.inject.Inject;
+
 import org.apache.james.imap.api.ImapConstants;
 import org.apache.james.imap.api.display.HumanReadableText;
 import org.apache.james.imap.api.message.Capability;
@@ -55,6 +57,7 @@ public class MyRightsProcessor extends AbstractMailboxProcessor<MyRightsRequest>
 
     private static final List<Capability> CAPABILITIES = Collections.singletonList(ImapConstants.SUPPORTS_ACL);
 
+    @Inject
     public MyRightsProcessor(MailboxManager mailboxManager, StatusResponseFactory factory, MetricFactory metricFactory) {
         super(MyRightsRequest.class, mailboxManager, factory, metricFactory);
     }
diff --git a/protocols/imap/src/main/java/org/apache/james/imap/processor/NamespaceProcessor.java b/protocols/imap/src/main/java/org/apache/james/imap/processor/NamespaceProcessor.java
index 9f618436d3..6adf7164ad 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/processor/NamespaceProcessor.java
+++ b/protocols/imap/src/main/java/org/apache/james/imap/processor/NamespaceProcessor.java
@@ -24,6 +24,8 @@ import java.util.ArrayList;
 import java.util.Collection;
 import java.util.List;
 
+import javax.inject.Inject;
+
 import org.apache.james.imap.api.message.Capability;
 import org.apache.james.imap.api.message.response.StatusResponseFactory;
 import org.apache.james.imap.api.process.ImapSession;
@@ -43,7 +45,8 @@ import reactor.core.publisher.Mono;
  */
 public class NamespaceProcessor extends AbstractMailboxProcessor<NamespaceRequest> implements CapabilityImplementingProcessor {
     private static final List<Capability> CAPS = ImmutableList.of(SUPPORTS_NAMESPACES);
-    
+
+    @Inject
     public NamespaceProcessor(MailboxManager mailboxManager, StatusResponseFactory factory, MetricFactory metricFactory) {
         super(NamespaceRequest.class, mailboxManager, factory, metricFactory);
     }
diff --git a/protocols/imap/src/main/java/org/apache/james/imap/processor/NoopProcessor.java b/protocols/imap/src/main/java/org/apache/james/imap/processor/NoopProcessor.java
index 37f9abe01c..6016c87ac7 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/processor/NoopProcessor.java
+++ b/protocols/imap/src/main/java/org/apache/james/imap/processor/NoopProcessor.java
@@ -19,6 +19,8 @@
 
 package org.apache.james.imap.processor;
 
+import javax.inject.Inject;
+
 import org.apache.james.imap.api.message.response.StatusResponseFactory;
 import org.apache.james.imap.api.process.ImapSession;
 import org.apache.james.imap.message.request.NoopRequest;
@@ -29,6 +31,8 @@ import org.apache.james.util.MDCBuilder;
 import reactor.core.publisher.Mono;
 
 public class NoopProcessor extends AbstractMailboxProcessor<NoopRequest> {
+
+    @Inject
     public NoopProcessor(MailboxManager mailboxManager, StatusResponseFactory factory, MetricFactory metricFactory) {
         super(NoopRequest.class, mailboxManager, factory, metricFactory);
     }
diff --git a/protocols/imap/src/main/java/org/apache/james/imap/processor/RenameProcessor.java b/protocols/imap/src/main/java/org/apache/james/imap/processor/RenameProcessor.java
index cd709e5d38..b572376882 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/processor/RenameProcessor.java
+++ b/protocols/imap/src/main/java/org/apache/james/imap/processor/RenameProcessor.java
@@ -21,6 +21,8 @@ package org.apache.james.imap.processor;
 
 import static org.apache.james.util.ReactorUtils.logAsMono;
 
+import javax.inject.Inject;
+
 import org.apache.james.imap.api.ImapConstants;
 import org.apache.james.imap.api.display.HumanReadableText;
 import org.apache.james.imap.api.message.response.StatusResponseFactory;
@@ -43,8 +45,9 @@ import reactor.core.publisher.Mono;
 public class RenameProcessor extends AbstractMailboxProcessor<RenameRequest> {
     private static final Logger LOGGER = LoggerFactory.getLogger(RenameProcessor.class);
 
+    @Inject
     public RenameProcessor(MailboxManager mailboxManager, StatusResponseFactory factory,
-            MetricFactory metricFactory) {
+                           MetricFactory metricFactory) {
         super(RenameRequest.class, mailboxManager, factory, metricFactory);
     }
 
diff --git a/protocols/imap/src/main/java/org/apache/james/imap/processor/SearchProcessor.java b/protocols/imap/src/main/java/org/apache/james/imap/processor/SearchProcessor.java
index fa1b9afb48..eb3ea375f2 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/processor/SearchProcessor.java
+++ b/protocols/imap/src/main/java/org/apache/james/imap/processor/SearchProcessor.java
@@ -29,6 +29,7 @@ import java.util.EnumSet;
 import java.util.List;
 import java.util.Optional;
 
+import javax.inject.Inject;
 import javax.mail.Flags.Flag;
 
 import org.apache.james.imap.api.ImapConstants;
@@ -82,9 +83,10 @@ public class SearchProcessor extends AbstractMailboxProcessor<SearchRequest> imp
 
     protected static final String SEARCH_MODSEQ = "SEARCH_MODSEQ";
     private static final List<Capability> CAPS = ImmutableList.of(Capability.of("WITHIN"), Capability.of("ESEARCH"), Capability.of("SEARCHRES"));
-    
+
+    @Inject
     public SearchProcessor(MailboxManager mailboxManager, StatusResponseFactory factory,
-            MetricFactory metricFactory) {
+                           MetricFactory metricFactory) {
         super(SearchRequest.class, mailboxManager, factory, metricFactory);
     }
 
diff --git a/protocols/imap/src/main/java/org/apache/james/imap/processor/SelectProcessor.java b/protocols/imap/src/main/java/org/apache/james/imap/processor/SelectProcessor.java
index 3a972f6470..b69bf9ded2 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/processor/SelectProcessor.java
+++ b/protocols/imap/src/main/java/org/apache/james/imap/processor/SelectProcessor.java
@@ -22,6 +22,8 @@ package org.apache.james.imap.processor;
 import java.util.Objects;
 import java.util.Optional;
 
+import javax.inject.Inject;
+
 import org.apache.james.events.EventBus;
 import org.apache.james.imap.api.message.IdRange;
 import org.apache.james.imap.api.message.UidRange;
@@ -33,6 +35,7 @@ import org.apache.james.util.MDCBuilder;
 
 public class SelectProcessor extends AbstractSelectionProcessor<SelectRequest> {
 
+    @Inject
     public SelectProcessor(MailboxManager mailboxManager, EventBus eventBus, StatusResponseFactory statusResponseFactory,
                            MetricFactory metricFactory) {
         super(SelectRequest.class, mailboxManager, statusResponseFactory, false, metricFactory, eventBus);
diff --git a/protocols/imap/src/main/java/org/apache/james/imap/processor/SetACLProcessor.java b/protocols/imap/src/main/java/org/apache/james/imap/processor/SetACLProcessor.java
index 7b47702c8f..269963abc0 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/processor/SetACLProcessor.java
+++ b/protocols/imap/src/main/java/org/apache/james/imap/processor/SetACLProcessor.java
@@ -21,6 +21,8 @@ package org.apache.james.imap.processor;
 
 import java.util.List;
 
+import javax.inject.Inject;
+
 import org.apache.james.imap.api.ImapConstants;
 import org.apache.james.imap.api.display.HumanReadableText;
 import org.apache.james.imap.api.message.Capability;
@@ -53,8 +55,9 @@ public class SetACLProcessor extends AbstractMailboxProcessor<SetACLRequest> imp
 
     private static final List<Capability> CAPABILITIES = ImmutableList.of(ImapConstants.SUPPORTS_ACL);
 
+    @Inject
     public SetACLProcessor(MailboxManager mailboxManager, StatusResponseFactory factory,
-            MetricFactory metricFactory) {
+                           MetricFactory metricFactory) {
         super(SetACLRequest.class, mailboxManager, factory, metricFactory);
     }
 
diff --git a/protocols/imap/src/main/java/org/apache/james/imap/processor/SetMetadataProcessor.java b/protocols/imap/src/main/java/org/apache/james/imap/processor/SetMetadataProcessor.java
index c50497d88a..4b9bc686ab 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/processor/SetMetadataProcessor.java
+++ b/protocols/imap/src/main/java/org/apache/james/imap/processor/SetMetadataProcessor.java
@@ -20,6 +20,9 @@
 package org.apache.james.imap.processor;
 
 import java.util.List;
+import java.util.Optional;
+
+import javax.inject.Inject;
 
 import org.apache.james.imap.api.ImapConstants;
 import org.apache.james.imap.api.display.HumanReadableText;
@@ -49,15 +52,25 @@ import com.google.common.collect.ImmutableList;
  */
 public class SetMetadataProcessor extends AbstractMailboxProcessor<SetMetadataRequest> implements CapabilityImplementingProcessor {
     private static final Logger LOGGER = LoggerFactory.getLogger(SetMetadataProcessor.class);
+    private final ImmutableList<Capability> capabilities;
 
+    @Inject
     public SetMetadataProcessor(MailboxManager mailboxManager, StatusResponseFactory factory,
                                 MetricFactory metricFactory) {
         super(SetMetadataRequest.class, mailboxManager, factory, metricFactory);
+        this.capabilities = computeCapabilities();
     }
 
     @Override
     public List<Capability> getImplementedCapabilities(ImapSession session) {
-        return ImmutableList.of(ImapConstants.SUPPORTS_ANNOTATION);
+        return capabilities;
+    }
+
+    private ImmutableList<Capability> computeCapabilities() {
+        return Optional.ofNullable(getMailboxManager().getSupportedMailboxCapabilities())
+            .map(capabilities -> capabilities.contains(MailboxManager.MailboxCapabilities.Annotation))
+            .map(annotationCap -> ImmutableList.of(ImapConstants.SUPPORTS_ANNOTATION))
+            .orElseGet(ImmutableList::of);
     }
 
     @Override
diff --git a/protocols/imap/src/main/java/org/apache/james/imap/processor/SetQuotaProcessor.java b/protocols/imap/src/main/java/org/apache/james/imap/processor/SetQuotaProcessor.java
index cbf33f95dc..c93e7d5290 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/processor/SetQuotaProcessor.java
+++ b/protocols/imap/src/main/java/org/apache/james/imap/processor/SetQuotaProcessor.java
@@ -21,6 +21,8 @@ package org.apache.james.imap.processor;
 
 import java.util.List;
 
+import javax.inject.Inject;
+
 import org.apache.james.imap.api.ImapConstants;
 import org.apache.james.imap.api.display.HumanReadableText;
 import org.apache.james.imap.api.message.Capability;
@@ -41,8 +43,9 @@ import reactor.core.publisher.Mono;
 public class SetQuotaProcessor extends AbstractMailboxProcessor<SetQuotaRequest> implements CapabilityImplementingProcessor {
     private static final List<Capability> CAPABILITIES = ImmutableList.of(ImapConstants.SUPPORTS_QUOTA);
 
+    @Inject
     public SetQuotaProcessor(MailboxManager mailboxManager, StatusResponseFactory factory,
-            MetricFactory metricFactory) {
+                             MetricFactory metricFactory) {
         super(SetQuotaRequest.class, mailboxManager, factory, metricFactory);
     }
 
diff --git a/protocols/imap/src/main/java/org/apache/james/imap/processor/StartTLSProcessor.java b/protocols/imap/src/main/java/org/apache/james/imap/processor/StartTLSProcessor.java
index 7882e9d69a..fabe1366c4 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/processor/StartTLSProcessor.java
+++ b/protocols/imap/src/main/java/org/apache/james/imap/processor/StartTLSProcessor.java
@@ -21,6 +21,8 @@ package org.apache.james.imap.processor;
 import java.util.Collections;
 import java.util.List;
 
+import javax.inject.Inject;
+
 import org.apache.james.imap.api.ImapConstants;
 import org.apache.james.imap.api.display.HumanReadableText;
 import org.apache.james.imap.api.message.Capability;
@@ -41,6 +43,7 @@ public class StartTLSProcessor extends AbstractProcessor<StartTLSRequest> implem
     private static final List<Capability> STARTTLS_CAP = ImmutableList.of(ImapConstants.SUPPORTS_STARTTLS);
     private final StatusResponseFactory factory;
 
+    @Inject
     public StartTLSProcessor(StatusResponseFactory factory) {
         super(StartTLSRequest.class);
         this.factory = factory;
diff --git a/protocols/imap/src/main/java/org/apache/james/imap/processor/StatusProcessor.java b/protocols/imap/src/main/java/org/apache/james/imap/processor/StatusProcessor.java
index 1b513bd1a7..c8af849e96 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/processor/StatusProcessor.java
+++ b/protocols/imap/src/main/java/org/apache/james/imap/processor/StatusProcessor.java
@@ -26,6 +26,7 @@ import java.util.EnumSet;
 import java.util.List;
 import java.util.Optional;
 
+import javax.inject.Inject;
 import javax.mail.Flags;
 
 import org.apache.james.imap.api.ImapConfiguration;
@@ -74,8 +75,9 @@ public class StatusProcessor extends AbstractMailboxProcessor<StatusRequest> imp
 
     private ImapConfiguration imapConfiguration;
 
+    @Inject
     public StatusProcessor(MailboxManager mailboxManager, StatusResponseFactory factory,
-            MetricFactory metricFactory) {
+                           MetricFactory metricFactory) {
         super(StatusRequest.class, mailboxManager, factory, metricFactory);
     }
 
diff --git a/protocols/imap/src/main/java/org/apache/james/imap/processor/StoreProcessor.java b/protocols/imap/src/main/java/org/apache/james/imap/processor/StoreProcessor.java
index d8e625845f..71acdae0a3 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/processor/StoreProcessor.java
+++ b/protocols/imap/src/main/java/org/apache/james/imap/processor/StoreProcessor.java
@@ -29,6 +29,7 @@ import java.util.Map;
 import java.util.Optional;
 import java.util.Set;
 
+import javax.inject.Inject;
 import javax.mail.Flags;
 
 import org.apache.james.imap.api.ImapConstants;
@@ -69,9 +70,10 @@ import reactor.core.publisher.Mono;
 
 public class StoreProcessor extends AbstractMailboxProcessor<StoreRequest> {
     private static final Logger LOGGER = LoggerFactory.getLogger(StoreProcessor.class);
-    
+
+    @Inject
     public StoreProcessor(MailboxManager mailboxManager, StatusResponseFactory factory,
-            MetricFactory metricFactory) {
+                          MetricFactory metricFactory) {
         super(StoreRequest.class, mailboxManager, factory, metricFactory);
     }
 
diff --git a/protocols/imap/src/main/java/org/apache/james/imap/processor/SubscribeProcessor.java b/protocols/imap/src/main/java/org/apache/james/imap/processor/SubscribeProcessor.java
index 1b36a638b7..d0b37c4699 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/processor/SubscribeProcessor.java
+++ b/protocols/imap/src/main/java/org/apache/james/imap/processor/SubscribeProcessor.java
@@ -19,6 +19,8 @@
 
 package org.apache.james.imap.processor;
 
+import javax.inject.Inject;
+
 import org.apache.james.imap.api.display.HumanReadableText;
 import org.apache.james.imap.api.message.response.StatusResponseFactory;
 import org.apache.james.imap.api.process.ImapSession;
@@ -40,8 +42,9 @@ import reactor.core.publisher.Mono;
 public class SubscribeProcessor extends AbstractSubscriptionProcessor<SubscribeRequest> {
     private static final Logger LOGGER = LoggerFactory.getLogger(SubscribeProcessor.class);
 
+    @Inject
     public SubscribeProcessor(MailboxManager mailboxManager, SubscriptionManager subscriptionManager, StatusResponseFactory factory,
-            MetricFactory metricFactory) {
+                              MetricFactory metricFactory) {
         super(SubscribeRequest.class, mailboxManager, subscriptionManager, factory, metricFactory);
     }
 
diff --git a/protocols/imap/src/main/java/org/apache/james/imap/processor/SystemMessageProcessor.java b/protocols/imap/src/main/java/org/apache/james/imap/processor/SystemMessageProcessor.java
index d202f0d659..26d0c310b6 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/processor/SystemMessageProcessor.java
+++ b/protocols/imap/src/main/java/org/apache/james/imap/processor/SystemMessageProcessor.java
@@ -19,6 +19,8 @@
 
 package org.apache.james.imap.processor;
 
+import javax.inject.Inject;
+
 import org.apache.james.imap.api.process.ImapSession;
 import org.apache.james.imap.message.request.SystemMessage;
 import org.apache.james.imap.processor.base.AbstractProcessor;
@@ -38,6 +40,7 @@ public class SystemMessageProcessor extends AbstractProcessor<SystemMessage> {
 
     private final MailboxManager mailboxManager;
 
+    @Inject
     public SystemMessageProcessor(MailboxManager mailboxManager) {
         super(SystemMessage.class);
         this.mailboxManager = mailboxManager;
diff --git a/protocols/imap/src/main/java/org/apache/james/imap/processor/UnselectProcessor.java b/protocols/imap/src/main/java/org/apache/james/imap/processor/UnselectProcessor.java
index 2e156cb5aa..1b7aa39365 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/processor/UnselectProcessor.java
+++ b/protocols/imap/src/main/java/org/apache/james/imap/processor/UnselectProcessor.java
@@ -22,6 +22,8 @@ import static org.apache.james.imap.api.ImapConstants.SUPPORTS_UNSELECT;
 
 import java.util.List;
 
+import javax.inject.Inject;
+
 import org.apache.james.imap.api.display.HumanReadableText;
 import org.apache.james.imap.api.message.Capability;
 import org.apache.james.imap.api.message.response.StatusResponseFactory;
@@ -43,8 +45,9 @@ import reactor.core.publisher.Mono;
 public class UnselectProcessor extends AbstractMailboxProcessor<UnselectRequest> implements CapabilityImplementingProcessor {
     private static final List<Capability> UNSELECT = ImmutableList.of(SUPPORTS_UNSELECT);
 
+    @Inject
     public UnselectProcessor(MailboxManager mailboxManager, StatusResponseFactory factory,
-            MetricFactory metricFactory) {
+                             MetricFactory metricFactory) {
         super(UnselectRequest.class, mailboxManager, factory, metricFactory);
     }
 
diff --git a/protocols/imap/src/main/java/org/apache/james/imap/processor/UnsubscribeProcessor.java b/protocols/imap/src/main/java/org/apache/james/imap/processor/UnsubscribeProcessor.java
index ef7c8457cf..02825d2f35 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/processor/UnsubscribeProcessor.java
+++ b/protocols/imap/src/main/java/org/apache/james/imap/processor/UnsubscribeProcessor.java
@@ -21,6 +21,8 @@ package org.apache.james.imap.processor;
 
 import static org.apache.james.util.ReactorUtils.logOnError;
 
+import javax.inject.Inject;
+
 import org.apache.james.imap.api.display.HumanReadableText;
 import org.apache.james.imap.api.message.response.StatusResponseFactory;
 import org.apache.james.imap.api.process.ImapSession;
@@ -41,8 +43,9 @@ import reactor.core.publisher.Mono;
 public class UnsubscribeProcessor extends AbstractSubscriptionProcessor<UnsubscribeRequest> {
     private static final Logger LOGGER = LoggerFactory.getLogger(UnsubscribeProcessor.class);
 
+    @Inject
     public UnsubscribeProcessor(MailboxManager mailboxManager, SubscriptionManager subscriptionManager, StatusResponseFactory factory,
-            MetricFactory metricFactory) {
+                                MetricFactory metricFactory) {
         super(UnsubscribeRequest.class, mailboxManager, subscriptionManager, factory, metricFactory);
     }
 
diff --git a/protocols/imap/src/main/java/org/apache/james/imap/processor/XListProcessor.java b/protocols/imap/src/main/java/org/apache/james/imap/processor/XListProcessor.java
index b6cf974c1b..1e7f53e350 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/processor/XListProcessor.java
+++ b/protocols/imap/src/main/java/org/apache/james/imap/processor/XListProcessor.java
@@ -23,6 +23,8 @@ import static org.apache.james.imap.api.ImapConstants.SUPPORTS_XLIST;
 import java.util.Collections;
 import java.util.List;
 
+import javax.inject.Inject;
+
 import org.apache.james.imap.api.message.Capability;
 import org.apache.james.imap.api.message.response.ImapResponseMessage;
 import org.apache.james.imap.api.message.response.StatusResponseFactory;
@@ -47,6 +49,12 @@ public class XListProcessor extends ListProcessor<XListRequest> implements Capab
 
     private static final List<Capability> XLIST_CAPS = ImmutableList.of(SUPPORTS_XLIST);
 
+    @Inject
+    public XListProcessor(MailboxManager mailboxManager, StatusResponseFactory factory, MetricFactory metricFactory,
+                          SubscriptionManager subscriptionManager) {
+        this(mailboxManager, factory, null, metricFactory, subscriptionManager);
+    }
+
     public XListProcessor(MailboxManager mailboxManager, StatusResponseFactory factory, MailboxTyper mailboxTyper,
                           MetricFactory metricFactory, SubscriptionManager subscriptionManager) {
         super(XListRequest.class, mailboxManager, factory, metricFactory, subscriptionManager, null, mailboxTyper);
diff --git a/protocols/imap/src/main/java/org/apache/james/imap/processor/base/AbstractProcessor.java b/protocols/imap/src/main/java/org/apache/james/imap/processor/base/AbstractProcessor.java
index 432adb204a..a8e6239ff4 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/processor/base/AbstractProcessor.java
+++ b/protocols/imap/src/main/java/org/apache/james/imap/processor/base/AbstractProcessor.java
@@ -19,6 +19,8 @@
 
 package org.apache.james.imap.processor.base;
 
+import java.util.List;
+
 import org.apache.james.imap.api.ImapConfiguration;
 import org.apache.james.imap.api.ImapMessage;
 import org.apache.james.imap.api.process.ImapProcessor;
@@ -28,6 +30,8 @@ import org.apache.james.util.ReactorUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import com.google.common.collect.ImmutableList;
+
 import reactor.core.publisher.Mono;
 
 public abstract class AbstractProcessor<M extends ImapMessage> implements ImapProcessor {
@@ -64,10 +68,14 @@ public abstract class AbstractProcessor<M extends ImapMessage> implements ImapPr
 
     }
 
-    public Class<M> acceptableClass() {
+    protected Class<M> acceptableClass() {
         return acceptableClass;
     }
 
+    public List<Class<? extends M>> acceptableClasses() {
+        return ImmutableList.of(acceptableClass);
+    }
+
     /**
      * Processes an acceptable message. Errors are managed.
      * 
diff --git a/protocols/imap/src/main/java/org/apache/james/imap/processor/fetch/FetchProcessor.java b/protocols/imap/src/main/java/org/apache/james/imap/processor/fetch/FetchProcessor.java
index 23f6327ce5..efc324e648 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/processor/fetch/FetchProcessor.java
+++ b/protocols/imap/src/main/java/org/apache/james/imap/processor/fetch/FetchProcessor.java
@@ -28,6 +28,8 @@ import java.util.List;
 import java.util.Optional;
 import java.util.Set;
 
+import javax.inject.Inject;
+
 import org.apache.james.imap.api.ImapConstants;
 import org.apache.james.imap.api.display.HumanReadableText;
 import org.apache.james.imap.api.message.Capability;
@@ -64,6 +66,7 @@ import reactor.core.publisher.Mono;
 public class FetchProcessor extends AbstractMailboxProcessor<FetchRequest> {
     private static final Logger LOGGER = LoggerFactory.getLogger(FetchProcessor.class);
 
+    @Inject
     public FetchProcessor(MailboxManager mailboxManager, StatusResponseFactory factory,
                           MetricFactory metricFactory) {
         super(FetchRequest.class, mailboxManager, factory, metricFactory);
diff --git a/protocols/imap/src/test/java/org/apache/james/imap/processor/GetAnnotationProcessorTest.java b/protocols/imap/src/test/java/org/apache/james/imap/processor/GetAnnotationProcessorTest.java
index 9d42c71203..6daee8a4ed 100644
--- a/protocols/imap/src/test/java/org/apache/james/imap/processor/GetAnnotationProcessorTest.java
+++ b/protocols/imap/src/test/java/org/apache/james/imap/processor/GetAnnotationProcessorTest.java
@@ -30,6 +30,7 @@ import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.verifyNoMoreInteractions;
 import static org.mockito.Mockito.when;
 
+import java.util.EnumSet;
 import java.util.Optional;
 import java.util.Set;
 
@@ -96,6 +97,7 @@ class GetAnnotationProcessorTest {
     private void initAndMockData() {
         statusResponse = mock(StatusResponse.class);
         mockMailboxManager = mock(MailboxManager.class);
+        when(mockMailboxManager.getSupportedMailboxCapabilities()).thenReturn(EnumSet.of(MailboxManager.MailboxCapabilities.Annotation));
         when(mockMailboxManager.manageProcessing(any(), any())).thenAnswer((Answer<Mono>) invocation -> {
             Object[] args = invocation.getArguments();
             return (Mono) args[0];
diff --git a/protocols/imap/src/test/java/org/apache/james/imap/processor/SetMetadataProcessorTest.java b/protocols/imap/src/test/java/org/apache/james/imap/processor/SetMetadataProcessorTest.java
index 1b49b44b08..885dd4a6ab 100644
--- a/protocols/imap/src/test/java/org/apache/james/imap/processor/SetMetadataProcessorTest.java
+++ b/protocols/imap/src/test/java/org/apache/james/imap/processor/SetMetadataProcessorTest.java
@@ -29,6 +29,7 @@ import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
+import java.util.EnumSet;
 import java.util.List;
 
 import org.apache.james.core.Username;
@@ -79,6 +80,7 @@ class SetMetadataProcessorTest {
     private void initAndMockData() {
         okResponse = mock(StatusResponse.class);
         mockMailboxManager = mock(MailboxManager.class);
+        when(mockMailboxManager.getSupportedMailboxCapabilities()).thenReturn(EnumSet.of(MailboxManager.MailboxCapabilities.Annotation));
         when(mockMailboxManager.manageProcessing(any(), any())).thenAnswer((Answer<Mono>) invocation -> {
             Object[] args = invocation.getArguments();
             return (Mono) args[0];
diff --git a/server/container/guice/common/src/main/java/org/apache/james/TemporaryJamesServer.java b/server/container/guice/common/src/main/java/org/apache/james/TemporaryJamesServer.java
new file mode 100644
index 0000000000..811189f360
--- /dev/null
+++ b/server/container/guice/common/src/main/java/org/apache/james/TemporaryJamesServer.java
@@ -0,0 +1,106 @@
+/****************************************************************
+ * 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;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.URL;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.List;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.james.server.core.configuration.Configuration;
+
+import com.google.common.collect.ImmutableList;
+
+public class TemporaryJamesServer {
+    private static final List<String> CONFIGURATION_FILE_NAMES = ImmutableList.of(
+        "dnsservice.xml",
+        "domainlist.xml",
+        "imapserver.xml",
+        "keystore",
+        "listeners.xml",
+        "lmtpserver.xml",
+        "mailetcontainer.xml",
+        "mailrepositorystore.xml",
+        "managesieveserver.xml",
+        "pop3server.xml",
+        "smtpserver.xml",
+        "usersrepository.xml");
+
+    private final Configuration configuration;
+    private final File configurationFolder;
+    private final List<String> configurationFileNames;
+    private GuiceJamesServer jamesServer;
+
+    public TemporaryJamesServer(File workingDir) {
+        this(workingDir, CONFIGURATION_FILE_NAMES);
+    }
+
+    public TemporaryJamesServer(File workingDir, List<String> configurationFileNames) {
+        this.configurationFileNames = configurationFileNames;
+        Configuration configuration = Configuration.builder().workingDirectory(workingDir).build();
+        configurationFolder = workingDir.toPath().resolve("conf").toFile();
+        if (!configurationFolder.exists()) {
+            configurationFolder.mkdir();
+        }
+        copyResources(Paths.get(configurationFolder.getAbsolutePath()));
+        this.configuration = configuration;
+    }
+
+    public GuiceJamesServer getJamesServer() {
+        if (jamesServer == null) {
+            jamesServer = GuiceJamesServer.forConfiguration(configuration);
+        }
+        return jamesServer;
+    }
+
+    public void appendConfigurationFile(String configurationData, String configurationFileName) throws IOException {
+        try (OutputStream outputStream = new FileOutputStream(Paths.get(configurationFolder.getAbsolutePath(), configurationFileName).toFile())) {
+            IOUtils.write(configurationData, outputStream, StandardCharsets.UTF_8);
+        }
+    }
+
+    private void copyResources(Path resourcesFolder) {
+        configurationFileNames
+            .forEach(resourceName -> copyResource(resourcesFolder, resourceName));
+    }
+
+    private void copyResource(Path resourcesFolder, String resourceName) {
+        var resolvedResource = resourcesFolder.resolve(resourceName);
+        try (OutputStream outputStream = new FileOutputStream(resolvedResource.toFile())) {
+            URL resource = ClassLoader.getSystemClassLoader().getResource(resourceName);
+            if (resource != null) {
+                try (InputStream stream = resource.openStream()) {
+                    stream.transferTo(outputStream);
+                }
+            } else {
+                throw new RuntimeException("Failed to load configuration resource " + resourceName);
+            }
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+    }
+}
diff --git a/server/container/guice/protocols/imap/pom.xml b/server/container/guice/protocols/imap/pom.xml
index 70f41be3b2..f020b3fcdc 100644
--- a/server/container/guice/protocols/imap/pom.xml
+++ b/server/container/guice/protocols/imap/pom.xml
@@ -36,6 +36,10 @@
             <groupId>${james.groupId}</groupId>
             <artifactId>james-server-guice-configuration</artifactId>
         </dependency>
+        <dependency>
+            <groupId>${james.groupId}</groupId>
+            <artifactId>james-server-guice-utils</artifactId>
+        </dependency>
         <dependency>
             <groupId>${james.groupId}</groupId>
             <artifactId>james-server-protocols-imap4</artifactId>
diff --git a/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/LsubCommandParser.java b/server/container/guice/protocols/imap/src/main/java/org/apache/james/modules/protocols/DefaultImapPackage.java
similarity index 62%
copy from protocols/imap/src/main/java/org/apache/james/imap/decode/parser/LsubCommandParser.java
copy to server/container/guice/protocols/imap/src/main/java/org/apache/james/modules/protocols/DefaultImapPackage.java
index 3d1d4ef785..038929089b 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/LsubCommandParser.java
+++ b/server/container/guice/protocols/imap/src/main/java/org/apache/james/modules/protocols/DefaultImapPackage.java
@@ -16,24 +16,21 @@
  * specific language governing permissions and limitations      *
  * under the License.                                           *
  ****************************************************************/
-package org.apache.james.imap.decode.parser;
 
-import org.apache.james.imap.api.ImapConstants;
-import org.apache.james.imap.api.ImapMessage;
-import org.apache.james.imap.api.Tag;
-import org.apache.james.imap.api.message.response.StatusResponseFactory;
-import org.apache.james.imap.message.request.LsubRequest;
+package org.apache.james.modules.protocols;
 
-/**
- * Parse LSUB commands
- */
-public class LsubCommandParser extends ListCommandParser {
-    public LsubCommandParser(StatusResponseFactory statusResponseFactory) {
-        super(ImapConstants.LSUB_COMMAND, statusResponseFactory);
-    }
+import javax.inject.Inject;
+
+import com.google.common.collect.ImmutableList;
 
-    @Override
-    protected ImapMessage createMessage(String referenceName, String mailboxPattern, Tag tag) {
-        return new LsubRequest(referenceName, mailboxPattern, tag);
+public class DefaultImapPackage extends ImapPackage.Impl {
+    @Inject
+    public DefaultImapPackage() {
+        super(DEFAULT.processors()
+                .stream().collect(ImmutableList.toImmutableList()),
+            DEFAULT.decoders()
+                .stream().collect(ImmutableList.toImmutableList()),
+            DEFAULT.encoders()
+                .stream().collect(ImmutableList.toImmutableList()));
     }
 }
diff --git a/server/container/guice/protocols/imap/src/main/java/org/apache/james/modules/protocols/IMAPServerModule.java b/server/container/guice/protocols/imap/src/main/java/org/apache/james/modules/protocols/IMAPServerModule.java
index e8620d2877..536aee23ac 100644
--- a/server/container/guice/protocols/imap/src/main/java/org/apache/james/modules/protocols/IMAPServerModule.java
+++ b/server/container/guice/protocols/imap/src/main/java/org/apache/james/modules/protocols/IMAPServerModule.java
@@ -18,24 +18,50 @@
  ****************************************************************/
 package org.apache.james.modules.protocols;
 
-import org.apache.james.events.EventBus;
+import java.util.Arrays;
+import java.util.Optional;
+import java.util.function.Function;
+import java.util.stream.Stream;
+
+import org.apache.commons.configuration2.ex.ConfigurationException;
+import org.apache.commons.lang3.tuple.Pair;
+import org.apache.james.imap.api.display.Localizer;
+import org.apache.james.imap.api.message.response.StatusResponseFactory;
+import org.apache.james.imap.api.process.DefaultMailboxTyper;
 import org.apache.james.imap.api.process.ImapProcessor;
+import org.apache.james.imap.api.process.MailboxTyper;
+import org.apache.james.imap.decode.ImapCommandParser;
+import org.apache.james.imap.decode.ImapCommandParserFactory;
 import org.apache.james.imap.decode.ImapDecoder;
+import org.apache.james.imap.decode.base.AbstractImapCommandParser;
+import org.apache.james.imap.decode.main.DefaultImapDecoder;
+import org.apache.james.imap.decode.parser.ImapParserFactory;
 import org.apache.james.imap.encode.ImapEncoder;
+import org.apache.james.imap.encode.ImapResponseEncoder;
+import org.apache.james.imap.encode.base.EndImapEncoder;
 import org.apache.james.imap.encode.main.DefaultImapEncoderFactory;
-import org.apache.james.imap.main.DefaultImapDecoderFactory;
-import org.apache.james.imap.processor.main.DefaultImapProcessorFactory;
+import org.apache.james.imap.encode.main.DefaultLocalizer;
+import org.apache.james.imap.message.response.UnpooledStatusResponseFactory;
+import org.apache.james.imap.processor.AuthenticateProcessor;
+import org.apache.james.imap.processor.CapabilityImplementingProcessor;
+import org.apache.james.imap.processor.CapabilityProcessor;
+import org.apache.james.imap.processor.DefaultProcessor;
+import org.apache.james.imap.processor.EnableProcessor;
+import org.apache.james.imap.processor.PermitEnableCapabilityProcessor;
+import org.apache.james.imap.processor.SelectProcessor;
+import org.apache.james.imap.processor.base.AbstractProcessor;
+import org.apache.james.imap.processor.base.UnknownRequestProcessor;
 import org.apache.james.imapserver.netty.IMAPServerFactory;
-import org.apache.james.mailbox.MailboxManager;
-import org.apache.james.mailbox.SubscriptionManager;
-import org.apache.james.mailbox.quota.QuotaManager;
-import org.apache.james.mailbox.quota.QuotaRootResolver;
-import org.apache.james.metrics.api.MetricFactory;
 import org.apache.james.server.core.configuration.ConfigurationProvider;
+import org.apache.james.utils.ClassName;
+import org.apache.james.utils.GuiceGenericLoader;
 import org.apache.james.utils.GuiceProbe;
 import org.apache.james.utils.InitializationOperation;
 import org.apache.james.utils.InitilizationOperationBuilder;
 
+import com.github.fge.lambdas.Throwing;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
 import com.google.inject.AbstractModule;
 import com.google.inject.Provides;
 import com.google.inject.Scopes;
@@ -45,41 +71,80 @@ import com.google.inject.multibindings.ProvidesIntoSet;
 
 public class IMAPServerModule extends AbstractModule {
 
+    private static Stream<Pair<Class, AbstractProcessor>> asPairStream(AbstractProcessor p) {
+        return p.acceptableClasses()
+            .stream().map(clazz -> Pair.of(clazz, p));
+    }
+
     @Override
     protected void configure() {
         bind(IMAPServerFactory.class).in(Scopes.SINGLETON);
+        bind(Localizer.class).to(DefaultLocalizer.class);
+        bind(UnpooledStatusResponseFactory.class).in(Scopes.SINGLETON);
+        bind(StatusResponseFactory.class).to(UnpooledStatusResponseFactory.class);
+
+        bind(CapabilityProcessor.class).in(Scopes.SINGLETON);
+        bind(AuthenticateProcessor.class).in(Scopes.SINGLETON);
+        bind(SelectProcessor.class).in(Scopes.SINGLETON);
+        bind(EnableProcessor.class).in(Scopes.SINGLETON);
+        bind(MailboxTyper.class).to(DefaultMailboxTyper.class).in(Scopes.SINGLETON);
 
         Multibinder.newSetBinder(binder(), GuiceProbe.class).addBinding().to(ImapGuiceProbe.class);
     }
 
     @Provides
-    ImapProcessor provideImapProcessor(
-            MailboxManager mailboxManager,
-            EventBus eventBus,
-            SubscriptionManager subscriptionManager,
-            QuotaManager quotaManager,
-            QuotaRootResolver quotaRootResolver,
-            MetricFactory metricFactory) {
-        return DefaultImapProcessorFactory.createXListSupportingProcessor(
-                mailboxManager,
-                eventBus,
-                subscriptionManager,
-                null,
-                quotaManager,
-                quotaRootResolver,
-                metricFactory);
+    ImapProcessor provideImapProcessor(ImapPackage imapPackage, GuiceGenericLoader loader, StatusResponseFactory statusResponseFactory) {
+        ImmutableMap<Class, ImapProcessor> processorMap = imapPackage.processors()
+            .stream()
+            .map(Throwing.function(loader::instantiate))
+            .map(AbstractProcessor.class::cast)
+            .flatMap(IMAPServerModule::asPairStream)
+            .collect(ImmutableMap.toImmutableMap(
+                Pair::getLeft,
+                Pair::getRight));
+
+        return new DefaultProcessor(processorMap, new UnknownRequestProcessor(statusResponseFactory));
+    }
+
+    @Provides
+    @Singleton
+    ImapPackage providePackage(ConfigurationProvider configurationProvider, GuiceGenericLoader loader) {
+        try {
+            String[] imapPackages = configurationProvider.getConfiguration("imapserver")
+                .getStringArray("imapPackages");
+
+            ImmutableList<ImapPackage> packages = Optional.ofNullable(imapPackages)
+                .stream()
+                .flatMap(Arrays::stream)
+                .map(ClassName::new)
+                .map(Throwing.function(loader::instantiate))
+                .map(ImapPackage.class::cast)
+                .collect(ImmutableList.toImmutableList());
+
+            if (packages.isEmpty()) {
+                return ImapPackage.DEFAULT;
+            }
+            return ImapPackage.and(packages);
+        } catch (ConfigurationException e) {
+            throw new RuntimeException(e);
+        }
     }
 
     @Provides
     @Singleton
-    ImapDecoder provideImapDecoder() {
-        return DefaultImapDecoderFactory.createDecoder();
+    ImapDecoder provideImapDecoder(ImapCommandParserFactory imapCommandParserFactory, StatusResponseFactory statusResponseFactory) {
+        return new DefaultImapDecoder(statusResponseFactory, imapCommandParserFactory);
     }
 
     @Provides
     @Singleton
-    ImapEncoder provideImapEncoder() {
-        return new DefaultImapEncoderFactory().buildImapEncoder();
+    ImapEncoder provideImapEncoder(ImapPackage imapPackage, GuiceGenericLoader loader) {
+        Stream<ImapResponseEncoder> encoders = imapPackage.encoders()
+            .stream()
+            .map(Throwing.function(loader::instantiate))
+            .map(ImapResponseEncoder.class::cast);
+
+        return new DefaultImapEncoderFactory.DefaultImapEncoder(encoders, new EndImapEncoder());
     }
 
     @ProvidesIntoSet
@@ -91,4 +156,40 @@ public class IMAPServerModule extends AbstractModule {
                 imapServerFactory.init();
             });
     }
+
+    @ProvidesIntoSet
+    InitializationOperation configureEnable(EnableProcessor enableProcessor, ImapPackage imapPackage) {
+        return InitilizationOperationBuilder
+            .forClass(IMAPServerFactory.class)
+            .init(() ->
+                imapPackage.processors().stream()
+                    .filter(PermitEnableCapabilityProcessor.class::isInstance)
+                    .map(PermitEnableCapabilityProcessor.class::cast)
+                    .forEach(enableProcessor::addProcessor));
+    }
+
+    @ProvidesIntoSet
+    InitializationOperation configureCapability(CapabilityProcessor capabilityProcessor, ImapPackage imapPackage) {
+        return InitilizationOperationBuilder
+            .forClass(IMAPServerFactory.class)
+            .init(() ->
+                imapPackage.processors().stream()
+                    .filter(CapabilityImplementingProcessor.class::isInstance)
+                    .map(CapabilityImplementingProcessor.class::cast)
+                    .forEach(capabilityProcessor::addProcessor));
+    }
+
+    @Provides
+    @Singleton
+    ImapCommandParserFactory provideImapCommandParserFactory(ImapPackage imapPackage, GuiceGenericLoader loader) {
+        ImmutableMap<String, ImapCommandParser> decoders = imapPackage.decoders()
+            .stream()
+            .map(Throwing.function(loader::instantiate))
+            .map(AbstractImapCommandParser.class::cast)
+            .collect(ImmutableMap.toImmutableMap(
+                parser -> parser.getCommand().getName(),
+                Function.identity()));
+
+        return new ImapParserFactory(decoders);
+    }
 }
\ No newline at end of file
diff --git a/server/container/guice/protocols/imap/src/main/java/org/apache/james/modules/protocols/ImapPackage.java b/server/container/guice/protocols/imap/src/main/java/org/apache/james/modules/protocols/ImapPackage.java
new file mode 100644
index 0000000000..ed65657a61
--- /dev/null
+++ b/server/container/guice/protocols/imap/src/main/java/org/apache/james/modules/protocols/ImapPackage.java
@@ -0,0 +1,335 @@
+/****************************************************************
+ * 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.modules.protocols;
+
+import java.util.Collection;
+
+import org.apache.james.imap.decode.parser.AppendCommandParser;
+import org.apache.james.imap.decode.parser.AuthenticateCommandParser;
+import org.apache.james.imap.decode.parser.CapabilityCommandParser;
+import org.apache.james.imap.decode.parser.CheckCommandParser;
+import org.apache.james.imap.decode.parser.CloseCommandParser;
+import org.apache.james.imap.decode.parser.CompressCommandParser;
+import org.apache.james.imap.decode.parser.CopyCommandParser;
+import org.apache.james.imap.decode.parser.CreateCommandParser;
+import org.apache.james.imap.decode.parser.DeleteACLCommandParser;
+import org.apache.james.imap.decode.parser.DeleteCommandParser;
+import org.apache.james.imap.decode.parser.EnableCommandParser;
+import org.apache.james.imap.decode.parser.ExamineCommandParser;
+import org.apache.james.imap.decode.parser.ExpungeCommandParser;
+import org.apache.james.imap.decode.parser.FetchCommandParser;
+import org.apache.james.imap.decode.parser.GetACLCommandParser;
+import org.apache.james.imap.decode.parser.GetMetadataCommandParser;
+import org.apache.james.imap.decode.parser.GetQuotaCommandParser;
+import org.apache.james.imap.decode.parser.GetQuotaRootCommandParser;
+import org.apache.james.imap.decode.parser.IDCommandParser;
+import org.apache.james.imap.decode.parser.IdleCommandParser;
+import org.apache.james.imap.decode.parser.ListCommandParser;
+import org.apache.james.imap.decode.parser.ListRightsCommandParser;
+import org.apache.james.imap.decode.parser.LoginCommandParser;
+import org.apache.james.imap.decode.parser.LsubCommandParser;
+import org.apache.james.imap.decode.parser.MoveCommandParser;
+import org.apache.james.imap.decode.parser.MyRightsCommandParser;
+import org.apache.james.imap.decode.parser.NamespaceCommandParser;
+import org.apache.james.imap.decode.parser.NoopCommandParser;
+import org.apache.james.imap.decode.parser.RenameCommandParser;
+import org.apache.james.imap.decode.parser.SearchCommandParser;
+import org.apache.james.imap.decode.parser.SelectCommandParser;
+import org.apache.james.imap.decode.parser.SetACLCommandParser;
+import org.apache.james.imap.decode.parser.SetAnnotationCommandParser;
+import org.apache.james.imap.decode.parser.SetQuotaCommandParser;
+import org.apache.james.imap.decode.parser.StartTLSCommandParser;
+import org.apache.james.imap.decode.parser.StatusCommandParser;
+import org.apache.james.imap.decode.parser.StoreCommandParser;
+import org.apache.james.imap.decode.parser.SubscribeCommandParser;
+import org.apache.james.imap.decode.parser.UidCommandParser;
+import org.apache.james.imap.decode.parser.UnselectCommandParser;
+import org.apache.james.imap.decode.parser.UnsubscribeCommandParser;
+import org.apache.james.imap.decode.parser.XListCommandParser;
+import org.apache.james.imap.encode.AuthenticateResponseEncoder;
+import org.apache.james.imap.encode.CapabilityResponseEncoder;
+import org.apache.james.imap.encode.ContinuationResponseEncoder;
+import org.apache.james.imap.encode.ESearchResponseEncoder;
+import org.apache.james.imap.encode.EnableResponseEncoder;
+import org.apache.james.imap.encode.ExistsResponseEncoder;
+import org.apache.james.imap.encode.ExpungeResponseEncoder;
+import org.apache.james.imap.encode.FetchResponseEncoder;
+import org.apache.james.imap.encode.FlagsResponseEncoder;
+import org.apache.james.imap.encode.IdResponseEncoder;
+import org.apache.james.imap.encode.LSubResponseEncoder;
+import org.apache.james.imap.encode.ListResponseEncoder;
+import org.apache.james.imap.encode.ListRightsResponseEncoder;
+import org.apache.james.imap.encode.MailboxStatusResponseEncoder;
+import org.apache.james.imap.encode.MetadataResponseEncoder;
+import org.apache.james.imap.encode.MyRightsResponseEncoder;
+import org.apache.james.imap.encode.NamespaceResponseEncoder;
+import org.apache.james.imap.encode.QuotaResponseEncoder;
+import org.apache.james.imap.encode.QuotaRootResponseEncoder;
+import org.apache.james.imap.encode.RecentResponseEncoder;
+import org.apache.james.imap.encode.SearchResponseEncoder;
+import org.apache.james.imap.encode.StatusResponseEncoder;
+import org.apache.james.imap.encode.VanishedResponseEncoder;
+import org.apache.james.imap.encode.XListResponseEncoder;
+import org.apache.james.imap.processor.AppendProcessor;
+import org.apache.james.imap.processor.AuthenticateProcessor;
+import org.apache.james.imap.processor.CapabilityProcessor;
+import org.apache.james.imap.processor.CheckProcessor;
+import org.apache.james.imap.processor.CloseProcessor;
+import org.apache.james.imap.processor.CompressProcessor;
+import org.apache.james.imap.processor.CopyProcessor;
+import org.apache.james.imap.processor.CreateProcessor;
+import org.apache.james.imap.processor.DeleteACLProcessor;
+import org.apache.james.imap.processor.DeleteProcessor;
+import org.apache.james.imap.processor.EnableProcessor;
+import org.apache.james.imap.processor.ExamineProcessor;
+import org.apache.james.imap.processor.ExpungeProcessor;
+import org.apache.james.imap.processor.GetACLProcessor;
+import org.apache.james.imap.processor.GetMetadataProcessor;
+import org.apache.james.imap.processor.GetQuotaProcessor;
+import org.apache.james.imap.processor.GetQuotaRootProcessor;
+import org.apache.james.imap.processor.IdProcessor;
+import org.apache.james.imap.processor.IdleProcessor;
+import org.apache.james.imap.processor.LSubProcessor;
+import org.apache.james.imap.processor.ListProcessor;
+import org.apache.james.imap.processor.ListRightsProcessor;
+import org.apache.james.imap.processor.LoginProcessor;
+import org.apache.james.imap.processor.LogoutProcessor;
+import org.apache.james.imap.processor.MoveProcessor;
+import org.apache.james.imap.processor.MyRightsProcessor;
+import org.apache.james.imap.processor.NamespaceProcessor;
+import org.apache.james.imap.processor.NoopProcessor;
+import org.apache.james.imap.processor.RenameProcessor;
+import org.apache.james.imap.processor.SearchProcessor;
+import org.apache.james.imap.processor.SelectProcessor;
+import org.apache.james.imap.processor.SetACLProcessor;
+import org.apache.james.imap.processor.SetMetadataProcessor;
+import org.apache.james.imap.processor.SetQuotaProcessor;
+import org.apache.james.imap.processor.StartTLSProcessor;
+import org.apache.james.imap.processor.StatusProcessor;
+import org.apache.james.imap.processor.StoreProcessor;
+import org.apache.james.imap.processor.SubscribeProcessor;
+import org.apache.james.imap.processor.UnselectProcessor;
+import org.apache.james.imap.processor.UnsubscribeProcessor;
+import org.apache.james.imap.processor.XListProcessor;
+import org.apache.james.imap.processor.base.ImapResponseMessageProcessor;
+import org.apache.james.imap.processor.fetch.FetchProcessor;
+import org.apache.james.utils.ClassName;
+
+import com.google.common.collect.ImmutableList;
+
+public interface ImapPackage {
+    Collection<ClassName> processors();
+
+    Collection<ClassName> decoders();
+
+    Collection<ClassName> encoders();
+
+    class Impl implements ImapPackage {
+        private final ImmutableList<ClassName> processors;
+        private final ImmutableList<ClassName> decoders;
+        private final ImmutableList<ClassName> encoders;
+
+        public Impl(ImmutableList<ClassName> processors,
+                    ImmutableList<ClassName> decoders,
+                    ImmutableList<ClassName> encoders) {
+            this.processors = processors;
+            this.decoders = decoders;
+            this.encoders = encoders;
+        }
+
+        @Override
+        public Collection<ClassName> processors() {
+            return processors;
+        }
+
+        @Override
+        public Collection<ClassName> decoders() {
+            return decoders;
+        }
+
+        @Override
+        public Collection<ClassName> encoders() {
+            return encoders;
+        }
+    }
+
+    static ImapPackage and(Collection<ImapPackage> packages) {
+        return new ImapPackage() {
+            @Override
+            public Collection<ClassName> processors() {
+                return packages.stream()
+                    .flatMap(p -> p.processors().stream())
+                    .collect(ImmutableList.toImmutableList());
+            }
+
+            @Override
+            public Collection<ClassName> decoders() {
+                return packages.stream()
+                    .flatMap(p -> p.decoders().stream())
+                    .collect(ImmutableList.toImmutableList());
+            }
+
+            @Override
+            public Collection<ClassName> encoders() {
+                return packages.stream()
+                    .flatMap(p -> p.encoders().stream())
+                    .collect(ImmutableList.toImmutableList());
+            }
+        };
+    }
+
+    ImapPackage DEFAULT = and(ImmutableList.of(new DefaultNoAuth(), new DefaultAuth()));
+
+    class DefaultNoAuth extends Impl {
+        public DefaultNoAuth() {
+            super(
+                ImmutableList.of(
+                    CapabilityProcessor.class,
+                    CheckProcessor.class,
+                    IdProcessor.class,
+                    RenameProcessor.class,
+                    DeleteProcessor.class,
+                    CreateProcessor.class,
+                    CloseProcessor.class,
+                    UnsubscribeProcessor.class,
+                    SubscribeProcessor.class,
+                    CopyProcessor.class,
+                    ExpungeProcessor.class,
+                    ExamineProcessor.class,
+                    AppendProcessor.class,
+                    StoreProcessor.class,
+                    NoopProcessor.class,
+                    IdleProcessor.class,
+                    StatusProcessor.class,
+                    LSubProcessor.class,
+                    XListProcessor.class,
+                    ListProcessor.class,
+                    SearchProcessor.class,
+                    SelectProcessor.class,
+                    NamespaceProcessor.class,
+                    FetchProcessor.class,
+                    StartTLSProcessor.class,
+                    UnselectProcessor.class,
+                    CompressProcessor.class,
+                    GetACLProcessor.class,
+                    SetACLProcessor.class,
+                    DeleteACLProcessor.class,
+                    ListRightsProcessor.class,
+                    MyRightsProcessor.class,
+                    EnableProcessor.class,
+                    GetQuotaProcessor.class,
+                    SetQuotaProcessor.class,
+                    GetQuotaRootProcessor.class,
+                    ImapResponseMessageProcessor.class,
+                    MoveProcessor.class,
+                    SetMetadataProcessor.class,
+                    GetMetadataProcessor.class,
+                    LogoutProcessor.class)
+                    .stream()
+                    .map(clazz -> new ClassName(clazz.getCanonicalName()))
+                    .collect(ImmutableList.toImmutableList()),
+                ImmutableList.of(
+                    CapabilityCommandParser.class,
+                    NoopCommandParser.class,
+                    IDCommandParser.class,
+                    SelectCommandParser.class,
+                    ExamineCommandParser.class,
+                    CreateCommandParser.class,
+                    DeleteCommandParser.class,
+                    RenameCommandParser.class,
+                    SubscribeCommandParser.class,
+                    UnsubscribeCommandParser.class,
+                    ListCommandParser.class,
+                    XListCommandParser.class,
+                    LsubCommandParser.class,
+                    StatusCommandParser.class,
+                    AppendCommandParser.class,
+                    NamespaceCommandParser.class,
+                    GetACLCommandParser.class,
+                    SetACLCommandParser.class,
+                    DeleteACLCommandParser.class,
+                    ListRightsCommandParser.class,
+                    MyRightsCommandParser.class,
+                    CheckCommandParser.class,
+                    CloseCommandParser.class,
+                    ExpungeCommandParser.class,
+                    CopyCommandParser.class,
+                    MoveCommandParser.class,
+                    SearchCommandParser.class,
+                    FetchCommandParser.class,
+                    StoreCommandParser.class,
+                    UidCommandParser.class,
+                    IdleCommandParser.class,
+                    StartTLSCommandParser.class,
+                    UnselectCommandParser.class,
+                    CompressCommandParser.class,
+                    EnableCommandParser.class,
+                    GetQuotaRootCommandParser.class,
+                    GetQuotaCommandParser.class,
+                    SetQuotaCommandParser.class,
+                    SetAnnotationCommandParser.class,
+                    GetMetadataCommandParser.class)
+                    .stream()
+                    .map(clazz -> new ClassName(clazz.getCanonicalName()))
+                    .collect(ImmutableList.toImmutableList()),
+                ImmutableList.of(MetadataResponseEncoder.class,
+                    MyRightsResponseEncoder.class,
+                    IdResponseEncoder.class,
+                    ListRightsResponseEncoder.class,
+                    ListResponseEncoder.class,
+                    NamespaceResponseEncoder.class,
+                    StatusResponseEncoder.class,
+                    RecentResponseEncoder.class,
+                    FetchResponseEncoder.class,
+                    ExpungeResponseEncoder.class,
+                    ExistsResponseEncoder.class,
+                    MailboxStatusResponseEncoder.class,
+                    SearchResponseEncoder.class,
+                    LSubResponseEncoder.class,
+                    XListResponseEncoder.class,
+                    FlagsResponseEncoder.class,
+                    CapabilityResponseEncoder.class,
+                    EnableResponseEncoder.class,
+                    ContinuationResponseEncoder.class,
+                    AuthenticateResponseEncoder.class,
+                    ESearchResponseEncoder.class,
+                    VanishedResponseEncoder.class,
+                    QuotaResponseEncoder.class,
+                    QuotaRootResponseEncoder.class)
+                    .stream()
+                    .map(clazz -> new ClassName(clazz.getCanonicalName()))
+                    .collect(ImmutableList.toImmutableList()));
+        }
+    }
+
+    class DefaultAuth extends Impl {
+        public DefaultAuth() {
+            super(ImmutableList.of(AuthenticateProcessor.class, LoginProcessor.class)
+                    .stream()
+                    .map(clazz -> new ClassName(clazz.getCanonicalName()))
+                    .collect(ImmutableList.toImmutableList()),
+                ImmutableList.of(AuthenticateCommandParser.class, LoginCommandParser.class)
+                    .stream()
+                    .map(clazz -> new ClassName(clazz.getCanonicalName()))
+                    .collect(ImmutableList.toImmutableList()),
+                ImmutableList.of());
+        }
+    }
+}


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