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/08/23 01:12:07 UTC

[james-project] branch master updated (8507e8bdb8 -> 1618018c41)

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

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


    from 8507e8bdb8 JAMES-3775 Guice packaging for RSpamd
     new 417ff299db JAMES-3797 drop spam assassin in james' internal module
     new 1618018c41 JAMES-3797 Moving all source code related to SpamAssassin to module third-party/spamassassin

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


Summary of changes:
 mailbox/plugin/spamassassin/pom.xml                |  93 -----
 mailbox/pom.xml                                    |   2 -
 pom.xml                                            |  16 -
 server/apps/cassandra-app/pom.xml                  |  10 -
 .../sample-configuration/listeners.xml             |   4 -
 .../org/apache/james/CassandraJamesServerMain.java |   4 +-
 server/apps/distributed-app/pom.xml                |   4 -
 .../sample-configuration/listeners.xml             |   4 -
 .../james/CassandraRabbitMQJamesServerMain.java    |   4 +-
 server/apps/distributed-pop3-app/pom.xml           |   4 -
 .../sample-configuration/listeners.xml             |   4 -
 server/apps/jpa-app/pom.xml                        |   4 -
 .../java/org/apache/james/JPAJamesServerMain.java  |   4 +-
 server/apps/memory-app/pom.xml                     |   4 -
 .../memory-app/sample-configuration/listeners.xml  |   4 -
 .../org/apache/james/MemoryJamesServerMain.java    |   4 +-
 .../memory-app/src/test/resources/listeners.xml    |   3 -
 .../src/test/resources/mailetcontainer.xml         |   8 -
 .../src/test/resources/spamassassin.properties     |   2 -
 .../src/test/resources/listeners.xml               |   3 -
 .../spring-app/src/main/resources/smtpserver.xml   |  12 +-
 .../guice/mailbox-plugin-spamassassin/pom.xml      |  66 ----
 .../spamassassin/SpamAssassinListenerModule.java   |  58 ---
 .../SpamAssassinConfigurationLoaderTest.java       |  58 ---
 server/container/guice/pom.xml                     |   6 -
 server/mailet/mailets/pom.xml                      |  10 -
 .../james/transport/matchers/IsMarkedAsSpam.java   |   7 +-
 .../jmap-draft-integration-testing-common/pom.xml  |  11 -
 .../src/test/resources/spamassassin_db/ham/ham1    | 113 ------
 .../src/test/resources/spamassassin_db/ham/ham2    |  73 ----
 .../src/test/resources/spamassassin_db/ham/ham3    |  82 ----
 .../src/test/resources/spamassassin_db/spam/spam1  | 108 ------
 .../src/test/resources/spamassassin_db/spam/spam2  | 186 ---------
 .../src/test/resources/spamassassin_db/spam/spam3  | 211 ----------
 .../memory-jmap-draft-integration-testing/pom.xml  |  11 -
 .../src/test/resources/listeners.xml               |   3 -
 .../src/test/resources/mailetcontainer.xml         |   8 -
 .../src/test/resources/spamassassin_db             |   1 -
 .../pom.xml                                        |   6 -
 .../RabbitMQAwsS3SpamAssassinContractTest.java     |  60 ---
 .../src/test/resources/listeners.xml               |   3 -
 .../src/test/resources/mailetcontainer.xml         |   8 -
 .../src/test/resources/spamassassin_db             |   1 -
 .../src/test/resources/mailetcontainer.xml         |   8 -
 server/protocols/protocols-smtp/pom.xml            |  10 -
 .../java/org/apache/james/util/docker/Images.java  |   1 -
 third-party/spamassassin/docker-compose.yml        |  32 ++
 third-party/spamassassin/pom.xml                   | 107 +++++-
 .../sample-configuration/extensions.properties     |   1 +
 .../spamassassin/sample-configuration}/keystore    | Bin
 .../sample-configuration/listeners.xml             |  26 ++
 .../sample-configuration}/mailetcontainer.xml      |  85 +++--
 .../sample-configuration/smtpserver.xml            | 158 ++++++++
 .../sample-configuration}/spamassassin.properties  |   2 +-
 .../apache/james/spamassassin}/SpamAssassin.java   |  60 +--
 .../spamassassin/SpamAssassinConfiguration.java    |  19 +-
 .../james/spamassassin}/SpamAssassinHandler.java   |  55 +--
 .../james/spamassassin/SpamAssassinLearner.java    |  31 +-
 .../james}/spamassassin/SpamAssassinListener.java  |  18 +-
 .../james/spamassassin/SpamAssassinModule.java     |  30 +-
 .../james/spamassassin/MemorySpamAssassinTest.java |  11 +-
 .../SpamAssassinConfigurationTest.java             |  18 +-
 .../james/spamassassin}/SpamAssassinContract.java  | 123 +++---
 .../spamassassin}/SpamAssassinHandlerTest.java     |  36 +-
 .../spamassassin}/SpamAssassinIntegrationTest.java |  28 +-
 .../spamassassin/SpamAssassinListenerTest.java     |  22 +-
 .../james/spamassassin}/SpamAssassinTest.java      | 117 +-----
 .../module}/SpamAssassinModuleExtension.java       |   9 +-
 .../module/SpamAssassinTestModule.java             |  33 +-
 .../test/resources/docker/spamassassin/spamd.sh    |   2 +-
 .../spamassassin}/src/test/resources/listeners.xml |   2 +-
 .../src/test/resources/mailetcontainer.xml         |   4 +-
 .../spamassassin/src/test/resources/smtpserver.xml |  54 +++
 .../src/test/resources/spamassassin_db/ham/ham4    |  78 ----
 .../src/test/resources/spamassassin_db/ham/ham5    |  77 ----
 .../src/test/resources/spamassassin_db/ham/ham6    |  74 ----
 .../src/test/resources/spamassassin_db/ham/ham7    |  88 -----
 .../src/test/resources/spamassassin_db/ham/ham8    |  85 -----
 .../src/test/resources/spamassassin_db/ham/ham9    | 176 ---------
 .../src/test/resources/spamassassin_db/spam/spam4  | 213 -----------
 .../src/test/resources/spamassassin_db/spam/spam5  | 161 --------
 .../src/test/resources/spamassassin_db/spam/spam6  | 423 ---------------------
 .../src/test/resources/spamassassin_db/spam/spam7  |  71 ----
 .../src/test/resources/spamassassin_db/spam/spam8  | 321 ----------------
 .../src/test/resources/spamassassin_db/spam/spam9  | 142 -------
 85 files changed, 651 insertions(+), 3647 deletions(-)
 delete mode 100644 mailbox/plugin/spamassassin/pom.xml
 delete mode 100644 server/apps/memory-app/src/test/resources/spamassassin.properties
 delete mode 100644 server/container/guice/mailbox-plugin-spamassassin/pom.xml
 delete mode 100644 server/container/guice/mailbox-plugin-spamassassin/src/main/java/org/apache/james/modules/spamassassin/SpamAssassinListenerModule.java
 delete mode 100644 server/container/guice/mailbox-plugin-spamassassin/src/test/java/org/apache/james/modules/spamassassin/SpamAssassinConfigurationLoaderTest.java
 delete mode 100644 server/protocols/jmap-draft-integration-testing/jmap-draft-integration-testing-common/src/test/resources/spamassassin_db/ham/ham1
 delete mode 100644 server/protocols/jmap-draft-integration-testing/jmap-draft-integration-testing-common/src/test/resources/spamassassin_db/ham/ham2
 delete mode 100644 server/protocols/jmap-draft-integration-testing/jmap-draft-integration-testing-common/src/test/resources/spamassassin_db/ham/ham3
 delete mode 100644 server/protocols/jmap-draft-integration-testing/jmap-draft-integration-testing-common/src/test/resources/spamassassin_db/spam/spam1
 delete mode 100644 server/protocols/jmap-draft-integration-testing/jmap-draft-integration-testing-common/src/test/resources/spamassassin_db/spam/spam2
 delete mode 100644 server/protocols/jmap-draft-integration-testing/jmap-draft-integration-testing-common/src/test/resources/spamassassin_db/spam/spam3
 delete mode 120000 server/protocols/jmap-draft-integration-testing/memory-jmap-draft-integration-testing/src/test/resources/spamassassin_db
 delete mode 100644 server/protocols/jmap-draft-integration-testing/rabbitmq-jmap-draft-integration-testing/src/test/java/org/apache/james/jmap/rabbitmq/RabbitMQAwsS3SpamAssassinContractTest.java
 delete mode 120000 server/protocols/jmap-draft-integration-testing/rabbitmq-jmap-draft-integration-testing/src/test/resources/spamassassin_db
 create mode 100644 third-party/spamassassin/docker-compose.yml
 create mode 100644 third-party/spamassassin/sample-configuration/extensions.properties
 copy {examples/imap-autoconf => third-party/spamassassin/sample-configuration}/keystore (100%)
 create mode 100644 third-party/spamassassin/sample-configuration/listeners.xml
 copy {server/apps/memory-app/src/test/resources => third-party/spamassassin/sample-configuration}/mailetcontainer.xml (72%)
 create mode 100644 third-party/spamassassin/sample-configuration/smtpserver.xml
 rename {server/apps/cassandra-app/src/test/resources => third-party/spamassassin/sample-configuration}/spamassassin.properties (57%)
 rename {server/mailet/mailets/src/main/java/org/apache/james/transport/mailets => third-party/spamassassin/src/main/java/org/apache/james/spamassassin}/SpamAssassin.java (71%)
 rename {mailbox/plugin/spamassassin/src/main/java/org/apache/james/mailbox => third-party/spamassassin/src/main/java/org/apache/james}/spamassassin/SpamAssassinConfiguration.java (84%)
 rename {server/protocols/protocols-smtp/src/main/java/org/apache/james/smtpserver/fastfail => third-party/spamassassin/src/main/java/org/apache/james/spamassassin}/SpamAssassinHandler.java (79%)
 rename mailbox/plugin/spamassassin/src/main/java/org/apache/james/mailbox/spamassassin/SpamAssassin.java => third-party/spamassassin/src/main/java/org/apache/james/spamassassin/SpamAssassinLearner.java (60%)
 rename {mailbox/plugin/spamassassin/src/main/java/org/apache/james/mailbox => third-party/spamassassin/src/main/java/org/apache/james}/spamassassin/SpamAssassinListener.java (92%)
 rename server/container/guice/mailbox-plugin-spamassassin/src/main/java/org/apache/james/modules/spamassassin/SpamAssassinConfigurationLoader.java => third-party/spamassassin/src/main/java/org/apache/james/spamassassin/SpamAssassinModule.java (64%)
 rename server/protocols/jmap-draft-integration-testing/memory-jmap-draft-integration-testing/src/test/java/org/apache/james/jmap/memory/MemorySpamAssassinContractTest.java => third-party/spamassassin/src/test/java/org/apache/james/spamassassin/MemorySpamAssassinTest.java (93%)
 rename {mailbox/plugin/spamassassin/src/test/java/org/apache/james/mailbox => third-party/spamassassin/src/test/java/org/apache/james}/spamassassin/SpamAssassinConfigurationTest.java (74%)
 rename {server/protocols/jmap-draft-integration-testing/jmap-draft-integration-testing-common/src/test/java/org/apache/james/jmap/draft/methods/integration => third-party/spamassassin/src/test/java/org/apache/james/spamassassin}/SpamAssassinContract.java (95%)
 rename {server/protocols/protocols-smtp/src/test/java/org/apache/james/smtpserver => third-party/spamassassin/src/test/java/org/apache/james/spamassassin}/SpamAssassinHandlerTest.java (85%)
 rename {server/mailet/integration-testing/src/test/java/org/apache/james/transport/mailets => third-party/spamassassin/src/test/java/org/apache/james/spamassassin}/SpamAssassinIntegrationTest.java (91%)
 rename {mailbox/plugin/spamassassin/src/test/java/org/apache/james/mailbox => third-party/spamassassin/src/test/java/org/apache/james}/spamassassin/SpamAssassinListenerTest.java (94%)
 rename {server/mailet/mailets/src/test/java/org/apache/james/transport/mailets => third-party/spamassassin/src/test/java/org/apache/james/spamassassin}/SpamAssassinTest.java (59%)
 rename {server/protocols/jmap-draft-integration-testing/jmap-draft-integration-testing-common/src/test/java/org/apache/james/jmap/draft/methods/integration => third-party/spamassassin/src/test/java/org/apache/james/spamassassin/module}/SpamAssassinModuleExtension.java (92%)
 rename server/protocols/jmap-draft-integration-testing/jmap-draft-integration-testing-common/src/test/java/org/apache/james/jmap/draft/methods/integration/SpamAssassinModule.java => third-party/spamassassin/src/test/java/org/apache/james/spamassassin/module/SpamAssassinTestModule.java (60%)
 copy {server/protocols/jmap-draft-integration-testing/memory-jmap-draft-integration-testing => third-party/spamassassin}/src/test/resources/listeners.xml (95%)
 copy {server/protocols/jmap-draft-integration-testing/memory-jmap-draft-integration-testing => third-party/spamassassin}/src/test/resources/mailetcontainer.xml (97%)
 create mode 100644 third-party/spamassassin/src/test/resources/smtpserver.xml
 delete mode 100644 third-party/spamassassin/src/test/resources/spamassassin_db/ham/ham4
 delete mode 100644 third-party/spamassassin/src/test/resources/spamassassin_db/ham/ham5
 delete mode 100644 third-party/spamassassin/src/test/resources/spamassassin_db/ham/ham6
 delete mode 100644 third-party/spamassassin/src/test/resources/spamassassin_db/ham/ham7
 delete mode 100644 third-party/spamassassin/src/test/resources/spamassassin_db/ham/ham8
 delete mode 100644 third-party/spamassassin/src/test/resources/spamassassin_db/ham/ham9
 delete mode 100644 third-party/spamassassin/src/test/resources/spamassassin_db/spam/spam4
 delete mode 100644 third-party/spamassassin/src/test/resources/spamassassin_db/spam/spam5
 delete mode 100644 third-party/spamassassin/src/test/resources/spamassassin_db/spam/spam6
 delete mode 100644 third-party/spamassassin/src/test/resources/spamassassin_db/spam/spam7
 delete mode 100644 third-party/spamassassin/src/test/resources/spamassassin_db/spam/spam8
 delete mode 100644 third-party/spamassassin/src/test/resources/spamassassin_db/spam/spam9


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


[james-project] 02/02: JAMES-3797 Moving all source code related to SpamAssassin to module third-party/spamassassin

Posted by bt...@apache.org.
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

commit 1618018c413f7ec6ec452baca995ab153af1f17d
Author: Tung Van TRAN <vt...@linagora.com>
AuthorDate: Mon Aug 8 08:20:16 2022 +0700

    JAMES-3797 Moving all source code related to SpamAssassin to module third-party/spamassassin
---
 pom.xml                                            |   5 -
 .../sample-configuration/listeners.xml             |   4 -
 .../src/test/resources/spamassassin.properties     |   2 -
 .../sample-configuration/listeners.xml             |   4 -
 .../sample-configuration/listeners.xml             |   4 -
 .../memory-app/sample-configuration/listeners.xml  |   4 -
 .../memory-app/src/test/resources/listeners.xml    |   3 -
 .../src/test/resources/listeners.xml               |   3 -
 .../spring-app/src/main/resources/smtpserver.xml   |  12 +-
 .../james/transport/matchers/IsMarkedAsSpam.java   |   7 +-
 .../jmap-draft-integration-testing-common/pom.xml  |   5 -
 .../memory-jmap-draft-integration-testing/pom.xml  |   5 -
 .../src/test/resources/listeners.xml               |   3 -
 .../src/test/resources/listeners.xml               |   3 -
 .../java/org/apache/james/util/docker/Images.java  |   1 -
 third-party/spamassassin/docker-compose.yml        |  32 +
 third-party/spamassassin/pom.xml                   | 107 +++-
 .../sample-configuration/extensions.properties     |   1 +
 .../spamassassin/sample-configuration/keystore     | Bin 0 -> 2711 bytes
 .../sample-configuration/listeners.xml             |  26 +
 .../sample-configuration/mailetcontainer.xml       | 167 +++++
 .../sample-configuration/smtpserver.xml            | 158 +++++
 .../sample-configuration}/spamassassin.properties  |   2 +-
 .../apache/james/spamassassin/SpamAssassin.java    | 102 +++
 .../spamassassin/SpamAssassinConfiguration.java    |  57 +-
 .../james/spamassassin}/SpamAssassinHandler.java   |  55 +-
 .../james/spamassassin/SpamAssassinLearner.java    |  56 ++
 .../james/spamassassin/SpamAssassinListener.java   | 185 ++++++
 .../james/spamassassin/SpamAssassinModule.java     |  50 ++
 .../james/spamassassin/MemorySpamAssassinTest.java |  89 +++
 .../SpamAssassinConfigurationTest.java             |  38 +-
 .../james/spamassassin/SpamAssassinContract.java   | 701 +++++++++++++++++++++
 .../spamassassin}/SpamAssassinHandlerTest.java     |  36 +-
 .../spamassassin/SpamAssassinIntegrationTest.java  | 211 +++++++
 .../spamassassin/SpamAssassinListenerTest.java     | 285 +++++++++
 .../james/spamassassin/SpamAssassinTest.java       | 158 +++++
 .../module/SpamAssassinModuleExtension.java        |  65 ++
 .../module/SpamAssassinTestModule.java             |  60 ++
 .../test/resources/docker/spamassassin/spamd.sh    |   2 +-
 .../spamassassin}/src/test/resources/listeners.xml |   2 +-
 .../src/test/resources/mailetcontainer.xml         | 133 ++++
 .../spamassassin/src/test/resources/smtpserver.xml |  54 ++
 42 files changed, 2743 insertions(+), 154 deletions(-)

diff --git a/pom.xml b/pom.xml
index 4667970ad5..9d7cb0d715 100644
--- a/pom.xml
+++ b/pom.xml
@@ -853,11 +853,6 @@
                 <version>${project.version}</version>
                 <type>test-jar</type>
             </dependency>
-            <dependency>
-                <groupId>${james.groupId}</groupId>
-                <artifactId>apache-james-mailbox-spamassassin</artifactId>
-                <version>${project.version}</version>
-            </dependency>
             <dependency>
                 <groupId>${james.groupId}</groupId>
                 <artifactId>apache-james-mailbox-spring</artifactId>
diff --git a/server/apps/cassandra-app/sample-configuration/listeners.xml b/server/apps/cassandra-app/sample-configuration/listeners.xml
index 948cb92031..6a1d26196f 100644
--- a/server/apps/cassandra-app/sample-configuration/listeners.xml
+++ b/server/apps/cassandra-app/sample-configuration/listeners.xml
@@ -21,10 +21,6 @@
 <!-- Read https://james.apache.org/server/config-listeners.html for further details -->
 
 <listeners>
-  <listener>
-    <class>org.apache.james.mailbox.spamassassin.SpamAssassinListener</class>
-    <async>true</async>
-  </listener>
   <listener>
     <class>org.apache.james.mailbox.cassandra.MailboxOperationLoggingListener</class>
   </listener>
diff --git a/server/apps/cassandra-app/src/test/resources/spamassassin.properties b/server/apps/cassandra-app/src/test/resources/spamassassin.properties
deleted file mode 100644
index 134ed31a97..0000000000
--- a/server/apps/cassandra-app/src/test/resources/spamassassin.properties
+++ /dev/null
@@ -1,2 +0,0 @@
-spamassassin.host=localhost
-spamassassin.host=783
\ No newline at end of file
diff --git a/server/apps/distributed-app/sample-configuration/listeners.xml b/server/apps/distributed-app/sample-configuration/listeners.xml
index 758c823704..f039b355a7 100644
--- a/server/apps/distributed-app/sample-configuration/listeners.xml
+++ b/server/apps/distributed-app/sample-configuration/listeners.xml
@@ -22,10 +22,6 @@
 
 <listeners>
   <executeGroupListeners>true</executeGroupListeners>
-  <listener>
-    <class>org.apache.james.mailbox.spamassassin.SpamAssassinListener</class>
-    <async>true</async>
-  </listener>
   <listener>
     <class>org.apache.james.mailbox.cassandra.MailboxOperationLoggingListener</class>
   </listener>
diff --git a/server/apps/distributed-pop3-app/sample-configuration/listeners.xml b/server/apps/distributed-pop3-app/sample-configuration/listeners.xml
index 758c823704..f039b355a7 100644
--- a/server/apps/distributed-pop3-app/sample-configuration/listeners.xml
+++ b/server/apps/distributed-pop3-app/sample-configuration/listeners.xml
@@ -22,10 +22,6 @@
 
 <listeners>
   <executeGroupListeners>true</executeGroupListeners>
-  <listener>
-    <class>org.apache.james.mailbox.spamassassin.SpamAssassinListener</class>
-    <async>true</async>
-  </listener>
   <listener>
     <class>org.apache.james.mailbox.cassandra.MailboxOperationLoggingListener</class>
   </listener>
diff --git a/server/apps/memory-app/sample-configuration/listeners.xml b/server/apps/memory-app/sample-configuration/listeners.xml
index 2eed88076c..41a4383c8d 100644
--- a/server/apps/memory-app/sample-configuration/listeners.xml
+++ b/server/apps/memory-app/sample-configuration/listeners.xml
@@ -21,10 +21,6 @@
 <!-- Read https://james.apache.org/server/config-listeners.html for further details -->
 
 <listeners>
-  <listener>
-    <class>org.apache.james.mailbox.spamassassin.SpamAssassinListener</class>
-    <async>true</async>
-  </listener>
   <preDeletionHook>
     <class>org.apache.james.vault.DeletedMessageVaultHook</class>
   </preDeletionHook>
diff --git a/server/apps/memory-app/src/test/resources/listeners.xml b/server/apps/memory-app/src/test/resources/listeners.xml
index 64f0770525..ae5937f1fa 100644
--- a/server/apps/memory-app/src/test/resources/listeners.xml
+++ b/server/apps/memory-app/src/test/resources/listeners.xml
@@ -19,7 +19,4 @@
  -->
 
 <listeners>
-  <listener>
-    <class>org.apache.james.mailbox.spamassassin.SpamAssassinListener</class>
-  </listener>
 </listeners>
\ No newline at end of file
diff --git a/server/apps/scaling-pulsar-smtp/src/test/resources/listeners.xml b/server/apps/scaling-pulsar-smtp/src/test/resources/listeners.xml
index eabdb5e112..71dccb1ccb 100644
--- a/server/apps/scaling-pulsar-smtp/src/test/resources/listeners.xml
+++ b/server/apps/scaling-pulsar-smtp/src/test/resources/listeners.xml
@@ -19,9 +19,6 @@
  -->
 
 <listeners>
-  <listener>
-    <class>org.apache.james.mailbox.spamassassin.SpamAssassinListener</class>
-  </listener>
   <listener>
     <class>org.apache.james.mailbox.cassandra.MailboxOperationLoggingListener</class>
   </listener>
diff --git a/server/apps/spring-app/src/main/resources/smtpserver.xml b/server/apps/spring-app/src/main/resources/smtpserver.xml
index 31765417da..1b618df439 100644
--- a/server/apps/spring-app/src/main/resources/smtpserver.xml
+++ b/server/apps/spring-app/src/main/resources/smtpserver.xml
@@ -277,17 +277,7 @@
             </handler>
              -->
              
-            <!-- This MessageHandler could be used to check message against spamd before -->
-            <!-- accept the email. So its possible to reject a message on smtplevel if a -->
-            <!-- configured hits amount is reached. -->
-            <!--
-            <handler class="org.apache.james.smtpserver.fastfail.SpamAssassinHandler">
-                <spamdHost>127.0.0.1</spamdHost>
-                <spamdPort>783</spamdPort>
-                <spamdRejectionHits>10</spamdRejectionHits>
-            </handler>
-             -->
-     
+
             <!-- This MessageHandler could be used to extract domain out of the message and check -->
             <!-- this domains against uriRbllists. See http://www.surbl.org for more information. -->
             <!-- The message get rejected if a domain matched . -->
diff --git a/server/mailet/mailets/src/main/java/org/apache/james/transport/matchers/IsMarkedAsSpam.java b/server/mailet/mailets/src/main/java/org/apache/james/transport/matchers/IsMarkedAsSpam.java
index a5ef1aac68..98072e88a3 100644
--- a/server/mailet/mailets/src/main/java/org/apache/james/transport/matchers/IsMarkedAsSpam.java
+++ b/server/mailet/mailets/src/main/java/org/apache/james/transport/matchers/IsMarkedAsSpam.java
@@ -26,7 +26,6 @@ import java.util.Optional;
 import javax.mail.MessagingException;
 
 import org.apache.james.core.MailAddress;
-import org.apache.james.spamassassin.SpamAssassinResult;
 import org.apache.mailet.Mail;
 import org.apache.mailet.base.GenericMatcher;
 
@@ -54,7 +53,9 @@ public class IsMarkedAsSpam extends GenericMatcher {
 
     private static final String YES = "yes";
 
-    private String spamStatusHeader = SpamAssassinResult.STATUS_MAIL.asString();
+    public static final String STATUS_MAIL_PACKAGE_DEFAULT = "org.apache.james.spamassassin.status";
+
+    private String spamStatusHeader = STATUS_MAIL_PACKAGE_DEFAULT;
 
     @Override
     public String getMatcherInfo() {
@@ -65,7 +66,7 @@ public class IsMarkedAsSpam extends GenericMatcher {
     public void init() throws MessagingException {
         spamStatusHeader = Optional.ofNullable(getCondition())
             .filter(s -> !s.isEmpty())
-            .orElse(SpamAssassinResult.STATUS_MAIL.asString());
+            .orElse(STATUS_MAIL_PACKAGE_DEFAULT);
     }
 
     @Override
diff --git a/server/protocols/jmap-draft-integration-testing/jmap-draft-integration-testing-common/pom.xml b/server/protocols/jmap-draft-integration-testing/jmap-draft-integration-testing-common/pom.xml
index 5fa8986b93..96fcb9264d 100644
--- a/server/protocols/jmap-draft-integration-testing/jmap-draft-integration-testing-common/pom.xml
+++ b/server/protocols/jmap-draft-integration-testing/jmap-draft-integration-testing-common/pom.xml
@@ -39,11 +39,6 @@
             <type>test-jar</type>
             <scope>test</scope>
         </dependency>
-        <dependency>
-            <groupId>${james.groupId}</groupId>
-            <artifactId>apache-james-mailbox-spamassassin</artifactId>
-            <scope>test</scope>
-        </dependency>
         <dependency>
             <groupId>${james.groupId}</groupId>
             <artifactId>backup</artifactId>
diff --git a/server/protocols/jmap-draft-integration-testing/memory-jmap-draft-integration-testing/pom.xml b/server/protocols/jmap-draft-integration-testing/memory-jmap-draft-integration-testing/pom.xml
index c0d841e38b..a6293dad92 100644
--- a/server/protocols/jmap-draft-integration-testing/memory-jmap-draft-integration-testing/pom.xml
+++ b/server/protocols/jmap-draft-integration-testing/memory-jmap-draft-integration-testing/pom.xml
@@ -45,11 +45,6 @@
             <type>test-jar</type>
             <scope>test</scope>
         </dependency>
-        <dependency>
-            <groupId>${james.groupId}</groupId>
-            <artifactId>apache-james-mailbox-spamassassin</artifactId>
-            <scope>test</scope>
-        </dependency>
         <dependency>
             <groupId>${james.groupId}</groupId>
             <artifactId>apache-mailet-base</artifactId>
diff --git a/server/protocols/jmap-draft-integration-testing/memory-jmap-draft-integration-testing/src/test/resources/listeners.xml b/server/protocols/jmap-draft-integration-testing/memory-jmap-draft-integration-testing/src/test/resources/listeners.xml
index a686755978..a1a139d2f1 100644
--- a/server/protocols/jmap-draft-integration-testing/memory-jmap-draft-integration-testing/src/test/resources/listeners.xml
+++ b/server/protocols/jmap-draft-integration-testing/memory-jmap-draft-integration-testing/src/test/resources/listeners.xml
@@ -43,9 +43,6 @@
       <name>second</name>
     </configuration>
   </listener>
-  <listener>
-    <class>org.apache.james.mailbox.spamassassin.SpamAssassinListener</class>
-  </listener>
   <listener>
     <class>org.apache.james.jmap.event.PopulateEmailQueryViewListener</class>
     <async>true</async>
diff --git a/server/protocols/jmap-draft-integration-testing/rabbitmq-jmap-draft-integration-testing/src/test/resources/listeners.xml b/server/protocols/jmap-draft-integration-testing/rabbitmq-jmap-draft-integration-testing/src/test/resources/listeners.xml
index 43c8b962ac..1ff4055a56 100644
--- a/server/protocols/jmap-draft-integration-testing/rabbitmq-jmap-draft-integration-testing/src/test/resources/listeners.xml
+++ b/server/protocols/jmap-draft-integration-testing/rabbitmq-jmap-draft-integration-testing/src/test/resources/listeners.xml
@@ -46,9 +46,6 @@
       <name>second</name>
     </configuration>
   </listener>
-  <listener>
-    <class>org.apache.james.mailbox.spamassassin.SpamAssassinListener</class>
-  </listener>
   <listener>
     <class>org.apache.james.jmap.event.PopulateEmailQueryViewListener</class>
     <async>true</async>
diff --git a/server/testing/src/main/java/org/apache/james/util/docker/Images.java b/server/testing/src/main/java/org/apache/james/util/docker/Images.java
index 87054f065a..61074e7596 100644
--- a/server/testing/src/main/java/org/apache/james/util/docker/Images.java
+++ b/server/testing/src/main/java/org/apache/james/util/docker/Images.java
@@ -27,6 +27,5 @@ public interface Images {
     String ELASTICSEARCH_7 = "docker.elastic.co/elasticsearch/elasticsearch:7.10.2";
     String OPENSEARCH = "opensearchproject/opensearch:2.1.0";
     String TIKA = "apache/tika:1.28.2";
-    String SPAMASSASSIN = "instantlinux/spamassassin:3.4.6-1";
     String MOCK_SMTP_SERVER = "linagora/mock-smtp-server:0.4";
 }
diff --git a/third-party/spamassassin/docker-compose.yml b/third-party/spamassassin/docker-compose.yml
new file mode 100644
index 0000000000..618806afc1
--- /dev/null
+++ b/third-party/spamassassin/docker-compose.yml
@@ -0,0 +1,32 @@
+version: '3'
+
+services:
+
+  james:
+    depends_on:
+      - spamassassin
+    image: apache/james:memory-latest
+    container_name: james
+    hostname: james.local
+    volumes:
+      - $PWD/target/apache-james-spamassassin-3.8.0-SNAPSHOT-jar-with-dependencies.jar:/root/extensions-jars/james-server-spamassassin.jar
+      - $PWD/sample-configuration/keystore:/root/conf/keystore
+      - $PWD/sample-configuration/extensions.properties:/root/conf/extensions.properties
+      - $PWD/sample-configuration/spamassassin.properties:/root/conf/spamassassin.properties
+      - $PWD/sample-configuration/mailetcontainer.xml:/root/conf/mailetcontainer.xml
+      - $PWD/sample-configuration/listeners.xml:/root/conf/listeners.xml
+      - $PWD/sample-configuration/smtpserver.xml:/root/conf/smtpserver.xml
+    ports:
+      - "80:80"
+      - "25:25"
+      - "110:110"
+      - "143:143"
+      - "465:465"
+      - "587:587"
+      - "993:993"
+      - "8000:8000"
+
+  spamassassin:
+    image: instantlinux/spamassassin:3.4.6-1
+    ports:
+      - "783:783"
\ No newline at end of file
diff --git a/third-party/spamassassin/pom.xml b/third-party/spamassassin/pom.xml
index 8510f370e8..2042349664 100644
--- a/third-party/spamassassin/pom.xml
+++ b/third-party/spamassassin/pom.xml
@@ -1,5 +1,4 @@
 <?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
@@ -32,14 +31,81 @@
     <description>SpamAssassin Java client and testing utilities</description>
 
     <dependencies>
+        <dependency>
+            <groupId>${james.groupId}</groupId>
+            <artifactId>apache-james-mailbox-api</artifactId>
+            <type>test-jar</type>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>${james.groupId}</groupId>
+            <artifactId>apache-james-mailbox-memory</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>${james.groupId}</groupId>
+            <artifactId>apache-james-mailbox-memory</artifactId>
+            <type>test-jar</type>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>${james.groupId}</groupId>
+            <artifactId>apache-james-mailbox-store</artifactId>
+        </dependency>
         <dependency>
             <groupId>${james.groupId}</groupId>
             <artifactId>apache-mailet-api</artifactId>
         </dependency>
+        <dependency>
+            <groupId>${james.groupId}</groupId>
+            <artifactId>apache-mailet-base</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>${james.groupId}</groupId>
+            <artifactId>event-bus-api</artifactId>
+            <type>test-jar</type>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>${james.groupId}</groupId>
+            <artifactId>event-bus-in-vm</artifactId>
+            <scope>test</scope>
+        </dependency>
         <dependency>
             <groupId>${james.groupId}</groupId>
             <artifactId>james-core</artifactId>
         </dependency>
+        <dependency>
+            <groupId>${james.groupId}</groupId>
+            <artifactId>james-server-data-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>${james.groupId}</groupId>
+            <artifactId>james-server-data-memory</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>${james.groupId}</groupId>
+            <artifactId>james-server-guice-common</artifactId>
+            <type>test-jar</type>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>${james.groupId}</groupId>
+            <artifactId>james-server-guice-configuration</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>${james.groupId}</groupId>
+            <artifactId>james-server-mailets-integration-testing</artifactId>
+            <version>${project.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>${james.groupId}</groupId>
+            <artifactId>james-server-protocols-smtp</artifactId>
+            <version>${project.version}</version>
+        </dependency>
         <dependency>
             <groupId>${james.groupId}</groupId>
             <artifactId>james-server-testing</artifactId>
@@ -59,6 +125,13 @@
             <artifactId>testing-base</artifactId>
             <scope>test</scope>
         </dependency>
+        <dependency>
+            <groupId>${james.protocols.groupId}</groupId>
+            <artifactId>protocols-smtp</artifactId>
+            <version>${project.version}</version>
+            <type>test-jar</type>
+            <scope>test</scope>
+        </dependency>
         <dependency>
             <groupId>com.github.fge</groupId>
             <artifactId>throwing-lambdas</artifactId>
@@ -67,6 +140,10 @@
             <groupId>com.google.guava</groupId>
             <artifactId>guava</artifactId>
         </dependency>
+        <dependency>
+            <groupId>com.google.inject</groupId>
+            <artifactId>guice</artifactId>
+        </dependency>
         <dependency>
             <groupId>com.sun.mail</groupId>
             <artifactId>javax.mail</artifactId>
@@ -79,6 +156,11 @@
             <groupId>org.apache.commons</groupId>
             <artifactId>commons-lang3</artifactId>
         </dependency>
+        <dependency>
+            <groupId>org.mockito</groupId>
+            <artifactId>mockito-core</artifactId>
+            <scope>test</scope>
+        </dependency>
         <dependency>
             <groupId>org.slf4j</groupId>
             <artifactId>slf4j-api</artifactId>
@@ -89,5 +171,24 @@
             <scope>test</scope>
         </dependency>
     </dependencies>
-
-</project>
\ No newline at end of file
+    <build>
+        <plugins>
+            <plugin>
+                <artifactId>maven-assembly-plugin</artifactId>
+                <configuration>
+                    <descriptorRefs>
+                        <descriptorRef>jar-with-dependencies</descriptorRef>
+                    </descriptorRefs>
+                </configuration>
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>single</goal>
+                        </goals>
+                        <phase>compile</phase>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+</project>
diff --git a/third-party/spamassassin/sample-configuration/extensions.properties b/third-party/spamassassin/sample-configuration/extensions.properties
new file mode 100644
index 0000000000..255e435b0d
--- /dev/null
+++ b/third-party/spamassassin/sample-configuration/extensions.properties
@@ -0,0 +1 @@
+guice.extension.module=org.apache.james.spamassassin.SpamAssassinModule
\ No newline at end of file
diff --git a/third-party/spamassassin/sample-configuration/keystore b/third-party/spamassassin/sample-configuration/keystore
new file mode 100644
index 0000000000..361cd01f43
Binary files /dev/null and b/third-party/spamassassin/sample-configuration/keystore differ
diff --git a/third-party/spamassassin/sample-configuration/listeners.xml b/third-party/spamassassin/sample-configuration/listeners.xml
new file mode 100644
index 0000000000..28d5e2c7d7
--- /dev/null
+++ b/third-party/spamassassin/sample-configuration/listeners.xml
@@ -0,0 +1,26 @@
+<?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-listeners.html for further details -->
+
+<listeners>
+    <listener>
+        <class>org.apache.james.spamassassin.SpamAssassinListener</class>
+        <async>true</async>
+    </listener>
+</listeners>
\ No newline at end of file
diff --git a/third-party/spamassassin/sample-configuration/mailetcontainer.xml b/third-party/spamassassin/sample-configuration/mailetcontainer.xml
new file mode 100644
index 0000000000..75d7e1d8f0
--- /dev/null
+++ b/third-party/spamassassin/sample-configuration/mailetcontainer.xml
@@ -0,0 +1,167 @@
+<?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-mailetcontainer.html for further details -->
+
+<mailetcontainer enableJmx="true">
+
+    <context>
+        <!-- When the domain part of the postmaster mailAddress is missing, the default domain is appended.
+        You can configure it to (for example) <postmaster>postmaster@myDomain.com</postmaster> -->
+        <postmaster>postmaster</postmaster>
+    </context>
+
+    <spooler>
+        <threads>20</threads>
+        <errorRepository>memory://var/mail/error/</errorRepository>
+    </spooler>
+
+    <processors>
+        <processor state="root" enableJmx="true">
+            <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="true">
+            <mailet match="All" class="MetricsMailet">
+                <metricName>mailetContainerErrors</metricName>
+            </mailet>
+            <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="true">
+            <matcher name="relay-allowed" match="org.apache.james.mailetcontainer.impl.matchers.Or">
+                <matcher match="SMTPAuthSuccessful"/>
+                <matcher match="SMTPIsAuthNetwork"/>
+                <matcher match="SentByMailet"/>
+                <matcher match="org.apache.james.jmap.mailet.SentByJmap"/>
+            </matcher>
+
+            <mailet match="All" class="RemoveMimeHeader">
+                <name>bcc</name>
+                <onMailetException>ignore</onMailetException>
+            </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="relay-allowed" class="ToProcessor">
+                <processor>relay</processor>
+            </mailet>
+            <mailet match="All" class="ToProcessor">
+                <processor>relay-denied</processor>
+            </mailet>
+        </processor>
+
+        <processor state="local-delivery" enableJmx="true">
+            <mailet match="All" class="org.apache.james.spamassassin.SpamAssassin">
+                <onMailetException>ignore</onMailetException>
+            </mailet>
+            <mailet match="IsMarkedAsSpam" class="WithStorageDirective">
+                <targetFolderName>Spam</targetFolderName>
+            </mailet>
+            <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="relay" enableJmx="true">
+            <mailet match="All" 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>
+        </processor>
+
+        <processor state="local-address-error" enableJmx="true">
+            <mailet match="All" class="MetricsMailet">
+                <metricName>mailetContainerLocalAddressError</metricName>
+            </mailet>
+            <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="true">
+            <mailet match="All" class="MetricsMailet">
+                <metricName>mailetContainerRelayDenied</metricName>
+            </mailet>
+            <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 authenticated to perform such an operation</notice>
+            </mailet>
+        </processor>
+
+        <processor state="bounces" enableJmx="true">
+            <mailet match="All" class="MetricsMailet">
+                <metricName>bounces</metricName>
+            </mailet>
+            <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/third-party/spamassassin/sample-configuration/smtpserver.xml b/third-party/spamassassin/sample-configuration/smtpserver.xml
new file mode 100644
index 0000000000..1909b95be1
--- /dev/null
+++ b/third-party/spamassassin/sample-configuration/smtpserver.xml
@@ -0,0 +1,158 @@
+<?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-smtp-lmtp.html#SMTP_Configuration for further details -->
+
+<smtpservers>
+    <smtpserver enabled="true">
+        <jmxName>smtpserver-global</jmxName>
+        <bind>0.0.0.0:25</bind>
+        <connectionBacklog>200</connectionBacklog>
+        <tls socketTLS="false" startTLS="false">
+            <!-- To create a new keystore execute:
+              keytool -genkey -alias james -keyalg RSA -storetype PKCS12 -keystore /path/to/james/conf/keystore
+             -->
+            <keystore>file://conf/keystore</keystore>
+            <keystoreType>PKCS12</keystoreType>
+            <secret>james72laBalle</secret>
+            <provider>org.bouncycastle.jce.provider.BouncyCastleProvider</provider>
+            <algorithm>SunX509</algorithm>
+
+            <!-- Alternatively TLS keys can be supplied via PEM files -->
+            <!-- <privateKey>file://conf/private.key</privateKey> -->
+            <!-- <certificates>file://conf/certs.self-signed.csr</certificates> -->
+            <!-- An optional secret might be specified for the private key -->
+            <!-- <secret>james72laBalle</secret> -->
+        </tls>
+        <connectiontimeout>360</connectiontimeout>
+        <connectionLimit>0</connectionLimit>
+        <connectionLimitPerIP>0</connectionLimitPerIP>
+        <auth>
+            <announce>never</announce>
+            <requireSSL>false</requireSSL>
+            <plainAuthEnabled>true</plainAuthEnabled>
+        </auth>
+        <authorizedAddresses>127.0.0.0/8</authorizedAddresses>
+        <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"/>
+            <handler class="org.apache.james.spamassassin.SpamAssassinHandler"/>
+        </handlerchain>
+    </smtpserver>
+    <smtpserver enabled="true">
+        <jmxName>smtpserver-TLS</jmxName>
+        <bind>0.0.0.0:465</bind>
+        <connectionBacklog>200</connectionBacklog>
+        <tls socketTLS="true" startTLS="false">
+            <!-- To create a new keystore execute:
+              keytool -genkey -alias james -keyalg RSA -storetype PKCS12 -keystore /path/to/james/conf/keystore
+             -->
+            <keystore>file://conf/keystore</keystore>
+            <keystoreType>PKCS12</keystoreType>
+            <secret>james72laBalle</secret>
+            <provider>org.bouncycastle.jce.provider.BouncyCastleProvider</provider>
+            <algorithm>SunX509</algorithm>
+
+            <!-- Alternatively TLS keys can be supplied via PEM files -->
+            <!-- <privateKey>file://conf/private.key</privateKey> -->
+            <!-- <certificates>file://conf/certs.self-signed.csr</certificates> -->
+            <!-- An optional secret might be specified for the private key -->
+            <!-- <secret>james72laBalle</secret> -->
+        </tls>
+        <connectiontimeout>360</connectiontimeout>
+        <connectionLimit>0</connectionLimit>
+        <connectionLimitPerIP>0</connectionLimitPerIP>
+        <auth>
+            <announce>forUnauthorizedAddresses</announce>
+            <requireSSL>true</requireSSL>
+            <plainAuthEnabled>true</plainAuthEnabled>
+            <oidc>
+                <oidcConfigurationURL>https://auth.upn.integration-open-paas.org/auth/realms/upn/.well-known/openid-configuration</oidcConfigurationURL>
+                <jwksURL>https://auth.upn.integration-open-paas.org/auth/realms/upn/protocol/openid-connect/certs</jwksURL>
+                <claim>email</claim>
+                <scope>openid profile email</scope>
+            </oidc>
+        </auth>
+        <authorizedAddresses>127.0.0.0/8</authorizedAddresses>
+        <!-- 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"/>
+            <handler class="org.apache.james.spamassassin.SpamAssassinHandler"/>
+        </handlerchain>
+    </smtpserver>
+    <smtpserver enabled="true">
+        <jmxName>smtpserver-authenticated</jmxName>
+        <bind>0.0.0.0:587</bind>
+        <connectionBacklog>200</connectionBacklog>
+        <tls socketTLS="false" startTLS="true">
+            <!-- To create a new keystore execute:
+              keytool -genkey -alias james -keyalg RSA -storetype PKCS12 -keystore /path/to/james/conf/keystore
+             -->
+            <keystore>file://conf/keystore</keystore>
+            <keystoreType>PKCS12</keystoreType>
+            <secret>james72laBalle</secret>
+            <provider>org.bouncycastle.jce.provider.BouncyCastleProvider</provider>
+            <algorithm>SunX509</algorithm>
+
+            <!-- Alternatively TLS keys can be supplied via PEM files -->
+            <!-- <privateKey>file://conf/private.key</privateKey> -->
+            <!-- <certificates>file://conf/certs.self-signed.csr</certificates> -->
+            <!-- An optional secret might be specified for the private key -->
+            <!-- <secret>james72laBalle</secret> -->
+        </tls>
+        <connectiontimeout>360</connectiontimeout>
+        <connectionLimit>0</connectionLimit>
+        <connectionLimitPerIP>0</connectionLimitPerIP>
+        <auth>
+            <announce>forUnauthorizedAddresses</announce>
+            <requireSSL>true</requireSSL>
+            <plainAuthEnabled>true</plainAuthEnabled>
+            <oidc>
+                <oidcConfigurationURL>https://auth.upn.integration-open-paas.org/auth/realms/upn/.well-known/openid-configuration</oidcConfigurationURL>
+                <jwksURL>https://auth.upn.integration-open-paas.org/auth/realms/upn/protocol/openid-connect/certs</jwksURL>
+                <claim>email</claim>
+                <scope>openid profile email</scope>
+            </oidc>
+        </auth>
+        <authorizedAddresses>127.0.0.0/8</authorizedAddresses>
+        <!-- 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"/>
+            <handler class="org.apache.james.spamassassin.SpamAssassinHandler"/>
+        </handlerchain>
+    </smtpserver>
+</smtpservers>
+
+
diff --git a/server/apps/memory-app/src/test/resources/spamassassin.properties b/third-party/spamassassin/sample-configuration/spamassassin.properties
similarity index 57%
rename from server/apps/memory-app/src/test/resources/spamassassin.properties
rename to third-party/spamassassin/sample-configuration/spamassassin.properties
index 134ed31a97..99312441dc 100644
--- a/server/apps/memory-app/src/test/resources/spamassassin.properties
+++ b/third-party/spamassassin/sample-configuration/spamassassin.properties
@@ -1,2 +1,2 @@
 spamassassin.host=localhost
-spamassassin.host=783
\ No newline at end of file
+spamassassin.port=783
\ No newline at end of file
diff --git a/third-party/spamassassin/src/main/java/org/apache/james/spamassassin/SpamAssassin.java b/third-party/spamassassin/src/main/java/org/apache/james/spamassassin/SpamAssassin.java
new file mode 100644
index 0000000000..892edbe18b
--- /dev/null
+++ b/third-party/spamassassin/src/main/java/org/apache/james/spamassassin/SpamAssassin.java
@@ -0,0 +1,102 @@
+/****************************************************************
+ * 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.spamassassin;
+
+import javax.inject.Inject;
+import javax.mail.MessagingException;
+import javax.mail.internet.MimeMessage;
+
+import org.apache.james.core.MailAddress;
+import org.apache.james.metrics.api.MetricFactory;
+import org.apache.james.user.api.UsersRepository;
+import org.apache.james.user.api.UsersRepositoryException;
+import org.apache.james.util.Host;
+import org.apache.mailet.Attribute;
+import org.apache.mailet.Mail;
+import org.apache.mailet.PerRecipientHeaders;
+import org.apache.mailet.base.GenericMailet;
+
+import com.github.fge.lambdas.Throwing;
+
+
+/**
+ * Sends the message through daemonized SpamAssassin (spamd), visit <a
+ * href="http://spamassassin.apache.org/">spamassassin.apache.org/</a> for info
+ * on configuration. The header X-Spam-Status is added to every message, this
+ * contains the score and the threshold score for spam (usually 5.0). If the
+ * message exceeds the threshold, the header X-Spam-Flag will be added with the
+ * value of YES. The default host for spamd is localhost and the default port is
+ * 783.
+ *
+ * <pre>
+ * <code>
+ *  org.apache.james.spamassassin.status - Holds the status
+ *  org.apache.james.spamassassin.flag   - Holds the flag
+ * </code>
+ * </pre>
+ *
+ * Sample Configuration:
+ *
+ * <pre>
+ * &lt;mailet notmatch="SenderHostIsLocal" class="SpamAssassin"&gt;
+ * </pre>
+ */
+public class SpamAssassin extends GenericMailet {
+    private final MetricFactory metricFactory;
+    private final UsersRepository usersRepository;
+
+    private final Host spamAssassinHost;
+
+    @Inject
+    public SpamAssassin(MetricFactory metricFactory, UsersRepository usersRepository, SpamAssassinConfiguration spamAssassinConfiguration) {
+        this.metricFactory = metricFactory;
+        this.usersRepository = usersRepository;
+        this.spamAssassinHost = spamAssassinConfiguration.getHost();
+    }
+
+    @Override
+    public void service(Mail mail) throws MessagingException {
+        MimeMessage message = mail.getMessage();
+
+        // Invoke SpamAssassin connection and scan the message
+        SpamAssassinInvoker sa = new SpamAssassinInvoker(metricFactory, spamAssassinHost.getHostName(), spamAssassinHost.getPort());
+        mail.getRecipients()
+            .forEach(
+                Throwing.consumer((MailAddress recipient) -> querySpamAssassin(mail, message, sa, recipient))
+                    .sneakyThrow());
+    }
+
+    private void querySpamAssassin(Mail mail, MimeMessage message, SpamAssassinInvoker sa, MailAddress recipient) throws MessagingException, UsersRepositoryException {
+        SpamAssassinResult result = sa.scanMail(message, usersRepository.getUsername(recipient));
+
+        // Add headers per recipient to mail object
+        for (Attribute attribute : result.getHeadersAsAttributes()) {
+            mail.addSpecificHeaderForRecipient(PerRecipientHeaders.Header.builder()
+                .name(attribute.getName().asString())
+                .value((String) attribute.getValue().value())
+                .build(), recipient);
+        }
+    }
+
+    @Override
+    public String getMailetInfo() {
+        return "Checks message against SpamAssassin";
+    }
+}
diff --git a/server/testing/src/main/java/org/apache/james/util/docker/Images.java b/third-party/spamassassin/src/main/java/org/apache/james/spamassassin/SpamAssassinConfiguration.java
similarity index 57%
copy from server/testing/src/main/java/org/apache/james/util/docker/Images.java
copy to third-party/spamassassin/src/main/java/org/apache/james/spamassassin/SpamAssassinConfiguration.java
index 87054f065a..728f6b270e 100644
--- a/server/testing/src/main/java/org/apache/james/util/docker/Images.java
+++ b/third-party/spamassassin/src/main/java/org/apache/james/spamassassin/SpamAssassinConfiguration.java
@@ -17,16 +17,47 @@
  * under the License.                                           *
  ****************************************************************/
 
-package org.apache.james.util.docker;
-
-public interface Images {
-    String FAKE_SMTP = "weave/rest-smtp-sink:latest";
-    String RABBITMQ = "rabbitmq:3.9.18-management";
-    String ELASTICSEARCH_2 = "elasticsearch:2.4.6";
-    String ELASTICSEARCH_6 = "docker.elastic.co/elasticsearch/elasticsearch:6.3.2";
-    String ELASTICSEARCH_7 = "docker.elastic.co/elasticsearch/elasticsearch:7.10.2";
-    String OPENSEARCH = "opensearchproject/opensearch:2.1.0";
-    String TIKA = "apache/tika:1.28.2";
-    String SPAMASSASSIN = "instantlinux/spamassassin:3.4.6-1";
-    String MOCK_SMTP_SERVER = "linagora/mock-smtp-server:0.4";
-}
+package org.apache.james.spamassassin;
+
+
+import java.util.Objects;
+
+import org.apache.james.util.Host;
+
+import com.google.common.base.MoreObjects;
+
+public class SpamAssassinConfiguration {
+
+    private final Host host;
+
+    public SpamAssassinConfiguration(Host host) {
+        this.host = host;
+    }
+
+
+    public Host getHost() {
+        return host;
+    }
+
+    @Override
+    public final boolean equals(Object o) {
+        if (o instanceof SpamAssassinConfiguration) {
+            SpamAssassinConfiguration that = (SpamAssassinConfiguration) o;
+
+            return Objects.equals(this.host, that.host);
+        }
+        return false;
+    }
+
+    @Override
+    public final int hashCode() {
+        return Objects.hash(host);
+    }
+
+    @Override
+    public String toString() {
+        return MoreObjects.toStringHelper(this)
+            .add("host", host)
+            .toString();
+    }
+}
\ No newline at end of file
diff --git a/server/protocols/protocols-smtp/src/main/java/org/apache/james/smtpserver/fastfail/SpamAssassinHandler.java b/third-party/spamassassin/src/main/java/org/apache/james/spamassassin/SpamAssassinHandler.java
similarity index 79%
rename from server/protocols/protocols-smtp/src/main/java/org/apache/james/smtpserver/fastfail/SpamAssassinHandler.java
rename to third-party/spamassassin/src/main/java/org/apache/james/spamassassin/SpamAssassinHandler.java
index b8ee0a5c93..56c4409172 100644
--- a/server/protocols/protocols-smtp/src/main/java/org/apache/james/smtpserver/fastfail/SpamAssassinHandler.java
+++ b/third-party/spamassassin/src/main/java/org/apache/james/spamassassin/SpamAssassinHandler.java
@@ -17,14 +17,14 @@
  * under the License.                                           *
  ****************************************************************/
 
-package org.apache.james.smtpserver.fastfail;
+package org.apache.james.spamassassin;
+
 
 import javax.inject.Inject;
 import javax.mail.MessagingException;
 import javax.mail.internet.MimeMessage;
 
 import org.apache.commons.configuration2.Configuration;
-import org.apache.commons.configuration2.ex.ConfigurationException;
 import org.apache.james.metrics.api.MetricFactory;
 import org.apache.james.protocols.api.ProtocolSession.State;
 import org.apache.james.protocols.api.handler.ProtocolHandler;
@@ -33,8 +33,6 @@ import org.apache.james.protocols.smtp.dsn.DSNStatus;
 import org.apache.james.protocols.smtp.hook.HookResult;
 import org.apache.james.protocols.smtp.hook.HookReturnCode;
 import org.apache.james.smtpserver.JamesMessageHook;
-import org.apache.james.spamassassin.SpamAssassinInvoker;
-import org.apache.james.spamassassin.SpamAssassinResult;
 import org.apache.mailet.Mail;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -59,8 +57,6 @@ import org.slf4j.LoggerFactory;
  * 
  * <pre>
  * &lt;handler class="org.apache.james.smtpserver.SpamAssassinHandler"&gt;
- *   &lt;spamdHost&gt;localhost&lt;/spamdHost&gt;
- *   &lt;spamdPort&gt;783&lt;/spamdPort&gt; <br>
  *   &lt;spamdRejectionHits&gt;15.0&lt;/spamdRejectionHits&gt;
  *   &lt;checkAuthNetworks&gt;false&lt;/checkAuthNetworks&gt;
  * &lt;/handler&gt;
@@ -72,46 +68,24 @@ public class SpamAssassinHandler implements JamesMessageHook, ProtocolHandler {
     private static final Logger LOGGER = LoggerFactory.getLogger(SpamAssassinHandler.class);
 
     private final MetricFactory metricFactory;
+    private final SpamAssassinConfiguration spamAssassinConfiguration;
 
-    /** The port spamd is listen on */
-    private int spamdPort = 783;
-
-    /** The host spamd is running on */
-    private String spamdHost = "localhost";
-
-    /** The hits on which the message get rejected */
+    /**
+     * The hits on which the message get rejected
+     */
     private double spamdRejectionHits = 0.0;
 
     @Inject
-    public SpamAssassinHandler(MetricFactory metricFactory) {
+    public SpamAssassinHandler(MetricFactory metricFactory, SpamAssassinConfiguration spamAssassinConfiguration) {
         this.metricFactory = metricFactory;
+        this.spamAssassinConfiguration = spamAssassinConfiguration;
     }
 
-    /**
-     * Set the host the spamd daemon is running at
-     * 
-     * @param spamdHost
-     *            The spamdHost
-     */
-    public void setSpamdHost(String spamdHost) {
-        this.spamdHost = spamdHost;
-    }
-
-    /**
-     * Set the port the spamd daemon is listen on
-     * 
-     * @param spamdPort
-     *            the spamdPort
-     */
-    public void setSpamdPort(int spamdPort) {
-        this.spamdPort = spamdPort;
-    }
 
     /**
      * Set the hits on which the message will be rejected.
-     * 
-     * @param spamdRejectionHits
-     *            The hits
+     *
+     * @param spamdRejectionHits The hits
      */
     public void setSpamdRejectionHits(double spamdRejectionHits) {
         this.spamdRejectionHits = spamdRejectionHits;
@@ -120,10 +94,9 @@ public class SpamAssassinHandler implements JamesMessageHook, ProtocolHandler {
 
     @Override
     public HookResult onMessage(SMTPSession session, Mail mail) {
-
         try {
             MimeMessage message = mail.getMessage();
-            SpamAssassinInvoker sa = new SpamAssassinInvoker(metricFactory, spamdHost, spamdPort);
+            SpamAssassinInvoker sa = new SpamAssassinInvoker(metricFactory, spamAssassinConfiguration.getHost().getHostName(), spamAssassinConfiguration.getHost().getPort());
             SpamAssassinResult result = sa.scanMail(message);
 
             // Add the headers
@@ -158,9 +131,7 @@ public class SpamAssassinHandler implements JamesMessageHook, ProtocolHandler {
     }
 
     @Override
-    public void init(Configuration config) throws ConfigurationException {
-        setSpamdHost(config.getString("spamdHost", "localhost"));
-        setSpamdPort(config.getInt("spamdPort", 783));
-        setSpamdRejectionHits(config.getDouble("spamdRejectionHits", 0.0));        
+    public void init(Configuration config) {
+        setSpamdRejectionHits(config.getDouble("spamdRejectionHits", 0.0));
     }
 }
diff --git a/third-party/spamassassin/src/main/java/org/apache/james/spamassassin/SpamAssassinLearner.java b/third-party/spamassassin/src/main/java/org/apache/james/spamassassin/SpamAssassinLearner.java
new file mode 100644
index 0000000000..7355cb146e
--- /dev/null
+++ b/third-party/spamassassin/src/main/java/org/apache/james/spamassassin/SpamAssassinLearner.java
@@ -0,0 +1,56 @@
+/****************************************************************
+ * 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.spamassassin;
+
+
+import java.io.InputStream;
+import java.util.List;
+
+import javax.inject.Inject;
+
+import org.apache.james.core.Username;
+import org.apache.james.metrics.api.MetricFactory;
+import org.apache.james.util.Host;
+
+import com.github.fge.lambdas.Throwing;
+
+public class SpamAssassinLearner {
+
+    private final MetricFactory metricFactory;
+    private final Host spamAssassinHost;
+
+    @Inject
+    public SpamAssassinLearner(MetricFactory metricFactory, SpamAssassinConfiguration spamAssassinConfiguration) {
+        this.metricFactory = metricFactory;
+        this.spamAssassinHost = spamAssassinConfiguration.getHost();
+    }
+
+    public void learnSpam(List<InputStream> messages, Username username) {
+        SpamAssassinInvoker invoker = new SpamAssassinInvoker(metricFactory, spamAssassinHost.getHostName(), spamAssassinHost.getPort());
+        messages
+            .forEach(Throwing.consumer(message -> invoker.learnAsSpam(message, username)));
+    }
+
+    public void learnHam(List<InputStream> messages, Username username) {
+        SpamAssassinInvoker invoker = new SpamAssassinInvoker(metricFactory, spamAssassinHost.getHostName(), spamAssassinHost.getPort());
+        messages
+            .forEach(Throwing.consumer(message -> invoker.learnAsHam(message, username)));
+    }
+}
diff --git a/third-party/spamassassin/src/main/java/org/apache/james/spamassassin/SpamAssassinListener.java b/third-party/spamassassin/src/main/java/org/apache/james/spamassassin/SpamAssassinListener.java
new file mode 100644
index 0000000000..19a86262df
--- /dev/null
+++ b/third-party/spamassassin/src/main/java/org/apache/james/spamassassin/SpamAssassinListener.java
@@ -0,0 +1,185 @@
+/****************************************************************
+ * 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.spamassassin;
+
+
+import java.io.InputStream;
+import java.util.List;
+import java.util.stream.Stream;
+
+import javax.inject.Inject;
+
+import org.apache.james.core.Username;
+import org.apache.james.events.Event;
+import org.apache.james.events.Group;
+import org.apache.james.mailbox.MailboxManager;
+import org.apache.james.mailbox.MailboxSession;
+import org.apache.james.mailbox.Role;
+import org.apache.james.mailbox.SystemMailboxesProvider;
+import org.apache.james.mailbox.events.MailboxEvents.Added;
+import org.apache.james.mailbox.events.MessageMoveEvent;
+import org.apache.james.mailbox.exception.MailboxException;
+import org.apache.james.mailbox.model.Mailbox;
+import org.apache.james.mailbox.model.MailboxId;
+import org.apache.james.mailbox.model.MessageRange;
+import org.apache.james.mailbox.store.MailboxSessionMapperFactory;
+import org.apache.james.mailbox.store.event.SpamEventListener;
+import org.apache.james.mailbox.store.mail.MessageMapper;
+import org.apache.james.mailbox.store.mail.model.MailboxMessage;
+import org.apache.james.mailbox.store.mail.model.Message;
+import org.apache.james.util.streams.Iterators;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.github.fge.lambdas.Throwing;
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.collect.ImmutableList;
+
+public class SpamAssassinListener implements SpamEventListener {
+    public static class SpamAssassinListenerGroup extends Group {
+
+    }
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(SpamAssassinListener.class);
+    private static final int LIMIT = 1;
+    private static final Group GROUP = new SpamAssassinListenerGroup();
+
+    private final SpamAssassinLearner spamAssassinLearner;
+    private final SystemMailboxesProvider systemMailboxesProvider;
+    private final MailboxManager mailboxManager;
+    private final MailboxSessionMapperFactory mapperFactory;
+    private final ExecutionMode executionMode;
+
+    @Inject
+    public SpamAssassinListener(SpamAssassinLearner spamAssassinLearner, SystemMailboxesProvider systemMailboxesProvider, MailboxManager mailboxManager, MailboxSessionMapperFactory mapperFactory, ExecutionMode executionMode) {
+        this.spamAssassinLearner = spamAssassinLearner;
+        this.systemMailboxesProvider = systemMailboxesProvider;
+        this.mailboxManager = mailboxManager;
+        this.mapperFactory = mapperFactory;
+        this.executionMode = executionMode;
+    }
+
+    @Override
+    public Group getDefaultGroup() {
+        return GROUP;
+    }
+
+    @Override
+    public ExecutionMode getExecutionMode() {
+        return executionMode;
+    }
+
+    @Override
+    public boolean isHandling(Event event) {
+        return event instanceof MessageMoveEvent || event instanceof Added;
+    }
+
+    @Override
+    public void event(Event event) throws MailboxException {
+        Username username = Username.of(getClass().getCanonicalName());
+        if (event instanceof MessageMoveEvent) {
+            MailboxSession session = mailboxManager.createSystemSession(username);
+            handleMessageMove(event, session, (MessageMoveEvent) event);
+        }
+        if (event instanceof Added) {
+            MailboxSession session = mailboxManager.createSystemSession(username);
+            handleAdded(event, session, (Added) event);
+        }
+    }
+
+    private void handleAdded(Event event, MailboxSession session, Added addedEvent) {
+        if (isAppendedToInbox(addedEvent)) {
+            Mailbox mailbox = mapperFactory.getMailboxMapper(session).findMailboxById(addedEvent.getMailboxId()).block();
+            MessageMapper messageMapper = mapperFactory.getMessageMapper(session);
+
+            List<InputStream> contents = MessageRange.toRanges(addedEvent.getUids())
+                .stream()
+                .flatMap(range -> retrieveMessages(messageMapper, mailbox, range))
+                .map(Throwing.function(MailboxMessage::getFullContent))
+                .collect(ImmutableList.toImmutableList());
+            spamAssassinLearner.learnHam(contents, event.getUsername());
+        }
+    }
+
+    private void handleMessageMove(Event event, MailboxSession session, MessageMoveEvent messageMoveEvent) {
+        if (isMessageMovedToSpamMailbox(messageMoveEvent)) {
+            LOGGER.debug("Spam event detected");
+            ImmutableList<InputStream> messages = retrieveMessages(messageMoveEvent, session);
+            spamAssassinLearner.learnSpam(messages, event.getUsername());
+        }
+        if (isMessageMovedOutOfSpamMailbox(messageMoveEvent)) {
+            ImmutableList<InputStream> messages = retrieveMessages(messageMoveEvent, session);
+            spamAssassinLearner.learnHam(messages, event.getUsername());
+        }
+    }
+
+    private Stream<MailboxMessage> retrieveMessages(MessageMapper messageMapper, Mailbox mailbox, MessageRange range) {
+        try {
+            return Iterators.toStream(messageMapper.findInMailbox(mailbox, range, MessageMapper.FetchType.FULL, LIMIT));
+        } catch (MailboxException e) {
+            LOGGER.warn("Can not retrieve message {} {}", mailbox.getMailboxId(), range.toString(), e);
+            return Stream.empty();
+        }
+    }
+
+    private boolean isAppendedToInbox(Added addedEvent) {
+        try {
+            return systemMailboxesProvider.findMailbox(Role.INBOX, addedEvent.getUsername())
+                .getId().equals(addedEvent.getMailboxId());
+        } catch (MailboxException e) {
+            LOGGER.warn("Could not resolve Inbox mailbox", e);
+            return false;
+        }
+    }
+
+    private ImmutableList<InputStream> retrieveMessages(MessageMoveEvent messageMoveEvent, MailboxSession session) {
+        return mapperFactory.getMessageIdMapper(session)
+            .find(messageMoveEvent.getMessageIds(), MessageMapper.FetchType.FULL)
+            .stream()
+            .map(Throwing.function(Message::getFullContent))
+            .collect(ImmutableList.toImmutableList());
+    }
+
+    @VisibleForTesting
+    boolean isMessageMovedToSpamMailbox(MessageMoveEvent event) {
+        try {
+            MailboxId spamMailboxId = systemMailboxesProvider.findMailbox(Role.SPAM, event.getUsername()).getId();
+
+            return event.getMessageMoves().addedMailboxIds().contains(spamMailboxId);
+        } catch (MailboxException e) {
+            LOGGER.warn("Could not resolve Spam mailbox", e);
+            return false;
+        }
+    }
+
+    @VisibleForTesting
+    boolean isMessageMovedOutOfSpamMailbox(MessageMoveEvent event) {
+        try {
+            MailboxId spamMailboxId = systemMailboxesProvider.findMailbox(Role.SPAM, event.getUsername()).getId();
+            MailboxId trashMailboxId = systemMailboxesProvider.findMailbox(Role.TRASH, event.getUsername()).getId();
+
+            return event.getMessageMoves().removedMailboxIds().contains(spamMailboxId)
+                && !event.getMessageMoves().addedMailboxIds().contains(trashMailboxId);
+        } catch (MailboxException e) {
+            LOGGER.warn("Could not resolve Spam mailbox", e);
+            return false;
+        }
+    }
+}
\ No newline at end of file
diff --git a/third-party/spamassassin/src/main/java/org/apache/james/spamassassin/SpamAssassinModule.java b/third-party/spamassassin/src/main/java/org/apache/james/spamassassin/SpamAssassinModule.java
new file mode 100644
index 0000000000..2ec1dd0ee9
--- /dev/null
+++ b/third-party/spamassassin/src/main/java/org/apache/james/spamassassin/SpamAssassinModule.java
@@ -0,0 +1,50 @@
+/****************************************************************
+ * 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.spamassassin;
+
+import java.io.FileNotFoundException;
+
+import javax.inject.Singleton;
+
+import org.apache.commons.configuration2.Configuration;
+import org.apache.commons.configuration2.ex.ConfigurationException;
+import org.apache.james.util.Host;
+import org.apache.james.utils.PropertiesProvider;
+
+import com.google.inject.AbstractModule;
+import com.google.inject.Provides;
+
+public class SpamAssassinModule extends AbstractModule {
+    private static final String SPAMASSASSIN_HOST = "spamassassin.host";
+    private static final String SPAMASSASSIN_PORT = "spamassassin.port";
+    public static final String DEFAULT_HOST = "127.0.0.1";
+    public static final int DEFAULT_PORT = 783;
+
+    @Provides
+    @Singleton
+    private SpamAssassinConfiguration getSpamAssassinConfiguration(PropertiesProvider propertiesProvider) throws ConfigurationException, FileNotFoundException {
+        Configuration configuration = propertiesProvider.getConfiguration("spamassassin");
+
+        Host host = Host.from(configuration.getString(SPAMASSASSIN_HOST, DEFAULT_HOST),
+            configuration.getInteger(SPAMASSASSIN_PORT, DEFAULT_PORT));
+
+        return new SpamAssassinConfiguration(host);
+    }
+}
diff --git a/third-party/spamassassin/src/test/java/org/apache/james/spamassassin/MemorySpamAssassinTest.java b/third-party/spamassassin/src/test/java/org/apache/james/spamassassin/MemorySpamAssassinTest.java
new file mode 100644
index 0000000000..2ebfe2d656
--- /dev/null
+++ b/third-party/spamassassin/src/test/java/org/apache/james/spamassassin/MemorySpamAssassinTest.java
@@ -0,0 +1,89 @@
+/****************************************************************
+ * 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.spamassassin;
+
+import static org.apache.james.data.UsersRepositoryModuleChooser.Implementation.DEFAULT;
+
+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.junit.categories.Unstable;
+import org.apache.james.modules.TestJMAPServerModule;
+import org.apache.james.spamassassin.module.SpamAssassinModuleExtension;
+import org.junit.jupiter.api.Tag;
+import org.junit.jupiter.api.extension.RegisterExtension;
+
+class MemorySpamAssassinTest implements SpamAssassinContract {
+    @RegisterExtension
+    static JamesServerExtension testExtension = new JamesServerBuilder<MemoryJamesConfiguration>(tmpDir ->
+        MemoryJamesConfiguration.builder()
+            .workingDirectory(tmpDir)
+            .configurationFromClasspath()
+            .usersRepository(DEFAULT)
+            .build())
+        .extension(new SpamAssassinModuleExtension())
+        .server(configuration -> MemoryJamesServerMain.createServer(configuration)
+            .overrideWith(new TestJMAPServerModule()))
+        .build();
+
+    @Override
+    @Tag(Unstable.TAG)
+    public void spamShouldBeDeliveredInSpamMailboxWhenSameMessageHasAlreadyBeenMovedToSpam(GuiceJamesServer jamesServer, SpamAssassinExtension.SpamAssassin spamAssassin) throws Exception {
+        SpamAssassinContract.super.spamShouldBeDeliveredInSpamMailboxWhenSameMessageHasAlreadyBeenMovedToSpam(jamesServer, spamAssassin);
+    }
+
+    @Override
+    @Tag(Unstable.TAG)
+    public void spamShouldBeDeliveredInSpamMailboxOrInboxWhenMultipleRecipientsConfigurations(GuiceJamesServer jamesServer, SpamAssassinExtension.SpamAssassin spamAssassin) throws Exception {
+        SpamAssassinContract.super.spamShouldBeDeliveredInSpamMailboxOrInboxWhenMultipleRecipientsConfigurations(jamesServer, spamAssassin);
+    }
+
+    @Override
+    @Tag(Unstable.TAG)
+    public void movingAMailToTrashShouldNotImpactSpamassassinLearning(GuiceJamesServer jamesServer, SpamAssassinExtension.SpamAssassin spamAssassin) throws Exception {
+        SpamAssassinContract.super.movingAMailToTrashShouldNotImpactSpamassassinLearning(jamesServer, spamAssassin);
+    }
+
+    @Override
+    @Tag(Unstable.TAG)
+    public void expungingSpamMessageShouldNotImpactSpamAssassinState(GuiceJamesServer jamesServer, SpamAssassinExtension.SpamAssassin spamAssassin) throws Exception {
+        SpamAssassinContract.super.expungingSpamMessageShouldNotImpactSpamAssassinState(jamesServer, spamAssassin);
+    }
+
+    @Override
+    @Tag(Unstable.TAG)
+    public void imapMovesToSpamMailboxShouldBeConsideredAsSpam(GuiceJamesServer jamesServer, SpamAssassinExtension.SpamAssassin spamAssassin) throws Exception {
+        SpamAssassinContract.super.imapMovesToSpamMailboxShouldBeConsideredAsSpam(jamesServer, spamAssassin);
+    }
+
+    @Override
+    @Tag(Unstable.TAG)
+    public void imapCopiesToSpamMailboxShouldBeConsideredAsSpam(GuiceJamesServer jamesServer, SpamAssassinExtension.SpamAssassin spamAssassin) throws Exception {
+        SpamAssassinContract.super.imapCopiesToSpamMailboxShouldBeConsideredAsSpam(jamesServer, spamAssassin);
+    }
+
+    @Override
+    @Tag(Unstable.TAG)
+    public void deletingSpamMessageShouldNotImpactSpamAssassinState(GuiceJamesServer jamesServer, SpamAssassinExtension.SpamAssassin spamAssassin) throws Exception {
+        SpamAssassinContract.super.deletingSpamMessageShouldNotImpactSpamAssassinState(jamesServer, spamAssassin);
+    }
+}
\ No newline at end of file
diff --git a/server/testing/src/main/java/org/apache/james/util/docker/Images.java b/third-party/spamassassin/src/test/java/org/apache/james/spamassassin/SpamAssassinConfigurationTest.java
similarity index 65%
copy from server/testing/src/main/java/org/apache/james/util/docker/Images.java
copy to third-party/spamassassin/src/test/java/org/apache/james/spamassassin/SpamAssassinConfigurationTest.java
index 87054f065a..aa58537e11 100644
--- a/server/testing/src/main/java/org/apache/james/util/docker/Images.java
+++ b/third-party/spamassassin/src/test/java/org/apache/james/spamassassin/SpamAssassinConfigurationTest.java
@@ -17,16 +17,28 @@
  * under the License.                                           *
  ****************************************************************/
 
-package org.apache.james.util.docker;
-
-public interface Images {
-    String FAKE_SMTP = "weave/rest-smtp-sink:latest";
-    String RABBITMQ = "rabbitmq:3.9.18-management";
-    String ELASTICSEARCH_2 = "elasticsearch:2.4.6";
-    String ELASTICSEARCH_6 = "docker.elastic.co/elasticsearch/elasticsearch:6.3.2";
-    String ELASTICSEARCH_7 = "docker.elastic.co/elasticsearch/elasticsearch:7.10.2";
-    String OPENSEARCH = "opensearchproject/opensearch:2.1.0";
-    String TIKA = "apache/tika:1.28.2";
-    String SPAMASSASSIN = "instantlinux/spamassassin:3.4.6-1";
-    String MOCK_SMTP_SERVER = "linagora/mock-smtp-server:0.4";
-}
+package org.apache.james.spamassassin;
+
+
+import static org.assertj.core.api.Assertions.assertThatCode;
+
+import org.apache.james.util.Host;
+import org.junit.jupiter.api.Test;
+
+import nl.jqno.equalsverifier.EqualsVerifier;
+
+class SpamAssassinConfigurationTest {
+
+    @Test
+    void spamAssassinConfigurationShouldRespectBeanContract() {
+        EqualsVerifier.forClass(SpamAssassinConfiguration.class)
+            .verify();
+    }
+
+
+    @Test
+    void isEnableShouldReturnTrueWhenConfigured() {
+        assertThatCode(() -> new SpamAssassinConfiguration(Host.from("hostname", 1)))
+            .doesNotThrowAnyException();
+    }
+}
\ No newline at end of file
diff --git a/third-party/spamassassin/src/test/java/org/apache/james/spamassassin/SpamAssassinContract.java b/third-party/spamassassin/src/test/java/org/apache/james/spamassassin/SpamAssassinContract.java
new file mode 100644
index 0000000000..082ec998e6
--- /dev/null
+++ b/third-party/spamassassin/src/test/java/org/apache/james/spamassassin/SpamAssassinContract.java
@@ -0,0 +1,701 @@
+/****************************************************************
+ * 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.spamassassin;
+
+
+import static io.restassured.RestAssured.given;
+import static io.restassured.RestAssured.with;
+import static io.restassured.config.EncoderConfig.encoderConfig;
+import static io.restassured.config.RestAssuredConfig.newConfig;
+import static org.apache.james.jmap.HttpJmapAuthentication.authenticateJamesUser;
+import static org.apache.james.jmap.JMAPTestingConstants.ARGUMENTS;
+import static org.apache.james.jmap.JMAPTestingConstants.LOCALHOST_IP;
+import static org.apache.james.jmap.JMAPTestingConstants.NAME;
+import static org.apache.james.jmap.JMAPTestingConstants.calmlyAwait;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.awaitility.Durations.ONE_MINUTE;
+import static org.hamcrest.Matchers.equalTo;
+import static org.hamcrest.Matchers.hasSize;
+
+import java.nio.charset.StandardCharsets;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.http.client.utils.URIBuilder;
+import org.apache.james.GuiceJamesServer;
+import org.apache.james.core.Username;
+import org.apache.james.jmap.AccessToken;
+import org.apache.james.jmap.LocalHostURIBuilder;
+import org.apache.james.jmap.draft.JmapGuiceProbe;
+import org.apache.james.mailbox.Role;
+import org.apache.james.modules.protocols.ImapGuiceProbe;
+import org.apache.james.util.Port;
+import org.apache.james.utils.DataProbeImpl;
+import org.apache.james.utils.SpoolerProbe;
+import org.apache.james.utils.TestIMAPClient;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import io.restassured.RestAssured;
+import io.restassured.builder.RequestSpecBuilder;
+import io.restassured.http.ContentType;
+import io.restassured.parsing.Parser;
+
+public interface SpamAssassinContract {
+
+    String BOBS_DOMAIN = "spamer.com";
+    String BOB = "bob@" + BOBS_DOMAIN;
+    String BOB_PASSWORD = "bobPassword";
+    String RECIPIENTS_DOMAIN = "angels.org";
+    String ALICE = "alice@" + RECIPIENTS_DOMAIN;
+    String ALICE_PASSWORD = "alicePassword";
+    String PAUL = "paul@" + RECIPIENTS_DOMAIN;
+    String PAUL_PASSWORD = "paulPassword";
+
+    @BeforeEach
+    default void setup(GuiceJamesServer jamesServer) throws Throwable {
+        RestAssured.requestSpecification = new RequestSpecBuilder()
+            .setContentType(ContentType.JSON)
+            .setAccept(ContentType.JSON)
+            .setConfig(newConfig().encoderConfig(encoderConfig().defaultContentCharset(StandardCharsets.UTF_8)))
+            .setPort(jamesServer.getProbe(JmapGuiceProbe.class).getJmapPort().getValue())
+            .build();
+        RestAssured.defaultParser = Parser.JSON;
+
+        jamesServer.getProbe(DataProbeImpl.class)
+            .fluent()
+            .addDomain(BOBS_DOMAIN)
+            .addDomain(RECIPIENTS_DOMAIN)
+            .addUser(BOB, BOB_PASSWORD)
+            .addUser(ALICE, ALICE_PASSWORD)
+            .addUser(PAUL, PAUL_PASSWORD);
+    }
+
+    @AfterEach
+    default void tearDown(SpamAssassinExtension.SpamAssassin spamAssassin, GuiceJamesServer jamesServer) throws Exception {
+        calmlyAwait.atMost(ONE_MINUTE).untilAsserted(() -> assertEveryListenerGotCalled(jamesServer));
+        spamAssassin.clear(ALICE);
+    }
+
+    default AccessToken accessTokenFor(GuiceJamesServer james, String user, String password) {
+        return authenticateJamesUser(baseUri(james), Username.of(user), password);
+    }
+
+    @Test
+    default void spamShouldBeDeliveredInSpamMailboxWhenSameMessageHasAlreadyBeenMovedToSpam(
+        GuiceJamesServer jamesServer,
+        SpamAssassinExtension.SpamAssassin spamAssassin) throws Exception {
+
+        spamAssassin.train(ALICE);
+        AccessToken aliceAccessToken = accessTokenFor(jamesServer, ALICE, ALICE_PASSWORD);
+        AccessToken bobAccessToken = accessTokenFor(jamesServer, BOB, BOB_PASSWORD);
+
+        // Bob is sending a message to Alice
+        given()
+            .header("Authorization", bobAccessToken.asString())
+            .body(setMessageCreate(bobAccessToken))
+            .when()
+            .post("/jmap");
+
+        calmlyAwait.atMost(ONE_MINUTE).untilAsserted(() -> assertMessagesFoundInMailbox(aliceAccessToken, getInboxId(aliceAccessToken), 1));
+        calmlyAwait.atMost(ONE_MINUTE).untilAsserted(() -> assertEveryListenerGotCalled(jamesServer));
+
+        // Alice is moving this message to Spam -> learning in SpamAssassin
+        List<String> messageIds = with()
+            .header("Authorization", aliceAccessToken.asString())
+            .body("[[\"getMessageList\", {\"filter\":{\"inMailboxes\":[\"" + getInboxId(aliceAccessToken) + "\"]}}, \"#0\"]]")
+            .when()
+            .post("/jmap")
+            .then()
+            .statusCode(200)
+            .body(NAME, equalTo("messageList"))
+            .body(ARGUMENTS + ".messageIds", hasSize(1))
+            .extract()
+            .path(ARGUMENTS + ".messageIds");
+
+        messageIds
+            .forEach(messageId -> given()
+                .header("Authorization", aliceAccessToken.asString())
+                .body(String.format("[[\"setMessages\", {\"update\": {\"%s\" : { \"mailboxIds\": [\"" + getSpamId(aliceAccessToken) + "\"] } } }, \"#0\"]]", messageId))
+                .when()
+                .post("/jmap")
+                .then()
+                .statusCode(200)
+                .body(NAME, equalTo("messagesSet"))
+                .body(ARGUMENTS + ".updated", hasSize(1)));
+        calmlyAwait.atMost(ONE_MINUTE).untilAsserted(() -> assertMessagesFoundInMailbox(aliceAccessToken, getSpamId(aliceAccessToken), 1));
+
+        // Bob is sending again the same message to Alice
+        given()
+            .header("Authorization", bobAccessToken.asString())
+            .body(setMessageCreate(bobAccessToken))
+            .when()
+            .post("/jmap");
+
+        // This message is delivered in Alice Spam mailbox (she now must have 2 messages in her Spam mailbox)
+        calmlyAwait.atMost(ONE_MINUTE).untilAsserted(() -> assertMessagesFoundInMailbox(aliceAccessToken, getSpamId(aliceAccessToken), 2));
+    }
+
+    @Test
+    default void imapCopiesToSpamMailboxShouldBeConsideredAsSpam(GuiceJamesServer jamesServer,
+                                                                 SpamAssassinExtension.SpamAssassin spamAssassin) throws Exception {
+        spamAssassin.train(ALICE);
+        AccessToken aliceAccessToken = accessTokenFor(jamesServer, ALICE, ALICE_PASSWORD);
+        AccessToken bobAccessToken = accessTokenFor(jamesServer, BOB, BOB_PASSWORD);
+
+        // Bob is sending a message to Alice
+        given()
+            .header("Authorization", bobAccessToken.asString())
+            .body(setMessageCreate(bobAccessToken))
+            .when()
+            .post("/jmap");
+        calmlyAwait.atMost(ONE_MINUTE).untilAsserted(() -> assertMessagesFoundInMailbox(aliceAccessToken, getInboxId(aliceAccessToken), 1));
+        calmlyAwait.atMost(ONE_MINUTE).untilAsserted(() -> assertEveryListenerGotCalled(jamesServer));
+
+
+        // Alice is copying this message to Spam -> learning in SpamAssassin
+        try (TestIMAPClient testIMAPClient = new TestIMAPClient()) {
+            testIMAPClient.connect(LOCALHOST_IP, jamesServer.getProbe(ImapGuiceProbe.class).getImapPort())
+                .login(ALICE, ALICE_PASSWORD)
+                .select(TestIMAPClient.INBOX);
+
+            testIMAPClient.copyFirstMessage("Spam");
+        }
+        calmlyAwait.atMost(ONE_MINUTE).untilAsserted(() -> assertMessagesFoundInMailbox(aliceAccessToken, getSpamId(aliceAccessToken), 1));
+
+        // Bob is sending again the same message to Alice
+        given()
+            .header("Authorization", bobAccessToken.asString())
+            .body(setMessageCreate(bobAccessToken))
+            .when()
+            .post("/jmap");
+
+        // This message is delivered in Alice Spam mailbox (she now must have 2 messages in her Spam mailbox)
+        calmlyAwait.atMost(ONE_MINUTE).untilAsserted(() -> assertMessagesFoundInMailbox(aliceAccessToken, getSpamId(aliceAccessToken), 2));
+    }
+
+    @Test
+    default void imapMovesToSpamMailboxShouldBeConsideredAsSpam(GuiceJamesServer jamesServer,
+                                                                SpamAssassinExtension.SpamAssassin spamAssassin) throws Exception {
+        spamAssassin.train(ALICE);
+        AccessToken aliceAccessToken = accessTokenFor(jamesServer, ALICE, ALICE_PASSWORD);
+        AccessToken bobAccessToken = accessTokenFor(jamesServer, BOB, BOB_PASSWORD);
+
+        // Bob is sending a message to Alice
+        given()
+            .header("Authorization", bobAccessToken.asString())
+            .body(setMessageCreate(bobAccessToken))
+            .when()
+            .post("/jmap");
+        calmlyAwait.atMost(ONE_MINUTE).untilAsserted(() -> assertMessagesFoundInMailbox(aliceAccessToken, getInboxId(aliceAccessToken), 1));
+        calmlyAwait.atMost(ONE_MINUTE).untilAsserted(() -> assertEveryListenerGotCalled(jamesServer));
+
+        try (TestIMAPClient testIMAPClient = new TestIMAPClient()) {
+            testIMAPClient.connect(LOCALHOST_IP, jamesServer.getProbe(ImapGuiceProbe.class).getImapPort())
+                .login(ALICE, ALICE_PASSWORD)
+                .select(TestIMAPClient.INBOX);
+
+            testIMAPClient.moveFirstMessage("Spam");
+        }
+        calmlyAwait.atMost(ONE_MINUTE).untilAsserted(() -> assertMessagesFoundInMailbox(aliceAccessToken, getSpamId(aliceAccessToken), 1));
+
+        // Bob is sending again the same message to Alice
+        given()
+            .header("Authorization", bobAccessToken.asString())
+            .body(setMessageCreate(bobAccessToken))
+            .when()
+            .post("/jmap");
+
+        // This message is delivered in Alice Spam mailbox (she now must have 2 messages in her Spam mailbox)
+        calmlyAwait.atMost(ONE_MINUTE).untilAsserted(() -> assertMessagesFoundInMailbox(aliceAccessToken, getSpamId(aliceAccessToken), 2));
+    }
+
+    @Test
+    default void spamAssassinShouldForgetMessagesMovedOutOfSpamFolderUsingJMAP(GuiceJamesServer jamesServer,
+                                                                               SpamAssassinExtension.SpamAssassin spamAssassin) throws Exception {
+        spamAssassin.train(ALICE);
+        AccessToken aliceAccessToken = accessTokenFor(jamesServer, ALICE, ALICE_PASSWORD);
+        AccessToken bobAccessToken = accessTokenFor(jamesServer, BOB, BOB_PASSWORD);
+
+        // Bob is sending a message to Alice
+        given()
+            .header("Authorization", bobAccessToken.asString())
+            .body(setMessageCreate(bobAccessToken))
+            .when()
+            .post("/jmap");
+        calmlyAwait.atMost(ONE_MINUTE).untilAsserted(() -> assertMessagesFoundInMailbox(aliceAccessToken, getInboxId(aliceAccessToken), 1));
+        calmlyAwait.atMost(ONE_MINUTE).untilAsserted(() -> assertEveryListenerGotCalled(jamesServer));
+
+        // Alice is moving this message to Spam -> learning in SpamAssassin
+        List<String> messageIds = with()
+            .header("Authorization", aliceAccessToken.asString())
+            .body("[[\"getMessageList\", {\"filter\":{\"inMailboxes\":[\"" + getInboxId(aliceAccessToken) + "\"]}}, \"#0\"]]")
+            .when()
+            .post("/jmap")
+            .then()
+            .statusCode(200)
+            .body(NAME, equalTo("messageList"))
+            .body(ARGUMENTS + ".messageIds", hasSize(1))
+            .extract()
+            .path(ARGUMENTS + ".messageIds");
+
+        messageIds
+            .forEach(messageId -> given()
+                .header("Authorization", aliceAccessToken.asString())
+                .body(String.format("[[\"setMessages\", {\"update\": {\"%s\" : { \"mailboxIds\": [\"" + getSpamId(aliceAccessToken) + "\"] } } }, \"#0\"]]", messageId))
+                .when()
+                .post("/jmap")
+                .then()
+                .statusCode(200)
+                .body(NAME, equalTo("messagesSet"))
+                .body(ARGUMENTS + ".updated", hasSize(1)));
+        calmlyAwait.atMost(ONE_MINUTE).untilAsserted(() -> assertMessagesFoundInMailbox(aliceAccessToken, getSpamId(aliceAccessToken), 1));
+
+        // Alice is moving this message out of Spam -> forgetting in SpamAssassin
+        messageIds
+            .forEach(messageId -> given()
+                .header("Authorization", aliceAccessToken.asString())
+                .body(String.format("[[\"setMessages\", {\"update\": {\"%s\" : { \"mailboxIds\": [\"" + getInboxId(aliceAccessToken) + "\"] } } }, \"#0\"]]", messageId))
+                .when()
+                .post("/jmap")
+                .then()
+                .statusCode(200)
+                .body(NAME, equalTo("messagesSet"))
+                .body(ARGUMENTS + ".updated", hasSize(1)));
+        calmlyAwait.atMost(ONE_MINUTE).untilAsserted(() -> assertMessagesFoundInMailbox(aliceAccessToken, getInboxId(aliceAccessToken), 1));
+
+        // Bob is sending again the same message to Alice
+        given()
+            .header("Authorization", bobAccessToken.asString())
+            .body(setMessageCreate(bobAccessToken))
+            .when()
+            .post("/jmap");
+
+        // This message is delivered in Alice INBOX mailbox (she now must have 2 messages in her Inbox mailbox)
+        calmlyAwait.atMost(ONE_MINUTE).untilAsserted(() -> assertMessagesFoundInMailbox(aliceAccessToken, getInboxId(aliceAccessToken), 2));
+    }
+
+    @Test
+    default void movingAMailToTrashShouldNotImpactSpamassassinLearning(GuiceJamesServer jamesServer,
+                                                                       SpamAssassinExtension.SpamAssassin spamAssassin) throws Exception {
+        spamAssassin.train(ALICE);
+        AccessToken aliceAccessToken = accessTokenFor(jamesServer, ALICE, ALICE_PASSWORD);
+        AccessToken bobAccessToken = accessTokenFor(jamesServer, BOB, BOB_PASSWORD);
+
+        // Bob is sending a message to Alice
+        given()
+            .header("Authorization", bobAccessToken.asString())
+            .body(setMessageCreate(bobAccessToken))
+            .when()
+            .post("/jmap");
+        calmlyAwait.atMost(ONE_MINUTE).untilAsserted(() -> assertMessagesFoundInMailbox(aliceAccessToken, getInboxId(aliceAccessToken), 1));
+        calmlyAwait.atMost(ONE_MINUTE).untilAsserted(() -> assertEveryListenerGotCalled(jamesServer));
+
+        // Alice is moving this message to Spam -> learning in SpamAssassin
+        List<String> messageIds = with()
+            .header("Authorization", aliceAccessToken.asString())
+            .body("[[\"getMessageList\", {\"filter\":{\"inMailboxes\":[\"" + getInboxId(aliceAccessToken) + "\"]}}, \"#0\"]]")
+            .when()
+            .post("/jmap")
+            .then()
+            .statusCode(200)
+            .body(NAME, equalTo("messageList"))
+            .body(ARGUMENTS + ".messageIds", hasSize(1))
+            .extract()
+            .path(ARGUMENTS + ".messageIds");
+
+        messageIds
+            .forEach(messageId -> given()
+                .header("Authorization", aliceAccessToken.asString())
+                .body(String.format("[[\"setMessages\", {\"update\": {\"%s\" : { \"mailboxIds\": [\"" + getSpamId(aliceAccessToken) + "\"] } } }, \"#0\"]]", messageId))
+                .when()
+                .post("/jmap")
+                .then()
+                .statusCode(200)
+                .body(NAME, equalTo("messagesSet"))
+                .body(ARGUMENTS + ".updated", hasSize(1)));
+        calmlyAwait.atMost(ONE_MINUTE).untilAsserted(() -> assertMessagesFoundInMailbox(aliceAccessToken, getSpamId(aliceAccessToken), 1));
+
+        // Alice is moving this message to trash
+        messageIds
+            .forEach(messageId -> given()
+                .header("Authorization", aliceAccessToken.asString())
+                .body(String.format("[[\"setMessages\", {\"update\": {\"%s\" : { \"mailboxIds\": [\"" + getTrashId(aliceAccessToken) + "\"] } } }, \"#0\"]]", messageId))
+                .when()
+                .post("/jmap")
+                .then()
+                .statusCode(200)
+                .body(NAME, equalTo("messagesSet"))
+                .body(ARGUMENTS + ".updated", hasSize(1)));
+        calmlyAwait.atMost(ONE_MINUTE).untilAsserted(() -> assertMessagesFoundInMailbox(aliceAccessToken, getTrashId(aliceAccessToken), 1));
+
+        // Bob is sending again the same message to Alice
+        given()
+            .header("Authorization", bobAccessToken.asString())
+            .body(setMessageCreate(bobAccessToken))
+            .when()
+            .post("/jmap");
+
+        // This message is delivered in Alice Spam mailbox (she now must have 1 messages in her Spam mailbox)
+        calmlyAwait.atMost(ONE_MINUTE).untilAsserted(() -> assertMessagesFoundInMailbox(aliceAccessToken, getSpamId(aliceAccessToken), 1));
+    }
+
+    @Test
+    default void spamAssassinShouldForgetMessagesMovedOutOfSpamFolderUsingIMAP(GuiceJamesServer jamesServer,
+                                                                               SpamAssassinExtension.SpamAssassin spamAssassin) throws Exception {
+        spamAssassin.train(ALICE);
+        AccessToken aliceAccessToken = accessTokenFor(jamesServer, ALICE, ALICE_PASSWORD);
+        AccessToken bobAccessToken = accessTokenFor(jamesServer, BOB, BOB_PASSWORD);
+
+        // Bob is sending a message to Alice
+        given()
+            .header("Authorization", bobAccessToken.asString())
+            .body(setMessageCreate(bobAccessToken))
+            .when()
+            .post("/jmap");
+        calmlyAwait.atMost(ONE_MINUTE).untilAsserted(() -> assertMessagesFoundInMailbox(aliceAccessToken, getInboxId(aliceAccessToken), 1));
+        calmlyAwait.atMost(ONE_MINUTE).untilAsserted(() -> assertEveryListenerGotCalled(jamesServer));
+
+        // Alice is moving this message to Spam -> learning in SpamAssassin
+        List<String> messageIds = with()
+            .header("Authorization", aliceAccessToken.asString())
+            .body("[[\"getMessageList\", {\"filter\":{\"inMailboxes\":[\"" + getInboxId(aliceAccessToken) + "\"]}}, \"#0\"]]")
+            .when()
+            .post("/jmap")
+            .then()
+            .statusCode(200)
+            .body(NAME, equalTo("messageList"))
+            .body(ARGUMENTS + ".messageIds", hasSize(1))
+            .extract()
+            .path(ARGUMENTS + ".messageIds");
+
+        messageIds
+            .forEach(messageId -> given()
+                .header("Authorization", aliceAccessToken.asString())
+                .body(String.format("[[\"setMessages\", {\"update\": {\"%s\" : { \"mailboxIds\": [\"" + getSpamId(aliceAccessToken) + "\"] } } }, \"#0\"]]", messageId))
+                .when()
+                .post("/jmap")
+                .then()
+                .statusCode(200)
+                .body(NAME, equalTo("messagesSet"))
+                .body(ARGUMENTS + ".updated", hasSize(1)));
+        calmlyAwait.atMost(ONE_MINUTE).untilAsserted(() -> assertMessagesFoundInMailbox(aliceAccessToken, getSpamId(aliceAccessToken), 1));
+
+        // Alice is moving this message out of Spam -> forgetting in SpamAssassin
+        try (TestIMAPClient testIMAPClient = new TestIMAPClient()) {
+            testIMAPClient.connect(LOCALHOST_IP, jamesServer.getProbe(ImapGuiceProbe.class).getImapPort())
+                .login(ALICE, ALICE_PASSWORD)
+                .select("Spam");
+
+            testIMAPClient.moveFirstMessage(TestIMAPClient.INBOX);
+        }
+        calmlyAwait.atMost(ONE_MINUTE).untilAsserted(() -> assertMessagesFoundInMailbox(aliceAccessToken, getInboxId(aliceAccessToken), 1));
+
+        // Bob is sending again the same message to Alice
+        given()
+            .header("Authorization", bobAccessToken.asString())
+            .body(setMessageCreate(bobAccessToken))
+            .when()
+            .post("/jmap");
+
+        // This message is delivered in Alice INBOX mailbox (she now must have 2 messages in her Inbox mailbox)
+        calmlyAwait.atMost(ONE_MINUTE).untilAsserted(() -> assertMessagesFoundInMailbox(aliceAccessToken, getInboxId(aliceAccessToken), 2));
+    }
+
+    @Test
+    default void expungingSpamMessageShouldNotImpactSpamAssassinState(GuiceJamesServer jamesServer,
+                                                                      SpamAssassinExtension.SpamAssassin spamAssassin) throws Exception {
+        spamAssassin.train(ALICE);
+        AccessToken aliceAccessToken = accessTokenFor(jamesServer, ALICE, ALICE_PASSWORD);
+        AccessToken bobAccessToken = accessTokenFor(jamesServer, BOB, BOB_PASSWORD);
+
+        // Bob is sending a message to Alice
+        given()
+            .header("Authorization", bobAccessToken.asString())
+            .body(setMessageCreate(bobAccessToken))
+            .when()
+            .post("/jmap");
+        calmlyAwait.atMost(ONE_MINUTE).untilAsserted(() -> assertMessagesFoundInMailbox(aliceAccessToken, getInboxId(aliceAccessToken), 1));
+        calmlyAwait.atMost(ONE_MINUTE).untilAsserted(() -> assertEveryListenerGotCalled(jamesServer));
+
+        // Alice is moving this message to Spam -> learning in SpamAssassin
+        List<String> messageIds = with()
+            .header("Authorization", aliceAccessToken.asString())
+            .body("[[\"getMessageList\", {\"filter\":{\"inMailboxes\":[\"" + getInboxId(aliceAccessToken) + "\"]}}, \"#0\"]]")
+            .when()
+            .post("/jmap")
+            .then()
+            .statusCode(200)
+            .body(NAME, equalTo("messageList"))
+            .body(ARGUMENTS + ".messageIds", hasSize(1))
+            .extract()
+            .path(ARGUMENTS + ".messageIds");
+
+        messageIds
+            .forEach(messageId -> given()
+                .header("Authorization", aliceAccessToken.asString())
+                .body(String.format("[[\"setMessages\", {\"update\": {\"%s\" : { \"mailboxIds\": [\"" + getSpamId(aliceAccessToken) + "\"] } } }, \"#0\"]]", messageId))
+                .when()
+                .post("/jmap")
+                .then()
+                .statusCode(200)
+                .body(NAME, equalTo("messagesSet"))
+                .body(ARGUMENTS + ".updated", hasSize(1)));
+        calmlyAwait.atMost(ONE_MINUTE).untilAsserted(() -> assertMessagesFoundInMailbox(aliceAccessToken, getSpamId(aliceAccessToken), 1));
+
+        // Alice is deleting this message
+        try (TestIMAPClient testIMAPClient = new TestIMAPClient()) {
+            testIMAPClient.connect(LOCALHOST_IP, jamesServer.getProbe(ImapGuiceProbe.class).getImapPort())
+                .login(ALICE, ALICE_PASSWORD)
+                .select("Spam");
+
+            testIMAPClient.setFlagsForAllMessagesInMailbox("\\Deleted");
+            testIMAPClient.expunge();
+        }
+        calmlyAwait.atMost(ONE_MINUTE).untilAsserted(() -> assertMessagesFoundInMailbox(aliceAccessToken, getSpamId(aliceAccessToken), 0));
+
+        // Bob is sending again the same message to Alice
+        given()
+            .header("Authorization", bobAccessToken.asString())
+            .body(setMessageCreate(bobAccessToken))
+            .when()
+            .post("/jmap");
+
+        // This message is delivered in Alice SPAM mailbox (she now must have 1 messages in her Spam mailbox)
+        calmlyAwait.atMost(ONE_MINUTE).untilAsserted(() -> assertMessagesFoundInMailbox(aliceAccessToken, getSpamId(aliceAccessToken), 1));
+    }
+
+    @Test
+    default void deletingSpamMessageShouldNotImpactSpamAssassinState(GuiceJamesServer jamesServer,
+                                                                     SpamAssassinExtension.SpamAssassin spamAssassin) throws Exception {
+        spamAssassin.train(ALICE);
+        AccessToken aliceAccessToken = accessTokenFor(jamesServer, ALICE, ALICE_PASSWORD);
+        AccessToken bobAccessToken = accessTokenFor(jamesServer, BOB, BOB_PASSWORD);
+
+        // Bob is sending a message to Alice
+        given()
+            .header("Authorization", bobAccessToken.asString())
+            .body(setMessageCreate(bobAccessToken))
+            .when()
+            .post("/jmap");
+        calmlyAwait.atMost(ONE_MINUTE).untilAsserted(() -> assertMessagesFoundInMailbox(aliceAccessToken, getInboxId(aliceAccessToken), 1));
+        calmlyAwait.atMost(ONE_MINUTE).untilAsserted(() -> assertEveryListenerGotCalled(jamesServer));
+
+        // Alice is moving this message to Spam -> learning in SpamAssassin
+        List<String> messageIds = with()
+            .header("Authorization", aliceAccessToken.asString())
+            .body("[[\"getMessageList\", {\"filter\":{\"inMailboxes\":[\"" + getInboxId(aliceAccessToken) + "\"]}}, \"#0\"]]")
+            .when()
+            .post("/jmap")
+            .then()
+            .statusCode(200)
+            .body(NAME, equalTo("messageList"))
+            .body(ARGUMENTS + ".messageIds", hasSize(1))
+            .extract()
+            .path(ARGUMENTS + ".messageIds");
+
+        messageIds
+            .forEach(messageId -> given()
+                .header("Authorization", aliceAccessToken.asString())
+                .body(String.format("[[\"setMessages\", {\"update\": {\"%s\" : { \"mailboxIds\": [\"" + getSpamId(aliceAccessToken) + "\"] } } }, \"#0\"]]", messageId))
+                .when()
+                .post("/jmap")
+                .then()
+                .statusCode(200)
+                .body(NAME, equalTo("messagesSet"))
+                .body(ARGUMENTS + ".updated", hasSize(1)));
+        calmlyAwait.atMost(ONE_MINUTE).untilAsserted(() -> assertMessagesFoundInMailbox(aliceAccessToken, getSpamId(aliceAccessToken), 1));
+
+        // Alice is deleting this message
+        messageIds
+            .forEach(messageId -> given()
+                .header("Authorization", aliceAccessToken.asString())
+                .body(String.format("[[\"setMessages\", {\"destroy\": [\"%s\"] }, \"#0\"]]", messageId))
+                .when()
+                .post("/jmap")
+                .then()
+                .statusCode(200)
+                .body(NAME, equalTo("messagesSet"))
+                .body(ARGUMENTS + ".destroyed", hasSize(1)));
+        calmlyAwait.atMost(ONE_MINUTE).untilAsserted(() -> assertMessagesFoundInMailbox(aliceAccessToken, getSpamId(aliceAccessToken), 0));
+
+        // Bob is sending again the same message to Alice
+        given()
+            .header("Authorization", bobAccessToken.asString())
+            .body(setMessageCreate(bobAccessToken))
+            .when()
+            .post("/jmap");
+
+        // This message is delivered in Alice SPAM mailbox (she now must have 1 messages in her Spam mailbox)
+        calmlyAwait.atMost(ONE_MINUTE).untilAsserted(() -> assertMessagesFoundInMailbox(aliceAccessToken, getSpamId(aliceAccessToken), 1));
+    }
+
+    default String setMessageCreate(AccessToken accessToken) {
+        return "[" +
+            "  [" +
+            "    \"setMessages\"," +
+            "    {" +
+            "      \"create\": { \"creationId1337\" : {" +
+            "        \"from\": { \"email\": \"" + BOB + "\"}," +
+            "        \"to\": [{ \"name\": \"recipient\", \"email\": \"" + ALICE + "\"}]," +
+            "        \"subject\": \"Happy News\"," +
+            "        \"textBody\": \"This is a SPAM!!!\r\n\r\n\"," +
+            "        \"mailboxIds\": [\"" + getOutboxId(accessToken) + "\"]" +
+            "      }}" +
+            "    }," +
+            "    \"#0\"" +
+            "  ]" +
+            "]";
+    }
+
+    @Test
+    default void spamShouldBeDeliveredInSpamMailboxOrInboxWhenMultipleRecipientsConfigurations(GuiceJamesServer jamesServer,
+                                                                                               SpamAssassinExtension.SpamAssassin spamAssassin) throws Exception {
+        spamAssassin.train(ALICE);
+        AccessToken aliceAccessToken = accessTokenFor(jamesServer, ALICE, ALICE_PASSWORD);
+        AccessToken bobAccessToken = accessTokenFor(jamesServer, BOB, BOB_PASSWORD);
+        AccessToken paulAccessToken = accessTokenFor(jamesServer, PAUL, PAUL_PASSWORD);
+
+        // Bob is sending a message to Alice & Paul
+        given()
+            .header("Authorization", bobAccessToken.asString())
+            .body(setMessageCreateToMultipleRecipients(bobAccessToken))
+            .when()
+            .post("/jmap");
+        calmlyAwait.atMost(ONE_MINUTE).untilAsserted(() -> assertMessagesFoundInMailbox(aliceAccessToken, getInboxId(aliceAccessToken), 1));
+        calmlyAwait.atMost(ONE_MINUTE).untilAsserted(() -> assertMessagesFoundInMailbox(paulAccessToken, getInboxId(paulAccessToken), 1));
+
+        // Alice is moving this message to Spam -> learning in SpamAssassin
+        List<String> messageIds = with()
+            .header("Authorization", aliceAccessToken.asString())
+            .body("[[\"getMessageList\", {\"filter\":{\"inMailboxes\":[\"" + getInboxId(aliceAccessToken) + "\"]}}, \"#0\"]]")
+            .when()
+            .post("/jmap")
+            .then()
+            .statusCode(200)
+            .body(NAME, equalTo("messageList"))
+            .body(ARGUMENTS + ".messageIds", hasSize(1))
+            .extract()
+            .path(ARGUMENTS + ".messageIds");
+
+        messageIds
+            .forEach(messageId -> given()
+                .header("Authorization", aliceAccessToken.asString())
+                .body(String.format("[[\"setMessages\", {\"update\": {\"%s\" : { \"mailboxIds\": [\"" + getSpamId(aliceAccessToken) + "\"] } } }, \"#0\"]]", messageId))
+                .when()
+                .post("/jmap")
+                .then()
+                .statusCode(200)
+                .body(NAME, equalTo("messagesSet"))
+                .body(ARGUMENTS + ".updated", hasSize(1)));
+        calmlyAwait.atMost(ONE_MINUTE).untilAsserted(() -> assertMessagesFoundInMailbox(aliceAccessToken, getSpamId(aliceAccessToken), 1));
+
+        // Bob is sending again the same message to Alice & Paul
+        given()
+            .header("Authorization", bobAccessToken.asString())
+            .body(setMessageCreateToMultipleRecipients(bobAccessToken))
+            .when()
+            .post("/jmap");
+
+        // This message is delivered in Alice Spam mailbox (she now must have 2 messages in her Spam mailbox)
+        calmlyAwait.atMost(ONE_MINUTE).untilAsserted(() -> assertMessagesFoundInMailbox(aliceAccessToken, getSpamId(aliceAccessToken), 2));
+        calmlyAwait.atMost(ONE_MINUTE).untilAsserted(() -> assertMessagesFoundInMailbox(aliceAccessToken, getInboxId(aliceAccessToken), 0));
+        // This message is delivered in Paul Inbox (he now must have 2 messages in his Inbox)
+        calmlyAwait.atMost(ONE_MINUTE).untilAsserted(() -> assertMessagesFoundInMailbox(paulAccessToken, getInboxId(paulAccessToken), 2));
+        calmlyAwait.atMost(ONE_MINUTE).untilAsserted(() -> assertMessagesFoundInMailbox(paulAccessToken, getSpamId(paulAccessToken), 0));
+    }
+
+    default String setMessageCreateToMultipleRecipients(AccessToken accessToken) {
+        return "[" +
+            "  [" +
+            "    \"setMessages\"," +
+            "    {" +
+            "      \"create\": { \"creationId1337\" : {" +
+            "        \"from\": { \"email\": \"" + BOB + "\"}," +
+            "        \"to\": [{ \"name\": \"alice\", \"email\": \"" + ALICE + "\"}, " +
+            "                 { \"name\": \"paul\", \"email\": \"" + PAUL + "\"}]," +
+            "        \"subject\": \"Happy News\"," +
+            "        \"textBody\": \"This is a SPAM!!!\r\n\r\n\"," +
+            "        \"mailboxIds\": [\"" + getOutboxId(accessToken) + "\"]" +
+            "      }}" +
+            "    }," +
+            "    \"#0\"" +
+            "  ]" +
+            "]";
+    }
+
+    default void assertMessagesFoundInMailbox(AccessToken accessToken, String mailboxId, int expectedNumberOfMessages) {
+        with()
+            .header("Authorization", accessToken.asString())
+            .body("[[\"getMessageList\", {\"filter\":{\"inMailboxes\":[\"" + mailboxId + "\"]}}, \"#0\"]]")
+            .when()
+            .post("/jmap")
+            .then()
+            .statusCode(200)
+            .body(NAME, equalTo("messageList"))
+            .body(ARGUMENTS + ".messageIds", hasSize(expectedNumberOfMessages));
+    }
+
+    default String getMailboxId(AccessToken accessToken, Role role) {
+        return getAllMailboxesIds(accessToken).stream()
+            .filter(x -> x.get("role").equalsIgnoreCase(role.serialize()))
+            .map(x -> x.get("id"))
+            .findFirst().get();
+    }
+
+    default List<Map<String, String>> getAllMailboxesIds(AccessToken accessToken) {
+        return with()
+            .header("Authorization", accessToken.asString())
+            .body("[[\"getMailboxes\", {\"properties\": [\"role\", \"id\"]}, \"#0\"]]")
+            .post("/jmap")
+            .andReturn()
+            .body()
+            .jsonPath()
+            .getList(ARGUMENTS + ".list");
+    }
+
+    default String getInboxId(AccessToken accessToken) {
+        return getMailboxId(accessToken, Role.INBOX);
+    }
+
+    default String getOutboxId(AccessToken accessToken) {
+        return getMailboxId(accessToken, Role.OUTBOX);
+    }
+
+    default String getSpamId(AccessToken accessToken) {
+        return getMailboxId(accessToken, Role.SPAM);
+    }
+
+    default String getTrashId(AccessToken accessToken) {
+        return getMailboxId(accessToken, Role.TRASH);
+    }
+
+    default void assertEveryListenerGotCalled(GuiceJamesServer jamesServer) {
+        assertThat(jamesServer.getProbe(SpoolerProbe.class).processingFinished())
+            .describedAs("waiting that every listener get called")
+            .isTrue();
+    }
+
+    private URIBuilder baseUri(GuiceJamesServer jamesServer) {
+        return LocalHostURIBuilder.baseUri(
+            Port.of(jamesServer.getProbe(JmapGuiceProbe.class).getJmapPort().getValue()));
+    }
+}
diff --git a/server/protocols/protocols-smtp/src/test/java/org/apache/james/smtpserver/SpamAssassinHandlerTest.java b/third-party/spamassassin/src/test/java/org/apache/james/spamassassin/SpamAssassinHandlerTest.java
similarity index 85%
rename from server/protocols/protocols-smtp/src/test/java/org/apache/james/smtpserver/SpamAssassinHandlerTest.java
rename to third-party/spamassassin/src/test/java/org/apache/james/spamassassin/SpamAssassinHandlerTest.java
index 52114261c1..7b976ab0d5 100644
--- a/server/protocols/protocols-smtp/src/test/java/org/apache/james/smtpserver/SpamAssassinHandlerTest.java
+++ b/third-party/spamassassin/src/test/java/org/apache/james/spamassassin/SpamAssassinHandlerTest.java
@@ -16,7 +16,9 @@
  * specific language governing permissions and limitations      *
  * under the License.                                           *
  ****************************************************************/
-package org.apache.james.smtpserver;
+
+package org.apache.james.spamassassin;
+
 
 import static org.apache.james.spamassassin.SpamAssassinResult.STATUS_MAIL;
 import static org.assertj.core.api.Assertions.assertThat;
@@ -32,14 +34,14 @@ import org.apache.james.core.MailAddress;
 import org.apache.james.core.MaybeSender;
 import org.apache.james.core.builder.MimeMessageBuilder;
 import org.apache.james.metrics.tests.RecordingMetricFactory;
+import org.apache.james.protocols.api.ProtocolSession;
 import org.apache.james.protocols.smtp.SMTPSession;
 import org.apache.james.protocols.smtp.hook.HookResult;
 import org.apache.james.protocols.smtp.hook.HookReturnCode;
 import org.apache.james.protocols.smtp.utils.BaseFakeSMTPSession;
-import org.apache.james.smtpserver.fastfail.SpamAssassinHandler;
-import org.apache.james.spamassassin.SpamAssassinResult;
 import org.apache.james.spamassassin.mock.MockSpamd;
 import org.apache.james.spamassassin.mock.MockSpamdExtension;
+import org.apache.james.util.Host;
 import org.apache.mailet.Attribute;
 import org.apache.mailet.AttributeValue;
 import org.apache.mailet.Mail;
@@ -62,16 +64,16 @@ class SpamAssassinHandlerTest {
 
         return new BaseFakeSMTPSession() {
 
-            private final HashMap<AttachmentKey<?>, Object> sessionState = new HashMap<>();
-            private final HashMap<AttachmentKey<?>, Object> connectionState = new HashMap<>();
+            private final HashMap<ProtocolSession.AttachmentKey<?>, Object> sessionState = new HashMap<>();
+            private final HashMap<ProtocolSession.AttachmentKey<?>, Object> connectionState = new HashMap<>();
             private boolean relayingAllowed;
 
             @Override
-            public <T> Optional<T> setAttachment(AttachmentKey<T> key, T value, State state) {
+            public <T> Optional<T> setAttachment(ProtocolSession.AttachmentKey<T> key, T value, ProtocolSession.State state) {
                 Preconditions.checkNotNull(key, "key cannot be null");
                 Preconditions.checkNotNull(value, "value cannot be null");
 
-                if (state == State.Connection) {
+                if (state == ProtocolSession.State.Connection) {
                     return key.convert(connectionState.put(key, value));
                 } else {
                     return key.convert(sessionState.put(key, value));
@@ -79,10 +81,10 @@ class SpamAssassinHandlerTest {
             }
 
             @Override
-            public <T> Optional<T> removeAttachment(AttachmentKey<T> key, State state) {
+            public <T> Optional<T> removeAttachment(ProtocolSession.AttachmentKey<T> key, ProtocolSession.State state) {
                 Preconditions.checkNotNull(key, "key cannot be null");
 
-                if (state == State.Connection) {
+                if (state == ProtocolSession.State.Connection) {
                     return key.convert(connectionState.remove(key));
                 } else {
                     return key.convert(sessionState.remove(key));
@@ -90,13 +92,13 @@ class SpamAssassinHandlerTest {
             }
 
             @Override
-            public <T> Optional<T> getAttachment(AttachmentKey<T> key, State state) {
+            public <T> Optional<T> getAttachment(ProtocolSession.AttachmentKey<T> key, ProtocolSession.State state) {
                 try {
                     sessionState.put(SMTPSession.SENDER, MaybeSender.of(new MailAddress("sender@james.apache.org")));
                 } catch (AddressException e) {
                     throw new RuntimeException(e);
                 }
-                if (state == State.Connection) {
+                if (state == ProtocolSession.State.Connection) {
                     return key.convert(connectionState.get(key));
                 } else {
                     return key.convert(sessionState.get(key));
@@ -136,10 +138,8 @@ class SpamAssassinHandlerTest {
     void testNonSpam() throws Exception {
         SMTPSession session = setupMockedSMTPSession(setupMockedMail(setupMockedMimeMessage("test")));
 
-        SpamAssassinHandler handler = new SpamAssassinHandler(new RecordingMetricFactory());
+        SpamAssassinHandler handler = new SpamAssassinHandler(new RecordingMetricFactory(), new SpamAssassinConfiguration(Host.from(SPAMD_HOST, spamd.getPort())));
 
-        handler.setSpamdHost(SPAMD_HOST);
-        handler.setSpamdPort(spamd.getPort());
         handler.setSpamdRejectionHits(200.0);
         HookResult response = handler.onMessage(session, mockedMail);
 
@@ -153,10 +153,8 @@ class SpamAssassinHandlerTest {
     void testSpam() throws Exception {
         SMTPSession session = setupMockedSMTPSession(setupMockedMail(setupMockedMimeMessage(MockSpamd.GTUBE)));
 
-        SpamAssassinHandler handler = new SpamAssassinHandler(new RecordingMetricFactory());
+        SpamAssassinHandler handler = new SpamAssassinHandler(new RecordingMetricFactory(), new SpamAssassinConfiguration(Host.from(SPAMD_HOST, spamd.getPort())));
 
-        handler.setSpamdHost(SPAMD_HOST);
-        handler.setSpamdPort(spamd.getPort());
         handler.setSpamdRejectionHits(2000.0);
         HookResult response = handler.onMessage(session, mockedMail);
 
@@ -169,10 +167,8 @@ class SpamAssassinHandlerTest {
     void testSpamReject() throws Exception {
         SMTPSession session = setupMockedSMTPSession(setupMockedMail(setupMockedMimeMessage(MockSpamd.GTUBE)));
 
-        SpamAssassinHandler handler = new SpamAssassinHandler(new RecordingMetricFactory());
+        SpamAssassinHandler handler = new SpamAssassinHandler(new RecordingMetricFactory(), new SpamAssassinConfiguration(Host.from(SPAMD_HOST, spamd.getPort())));
 
-        handler.setSpamdHost(SPAMD_HOST);
-        handler.setSpamdPort(spamd.getPort());
         handler.setSpamdRejectionHits(200.0);
         HookResult response = handler.onMessage(session, mockedMail);
 
diff --git a/third-party/spamassassin/src/test/java/org/apache/james/spamassassin/SpamAssassinIntegrationTest.java b/third-party/spamassassin/src/test/java/org/apache/james/spamassassin/SpamAssassinIntegrationTest.java
new file mode 100644
index 0000000000..2578092b5a
--- /dev/null
+++ b/third-party/spamassassin/src/test/java/org/apache/james/spamassassin/SpamAssassinIntegrationTest.java
@@ -0,0 +1,211 @@
+/****************************************************************
+ * 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.spamassassin;
+
+import static org.apache.james.MemoryJamesServerMain.SMTP_AND_IMAP_MODULE;
+import static org.apache.james.mailets.configuration.Constants.DEFAULT_DOMAIN;
+import static org.apache.james.mailets.configuration.Constants.FROM;
+import static org.apache.james.mailets.configuration.Constants.LOCALHOST_IP;
+import static org.apache.james.mailets.configuration.Constants.PASSWORD;
+import static org.apache.james.mailets.configuration.Constants.RECIPIENT;
+import static org.apache.james.mailets.configuration.Constants.RECIPIENT2;
+import static org.apache.james.mailets.configuration.Constants.awaitAtMostOneMinute;
+import static org.assertj.core.api.Assertions.assertThat;
+
+import java.io.File;
+import java.util.UUID;
+
+import javax.mail.MessagingException;
+
+import org.apache.james.core.builder.MimeMessageBuilder;
+import org.apache.james.mailets.TemporaryJamesServer;
+import org.apache.james.mailets.configuration.CommonProcessors;
+import org.apache.james.mailets.configuration.MailetConfiguration;
+import org.apache.james.mailets.configuration.MailetContainer;
+import org.apache.james.mailets.configuration.ProcessorConfiguration;
+import org.apache.james.modules.protocols.ImapGuiceProbe;
+import org.apache.james.modules.protocols.SmtpGuiceProbe;
+import org.apache.james.transport.matchers.All;
+import org.apache.james.util.Host;
+import org.apache.james.util.docker.DockerContainer;
+import org.apache.james.util.docker.RateLimiters;
+import org.apache.james.utils.DataProbeImpl;
+import org.apache.james.utils.SMTPMessageSender;
+import org.apache.james.utils.TestIMAPClient;
+import org.apache.mailet.base.test.FakeMail;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.RegisterExtension;
+import org.junit.jupiter.api.io.TempDir;
+import org.testcontainers.containers.wait.strategy.HostPortWaitStrategy;
+
+import com.google.inject.Binder;
+import com.google.inject.Module;
+import com.google.inject.Provides;
+import com.google.inject.Singleton;
+
+class SpamAssassinIntegrationTest {
+    private static final String SPAM_CONTENT = "XJS*C4JDBQADN1.NSBN3*2IDNEN*GTUBE-STANDARD-ANTI-UBE-TEST-EMAIL*C.34X";
+    private static final String SPAMASSASSIN_IMAGE = "instantlinux/spamassassin:3.4.6-1";
+
+    @RegisterExtension
+    public static DockerContainer spamAssassinContainer = DockerContainer.fromName(SPAMASSASSIN_IMAGE)
+        .withExposedPorts(783)
+        .withAffinityToContainer()
+        .waitingFor(new HostPortWaitStrategy().withRateLimiter(RateLimiters.TWENTIES_PER_SECOND))
+        .withName("james-testing-spamassassin-" + UUID.randomUUID());
+
+    @RegisterExtension
+    public TestIMAPClient messageReader = new TestIMAPClient();
+    @RegisterExtension
+    public SMTPMessageSender messageSender = new SMTPMessageSender(DEFAULT_DOMAIN);
+
+    private TemporaryJamesServer jamesServer;
+
+    @BeforeEach
+    void setup(@TempDir File temporaryFolder) throws Exception {
+        MailetContainer.Builder mailets = TemporaryJamesServer.defaultMailetContainerConfiguration()
+            .putProcessor(
+                ProcessorConfiguration.transport()
+                    .addMailet(MailetConfiguration.builder()
+                        .matcher(All.class)
+                        .mailet(SpamAssassin.class))
+                    .addMailetsFrom(CommonProcessors.deliverOnlyTransport()));
+
+        jamesServer = TemporaryJamesServer.builder()
+            .withBase(SMTP_AND_IMAP_MODULE)
+            .withMailetContainer(mailets)
+            .withOverrides(new Module() {
+                @Override
+                public void configure(Binder binder) {
+                }
+                @Provides
+                @Singleton
+                private SpamAssassinConfiguration provideSpamAssassinConfiguration(){
+                    return new SpamAssassinConfiguration(Host.parseConfString("localhost", spamAssassinContainer.getMappedPort(783)));
+                }
+            })
+            .build(temporaryFolder);
+        jamesServer.start();
+
+        jamesServer.getProbe(DataProbeImpl.class)
+            .fluent()
+            .addDomain(DEFAULT_DOMAIN)
+            .addUser(FROM, PASSWORD)
+            .addUser(RECIPIENT, PASSWORD)
+            .addUser(RECIPIENT2, PASSWORD);
+    }
+
+    @AfterEach
+    void tearDown() {
+        jamesServer.shutdown();
+    }
+
+    @Test
+    void spamAssassinShouldAppendNewHeaderOnMessage() throws Exception {
+        messageSender.connect(LOCALHOST_IP, jamesServer.getProbe(SmtpGuiceProbe.class).getSmtpPort())
+            .authenticate(FROM, PASSWORD)
+            .sendMessage(mailWithContent("This is the content", RECIPIENT));
+
+        messageReader.connect(LOCALHOST_IP, jamesServer.getProbe(ImapGuiceProbe.class).getImapPort())
+            .login(RECIPIENT, PASSWORD)
+            .select(TestIMAPClient.INBOX)
+            .awaitMessage(awaitAtMostOneMinute);
+
+        assertThat(messageReader.readFirstMessageHeaders())
+            .contains(
+                SpamAssassinResult.FLAG_MAIL.asString(),
+                SpamAssassinResult.STATUS_MAIL.asString());
+    }
+
+    @Test
+    void spamAssassinShouldAppendNewHeaderWhichDetectIsSpamWhenSpamMessage() throws Exception {
+        messageSender.connect(LOCALHOST_IP, jamesServer.getProbe(SmtpGuiceProbe.class).getSmtpPort())
+            .authenticate(FROM, PASSWORD)
+            .sendMessage(mailWithContent(SPAM_CONTENT, RECIPIENT));
+
+        messageReader.connect(LOCALHOST_IP, jamesServer.getProbe(ImapGuiceProbe.class).getImapPort())
+            .login(RECIPIENT, PASSWORD)
+            .select(TestIMAPClient.INBOX)
+            .awaitMessage(awaitAtMostOneMinute);
+
+        String receivedHeaders = messageReader.readFirstMessageHeaders();
+        assertThat(receivedHeaders).contains(SpamAssassinResult.FLAG_MAIL.asString() + ": YES");
+        assertThat(receivedHeaders).contains(SpamAssassinResult.STATUS_MAIL.asString() + ": Yes");
+    }
+
+    @Test
+    void spamAssassinShouldAppendNewHeaderWhichNoWhenNonSpamMessage() throws Exception {
+        messageSender.connect(LOCALHOST_IP, jamesServer.getProbe(SmtpGuiceProbe.class).getSmtpPort())
+            .authenticate(FROM, PASSWORD)
+            .sendMessage(mailWithContent("This is the content", RECIPIENT));
+
+        messageReader.connect(LOCALHOST_IP, jamesServer.getProbe(ImapGuiceProbe.class).getImapPort())
+            .login(RECIPIENT, PASSWORD)
+            .select(TestIMAPClient.INBOX)
+            .awaitMessage(awaitAtMostOneMinute);
+
+        String receivedHeaders = messageReader.readFirstMessageHeaders();
+        assertThat(receivedHeaders).contains(SpamAssassinResult.FLAG_MAIL.asString() + ": NO");
+        assertThat(receivedHeaders).contains(SpamAssassinResult.STATUS_MAIL.asString() + ": No");
+    }
+
+    @Test
+    void spamAssassinShouldAppendNewHeaderPerRecipientOnMessage() throws Exception {
+        messageSender.connect(LOCALHOST_IP, jamesServer.getProbe(SmtpGuiceProbe.class).getSmtpPort())
+            .authenticate(FROM, PASSWORD)
+            .sendMessage(mailWithContent("This is the content", RECIPIENT, RECIPIENT2));
+
+        messageReader.connect(LOCALHOST_IP, jamesServer.getProbe(ImapGuiceProbe.class).getImapPort())
+            .login(RECIPIENT, PASSWORD)
+            .select(TestIMAPClient.INBOX)
+            .awaitMessage(awaitAtMostOneMinute);
+
+        assertThat(messageReader.readFirstMessageHeaders())
+            .contains(
+                SpamAssassinResult.FLAG_MAIL.asString(),
+                SpamAssassinResult.STATUS_MAIL.asString());
+
+        messageReader.disconnect()
+            .connect(LOCALHOST_IP, jamesServer.getProbe(ImapGuiceProbe.class).getImapPort())
+            .login(RECIPIENT2, PASSWORD)
+            .select(TestIMAPClient.INBOX)
+            .awaitMessage(awaitAtMostOneMinute);
+
+        assertThat(messageReader.readFirstMessageHeaders())
+            .contains(
+                SpamAssassinResult.FLAG_MAIL.asString(),
+                SpamAssassinResult.STATUS_MAIL.asString());
+    }
+
+    private FakeMail.Builder mailWithContent(String textContent, String... recipients) throws MessagingException {
+        return FakeMail.builder()
+            .name("name")
+            .mimeMessage(MimeMessageBuilder.mimeMessageBuilder()
+                .setSender(FROM)
+                .addToRecipient(recipients)
+                .setSubject("This is the subject")
+                .setText(textContent))
+            .sender(FROM)
+            .recipients(recipients);
+    }
+
+}
diff --git a/third-party/spamassassin/src/test/java/org/apache/james/spamassassin/SpamAssassinListenerTest.java b/third-party/spamassassin/src/test/java/org/apache/james/spamassassin/SpamAssassinListenerTest.java
new file mode 100644
index 0000000000..37dedae991
--- /dev/null
+++ b/third-party/spamassassin/src/test/java/org/apache/james/spamassassin/SpamAssassinListenerTest.java
@@ -0,0 +1,285 @@
+/****************************************************************
+ * 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.spamassassin;
+
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+import static org.mockito.Mockito.when;
+
+import java.nio.charset.StandardCharsets;
+import java.util.Date;
+
+import javax.mail.Flags;
+
+import org.apache.james.core.Username;
+import org.apache.james.events.EventListener;
+import org.apache.james.events.Group;
+import org.apache.james.mailbox.DefaultMailboxes;
+import org.apache.james.mailbox.MailboxSession;
+import org.apache.james.mailbox.MailboxSessionUtil;
+import org.apache.james.mailbox.events.MailboxEvents.Added;
+import org.apache.james.mailbox.events.MessageMoveEvent;
+import org.apache.james.mailbox.exception.MailboxException;
+import org.apache.james.mailbox.inmemory.manager.InMemoryIntegrationResources;
+import org.apache.james.mailbox.model.ByteContent;
+import org.apache.james.mailbox.model.Mailbox;
+import org.apache.james.mailbox.model.MailboxId;
+import org.apache.james.mailbox.model.MailboxPath;
+import org.apache.james.mailbox.model.MessageMetaData;
+import org.apache.james.mailbox.model.MessageMoves;
+import org.apache.james.mailbox.model.TestMessageId;
+import org.apache.james.mailbox.model.ThreadId;
+import org.apache.james.mailbox.model.UidValidity;
+import org.apache.james.mailbox.store.MailboxSessionMapperFactory;
+import org.apache.james.mailbox.store.StoreMailboxManager;
+import org.apache.james.mailbox.store.SystemMailboxesProviderImpl;
+import org.apache.james.mailbox.store.event.EventFactory;
+import org.apache.james.mailbox.store.mail.MailboxMapper;
+import org.apache.james.mailbox.store.mail.model.impl.PropertyBuilder;
+import org.apache.james.mailbox.store.mail.model.impl.SimpleMailboxMessage;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+class SpamAssassinListenerTest {
+    static final Username USER = Username.of("user");
+    static final MailboxSession MAILBOX_SESSION = MailboxSessionUtil.create(USER);
+    static final UidValidity UID_VALIDITY = UidValidity.of(43);
+    static final TestMessageId MESSAGE_ID = TestMessageId.of(45);
+    static final ThreadId THREAD_ID = ThreadId.fromBaseMessageId(MESSAGE_ID);
+
+    SpamAssassinLearner spamAssassinLearner;
+    SpamAssassinListener listener;
+    Mailbox inbox;
+    Mailbox mailbox1;
+    MailboxId mailboxId1;
+    MailboxId mailboxId2;
+    MailboxId spamMailboxId;
+    MailboxId spamCapitalMailboxId;
+    MailboxId trashMailboxId;
+    MailboxSessionMapperFactory mapperFactory;
+    Mailbox mailbox2;
+
+    @BeforeEach
+    void setup() throws Exception {
+        StoreMailboxManager mailboxManager = spy(InMemoryIntegrationResources.defaultResources().getMailboxManager());
+        SystemMailboxesProviderImpl systemMailboxesProvider = new SystemMailboxesProviderImpl(mailboxManager);
+        when(mailboxManager.createSystemSession(USER))
+            .thenReturn(MAILBOX_SESSION);
+
+        spamAssassinLearner = mock(SpamAssassinLearner.class);
+        mapperFactory = mailboxManager.getMapperFactory();
+        MailboxMapper mailboxMapper = mapperFactory.createMailboxMapper(MAILBOX_SESSION);
+        inbox = mailboxMapper.create(MailboxPath.forUser(USER, DefaultMailboxes.INBOX), UID_VALIDITY).block();
+        mailbox1 = mailboxMapper.create(MailboxPath.forUser(USER, "mailbox1"), UID_VALIDITY).block();
+        mailbox2 = mailboxMapper.create(MailboxPath.forUser(USER, "mailbox2"), UID_VALIDITY).block();
+        mailboxId1 = mailbox1.getMailboxId();
+        mailboxId2 = mailbox2.getMailboxId();
+        spamMailboxId = mailboxMapper.create(MailboxPath.forUser(USER, "Spam"), UID_VALIDITY).block().getMailboxId();
+        spamCapitalMailboxId = mailboxMapper.create(MailboxPath.forUser(USER, "SPAM"), UID_VALIDITY).block().getMailboxId();
+        trashMailboxId = mailboxMapper.create(MailboxPath.forUser(USER, "Trash"), UID_VALIDITY).block().getMailboxId();
+
+        listener = new SpamAssassinListener(spamAssassinLearner, systemMailboxesProvider, mailboxManager, mapperFactory, EventListener.ExecutionMode.SYNCHRONOUS);
+    }
+
+    @Test
+    void deserializeSpamAssassinListenerGroup() throws Exception {
+        assertThat(Group.deserialize("org.apache.james.spamassassin.SpamAssassinListener$SpamAssassinListenerGroup"))
+            .isEqualTo(new SpamAssassinListener.SpamAssassinListenerGroup());
+    }
+
+    @Test
+    void isEventOnSpamMailboxShouldReturnFalseWhenMessageIsMovedToANonSpamMailbox() {
+        MessageMoveEvent messageMoveEvent = MessageMoveEvent.builder()
+            .session(MAILBOX_SESSION)
+            .messageMoves(MessageMoves.builder()
+                .previousMailboxIds(mailboxId1)
+                .targetMailboxIds(mailboxId2)
+                .build())
+            .messageId(MESSAGE_ID)
+            .build();
+
+        assertThat(listener.isMessageMovedToSpamMailbox(messageMoveEvent)).isFalse();
+    }
+
+    @Test
+    void isEventOnSpamMailboxShouldReturnTrueWhenMailboxIsSpam() {
+        MessageMoveEvent messageMoveEvent = MessageMoveEvent.builder()
+            .session(MAILBOX_SESSION)
+            .messageMoves(MessageMoves.builder()
+                .previousMailboxIds(mailboxId1)
+                .targetMailboxIds(spamMailboxId)
+                .build())
+            .messageId(MESSAGE_ID)
+            .build();
+
+        assertThat(listener.isMessageMovedToSpamMailbox(messageMoveEvent)).isTrue();
+    }
+
+    @Test
+    void isEventOnSpamMailboxShouldReturnFalseWhenMailboxIsSpamOtherCase() {
+        MessageMoveEvent messageMoveEvent = MessageMoveEvent.builder()
+            .session(MAILBOX_SESSION)
+            .messageMoves(MessageMoves.builder()
+                .previousMailboxIds(mailboxId1)
+                .targetMailboxIds(spamCapitalMailboxId)
+                .build())
+            .messageId(MESSAGE_ID)
+            .build();
+
+        assertThat(listener.isMessageMovedToSpamMailbox(messageMoveEvent)).isFalse();
+    }
+
+    @Test
+    void eventShouldCallSpamAssassinSpamLearningWhenTheEventMatches() throws Exception {
+        MessageMoveEvent messageMoveEvent = MessageMoveEvent.builder()
+            .session(MAILBOX_SESSION)
+            .messageMoves(MessageMoves.builder()
+                .previousMailboxIds(mailboxId1)
+                .targetMailboxIds(spamMailboxId)
+                .build())
+            .messageId(MESSAGE_ID)
+            .build();
+
+        listener.event(messageMoveEvent);
+
+        verify(spamAssassinLearner).learnSpam(any(), any());
+    }
+
+    @Test
+    void isMessageMovedOutOfSpamMailboxShouldReturnFalseWhenMessageMovedBetweenNonSpamMailboxes() {
+        MessageMoveEvent messageMoveEvent = MessageMoveEvent.builder()
+            .session(MAILBOX_SESSION)
+            .messageMoves(MessageMoves.builder()
+                .previousMailboxIds(mailboxId1)
+                .targetMailboxIds(mailboxId2)
+                .build())
+            .messageId(MESSAGE_ID)
+            .build();
+
+        assertThat(listener.isMessageMovedOutOfSpamMailbox(messageMoveEvent)).isFalse();
+    }
+
+    @Test
+    void isMessageMovedOutOfSpamMailboxShouldReturnFalseWhenMessageMovedOutOfCapitalSpamMailbox() {
+        MessageMoveEvent messageMoveEvent = MessageMoveEvent.builder()
+            .session(MAILBOX_SESSION)
+            .messageMoves(MessageMoves.builder()
+                .previousMailboxIds(spamCapitalMailboxId)
+                .targetMailboxIds(mailboxId2)
+                .build())
+            .messageId(MESSAGE_ID)
+            .build();
+
+        assertThat(listener.isMessageMovedOutOfSpamMailbox(messageMoveEvent)).isFalse();
+    }
+
+    @Test
+    void isMessageMovedOutOfSpamMailboxShouldReturnTrueWhenMessageMovedOutOfSpamMailbox() {
+        MessageMoveEvent messageMoveEvent = MessageMoveEvent.builder()
+            .session(MAILBOX_SESSION)
+            .messageMoves(MessageMoves.builder()
+                .previousMailboxIds(spamMailboxId)
+                .targetMailboxIds(mailboxId2)
+                .build())
+            .messageId(MESSAGE_ID)
+            .build();
+
+        assertThat(listener.isMessageMovedOutOfSpamMailbox(messageMoveEvent)).isTrue();
+    }
+
+    @Test
+    void isMessageMovedOutOfSpamMailboxShouldReturnFalseWhenMessageMovedToTrash() {
+        MessageMoveEvent messageMoveEvent = MessageMoveEvent.builder()
+            .session(MAILBOX_SESSION)
+            .messageMoves(MessageMoves.builder()
+                .previousMailboxIds(spamMailboxId)
+                .targetMailboxIds(trashMailboxId)
+                .build())
+            .messageId(MESSAGE_ID)
+            .build();
+
+        assertThat(listener.isMessageMovedOutOfSpamMailbox(messageMoveEvent)).isFalse();
+    }
+
+    @Test
+    void eventShouldCallSpamAssassinHamLearningWhenTheEventMatches() throws Exception {
+        MessageMoveEvent messageMoveEvent = MessageMoveEvent.builder()
+            .session(MAILBOX_SESSION)
+            .messageMoves(MessageMoves.builder()
+                .previousMailboxIds(spamMailboxId)
+                .targetMailboxIds(mailboxId1)
+                .build())
+            .messageId(MESSAGE_ID)
+            .build();
+
+        listener.event(messageMoveEvent);
+
+        verify(spamAssassinLearner).learnHam(any(), any());
+    }
+
+    @Test
+    void eventShouldCallSpamAssassinHamLearningWhenTheMessageIsAddedInInbox() throws Exception {
+        SimpleMailboxMessage message = createMessage(inbox);
+
+        Added addedEvent = EventFactory.added()
+            .randomEventId()
+            .mailboxSession(MAILBOX_SESSION)
+            .mailbox(inbox)
+            .addMetaData(message.metaData())
+            .build();
+
+        listener.event(addedEvent);
+
+        verify(spamAssassinLearner).learnHam(any(), any());
+    }
+
+    @Test
+    void eventShouldNotCallSpamAssassinHamLearningWhenTheMessageIsAddedInAMailboxOtherThanInbox() throws Exception {
+        SimpleMailboxMessage message = createMessage(mailbox1);
+
+        Added addedEvent = EventFactory.added()
+            .randomEventId()
+            .mailboxSession(MAILBOX_SESSION)
+            .mailbox(mailbox1)
+            .addMetaData(message.metaData())
+            .build();
+
+        listener.event(addedEvent);
+
+        verifyNoMoreInteractions(spamAssassinLearner);
+    }
+
+    private SimpleMailboxMessage createMessage(Mailbox mailbox) throws MailboxException {
+        int size = 45;
+        int bodyStartOctet = 25;
+        byte[] content = "Subject: test\r\n\r\nBody\r\n".getBytes(StandardCharsets.UTF_8);
+        SimpleMailboxMessage message = new SimpleMailboxMessage(MESSAGE_ID, THREAD_ID, new Date(),
+            size, bodyStartOctet, new ByteContent(content), new Flags(), new PropertyBuilder().build(),
+            mailbox.getMailboxId());
+        MessageMetaData messageMetaData = mapperFactory.createMessageMapper(null).add(mailbox, message);
+        message.setUid(messageMetaData.getUid());
+        return message;
+    }
+}
\ No newline at end of file
diff --git a/third-party/spamassassin/src/test/java/org/apache/james/spamassassin/SpamAssassinTest.java b/third-party/spamassassin/src/test/java/org/apache/james/spamassassin/SpamAssassinTest.java
new file mode 100644
index 0000000000..a717108737
--- /dev/null
+++ b/third-party/spamassassin/src/test/java/org/apache/james/spamassassin/SpamAssassinTest.java
@@ -0,0 +1,158 @@
+/****************************************************************
+ * 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.spamassassin;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import org.apache.james.core.MailAddress;
+import org.apache.james.core.builder.MimeMessageBuilder;
+import org.apache.james.domainlist.api.DomainList;
+import org.apache.james.metrics.tests.RecordingMetricFactory;
+import org.apache.james.spamassassin.mock.MockSpamd;
+import org.apache.james.spamassassin.mock.MockSpamdExtension;
+import org.apache.james.user.memory.MemoryUsersRepository;
+import org.apache.james.util.Host;
+import org.apache.mailet.Mail;
+import org.apache.mailet.PerRecipientHeaders;
+import org.apache.mailet.base.test.FakeMail;
+import org.apache.mailet.base.test.FakeMailetConfig;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.RegisterExtension;
+
+import com.google.common.collect.ImmutableList;
+
+class SpamAssassinTest {
+
+    private static final DomainList NO_DOMAIN_LIST = null;
+
+    @RegisterExtension
+    MockSpamdExtension spamd = new MockSpamdExtension();
+
+    private SpamAssassin mailet() {
+        return new SpamAssassin(new RecordingMetricFactory(), MemoryUsersRepository.withVirtualHosting(NO_DOMAIN_LIST), new SpamAssassinConfiguration(Host.from("localhost", spamd.getPort())));
+    }
+
+    @Test
+    void serviceShouldWriteSpamAttributeOnMail() throws Exception {
+        FakeMailetConfig mailetConfiguration = FakeMailetConfig.builder()
+            .mailetName("SpamAssassin")
+            .build();
+        SpamAssassin mailet = mailet();
+        mailet.init(mailetConfiguration);
+
+        Mail mail = FakeMail.builder()
+            .name("name")
+            .recipient("user1@exemple.com")
+            .mimeMessage(MimeMessageBuilder.mimeMessageBuilder()
+                .addToRecipient("user1@exemple.com")
+                .addFrom("sender@exemple.com")
+                .setSubject("testing")
+                .setText("Please!")
+                .build())
+            .build();
+
+        mailet.service(mail);
+
+
+        assertThat(
+            mail.getPerRecipientSpecificHeaders()
+                .getHeadersByRecipient()
+                .get(new MailAddress("user1@exemple.com"))
+                .stream()
+                .map(PerRecipientHeaders.Header::getName)
+                .collect(ImmutableList.toImmutableList()))
+            .contains(SpamAssassinResult.FLAG_MAIL.asString(), SpamAssassinResult.STATUS_MAIL.asString());
+    }
+
+    @Test
+    void serviceShouldWriteMessageAsNotSpamWhenNotSpam() throws Exception {
+        FakeMailetConfig mailetConfiguration = FakeMailetConfig.builder()
+            .mailetName("SpamAssassin")
+            .build();
+        SpamAssassin mailet = mailet();
+        mailet.init(mailetConfiguration);
+
+        Mail mail = FakeMail.builder()
+            .name("name")
+            .recipient("user1@exemple.com")
+            .mimeMessage(MimeMessageBuilder.mimeMessageBuilder()
+                .addToRecipient("user1@exemple.com")
+                .addFrom("sender@exemple.com")
+                .setSubject("testing")
+                .setText("Please!")
+                .build())
+            .build();
+
+        mailet.service(mail);
+
+        assertThat(mail.getPerRecipientSpecificHeaders())
+            .isEqualTo(new PerRecipientHeaders()
+                .addHeaderForRecipient(
+                    PerRecipientHeaders.Header.builder()
+                        .name(SpamAssassinResult.FLAG_MAIL.asString())
+                        .value("NO"),
+                    new MailAddress("user1@exemple.com"))
+                .addHeaderForRecipient(
+                    PerRecipientHeaders.Header.builder()
+                        .name(SpamAssassinResult.STATUS_MAIL.asString())
+                        .value("No, hits=3 required=5"),
+                    new MailAddress("user1@exemple.com")));
+    }
+
+    @Test
+    void serviceShouldWriteMessageAsSpamWhenSpam() throws Exception {
+        FakeMailetConfig mailetConfiguration = FakeMailetConfig.builder()
+            .mailetName("SpamAssassin")
+            .build();
+        SpamAssassin mailet = mailet();
+        mailet.init(mailetConfiguration);
+
+        Mail mail = FakeMail.builder()
+            .name("name")
+            .recipient("user1@exemple.com")
+            .mimeMessage(MimeMessageBuilder.mimeMessageBuilder()
+                .addToRecipient("user1@exemple.com")
+                .addFrom("sender@exemple.com")
+                .setSubject(MockSpamd.GTUBE + " testing")
+                .setText("Please!")
+                .build())
+            .build();
+
+        mailet.service(mail);
+
+        assertThat(mail.getPerRecipientSpecificHeaders())
+            .isEqualTo(new PerRecipientHeaders()
+                .addHeaderForRecipient(
+                    PerRecipientHeaders.Header.builder()
+                        .name(SpamAssassinResult.FLAG_MAIL.asString())
+                        .value("YES"),
+                    new MailAddress("user1@exemple.com"))
+                .addHeaderForRecipient(
+                    PerRecipientHeaders.Header.builder()
+                        .name(SpamAssassinResult.STATUS_MAIL.asString())
+                        .value("Yes, hits=1000 required=5"),
+                    new MailAddress("user1@exemple.com")));
+    }
+
+    @Test
+    void getMailetInfoShouldReturnSpamAssasinMailetInformation() {
+        assertThat(mailet().getMailetInfo()).isEqualTo("Checks message against SpamAssassin");
+    }
+}
diff --git a/third-party/spamassassin/src/test/java/org/apache/james/spamassassin/module/SpamAssassinModuleExtension.java b/third-party/spamassassin/src/test/java/org/apache/james/spamassassin/module/SpamAssassinModuleExtension.java
new file mode 100644
index 0000000000..d16ad4476f
--- /dev/null
+++ b/third-party/spamassassin/src/test/java/org/apache/james/spamassassin/module/SpamAssassinModuleExtension.java
@@ -0,0 +1,65 @@
+/****************************************************************
+ * 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.spamassassin.module;
+
+
+import java.util.Optional;
+
+import org.apache.james.GuiceModuleTestExtension;
+import org.apache.james.spamassassin.SpamAssassinExtension;
+import org.junit.jupiter.api.extension.ExtensionContext;
+import org.junit.jupiter.api.extension.ParameterContext;
+import org.junit.jupiter.api.extension.ParameterResolutionException;
+
+import com.google.inject.Module;
+
+public class SpamAssassinModuleExtension implements GuiceModuleTestExtension {
+
+    private final SpamAssassinExtension spamAssassin;
+
+    public SpamAssassinModuleExtension() {
+        this.spamAssassin = new SpamAssassinExtension();
+    }
+
+    @Override
+    public void beforeAll(ExtensionContext extensionContext) {
+        spamAssassin.beforeAll(extensionContext);
+    }
+
+    @Override
+    public void afterAll(ExtensionContext extensionContext) {
+        spamAssassin.afterAll(extensionContext);
+    }
+
+    @Override
+    public Module getModule() {
+        return new SpamAssassinTestModule(spamAssassin);
+    }
+
+    @Override
+    public Optional<Class<?>> supportedParameterClass() {
+        return Optional.of(SpamAssassinExtension.SpamAssassin.class);
+    }
+
+    @Override
+    public Object resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext) throws ParameterResolutionException {
+        return spamAssassin.getSpamAssassin();
+    }
+}
\ No newline at end of file
diff --git a/third-party/spamassassin/src/test/java/org/apache/james/spamassassin/module/SpamAssassinTestModule.java b/third-party/spamassassin/src/test/java/org/apache/james/spamassassin/module/SpamAssassinTestModule.java
new file mode 100644
index 0000000000..c156a46ca1
--- /dev/null
+++ b/third-party/spamassassin/src/test/java/org/apache/james/spamassassin/module/SpamAssassinTestModule.java
@@ -0,0 +1,60 @@
+/****************************************************************
+ * 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.spamassassin.module;
+
+import javax.inject.Singleton;
+
+import org.apache.james.mailetcontainer.impl.MailetConfigImpl;
+import org.apache.james.modules.mailbox.ListenerConfiguration;
+import org.apache.james.modules.mailbox.ListenersConfiguration;
+import org.apache.james.spamassassin.SpamAssassin;
+import org.apache.james.spamassassin.SpamAssassinConfiguration;
+import org.apache.james.spamassassin.SpamAssassinExtension;
+import org.apache.james.spamassassin.SpamAssassinListener;
+import org.apache.james.util.Host;
+import org.apache.james.utils.MailetConfigurationOverride;
+
+import com.google.inject.AbstractModule;
+import com.google.inject.Provides;
+import com.google.inject.multibindings.Multibinder;
+
+public class SpamAssassinTestModule extends AbstractModule {
+
+    private final SpamAssassinExtension spamAssassinExtension;
+
+    public SpamAssassinTestModule(SpamAssassinExtension spamAssassinExtension) {
+        this.spamAssassinExtension = spamAssassinExtension;
+    }
+
+    @Override
+    protected void configure() {
+        bind(ListenersConfiguration.class)
+            .toInstance(ListenersConfiguration.of(
+                ListenerConfiguration.forClass(SpamAssassinListener.class.getCanonicalName())));
+    }
+
+    @Provides
+    @Singleton
+    private SpamAssassinConfiguration getSpamAssassinConfiguration() {
+        SpamAssassinExtension.SpamAssassin spamAssassin = spamAssassinExtension.getSpamAssassin();
+        return new SpamAssassinConfiguration(Host.from(spamAssassin.getIp(), spamAssassin.getBindingPort()));
+    }
+
+}
diff --git a/third-party/spamassassin/src/test/resources/docker/spamassassin/spamd.sh b/third-party/spamassassin/src/test/resources/docker/spamassassin/spamd.sh
index 2093cf8f04..31c2261364 100755
--- a/third-party/spamassassin/src/test/resources/docker/spamassassin/spamd.sh
+++ b/third-party/spamassassin/src/test/resources/docker/spamassassin/spamd.sh
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/bin/sh
 
 echo "Run Postgres"
 /usr/local/bin/docker-entrypoint.sh postgres &
diff --git a/server/protocols/jmap-draft-integration-testing/memory-jmap-draft-integration-testing/src/test/resources/listeners.xml b/third-party/spamassassin/src/test/resources/listeners.xml
similarity index 95%
copy from server/protocols/jmap-draft-integration-testing/memory-jmap-draft-integration-testing/src/test/resources/listeners.xml
copy to third-party/spamassassin/src/test/resources/listeners.xml
index a686755978..cc7c38e00e 100644
--- a/server/protocols/jmap-draft-integration-testing/memory-jmap-draft-integration-testing/src/test/resources/listeners.xml
+++ b/third-party/spamassassin/src/test/resources/listeners.xml
@@ -44,7 +44,7 @@
     </configuration>
   </listener>
   <listener>
-    <class>org.apache.james.mailbox.spamassassin.SpamAssassinListener</class>
+    <class>org.apache.james.spamassassin.SpamAssassinListener</class>
   </listener>
   <listener>
     <class>org.apache.james.jmap.event.PopulateEmailQueryViewListener</class>
diff --git a/third-party/spamassassin/src/test/resources/mailetcontainer.xml b/third-party/spamassassin/src/test/resources/mailetcontainer.xml
new file mode 100644
index 0000000000..f67bfae612
--- /dev/null
+++ b/third-party/spamassassin/src/test/resources/mailetcontainer.xml
@@ -0,0 +1,133 @@
+<?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>2</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>
+        </processor>
+
+        <processor state="transport" enableJmx="false">
+            <matcher name="mdn-matcher" match="org.apache.james.mailetcontainer.impl.matchers.And">
+                <matcher match="HasMimeType=multipart/report"/>
+                <matcher match="HasMimeTypeParameter=report-type=disposition-notification"/>
+            </matcher>
+            <matcher name="relay-allowed" match="org.apache.james.mailetcontainer.impl.matchers.Or">
+                <matcher match="SMTPAuthSuccessful"/>
+                <matcher match="SMTPIsAuthNetwork"/>
+                <matcher match="SentByMailet"/>
+                <matcher match="org.apache.james.jmap.mailet.SentByJmap"/>
+            </matcher>
+
+            <mailet match="All" class="RemoveMimeHeader">
+                <name>bcc</name>
+            </mailet>
+            <mailet match="All" class="ICSSanitizer"/>
+            <mailet match="All" class="org.apache.james.jmap.mailet.TextCalendarBodyToAttachment"/>
+            <mailet match="All" class="RecipientRewriteTable">
+                <errorProcessor>rrt-error</errorProcessor>
+            </mailet>
+            <mailet match="RecipientIsLocal" class="VacationMailet"/>
+            <mailet match="mdn-matcher" class="org.apache.james.jmap.mailet.ExtractMDNOriginalJMAPMessageId" >
+                <onMailetException>ignore</onMailetException>
+            </mailet>
+            <mailet match="RecipientIsLocal" class="Sieve"/>
+            <mailet match="RecipientIsLocal" class="org.apache.james.spamassassin.SpamAssassin">
+                <onMailetException>ignore</onMailetException>
+            </mailet>
+            <mailet match="IsMarkedAsSpam" class="WithStorageDirective">
+                <targetFolderName>Spam</targetFolderName>
+            </mailet>
+            <mailet match="RecipientIsLocal" class="org.apache.james.jmap.mailet.filter.JMAPFiltering"/>
+            <mailet match="RecipientIsLocal" class="LocalDelivery"/>
+            <mailet match="HostIsLocal" class="ToProcessor">
+                <processor>local-address-error</processor>
+                <notice>550 - Requested action not taken: no such user here</notice>
+            </mailet>
+
+            <mailet match="relay-allowed" 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-address-error" enableJmx="false">
+            <mailet match="All" class="Bounce">
+                <attachment>none</attachment>
+            </mailet>
+        </processor>
+
+        <processor state="relay-denied" enableJmx="false">
+            <mailet match="All" class="Bounce">
+                <attachment>none</attachment>
+            </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/third-party/spamassassin/src/test/resources/smtpserver.xml b/third-party/spamassassin/src/test/resources/smtpserver.xml
new file mode 100644
index 0000000000..02fbbdadf5
--- /dev/null
+++ b/third-party/spamassassin/src/test/resources/smtpserver.xml
@@ -0,0 +1,54 @@
+<?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>
+            <plainAuthEnabled>true</plainAuthEnabled>
+        </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"/>
+            <handler class="org.apache.james.spamassassin.SpamAssassinHandler"/>
+        </handlerchain>
+        <gracefulShutdown>false</gracefulShutdown>
+    </smtpserver>
+</smtpservers>
+
+


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


[james-project] 01/02: JAMES-3797 drop spam assassin in james' internal module

Posted by bt...@apache.org.
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

commit 417ff299dbca903da614780d08556f179f9d1a09
Author: Tung Van TRAN <vt...@linagora.com>
AuthorDate: Thu Aug 4 17:24:27 2022 +0700

    JAMES-3797 drop spam assassin in james' internal module
---
 mailbox/plugin/spamassassin/pom.xml                |  93 ---
 .../james/mailbox/spamassassin/SpamAssassin.java   |  61 --
 .../spamassassin/SpamAssassinConfiguration.java    |  66 --
 .../mailbox/spamassassin/SpamAssassinListener.java | 183 ------
 .../SpamAssassinConfigurationTest.java             |  50 --
 .../spamassassin/SpamAssassinListenerTest.java     | 283 ---------
 mailbox/pom.xml                                    |   2 -
 pom.xml                                            |  11 -
 server/apps/cassandra-app/pom.xml                  |  10 -
 .../org/apache/james/CassandraJamesServerMain.java |   4 +-
 server/apps/distributed-app/pom.xml                |   4 -
 .../james/CassandraRabbitMQJamesServerMain.java    |   4 +-
 server/apps/distributed-pop3-app/pom.xml           |   4 -
 server/apps/jpa-app/pom.xml                        |   4 -
 .../java/org/apache/james/JPAJamesServerMain.java  |   4 +-
 server/apps/memory-app/pom.xml                     |   4 -
 .../org/apache/james/MemoryJamesServerMain.java    |   4 +-
 .../src/test/resources/mailetcontainer.xml         |   8 -
 .../guice/mailbox-plugin-spamassassin/pom.xml      |  66 --
 .../SpamAssassinConfigurationLoader.java           |  48 --
 .../spamassassin/SpamAssassinListenerModule.java   |  58 --
 .../SpamAssassinConfigurationLoaderTest.java       |  58 --
 server/container/guice/pom.xml                     |   6 -
 .../mailets/SpamAssassinIntegrationTest.java       | 195 ------
 server/mailet/mailets/pom.xml                      |  10 -
 .../james/transport/mailets/SpamAssassin.java      | 136 ----
 .../james/transport/mailets/SpamAssassinTest.java  | 257 --------
 .../jmap-draft-integration-testing-common/pom.xml  |   6 -
 .../methods/integration/SpamAssassinContract.java  | 694 ---------------------
 .../methods/integration/SpamAssassinModule.java    |  79 ---
 .../integration/SpamAssassinModuleExtension.java   |  64 --
 .../src/test/resources/spamassassin_db/ham/ham1    | 113 ----
 .../src/test/resources/spamassassin_db/ham/ham2    |  73 ---
 .../src/test/resources/spamassassin_db/ham/ham3    |  82 ---
 .../src/test/resources/spamassassin_db/spam/spam1  | 108 ----
 .../src/test/resources/spamassassin_db/spam/spam2  | 186 ------
 .../src/test/resources/spamassassin_db/spam/spam3  | 211 -------
 .../memory-jmap-draft-integration-testing/pom.xml  |   6 -
 .../memory/MemorySpamAssassinContractTest.java     |  90 ---
 .../src/test/resources/mailetcontainer.xml         |   8 -
 .../src/test/resources/spamassassin_db             |   1 -
 .../pom.xml                                        |   6 -
 .../RabbitMQAwsS3SpamAssassinContractTest.java     |  60 --
 .../src/test/resources/mailetcontainer.xml         |   8 -
 .../src/test/resources/spamassassin_db             |   1 -
 .../src/test/resources/mailetcontainer.xml         |   8 -
 server/protocols/protocols-smtp/pom.xml            |  10 -
 .../src/test/resources/spamassassin_db/ham/ham4    |  78 ---
 .../src/test/resources/spamassassin_db/ham/ham5    |  77 ---
 .../src/test/resources/spamassassin_db/ham/ham6    |  74 ---
 .../src/test/resources/spamassassin_db/ham/ham7    |  88 ---
 .../src/test/resources/spamassassin_db/ham/ham8    |  85 ---
 .../src/test/resources/spamassassin_db/ham/ham9    | 176 ------
 .../src/test/resources/spamassassin_db/spam/spam4  | 213 -------
 .../src/test/resources/spamassassin_db/spam/spam5  | 161 -----
 .../src/test/resources/spamassassin_db/spam/spam6  | 423 -------------
 .../src/test/resources/spamassassin_db/spam/spam7  |  71 ---
 .../src/test/resources/spamassassin_db/spam/spam8  | 321 ----------
 .../src/test/resources/spamassassin_db/spam/spam9  | 142 -----
 59 files changed, 4 insertions(+), 5352 deletions(-)

diff --git a/mailbox/plugin/spamassassin/pom.xml b/mailbox/plugin/spamassassin/pom.xml
deleted file mode 100644
index 94d0a77c77..0000000000
--- a/mailbox/plugin/spamassassin/pom.xml
+++ /dev/null
@@ -1,93 +0,0 @@
-<?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/maven-v4_0_0.xsd">
-    <modelVersion>4.0.0</modelVersion>
-
-    <parent>
-        <groupId>org.apache.james</groupId>
-        <artifactId>apache-james-mailbox</artifactId>
-        <version>3.8.0-SNAPSHOT</version>
-        <relativePath>../../pom.xml</relativePath>
-    </parent>
-
-    <artifactId>apache-james-mailbox-spamassassin</artifactId>
-    <name>Apache James :: Mailbox :: Plugin :: SpamAssassin</name>
-    <description>Apache James Mailbox SpamAssassin integration</description>
-
-    <dependencies>
-        <dependency>
-            <groupId>${james.groupId}</groupId>
-            <artifactId>apache-james-mailbox-api</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>${james.groupId}</groupId>
-            <artifactId>apache-james-mailbox-api</artifactId>
-            <type>test-jar</type>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>${james.groupId}</groupId>
-            <artifactId>apache-james-mailbox-memory</artifactId>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>${james.groupId}</groupId>
-            <artifactId>apache-james-mailbox-memory</artifactId>
-            <type>test-jar</type>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>${james.groupId}</groupId>
-            <artifactId>apache-james-mailbox-store</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>${james.groupId}</groupId>
-            <artifactId>apache-james-spamassassin</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>${james.groupId}</groupId>
-            <artifactId>apache-james-spamassassin</artifactId>
-            <type>test-jar</type>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>${james.groupId}</groupId>
-            <artifactId>event-bus-api</artifactId>
-            <type>test-jar</type>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>${james.groupId}</groupId>
-            <artifactId>metrics-tests</artifactId>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>${james.groupId}</groupId>
-            <artifactId>testing-base</artifactId>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.mockito</groupId>
-            <artifactId>mockito-core</artifactId>
-            <scope>test</scope>
-        </dependency>
-    </dependencies>
-
-</project>
diff --git a/mailbox/plugin/spamassassin/src/main/java/org/apache/james/mailbox/spamassassin/SpamAssassin.java b/mailbox/plugin/spamassassin/src/main/java/org/apache/james/mailbox/spamassassin/SpamAssassin.java
deleted file mode 100644
index ec03b1f3cc..0000000000
--- a/mailbox/plugin/spamassassin/src/main/java/org/apache/james/mailbox/spamassassin/SpamAssassin.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/****************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one   *
- * or more contributor license agreements.  See the NOTICE file *
- * distributed with this work for additional information        *
- * regarding copyright ownership.  The ASF licenses this file   *
- * to you under the Apache License, Version 2.0 (the            *
- * "License"); you may not use this file except in compliance   *
- * with the License.  You may obtain a copy of the License at   *
- *                                                              *
- *   http://www.apache.org/licenses/LICENSE-2.0                 *
- *                                                              *
- * Unless required by applicable law or agreed to in writing,   *
- * software distributed under the License is distributed on an  *
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
- * KIND, either express or implied.  See the License for the    *
- * specific language governing permissions and limitations      *
- * under the License.                                           *
- ****************************************************************/
-package org.apache.james.mailbox.spamassassin;
-
-import java.io.InputStream;
-import java.util.List;
-
-import javax.inject.Inject;
-
-import org.apache.james.core.Username;
-import org.apache.james.metrics.api.MetricFactory;
-import org.apache.james.spamassassin.SpamAssassinInvoker;
-import org.apache.james.util.Host;
-
-import com.github.fge.lambdas.Throwing;
-
-public class SpamAssassin {
-
-    private final MetricFactory metricFactory;
-    private final SpamAssassinConfiguration spamAssassinConfiguration;
-
-    @Inject
-    public SpamAssassin(MetricFactory metricFactory, SpamAssassinConfiguration spamAssassinConfiguration) {
-        this.metricFactory = metricFactory;
-        this.spamAssassinConfiguration = spamAssassinConfiguration;
-    }
-
-    public void learnSpam(List<InputStream> messages, Username username) {
-        if (spamAssassinConfiguration.isEnable()) {
-            Host host = spamAssassinConfiguration.getHost().get();
-            SpamAssassinInvoker invoker = new SpamAssassinInvoker(metricFactory, host.getHostName(), host.getPort());
-            messages
-                .forEach(Throwing.consumer(message -> invoker.learnAsSpam(message, username)));
-        }
-    }
-
-    public void learnHam(List<InputStream> messages, Username username) {
-        if (spamAssassinConfiguration.isEnable()) {
-            Host host = spamAssassinConfiguration.getHost().get();
-            SpamAssassinInvoker invoker = new SpamAssassinInvoker(metricFactory, host.getHostName(), host.getPort());
-            messages
-                .forEach(Throwing.consumer(message -> invoker.learnAsHam(message, username)));
-        }
-    }
-}
diff --git a/mailbox/plugin/spamassassin/src/main/java/org/apache/james/mailbox/spamassassin/SpamAssassinConfiguration.java b/mailbox/plugin/spamassassin/src/main/java/org/apache/james/mailbox/spamassassin/SpamAssassinConfiguration.java
deleted file mode 100644
index bfc5f82c23..0000000000
--- a/mailbox/plugin/spamassassin/src/main/java/org/apache/james/mailbox/spamassassin/SpamAssassinConfiguration.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/****************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one   *
- * or more contributor license agreements.  See the NOTICE file *
- * distributed with this work for additional information        *
- * regarding copyright ownership.  The ASF licenses this file   *
- * to you under the Apache License, Version 2.0 (the            *
- * "License"); you may not use this file except in compliance   *
- * with the License.  You may obtain a copy of the License at   *
- *                                                              *
- *   http://www.apache.org/licenses/LICENSE-2.0                 *
- *                                                              *
- * Unless required by applicable law or agreed to in writing,   *
- * software distributed under the License is distributed on an  *
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
- * KIND, either express or implied.  See the License for the    *
- * specific language governing permissions and limitations      *
- * under the License.                                           *
- ****************************************************************/
-
-package org.apache.james.mailbox.spamassassin;
-
-import java.util.Objects;
-import java.util.Optional;
-
-import org.apache.james.util.Host;
-
-import com.google.common.base.MoreObjects;
-
-public class SpamAssassinConfiguration {
-
-    private final Optional<Host> host;
-
-    public SpamAssassinConfiguration(Optional<Host> host) {
-        this.host = host;
-    }
-
-    public boolean isEnable() {
-        return host.isPresent();
-    }
-
-    public Optional<Host> getHost() {
-        return host;
-    }
-
-    @Override
-    public final boolean equals(Object o) {
-        if (o instanceof SpamAssassinConfiguration) {
-            SpamAssassinConfiguration that = (SpamAssassinConfiguration) o;
-
-            return Objects.equals(this.host, that.host);
-        }
-        return false;
-    }
-
-    @Override
-    public final int hashCode() {
-        return Objects.hash(host);
-    }
-
-    @Override
-    public String toString() {
-        return MoreObjects.toStringHelper(this)
-                .add("host", host)
-                .toString();
-    }
-}
diff --git a/mailbox/plugin/spamassassin/src/main/java/org/apache/james/mailbox/spamassassin/SpamAssassinListener.java b/mailbox/plugin/spamassassin/src/main/java/org/apache/james/mailbox/spamassassin/SpamAssassinListener.java
deleted file mode 100644
index 65bc3bce2c..0000000000
--- a/mailbox/plugin/spamassassin/src/main/java/org/apache/james/mailbox/spamassassin/SpamAssassinListener.java
+++ /dev/null
@@ -1,183 +0,0 @@
-/****************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one   *
- * or more contributor license agreements.  See the NOTICE file *
- * distributed with this work for additional information        *
- * regarding copyright ownership.  The ASF licenses this file   *
- * to you under the Apache License, Version 2.0 (the            *
- * "License"); you may not use this file except in compliance   *
- * with the License.  You may obtain a copy of the License at   *
- *                                                              *
- *   http://www.apache.org/licenses/LICENSE-2.0                 *
- *                                                              *
- * Unless required by applicable law or agreed to in writing,   *
- * software distributed under the License is distributed on an  *
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
- * KIND, either express or implied.  See the License for the    *
- * specific language governing permissions and limitations      *
- * under the License.                                           *
- ****************************************************************/
-package org.apache.james.mailbox.spamassassin;
-
-import java.io.InputStream;
-import java.util.List;
-import java.util.stream.Stream;
-
-import javax.inject.Inject;
-
-import org.apache.james.core.Username;
-import org.apache.james.events.Event;
-import org.apache.james.events.Group;
-import org.apache.james.mailbox.MailboxManager;
-import org.apache.james.mailbox.MailboxSession;
-import org.apache.james.mailbox.Role;
-import org.apache.james.mailbox.SystemMailboxesProvider;
-import org.apache.james.mailbox.events.MailboxEvents.Added;
-import org.apache.james.mailbox.events.MessageMoveEvent;
-import org.apache.james.mailbox.exception.MailboxException;
-import org.apache.james.mailbox.model.Mailbox;
-import org.apache.james.mailbox.model.MailboxId;
-import org.apache.james.mailbox.model.MessageRange;
-import org.apache.james.mailbox.store.MailboxSessionMapperFactory;
-import org.apache.james.mailbox.store.event.SpamEventListener;
-import org.apache.james.mailbox.store.mail.MessageMapper;
-import org.apache.james.mailbox.store.mail.model.MailboxMessage;
-import org.apache.james.mailbox.store.mail.model.Message;
-import org.apache.james.util.streams.Iterators;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.github.fge.lambdas.Throwing;
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.collect.ImmutableList;
-
-public class SpamAssassinListener implements SpamEventListener {
-    public static class SpamAssassinListenerGroup extends Group {
-
-    }
-
-    private static final Logger LOGGER = LoggerFactory.getLogger(SpamAssassinListener.class);
-    private static final int LIMIT = 1;
-    private static final Group GROUP = new SpamAssassinListenerGroup();
-
-    private final SpamAssassin spamAssassin;
-    private final SystemMailboxesProvider systemMailboxesProvider;
-    private final MailboxManager mailboxManager;
-    private final MailboxSessionMapperFactory mapperFactory;
-    private final ExecutionMode executionMode;
-
-    @Inject
-    public SpamAssassinListener(SpamAssassin spamAssassin, SystemMailboxesProvider systemMailboxesProvider, MailboxManager mailboxManager, MailboxSessionMapperFactory mapperFactory, ExecutionMode executionMode) {
-        this.spamAssassin = spamAssassin;
-        this.systemMailboxesProvider = systemMailboxesProvider;
-        this.mailboxManager = mailboxManager;
-        this.mapperFactory = mapperFactory;
-        this.executionMode = executionMode;
-    }
-
-    @Override
-    public Group getDefaultGroup() {
-        return GROUP;
-    }
-
-    @Override
-    public ExecutionMode getExecutionMode() {
-        return executionMode;
-    }
-
-    @Override
-    public boolean isHandling(Event event) {
-        return event instanceof MessageMoveEvent || event instanceof Added;
-    }
-
-    @Override
-    public void event(Event event) throws MailboxException {
-        Username username = Username.of(getClass().getCanonicalName());
-        if (event instanceof MessageMoveEvent) {
-            MailboxSession session = mailboxManager.createSystemSession(username);
-            handleMessageMove(event, session, (MessageMoveEvent) event);
-        }
-        if (event instanceof Added) {
-            MailboxSession session = mailboxManager.createSystemSession(username);
-            handleAdded(event, session, (Added) event);
-        }
-    }
-
-    private void handleAdded(Event event, MailboxSession session, Added addedEvent) {
-        if (isAppendedToInbox(addedEvent)) {
-            Mailbox mailbox = mapperFactory.getMailboxMapper(session).findMailboxById(addedEvent.getMailboxId()).block();
-            MessageMapper messageMapper = mapperFactory.getMessageMapper(session);
-
-            List<InputStream> contents = MessageRange.toRanges(addedEvent.getUids())
-                .stream()
-                .flatMap(range -> retrieveMessages(messageMapper, mailbox, range))
-                .map(Throwing.function(MailboxMessage::getFullContent))
-                .collect(ImmutableList.toImmutableList());
-            spamAssassin.learnHam(contents, event.getUsername());
-        }
-    }
-
-    private void handleMessageMove(Event event, MailboxSession session, MessageMoveEvent messageMoveEvent) {
-        if (isMessageMovedToSpamMailbox(messageMoveEvent)) {
-            LOGGER.debug("Spam event detected");
-            ImmutableList<InputStream> messages = retrieveMessages(messageMoveEvent, session);
-            spamAssassin.learnSpam(messages, event.getUsername());
-        }
-        if (isMessageMovedOutOfSpamMailbox(messageMoveEvent)) {
-            ImmutableList<InputStream> messages = retrieveMessages(messageMoveEvent, session);
-            spamAssassin.learnHam(messages, event.getUsername());
-        }
-    }
-
-    private Stream<MailboxMessage> retrieveMessages(MessageMapper messageMapper, Mailbox mailbox, MessageRange range) {
-        try {
-            return Iterators.toStream(messageMapper.findInMailbox(mailbox, range, MessageMapper.FetchType.FULL, LIMIT));
-        } catch (MailboxException e) {
-            LOGGER.warn("Can not retrieve message {} {}", mailbox.getMailboxId(), range.toString(), e);
-            return Stream.empty();
-        }
-    }
-
-    private boolean isAppendedToInbox(Added addedEvent) {
-        try {
-            return systemMailboxesProvider.findMailbox(Role.INBOX, addedEvent.getUsername())
-                .getId().equals(addedEvent.getMailboxId());
-        } catch (MailboxException e) {
-            LOGGER.warn("Could not resolve Inbox mailbox", e);
-            return false;
-        }
-    }
-
-    private ImmutableList<InputStream> retrieveMessages(MessageMoveEvent messageMoveEvent, MailboxSession session) {
-        return mapperFactory.getMessageIdMapper(session)
-            .find(messageMoveEvent.getMessageIds(), MessageMapper.FetchType.FULL)
-            .stream()
-            .map(Throwing.function(Message::getFullContent))
-            .collect(ImmutableList.toImmutableList());
-    }
-
-    @VisibleForTesting
-    boolean isMessageMovedToSpamMailbox(MessageMoveEvent event) {
-        try {
-            MailboxId spamMailboxId = systemMailboxesProvider.findMailbox(Role.SPAM, event.getUsername()).getId();
-
-            return event.getMessageMoves().addedMailboxIds().contains(spamMailboxId);
-        } catch (MailboxException e) {
-            LOGGER.warn("Could not resolve Spam mailbox", e);
-            return false;
-        }
-    }
-
-    @VisibleForTesting
-    boolean isMessageMovedOutOfSpamMailbox(MessageMoveEvent event) {
-        try {
-            MailboxId spamMailboxId = systemMailboxesProvider.findMailbox(Role.SPAM, event.getUsername()).getId();
-            MailboxId trashMailboxId = systemMailboxesProvider.findMailbox(Role.TRASH, event.getUsername()).getId();
-
-            return event.getMessageMoves().removedMailboxIds().contains(spamMailboxId)
-                && !event.getMessageMoves().addedMailboxIds().contains(trashMailboxId);
-        } catch (MailboxException e) {
-            LOGGER.warn("Could not resolve Spam mailbox", e);
-            return false;
-        }
-    }
-}
diff --git a/mailbox/plugin/spamassassin/src/test/java/org/apache/james/mailbox/spamassassin/SpamAssassinConfigurationTest.java b/mailbox/plugin/spamassassin/src/test/java/org/apache/james/mailbox/spamassassin/SpamAssassinConfigurationTest.java
deleted file mode 100644
index c27f8f6be3..0000000000
--- a/mailbox/plugin/spamassassin/src/test/java/org/apache/james/mailbox/spamassassin/SpamAssassinConfigurationTest.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/****************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one   *
- * or more contributor license agreements.  See the NOTICE file *
- * distributed with this work for additional information        *
- * regarding copyright ownership.  The ASF licenses this file   *
- * to you under the Apache License, Version 2.0 (the            *
- * "License"); you may not use this file except in compliance   *
- * with the License.  You may obtain a copy of the License at   *
- *                                                              *
- *   http://www.apache.org/licenses/LICENSE-2.0                 *
- *                                                              *
- * Unless required by applicable law or agreed to in writing,   *
- * software distributed under the License is distributed on an  *
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
- * KIND, either express or implied.  See the License for the    *
- * specific language governing permissions and limitations      *
- * under the License.                                           *
- ****************************************************************/
-package org.apache.james.mailbox.spamassassin;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-import java.util.Optional;
-
-import org.apache.james.util.Host;
-import org.junit.jupiter.api.Test;
-
-import nl.jqno.equalsverifier.EqualsVerifier;
-
-class SpamAssassinConfigurationTest {
-
-    @Test
-    void spamAssassinConfigurationShouldRespectBeanContract() {
-        EqualsVerifier.forClass(SpamAssassinConfiguration.class)
-            .verify();
-    }
-
-    @Test
-    void isEnableShouldReturnFalseWhenEmpty() {
-        SpamAssassinConfiguration configuration = new SpamAssassinConfiguration(Optional.empty());
-        assertThat(configuration.isEnable()).isFalse();
-    }
-
-    @Test
-    void isEnableShouldReturnTrueWhenConfigured() {
-        int port = 1;
-        SpamAssassinConfiguration configuration = new SpamAssassinConfiguration(Optional.of(Host.from("hostname", port)));
-        assertThat(configuration.isEnable()).isTrue();
-    }
-}
diff --git a/mailbox/plugin/spamassassin/src/test/java/org/apache/james/mailbox/spamassassin/SpamAssassinListenerTest.java b/mailbox/plugin/spamassassin/src/test/java/org/apache/james/mailbox/spamassassin/SpamAssassinListenerTest.java
deleted file mode 100644
index 2c6d28a052..0000000000
--- a/mailbox/plugin/spamassassin/src/test/java/org/apache/james/mailbox/spamassassin/SpamAssassinListenerTest.java
+++ /dev/null
@@ -1,283 +0,0 @@
-/****************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one   *
- * or more contributor license agreements.  See the NOTICE file *
- * distributed with this work for additional information        *
- * regarding copyright ownership.  The ASF licenses this file   *
- * to you under the Apache License, Version 2.0 (the            *
- * "License"); you may not use this file except in compliance   *
- * with the License.  You may obtain a copy of the License at   *
- *                                                              *
- *   http://www.apache.org/licenses/LICENSE-2.0                 *
- *                                                              *
- * Unless required by applicable law or agreed to in writing,   *
- * software distributed under the License is distributed on an  *
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
- * KIND, either express or implied.  See the License for the    *
- * specific language governing permissions and limitations      *
- * under the License.                                           *
- ****************************************************************/
-package org.apache.james.mailbox.spamassassin;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.verifyNoMoreInteractions;
-import static org.mockito.Mockito.when;
-
-import java.nio.charset.StandardCharsets;
-import java.util.Date;
-
-import javax.mail.Flags;
-
-import org.apache.james.core.Username;
-import org.apache.james.events.EventListener;
-import org.apache.james.events.Group;
-import org.apache.james.mailbox.DefaultMailboxes;
-import org.apache.james.mailbox.MailboxSession;
-import org.apache.james.mailbox.MailboxSessionUtil;
-import org.apache.james.mailbox.events.MailboxEvents.Added;
-import org.apache.james.mailbox.events.MessageMoveEvent;
-import org.apache.james.mailbox.exception.MailboxException;
-import org.apache.james.mailbox.inmemory.manager.InMemoryIntegrationResources;
-import org.apache.james.mailbox.model.ByteContent;
-import org.apache.james.mailbox.model.Mailbox;
-import org.apache.james.mailbox.model.MailboxId;
-import org.apache.james.mailbox.model.MailboxPath;
-import org.apache.james.mailbox.model.MessageMetaData;
-import org.apache.james.mailbox.model.MessageMoves;
-import org.apache.james.mailbox.model.TestMessageId;
-import org.apache.james.mailbox.model.ThreadId;
-import org.apache.james.mailbox.model.UidValidity;
-import org.apache.james.mailbox.store.MailboxSessionMapperFactory;
-import org.apache.james.mailbox.store.StoreMailboxManager;
-import org.apache.james.mailbox.store.SystemMailboxesProviderImpl;
-import org.apache.james.mailbox.store.event.EventFactory;
-import org.apache.james.mailbox.store.mail.MailboxMapper;
-import org.apache.james.mailbox.store.mail.model.impl.PropertyBuilder;
-import org.apache.james.mailbox.store.mail.model.impl.SimpleMailboxMessage;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-
-class SpamAssassinListenerTest {
-    static final Username USER = Username.of("user");
-    static final MailboxSession MAILBOX_SESSION = MailboxSessionUtil.create(USER);
-    static final UidValidity UID_VALIDITY = UidValidity.of(43);
-    static final TestMessageId MESSAGE_ID = TestMessageId.of(45);
-    static final ThreadId THREAD_ID = ThreadId.fromBaseMessageId(MESSAGE_ID);
-
-    SpamAssassin spamAssassin;
-    SpamAssassinListener listener;
-    Mailbox inbox;
-    Mailbox mailbox1;
-    MailboxId mailboxId1;
-    MailboxId mailboxId2;
-    MailboxId spamMailboxId;
-    MailboxId spamCapitalMailboxId;
-    MailboxId trashMailboxId;
-    MailboxSessionMapperFactory mapperFactory;
-    Mailbox mailbox2;
-
-    @BeforeEach
-    void setup() throws Exception {
-        StoreMailboxManager mailboxManager = spy(InMemoryIntegrationResources.defaultResources().getMailboxManager());
-        SystemMailboxesProviderImpl systemMailboxesProvider = new SystemMailboxesProviderImpl(mailboxManager);
-        when(mailboxManager.createSystemSession(USER))
-            .thenReturn(MAILBOX_SESSION);
-
-        spamAssassin = mock(SpamAssassin.class);
-        mapperFactory = mailboxManager.getMapperFactory();
-        MailboxMapper mailboxMapper = mapperFactory.createMailboxMapper(MAILBOX_SESSION);
-        inbox = mailboxMapper.create(MailboxPath.forUser(USER, DefaultMailboxes.INBOX), UID_VALIDITY).block();
-        mailbox1 = mailboxMapper.create(MailboxPath.forUser(USER, "mailbox1"), UID_VALIDITY).block();
-        mailbox2 = mailboxMapper.create(MailboxPath.forUser(USER, "mailbox2"), UID_VALIDITY).block();
-        mailboxId1 = mailbox1.getMailboxId();
-        mailboxId2 = mailbox2.getMailboxId();
-        spamMailboxId = mailboxMapper.create(MailboxPath.forUser(USER, "Spam"), UID_VALIDITY).block().getMailboxId();
-        spamCapitalMailboxId = mailboxMapper.create(MailboxPath.forUser(USER, "SPAM"), UID_VALIDITY).block().getMailboxId();
-        trashMailboxId = mailboxMapper.create(MailboxPath.forUser(USER, "Trash"), UID_VALIDITY).block().getMailboxId();
-
-        listener = new SpamAssassinListener(spamAssassin, systemMailboxesProvider, mailboxManager, mapperFactory, EventListener.ExecutionMode.SYNCHRONOUS);
-    }
-
-    @Test
-    void deserializeSpamAssassinListenerGroup() throws Exception {
-        assertThat(Group.deserialize("org.apache.james.mailbox.spamassassin.SpamAssassinListener$SpamAssassinListenerGroup"))
-            .isEqualTo(new SpamAssassinListener.SpamAssassinListenerGroup());
-    }
-
-    @Test
-    void isEventOnSpamMailboxShouldReturnFalseWhenMessageIsMovedToANonSpamMailbox() {
-        MessageMoveEvent messageMoveEvent = MessageMoveEvent.builder()
-            .session(MAILBOX_SESSION)
-            .messageMoves(MessageMoves.builder()
-                .previousMailboxIds(mailboxId1)
-                .targetMailboxIds(mailboxId2)
-                .build())
-            .messageId(MESSAGE_ID)
-            .build();
-
-        assertThat(listener.isMessageMovedToSpamMailbox(messageMoveEvent)).isFalse();
-    }
-
-    @Test
-    void isEventOnSpamMailboxShouldReturnTrueWhenMailboxIsSpam() {
-        MessageMoveEvent messageMoveEvent = MessageMoveEvent.builder()
-            .session(MAILBOX_SESSION)
-            .messageMoves(MessageMoves.builder()
-                .previousMailboxIds(mailboxId1)
-                .targetMailboxIds(spamMailboxId)
-                .build())
-            .messageId(MESSAGE_ID)
-            .build();
-
-        assertThat(listener.isMessageMovedToSpamMailbox(messageMoveEvent)).isTrue();
-    }
-
-    @Test
-    void isEventOnSpamMailboxShouldReturnFalseWhenMailboxIsSpamOtherCase() {
-        MessageMoveEvent messageMoveEvent = MessageMoveEvent.builder()
-            .session(MAILBOX_SESSION)
-            .messageMoves(MessageMoves.builder()
-                .previousMailboxIds(mailboxId1)
-                .targetMailboxIds(spamCapitalMailboxId)
-                .build())
-            .messageId(MESSAGE_ID)
-            .build();
-
-        assertThat(listener.isMessageMovedToSpamMailbox(messageMoveEvent)).isFalse();
-    }
-
-    @Test
-    void eventShouldCallSpamAssassinSpamLearningWhenTheEventMatches() throws Exception {
-        MessageMoveEvent messageMoveEvent = MessageMoveEvent.builder()
-            .session(MAILBOX_SESSION)
-            .messageMoves(MessageMoves.builder()
-                .previousMailboxIds(mailboxId1)
-                .targetMailboxIds(spamMailboxId)
-                .build())
-            .messageId(MESSAGE_ID)
-            .build();
-
-        listener.event(messageMoveEvent);
-
-        verify(spamAssassin).learnSpam(any(), any());
-    }
-
-    @Test
-    void isMessageMovedOutOfSpamMailboxShouldReturnFalseWhenMessageMovedBetweenNonSpamMailboxes() {
-        MessageMoveEvent messageMoveEvent = MessageMoveEvent.builder()
-            .session(MAILBOX_SESSION)
-            .messageMoves(MessageMoves.builder()
-                .previousMailboxIds(mailboxId1)
-                .targetMailboxIds(mailboxId2)
-                .build())
-            .messageId(MESSAGE_ID)
-            .build();
-
-        assertThat(listener.isMessageMovedOutOfSpamMailbox(messageMoveEvent)).isFalse();
-    }
-
-    @Test
-    void isMessageMovedOutOfSpamMailboxShouldReturnFalseWhenMessageMovedOutOfCapitalSpamMailbox() {
-        MessageMoveEvent messageMoveEvent = MessageMoveEvent.builder()
-            .session(MAILBOX_SESSION)
-            .messageMoves(MessageMoves.builder()
-                .previousMailboxIds(spamCapitalMailboxId)
-                .targetMailboxIds(mailboxId2)
-                .build())
-            .messageId(MESSAGE_ID)
-            .build();
-
-        assertThat(listener.isMessageMovedOutOfSpamMailbox(messageMoveEvent)).isFalse();
-    }
-
-    @Test
-    void isMessageMovedOutOfSpamMailboxShouldReturnTrueWhenMessageMovedOutOfSpamMailbox() {
-        MessageMoveEvent messageMoveEvent = MessageMoveEvent.builder()
-            .session(MAILBOX_SESSION)
-            .messageMoves(MessageMoves.builder()
-                .previousMailboxIds(spamMailboxId)
-                .targetMailboxIds(mailboxId2)
-                .build())
-            .messageId(MESSAGE_ID)
-            .build();
-
-        assertThat(listener.isMessageMovedOutOfSpamMailbox(messageMoveEvent)).isTrue();
-    }
-
-    @Test
-    void isMessageMovedOutOfSpamMailboxShouldReturnFalseWhenMessageMovedToTrash() {
-        MessageMoveEvent messageMoveEvent = MessageMoveEvent.builder()
-            .session(MAILBOX_SESSION)
-            .messageMoves(MessageMoves.builder()
-                .previousMailboxIds(spamMailboxId)
-                .targetMailboxIds(trashMailboxId)
-                .build())
-            .messageId(MESSAGE_ID)
-            .build();
-
-        assertThat(listener.isMessageMovedOutOfSpamMailbox(messageMoveEvent)).isFalse();
-    }
-
-    @Test
-    void eventShouldCallSpamAssassinHamLearningWhenTheEventMatches() throws Exception {
-        MessageMoveEvent messageMoveEvent = MessageMoveEvent.builder()
-            .session(MAILBOX_SESSION)
-            .messageMoves(MessageMoves.builder()
-                .previousMailboxIds(spamMailboxId)
-                .targetMailboxIds(mailboxId1)
-                .build())
-            .messageId(MESSAGE_ID)
-            .build();
-
-        listener.event(messageMoveEvent);
-
-        verify(spamAssassin).learnHam(any(), any());
-    }
-
-    @Test
-    void eventShouldCallSpamAssassinHamLearningWhenTheMessageIsAddedInInbox() throws Exception {
-        SimpleMailboxMessage message = createMessage(inbox);
-
-        Added addedEvent = EventFactory.added()
-            .randomEventId()
-            .mailboxSession(MAILBOX_SESSION)
-            .mailbox(inbox)
-            .addMetaData(message.metaData())
-            .build();
-
-        listener.event(addedEvent);
-
-        verify(spamAssassin).learnHam(any(), any());
-    }
-
-    @Test
-    void eventShouldNotCallSpamAssassinHamLearningWhenTheMessageIsAddedInAMailboxOtherThanInbox() throws Exception {
-        SimpleMailboxMessage message = createMessage(mailbox1);
-
-        Added addedEvent = EventFactory.added()
-            .randomEventId()
-            .mailboxSession(MAILBOX_SESSION)
-            .mailbox(mailbox1)
-            .addMetaData(message.metaData())
-            .build();
-
-        listener.event(addedEvent);
-
-        verifyNoMoreInteractions(spamAssassin);
-    }
-
-    private SimpleMailboxMessage createMessage(Mailbox mailbox) throws MailboxException {
-        int size = 45;
-        int bodyStartOctet = 25;
-        byte[] content = "Subject: test\r\n\r\nBody\r\n".getBytes(StandardCharsets.UTF_8);
-        SimpleMailboxMessage message = new SimpleMailboxMessage(MESSAGE_ID, THREAD_ID, new Date(),
-            size, bodyStartOctet, new ByteContent(content), new Flags(), new PropertyBuilder().build(),
-            mailbox.getMailboxId());
-        MessageMetaData messageMetaData = mapperFactory.createMessageMapper(null).add(mailbox, message);
-        message.setUid(messageMetaData.getUid());
-        return message;
-    }
-}
diff --git a/mailbox/pom.xml b/mailbox/pom.xml
index 6e13a3750c..e97efc6f7e 100644
--- a/mailbox/pom.xml
+++ b/mailbox/pom.xml
@@ -58,8 +58,6 @@
         <module>plugin/quota-search-opensearch</module>
         <module>plugin/quota-search-scanning</module>
 
-        <module>plugin/spamassassin</module>
-
         <module>scanning-search</module>
         <module>spring</module>
         <module>store</module>
diff --git a/pom.xml b/pom.xml
index 1ab8ed330f..4667970ad5 100644
--- a/pom.xml
+++ b/pom.xml
@@ -945,17 +945,6 @@
                 <version>${project.version}</version>
                 <type>test-jar</type>
             </dependency>
-            <dependency>
-                <groupId>${james.groupId}</groupId>
-                <artifactId>apache-james-spamassassin</artifactId>
-                <version>${project.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>${james.groupId}</groupId>
-                <artifactId>apache-james-spamassassin</artifactId>
-                <version>${project.version}</version>
-                <type>test-jar</type>
-            </dependency>
             <dependency>
                 <groupId>${james.groupId}</groupId>
                 <artifactId>apache-jsieve-core</artifactId>
diff --git a/server/apps/cassandra-app/pom.xml b/server/apps/cassandra-app/pom.xml
index c0bc26048c..d4d09c3739 100644
--- a/server/apps/cassandra-app/pom.xml
+++ b/server/apps/cassandra-app/pom.xml
@@ -82,12 +82,6 @@
             <type>test-jar</type>
             <scope>test</scope>
         </dependency>
-        <dependency>
-            <groupId>${james.groupId}</groupId>
-            <artifactId>apache-james-spamassassin</artifactId>
-            <type>test-jar</type>
-            <scope>test</scope>
-        </dependency>
         <dependency>
             <groupId>${james.groupId}</groupId>
             <artifactId>apache-mailet-icalendar</artifactId>
@@ -173,10 +167,6 @@
             <groupId>${james.groupId}</groupId>
             <artifactId>james-server-guice-mailbox</artifactId>
         </dependency>
-        <dependency>
-            <groupId>${james.groupId}</groupId>
-            <artifactId>james-server-guice-mailbox-plugin-spamassassin</artifactId>
-        </dependency>
         <dependency>
             <groupId>${james.groupId}</groupId>
             <artifactId>james-server-guice-mailet</artifactId>
diff --git a/server/apps/cassandra-app/src/main/java/org/apache/james/CassandraJamesServerMain.java b/server/apps/cassandra-app/src/main/java/org/apache/james/CassandraJamesServerMain.java
index 83968df30a..b16dd4a273 100644
--- a/server/apps/cassandra-app/src/main/java/org/apache/james/CassandraJamesServerMain.java
+++ b/server/apps/cassandra-app/src/main/java/org/apache/james/CassandraJamesServerMain.java
@@ -73,7 +73,6 @@ import org.apache.james.modules.server.VacationRoutesModule;
 import org.apache.james.modules.server.WebAdminMailOverWebModule;
 import org.apache.james.modules.server.WebAdminReIndexingTaskSerializationModule;
 import org.apache.james.modules.server.WebAdminServerModule;
-import org.apache.james.modules.spamassassin.SpamAssassinListenerModule;
 import org.apache.james.modules.vault.DeletedMessageVaultRoutesModule;
 import org.apache.james.modules.webadmin.CassandraRoutesModule;
 import org.apache.james.modules.webadmin.InconsistencySolvingRoutesModule;
@@ -155,8 +154,7 @@ public class CassandraJamesServerMain implements JamesServerMain {
         new CassandraMailboxModule(),
         new CassandraDeletedMessageVaultModule(),
         new MailboxModule(),
-        new TikaMailboxModule(),
-        new SpamAssassinListenerModule());
+        new TikaMailboxModule());
 
     public static final Module REQUIRE_TASK_MANAGER_MODULE = Modules.combine(
         CASSANDRA_SERVER_CORE_MODULE,
diff --git a/server/apps/distributed-app/pom.xml b/server/apps/distributed-app/pom.xml
index c79d46c1cb..61724111cc 100644
--- a/server/apps/distributed-app/pom.xml
+++ b/server/apps/distributed-app/pom.xml
@@ -202,10 +202,6 @@
             <groupId>${james.groupId}</groupId>
             <artifactId>james-server-guice-mailbox</artifactId>
         </dependency>
-        <dependency>
-            <groupId>${james.groupId}</groupId>
-            <artifactId>james-server-guice-mailbox-plugin-spamassassin</artifactId>
-        </dependency>
         <dependency>
             <groupId>${james.groupId}</groupId>
             <artifactId>james-server-guice-mailet</artifactId>
diff --git a/server/apps/distributed-app/src/main/java/org/apache/james/CassandraRabbitMQJamesServerMain.java b/server/apps/distributed-app/src/main/java/org/apache/james/CassandraRabbitMQJamesServerMain.java
index fc59322be8..7df5da7563 100644
--- a/server/apps/distributed-app/src/main/java/org/apache/james/CassandraRabbitMQJamesServerMain.java
+++ b/server/apps/distributed-app/src/main/java/org/apache/james/CassandraRabbitMQJamesServerMain.java
@@ -80,7 +80,6 @@ import org.apache.james.modules.server.VacationRoutesModule;
 import org.apache.james.modules.server.WebAdminMailOverWebModule;
 import org.apache.james.modules.server.WebAdminReIndexingTaskSerializationModule;
 import org.apache.james.modules.server.WebAdminServerModule;
-import org.apache.james.modules.spamassassin.SpamAssassinListenerModule;
 import org.apache.james.modules.vault.DeletedMessageVaultRoutesModule;
 import org.apache.james.modules.webadmin.CassandraRoutesModule;
 import org.apache.james.modules.webadmin.InconsistencySolvingRoutesModule;
@@ -151,8 +150,7 @@ public class CassandraRabbitMQJamesServerMain implements JamesServerMain {
         new CassandraMailboxModule(),
         new CassandraDeletedMessageVaultModule(),
         new MailboxModule(),
-        new TikaMailboxModule(),
-        new SpamAssassinListenerModule());
+        new TikaMailboxModule());
 
     public static final Module REQUIRE_TASK_MANAGER_MODULE = Modules.combine(
         new MailetProcessingModule(),
diff --git a/server/apps/distributed-pop3-app/pom.xml b/server/apps/distributed-pop3-app/pom.xml
index b5a54d9acf..1da2c13403 100644
--- a/server/apps/distributed-pop3-app/pom.xml
+++ b/server/apps/distributed-pop3-app/pom.xml
@@ -205,10 +205,6 @@
             <groupId>${james.groupId}</groupId>
             <artifactId>james-server-guice-mailbox</artifactId>
         </dependency>
-        <dependency>
-            <groupId>${james.groupId}</groupId>
-            <artifactId>james-server-guice-mailbox-plugin-spamassassin</artifactId>
-        </dependency>
         <dependency>
             <groupId>${james.groupId}</groupId>
             <artifactId>james-server-guice-mailet</artifactId>
diff --git a/server/apps/jpa-app/pom.xml b/server/apps/jpa-app/pom.xml
index f89fea971f..3d0de60627 100644
--- a/server/apps/jpa-app/pom.xml
+++ b/server/apps/jpa-app/pom.xml
@@ -120,10 +120,6 @@
             <groupId>${james.groupId}</groupId>
             <artifactId>james-server-guice-mailbox-jpa</artifactId>
         </dependency>
-        <dependency>
-            <groupId>${james.groupId}</groupId>
-            <artifactId>james-server-guice-mailbox-plugin-spamassassin</artifactId>
-        </dependency>
         <dependency>
             <groupId>${james.groupId}</groupId>
             <artifactId>james-server-guice-managedsieve</artifactId>
diff --git a/server/apps/jpa-app/src/main/java/org/apache/james/JPAJamesServerMain.java b/server/apps/jpa-app/src/main/java/org/apache/james/JPAJamesServerMain.java
index b0faa37247..c1dcdf341b 100644
--- a/server/apps/jpa-app/src/main/java/org/apache/james/JPAJamesServerMain.java
+++ b/server/apps/jpa-app/src/main/java/org/apache/james/JPAJamesServerMain.java
@@ -51,7 +51,6 @@ import org.apache.james.modules.server.SieveRoutesModule;
 import org.apache.james.modules.server.TaskManagerModule;
 import org.apache.james.modules.server.WebAdminReIndexingTaskSerializationModule;
 import org.apache.james.modules.server.WebAdminServerModule;
-import org.apache.james.modules.spamassassin.SpamAssassinListenerModule;
 
 import com.google.inject.Module;
 import com.google.inject.util.Modules;
@@ -91,8 +90,7 @@ public class JPAJamesServerMain implements JamesServerMain {
         new SieveJPARepositoryModules(),
         new DefaultEventModule(),
         new TaskManagerModule(),
-        new MemoryDeadLetterModule(),
-        new SpamAssassinListenerModule());
+        new MemoryDeadLetterModule());
 
     private static final Module JPA_MODULE_AGGREGATE = Modules.combine(
         new MailetProcessingModule(), JPA_SERVER_MODULE, PROTOCOLS);
diff --git a/server/apps/memory-app/pom.xml b/server/apps/memory-app/pom.xml
index e1eedc5e38..815b398dff 100644
--- a/server/apps/memory-app/pom.xml
+++ b/server/apps/memory-app/pom.xml
@@ -106,10 +106,6 @@
             <groupId>${james.groupId}</groupId>
             <artifactId>james-server-guice-mailbox</artifactId>
         </dependency>
-        <dependency>
-            <groupId>${james.groupId}</groupId>
-            <artifactId>james-server-guice-mailbox-plugin-spamassassin</artifactId>
-        </dependency>
         <dependency>
             <groupId>${james.groupId}</groupId>
             <artifactId>james-server-guice-mailet</artifactId>
diff --git a/server/apps/memory-app/src/main/java/org/apache/james/MemoryJamesServerMain.java b/server/apps/memory-app/src/main/java/org/apache/james/MemoryJamesServerMain.java
index 6e61da65ef..b9de867c7c 100644
--- a/server/apps/memory-app/src/main/java/org/apache/james/MemoryJamesServerMain.java
+++ b/server/apps/memory-app/src/main/java/org/apache/james/MemoryJamesServerMain.java
@@ -57,7 +57,6 @@ import org.apache.james.modules.server.SieveRoutesModule;
 import org.apache.james.modules.server.TaskManagerModule;
 import org.apache.james.modules.server.VacationRoutesModule;
 import org.apache.james.modules.server.WebAdminServerModule;
-import org.apache.james.modules.spamassassin.SpamAssassinListenerModule;
 import org.apache.james.modules.vault.DeletedMessageVaultModule;
 import org.apache.james.modules.vault.DeletedMessageVaultRoutesModule;
 import org.apache.james.webadmin.WebAdminConfiguration;
@@ -97,8 +96,7 @@ public class MemoryJamesServerMain implements JamesServerMain {
         new ManageSieveServerModule(),
         new POP3ServerModule(),
         new ProtocolHandlerModule(),
-        new SMTPServerModule(),
-        new SpamAssassinListenerModule());
+        new SMTPServerModule());
 
     public static final Module JMAP = Modules.combine(
         new JmapEventBusModule(),
diff --git a/server/apps/memory-app/src/test/resources/mailetcontainer.xml b/server/apps/memory-app/src/test/resources/mailetcontainer.xml
index e597fbe8b3..71c532db77 100644
--- a/server/apps/memory-app/src/test/resources/mailetcontainer.xml
+++ b/server/apps/memory-app/src/test/resources/mailetcontainer.xml
@@ -98,14 +98,6 @@
         </processor>
 
         <processor state="local-delivery" enableJmx="true">
-            <mailet match="All" class="SpamAssassin">
-                <spamdHost>localhost</spamdHost>
-                <spamdPort>783</spamdPort>
-                <onMailetException>ignore</onMailetException>
-            </mailet>
-            <mailet match="IsMarkedAsSpam" class="WithStorageDirective">
-                <targetFolderName>Spam</targetFolderName>
-            </mailet>
             <mailet match="All" class="VacationMailet">
                 <onMailetException>ignore</onMailetException>
             </mailet>
diff --git a/server/container/guice/mailbox-plugin-spamassassin/pom.xml b/server/container/guice/mailbox-plugin-spamassassin/pom.xml
deleted file mode 100644
index 954634116c..0000000000
--- a/server/container/guice/mailbox-plugin-spamassassin/pom.xml
+++ /dev/null
@@ -1,66 +0,0 @@
-<?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</groupId>
-        <artifactId>james-server-guice</artifactId>
-        <version>3.8.0-SNAPSHOT</version>
-        <relativePath>../pom.xml</relativePath>
-    </parent>
-
-    <artifactId>james-server-guice-mailbox-plugin-spamassassin</artifactId>
-
-    <name>Apache James :: Server :: Guice :: Mailbox :: Plugin :: SpamAssassin</name>
-    <description>Mailbox modules for Guice implementation of James server</description>
-
-    <dependencies>
-        <dependency>
-            <groupId>${james.groupId}</groupId>
-            <artifactId>apache-james-mailbox-spamassassin</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>${james.groupId}</groupId>
-            <artifactId>james-server-guice-configuration</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>${james.groupId}</groupId>
-            <artifactId>testing-base</artifactId>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>com.google.inject</groupId>
-            <artifactId>guice</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.commons</groupId>
-            <artifactId>commons-configuration2</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.slf4j</groupId>
-            <artifactId>jcl-over-slf4j</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.slf4j</groupId>
-            <artifactId>log4j-over-slf4j</artifactId>
-        </dependency>
-    </dependencies>
-
-</project>
diff --git a/server/container/guice/mailbox-plugin-spamassassin/src/main/java/org/apache/james/modules/spamassassin/SpamAssassinConfigurationLoader.java b/server/container/guice/mailbox-plugin-spamassassin/src/main/java/org/apache/james/modules/spamassassin/SpamAssassinConfigurationLoader.java
deleted file mode 100644
index 17d9d9f12b..0000000000
--- a/server/container/guice/mailbox-plugin-spamassassin/src/main/java/org/apache/james/modules/spamassassin/SpamAssassinConfigurationLoader.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/****************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one   *
- * or more contributor license agreements.  See the NOTICE file *
- * distributed with this work for additional information        *
- * regarding copyright ownership.  The ASF licenses this file   *
- * to you under the Apache License, Version 2.0 (the            *
- * "License"); you may not use this file except in compliance   *
- * with the License.  You may obtain a copy of the License at   *
- *                                                              *
- *   http://www.apache.org/licenses/LICENSE-2.0                 *
- *                                                              *
- * Unless required by applicable law or agreed to in writing,   *
- * software distributed under the License is distributed on an  *
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
- * KIND, either express or implied.  See the License for the    *
- * specific language governing permissions and limitations      *
- * under the License.                                           *
- ****************************************************************/
-
-package org.apache.james.modules.spamassassin;
-
-import java.util.Optional;
-
-import org.apache.commons.configuration2.Configuration;
-import org.apache.james.mailbox.spamassassin.SpamAssassinConfiguration;
-import org.apache.james.util.Host;
-
-public class SpamAssassinConfigurationLoader {
-
-    private static final String SPAMASSASSIN_HOST = "spamassassin.host";
-    private static final String SPAMASSASSIN_PORT = "spamassassin.port";
-    public static final String DEFAULT_HOST = "127.0.0.1";
-    public static final int DEFAULT_PORT = 783;
-
-    public static SpamAssassinConfiguration disable() {
-        return new SpamAssassinConfiguration(Optional.empty());
-    }
-
-    public static SpamAssassinConfiguration fromProperties(Configuration configuration) {
-        Host host = getHost(configuration);
-        return new SpamAssassinConfiguration(Optional.of(host));
-    }
-
-    private static Host getHost(Configuration propertiesReader) {
-        return Host.from(propertiesReader.getString(SPAMASSASSIN_HOST, DEFAULT_HOST), 
-                propertiesReader.getInteger(SPAMASSASSIN_PORT, DEFAULT_PORT));
-    }
-}
diff --git a/server/container/guice/mailbox-plugin-spamassassin/src/main/java/org/apache/james/modules/spamassassin/SpamAssassinListenerModule.java b/server/container/guice/mailbox-plugin-spamassassin/src/main/java/org/apache/james/modules/spamassassin/SpamAssassinListenerModule.java
deleted file mode 100644
index 06e18b3d73..0000000000
--- a/server/container/guice/mailbox-plugin-spamassassin/src/main/java/org/apache/james/modules/spamassassin/SpamAssassinListenerModule.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/****************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one   *
- * or more contributor license agreements.  See the NOTICE file *
- * distributed with this work for additional information        *
- * regarding copyright ownership.  The ASF licenses this file   *
- * to you under the Apache License, Version 2.0 (the            *
- * "License"); you may not use this file except in compliance   *
- * with the License.  You may obtain a copy of the License at   *
- *                                                              *
- *   http://www.apache.org/licenses/LICENSE-2.0                 *
- *                                                              *
- * Unless required by applicable law or agreed to in writing,   *
- * software distributed under the License is distributed on an  *
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
- * KIND, either express or implied.  See the License for the    *
- * specific language governing permissions and limitations      *
- * under the License.                                           *
- ****************************************************************/
-
-package org.apache.james.modules.spamassassin;
-
-import java.io.FileNotFoundException;
-
-import javax.inject.Singleton;
-
-import org.apache.commons.configuration2.Configuration;
-import org.apache.commons.configuration2.ex.ConfigurationException;
-import org.apache.james.mailbox.spamassassin.SpamAssassinConfiguration;
-import org.apache.james.utils.PropertiesProvider;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.google.inject.AbstractModule;
-import com.google.inject.Provides;
-
-public class SpamAssassinListenerModule extends AbstractModule {
-    private static final Logger LOGGER = LoggerFactory.getLogger(SpamAssassinListenerModule.class);
-
-    public static final String SPAMASSASSIN_CONFIGURATION_NAME = "spamassassin";
-
-    @Override
-    protected void configure() {
-
-    }
-
-    @Provides
-    @Singleton
-    private SpamAssassinConfiguration getSpamAssassinConfiguration(PropertiesProvider propertiesProvider) throws ConfigurationException {
-        try {
-            Configuration configuration = propertiesProvider.getConfiguration(SPAMASSASSIN_CONFIGURATION_NAME);
-            return SpamAssassinConfigurationLoader.fromProperties(configuration);
-        } catch (FileNotFoundException e) {
-            LOGGER.warn("Could not find " + SPAMASSASSIN_CONFIGURATION_NAME + " configuration file. Disabling this service.");
-            return SpamAssassinConfigurationLoader.disable();
-        }
-    }
-
-}
diff --git a/server/container/guice/mailbox-plugin-spamassassin/src/test/java/org/apache/james/modules/spamassassin/SpamAssassinConfigurationLoaderTest.java b/server/container/guice/mailbox-plugin-spamassassin/src/test/java/org/apache/james/modules/spamassassin/SpamAssassinConfigurationLoaderTest.java
deleted file mode 100644
index 7c056b1171..0000000000
--- a/server/container/guice/mailbox-plugin-spamassassin/src/test/java/org/apache/james/modules/spamassassin/SpamAssassinConfigurationLoaderTest.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/****************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one   *
- * or more contributor license agreements.  See the NOTICE file *
- * distributed with this work for additional information        *
- * regarding copyright ownership.  The ASF licenses this file   *
- * to you under the Apache License, Version 2.0 (the            *
- * "License"); you may not use this file except in compliance   *
- * with the License.  You may obtain a copy of the License at   *
- *                                                              *
- *   http://www.apache.org/licenses/LICENSE-2.0                 *
- *                                                              *
- * Unless required by applicable law or agreed to in writing,   *
- * software distributed under the License is distributed on an  *
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
- * KIND, either express or implied.  See the License for the    *
- * specific language governing permissions and limitations      *
- * under the License.                                           *
- ****************************************************************/
-package org.apache.james.modules.spamassassin;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-import org.apache.commons.configuration2.PropertiesConfiguration;
-import org.apache.james.mailbox.spamassassin.SpamAssassinConfiguration;
-import org.apache.james.util.Host;
-import org.junit.jupiter.api.Test;
-
-public class SpamAssassinConfigurationLoaderTest {
-    @Test
-    void isEnableShouldReturnFalseWhenDisable() {
-        SpamAssassinConfiguration configuration = SpamAssassinConfigurationLoader.disable();
-        assertThat(configuration.isEnable()).isFalse();
-    }
-
-    @Test
-    void isEnableShouldReturnTrueWhenEnable() {
-        SpamAssassinConfiguration configuration = SpamAssassinConfigurationLoader.fromProperties(new PropertiesConfiguration());
-        assertThat(configuration.isEnable()).isTrue();
-    }
-
-    @Test
-    void hostShouldReturnDefaultWhenConfigurationIsEmpty() {
-        SpamAssassinConfiguration configuration = SpamAssassinConfigurationLoader.fromProperties(new PropertiesConfiguration());
-        assertThat(configuration.getHost().get()).isEqualTo(Host.from(SpamAssassinConfigurationLoader.DEFAULT_HOST, SpamAssassinConfigurationLoader.DEFAULT_PORT));
-    }
-
-    @Test
-    void hostShouldReturnCustomWhenConfigurationIsProvided() {
-        PropertiesConfiguration propertiesConfiguration = new PropertiesConfiguration();
-        String host = "10.69.1.123";
-        propertiesConfiguration.addProperty("spamassassin.host", host);
-        int port = 1783;
-        propertiesConfiguration.addProperty("spamassassin.port", port);
-
-        SpamAssassinConfiguration configuration = SpamAssassinConfigurationLoader.fromProperties(propertiesConfiguration);
-        assertThat(configuration.getHost().get()).isEqualTo(Host.from(host, port));
-    }
-}
diff --git a/server/container/guice/pom.xml b/server/container/guice/pom.xml
index 4a04395634..d689d99ad0 100644
--- a/server/container/guice/pom.xml
+++ b/server/container/guice/pom.xml
@@ -51,7 +51,6 @@
         <module>mailbox</module>
         <module>mailbox-jpa</module>
         <module>mailbox-plugin-deleted-messages-vault</module>
-        <module>mailbox-plugin-spamassassin</module>
         <module>mailet</module>
         <module>mailrepository-cassandra</module>
         <module>memory</module>
@@ -160,11 +159,6 @@
                 <artifactId>james-server-guice-mailbox-jpa</artifactId>
                 <version>${project.version}</version>
             </dependency>
-            <dependency>
-                <groupId>${james.groupId}</groupId>
-                <artifactId>james-server-guice-mailbox-plugin-spamassassin</artifactId>
-                <version>${project.version}</version>
-            </dependency>
             <dependency>
                 <groupId>${james.groupId}</groupId>
                 <artifactId>james-server-guice-mailet</artifactId>
diff --git a/server/mailet/integration-testing/src/test/java/org/apache/james/transport/mailets/SpamAssassinIntegrationTest.java b/server/mailet/integration-testing/src/test/java/org/apache/james/transport/mailets/SpamAssassinIntegrationTest.java
deleted file mode 100644
index 5592ee5a66..0000000000
--- a/server/mailet/integration-testing/src/test/java/org/apache/james/transport/mailets/SpamAssassinIntegrationTest.java
+++ /dev/null
@@ -1,195 +0,0 @@
-/****************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one   *
- * or more contributor license agreements.  See the NOTICE file *
- * distributed with this work for additional information        *
- * regarding copyright ownership.  The ASF licenses this file   *
- * to you under the Apache License, Version 2.0 (the            *
- * "License"); you may not use this file except in compliance   *
- * with the License.  You may obtain a copy of the License at   *
- *                                                              *
- *   http://www.apache.org/licenses/LICENSE-2.0                 *
- *                                                              *
- * Unless required by applicable law or agreed to in writing,   *
- * software distributed under the License is distributed on an  *
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
- * KIND, either express or implied.  See the License for the    *
- * specific language governing permissions and limitations      *
- * under the License.                                           *
- ****************************************************************/
-package org.apache.james.transport.mailets;
-
-import static org.apache.james.MemoryJamesServerMain.SMTP_AND_IMAP_MODULE;
-import static org.apache.james.mailets.configuration.Constants.DEFAULT_DOMAIN;
-import static org.apache.james.mailets.configuration.Constants.FROM;
-import static org.apache.james.mailets.configuration.Constants.LOCALHOST_IP;
-import static org.apache.james.mailets.configuration.Constants.PASSWORD;
-import static org.apache.james.mailets.configuration.Constants.RECIPIENT;
-import static org.apache.james.mailets.configuration.Constants.RECIPIENT2;
-import static org.apache.james.mailets.configuration.Constants.awaitAtMostOneMinute;
-import static org.assertj.core.api.Assertions.assertThat;
-
-import java.io.File;
-import java.util.UUID;
-
-import javax.mail.MessagingException;
-
-import org.apache.james.core.builder.MimeMessageBuilder;
-import org.apache.james.mailets.TemporaryJamesServer;
-import org.apache.james.mailets.configuration.CommonProcessors;
-import org.apache.james.mailets.configuration.MailetConfiguration;
-import org.apache.james.mailets.configuration.MailetContainer;
-import org.apache.james.mailets.configuration.ProcessorConfiguration;
-import org.apache.james.modules.protocols.ImapGuiceProbe;
-import org.apache.james.modules.protocols.SmtpGuiceProbe;
-import org.apache.james.spamassassin.SpamAssassinResult;
-import org.apache.james.transport.matchers.All;
-import org.apache.james.util.docker.DockerContainer;
-import org.apache.james.util.docker.Images;
-import org.apache.james.util.docker.RateLimiters;
-import org.apache.james.utils.DataProbeImpl;
-import org.apache.james.utils.SMTPMessageSender;
-import org.apache.james.utils.TestIMAPClient;
-import org.apache.mailet.base.test.FakeMail;
-import org.junit.jupiter.api.AfterEach;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.extension.RegisterExtension;
-import org.junit.jupiter.api.io.TempDir;
-import org.testcontainers.containers.wait.strategy.HostPortWaitStrategy;
-
-class SpamAssassinIntegrationTest {
-    private static final String SPAM_CONTENT = "XJS*C4JDBQADN1.NSBN3*2IDNEN*GTUBE-STANDARD-ANTI-UBE-TEST-EMAIL*C.34X";
-
-    @RegisterExtension
-    public static DockerContainer spamAssassinContainer = DockerContainer.fromName(Images.SPAMASSASSIN)
-        .withExposedPorts(783)
-        .withAffinityToContainer()
-        .waitingFor(new HostPortWaitStrategy().withRateLimiter(RateLimiters.TWENTIES_PER_SECOND))
-        .withName("james-testing-spamassassin-" + UUID.randomUUID());
-
-    @RegisterExtension
-    public TestIMAPClient messageReader = new TestIMAPClient();
-    @RegisterExtension
-    public SMTPMessageSender messageSender = new SMTPMessageSender(DEFAULT_DOMAIN);
-
-    private TemporaryJamesServer jamesServer;
-
-    @BeforeEach
-    void setup(@TempDir File temporaryFolder) throws Exception {
-        MailetContainer.Builder mailets = TemporaryJamesServer.defaultMailetContainerConfiguration()
-            .putProcessor(
-                ProcessorConfiguration.transport()
-                    .addMailet(MailetConfiguration.builder()
-                        .matcher(All.class)
-                        .mailet(SpamAssassin.class)
-                        .addProperty(SpamAssassin.SPAMD_HOST, spamAssassinContainer.getContainerIp()))
-                    .addMailetsFrom(CommonProcessors.deliverOnlyTransport()));
-
-        jamesServer = TemporaryJamesServer.builder()
-            .withBase(SMTP_AND_IMAP_MODULE)
-            .withMailetContainer(mailets)
-            .build(temporaryFolder);
-        jamesServer.start();
-
-        jamesServer.getProbe(DataProbeImpl.class)
-            .fluent()
-            .addDomain(DEFAULT_DOMAIN)
-            .addUser(FROM, PASSWORD)
-            .addUser(RECIPIENT, PASSWORD)
-            .addUser(RECIPIENT2, PASSWORD);
-    }
-
-    @AfterEach
-    void tearDown() {
-        jamesServer.shutdown();
-    }
-
-    @Test
-    void spamAssassinShouldAppendNewHeaderOnMessage() throws Exception {
-        messageSender.connect(LOCALHOST_IP, jamesServer.getProbe(SmtpGuiceProbe.class).getSmtpPort())
-            .authenticate(FROM, PASSWORD)
-            .sendMessage(mailWithContent("This is the content", RECIPIENT));
-
-        messageReader.connect(LOCALHOST_IP, jamesServer.getProbe(ImapGuiceProbe.class).getImapPort())
-            .login(RECIPIENT, PASSWORD)
-            .select(TestIMAPClient.INBOX)
-            .awaitMessage(awaitAtMostOneMinute);
-
-        assertThat(messageReader.readFirstMessageHeaders())
-            .contains(
-                SpamAssassinResult.FLAG_MAIL.asString(),
-                SpamAssassinResult.STATUS_MAIL.asString());
-    }
-
-    @Test
-    void spamAssassinShouldAppendNewHeaderWhichDetectIsSpamWhenSpamMessage() throws Exception {
-        messageSender.connect(LOCALHOST_IP, jamesServer.getProbe(SmtpGuiceProbe.class).getSmtpPort())
-            .authenticate(FROM, PASSWORD)
-            .sendMessage(mailWithContent(SPAM_CONTENT, RECIPIENT));
-
-        messageReader.connect(LOCALHOST_IP, jamesServer.getProbe(ImapGuiceProbe.class).getImapPort())
-            .login(RECIPIENT, PASSWORD)
-            .select(TestIMAPClient.INBOX)
-            .awaitMessage(awaitAtMostOneMinute);
-
-        String receivedHeaders = messageReader.readFirstMessageHeaders();
-        assertThat(receivedHeaders).contains(SpamAssassinResult.FLAG_MAIL.asString() + ": YES");
-        assertThat(receivedHeaders).contains(SpamAssassinResult.STATUS_MAIL.asString() + ": Yes");
-    }
-
-    @Test
-    void spamAssassinShouldAppendNewHeaderWhichNoWhenNonSpamMessage() throws Exception {
-        messageSender.connect(LOCALHOST_IP, jamesServer.getProbe(SmtpGuiceProbe.class).getSmtpPort())
-            .authenticate(FROM, PASSWORD)
-            .sendMessage(mailWithContent("This is the content", RECIPIENT));
-
-        messageReader.connect(LOCALHOST_IP, jamesServer.getProbe(ImapGuiceProbe.class).getImapPort())
-            .login(RECIPIENT, PASSWORD)
-            .select(TestIMAPClient.INBOX)
-            .awaitMessage(awaitAtMostOneMinute);
-
-        String receivedHeaders = messageReader.readFirstMessageHeaders();
-        assertThat(receivedHeaders).contains(SpamAssassinResult.FLAG_MAIL.asString() + ": NO");
-        assertThat(receivedHeaders).contains(SpamAssassinResult.STATUS_MAIL.asString() + ": No");
-    }
-
-    @Test
-    void spamAssassinShouldAppendNewHeaderPerRecipientOnMessage() throws Exception {
-        messageSender.connect(LOCALHOST_IP, jamesServer.getProbe(SmtpGuiceProbe.class).getSmtpPort())
-            .authenticate(FROM, PASSWORD)
-            .sendMessage(mailWithContent("This is the content", RECIPIENT, RECIPIENT2));
-
-        messageReader.connect(LOCALHOST_IP, jamesServer.getProbe(ImapGuiceProbe.class).getImapPort())
-            .login(RECIPIENT, PASSWORD)
-            .select(TestIMAPClient.INBOX)
-            .awaitMessage(awaitAtMostOneMinute);
-
-        assertThat(messageReader.readFirstMessageHeaders())
-            .contains(
-                SpamAssassinResult.FLAG_MAIL.asString(),
-                SpamAssassinResult.STATUS_MAIL.asString());
-
-        messageReader.disconnect()
-            .connect(LOCALHOST_IP, jamesServer.getProbe(ImapGuiceProbe.class).getImapPort())
-            .login(RECIPIENT2, PASSWORD)
-            .select(TestIMAPClient.INBOX)
-            .awaitMessage(awaitAtMostOneMinute);
-
-        assertThat(messageReader.readFirstMessageHeaders())
-            .contains(
-                SpamAssassinResult.FLAG_MAIL.asString(),
-                SpamAssassinResult.STATUS_MAIL.asString());
-    }
-
-    private FakeMail.Builder mailWithContent(String textContent, String... recipients) throws MessagingException {
-        return FakeMail.builder()
-            .name("name")
-            .mimeMessage(MimeMessageBuilder.mimeMessageBuilder()
-                .setSender(FROM)
-                .addToRecipient(recipients)
-                .setSubject("This is the subject")
-                .setText(textContent))
-            .sender(FROM)
-            .recipients(recipients);
-    }
-}
diff --git a/server/mailet/mailets/pom.xml b/server/mailet/mailets/pom.xml
index 4d81187ce9..9126e4e94a 100644
--- a/server/mailet/mailets/pom.xml
+++ b/server/mailet/mailets/pom.xml
@@ -63,16 +63,6 @@
             <artifactId>apache-james-mailbox-store</artifactId>
             <scope>test</scope>
         </dependency>
-        <dependency>
-            <groupId>${james.groupId}</groupId>
-            <artifactId>apache-james-spamassassin</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>${james.groupId}</groupId>
-            <artifactId>apache-james-spamassassin</artifactId>
-            <type>test-jar</type>
-            <scope>test</scope>
-        </dependency>
         <dependency>
             <groupId>${james.groupId}</groupId>
             <artifactId>apache-mailet-api</artifactId>
diff --git a/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/SpamAssassin.java b/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/SpamAssassin.java
deleted file mode 100644
index 00b561766e..0000000000
--- a/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/SpamAssassin.java
+++ /dev/null
@@ -1,136 +0,0 @@
-/****************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one   *
- * or more contributor license agreements.  See the NOTICE file *
- * distributed with this work for additional information        *
- * regarding copyright ownership.  The ASF licenses this file   *
- * to you under the Apache License, Version 2.0 (the            *
- * "License"); you may not use this file except in compliance   *
- * with the License.  You may obtain a copy of the License at   *
- *                                                              *
- *   http://www.apache.org/licenses/LICENSE-2.0                 *
- *                                                              *
- * Unless required by applicable law or agreed to in writing,   *
- * software distributed under the License is distributed on an  *
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
- * KIND, either express or implied.  See the License for the    *
- * specific language governing permissions and limitations      *
- * under the License.                                           *
- ****************************************************************/
-
-package org.apache.james.transport.mailets;
-
-import java.util.Optional;
-import java.util.function.Predicate;
-
-import javax.inject.Inject;
-import javax.mail.MessagingException;
-import javax.mail.internet.MimeMessage;
-
-import org.apache.james.core.MailAddress;
-import org.apache.james.metrics.api.MetricFactory;
-import org.apache.james.spamassassin.SpamAssassinInvoker;
-import org.apache.james.spamassassin.SpamAssassinResult;
-import org.apache.james.user.api.UsersRepository;
-import org.apache.james.user.api.UsersRepositoryException;
-import org.apache.james.util.Port;
-import org.apache.mailet.Attribute;
-import org.apache.mailet.Mail;
-import org.apache.mailet.PerRecipientHeaders;
-import org.apache.mailet.base.GenericMailet;
-import org.apache.mailet.base.MailetUtil;
-
-import com.github.fge.lambdas.Throwing;
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Strings;
-
-/**
- * Sends the message through daemonized SpamAssassin (spamd), visit <a
- * href="http://spamassassin.apache.org/">spamassassin.apache.org/</a> for info
- * on configuration. The header X-Spam-Status is added to every message, this
- * contains the score and the threshold score for spam (usually 5.0). If the
- * message exceeds the threshold, the header X-Spam-Flag will be added with the
- * value of YES. The default host for spamd is localhost and the default port is
- * 783.
- * 
- * <pre>
- * <code>
- *  org.apache.james.spamassassin.status - Holds the status
- *  org.apache.james.spamassassin.flag   - Holds the flag
- * </code>
- * </pre>
- * 
- * Sample Configuration:
- * 
- * <pre>
- * &lt;mailet notmatch="SenderHostIsLocal" class="SpamAssassin"&gt;
- * &lt;spamdHost&gt;localhost&lt;/spamdHost&gt;
- * &lt;spamdPort&gt;783&lt;/spamdPort&gt;
- * </pre>
- */
-public class SpamAssassin extends GenericMailet {
-    public static final String SPAMD_HOST = "spamdHost";
-    public static final String SPAMD_PORT = "spamdPort";
-    public static final String DEFAULT_HOST = "127.0.0.1";
-    public static final int DEFAULT_PORT = 783;
-
-    private final MetricFactory metricFactory;
-    private final UsersRepository usersRepository;
-
-    private String spamdHost;
-    private int spamdPort;
-
-    @Inject
-    public SpamAssassin(MetricFactory metricFactory, UsersRepository usersRepository) {
-        this.metricFactory = metricFactory;
-        this.usersRepository = usersRepository;
-    }
-
-    @Override
-    public void init() throws MessagingException {
-        spamdHost = Optional.ofNullable(getInitParameter(SPAMD_HOST))
-            .filter(Predicate.not(Strings::isNullOrEmpty))
-            .orElse(DEFAULT_HOST);
-
-        spamdPort = MailetUtil.getInitParameterAsStrictlyPositiveInteger(getInitParameter(SPAMD_PORT), DEFAULT_PORT);
-        Port.assertValid(spamdPort);
-    }
-
-    @Override
-    public void service(Mail mail) throws MessagingException {
-        MimeMessage message = mail.getMessage();
-
-        // Invoke SpamAssassin connection and scan the message
-        SpamAssassinInvoker sa = new SpamAssassinInvoker(metricFactory, spamdHost, spamdPort);
-        mail.getRecipients()
-            .forEach(
-                Throwing.consumer((MailAddress recipient) -> querySpamAssassin(mail, message, sa, recipient))
-                    .sneakyThrow());
-    }
-
-    private void querySpamAssassin(Mail mail, MimeMessage message, SpamAssassinInvoker sa, MailAddress recipient) throws MessagingException, UsersRepositoryException {
-        SpamAssassinResult result = sa.scanMail(message, usersRepository.getUsername(recipient));
-
-        // Add headers per recipient to mail object
-        for (Attribute attribute : result.getHeadersAsAttributes()) {
-            mail.addSpecificHeaderForRecipient(PerRecipientHeaders.Header.builder()
-                    .name(attribute.getName().asString())
-                    .value((String) attribute.getValue().value())
-                    .build(), recipient);
-        }
-    }
-
-    @Override
-    public String getMailetInfo() {
-        return "Checks message against SpamAssassin";
-    }
-
-    @VisibleForTesting
-    String getSpamdHost() {
-        return spamdHost;
-    }
-
-    @VisibleForTesting
-    int getSpamdPort() {
-        return spamdPort;
-    }
-}
diff --git a/server/mailet/mailets/src/test/java/org/apache/james/transport/mailets/SpamAssassinTest.java b/server/mailet/mailets/src/test/java/org/apache/james/transport/mailets/SpamAssassinTest.java
deleted file mode 100644
index ffe8fad7e8..0000000000
--- a/server/mailet/mailets/src/test/java/org/apache/james/transport/mailets/SpamAssassinTest.java
+++ /dev/null
@@ -1,257 +0,0 @@
-/****************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one   *
- * or more contributor license agreements.  See the NOTICE file *
- * distributed with this work for additional information        *
- * regarding copyright ownership.  The ASF licenses this file   *
- * to you under the Apache License, Version 2.0 (the            *
- * "License"); you may not use this file except in compliance   *
- * with the License.  You may obtain a copy of the License at   *
- *                                                              *
- *   http://www.apache.org/licenses/LICENSE-2.0                 *
- *                                                              *
- * Unless required by applicable law or agreed to in writing,   *
- * software distributed under the License is distributed on an  *
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
- * KIND, either express or implied.  See the License for the    *
- * specific language governing permissions and limitations      *
- * under the License.                                           *
- ****************************************************************/
-
-package org.apache.james.transport.mailets;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.assertj.core.api.Assertions.assertThatThrownBy;
-
-import javax.mail.MessagingException;
-
-import org.apache.james.core.MailAddress;
-import org.apache.james.core.builder.MimeMessageBuilder;
-import org.apache.james.domainlist.api.DomainList;
-import org.apache.james.metrics.tests.RecordingMetricFactory;
-import org.apache.james.spamassassin.SpamAssassinResult;
-import org.apache.james.spamassassin.mock.MockSpamd;
-import org.apache.james.spamassassin.mock.MockSpamdExtension;
-import org.apache.james.user.memory.MemoryUsersRepository;
-import org.apache.james.util.Port;
-import org.apache.mailet.Mail;
-import org.apache.mailet.PerRecipientHeaders;
-import org.apache.mailet.base.test.FakeMail;
-import org.apache.mailet.base.test.FakeMailetConfig;
-import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.extension.RegisterExtension;
-
-import com.google.common.collect.ImmutableList;
-
-class SpamAssassinTest {
-
-    private static final DomainList NO_DOMAIN_LIST = null;
-
-    @RegisterExtension
-    MockSpamdExtension spamd = new MockSpamdExtension();
-
-    private SpamAssassin mailet = new SpamAssassin(new RecordingMetricFactory(), MemoryUsersRepository.withVirtualHosting(NO_DOMAIN_LIST));
-
-    @Test
-    void initShouldSetDefaultSpamdHostWhenNone() throws Exception {
-        mailet.init(FakeMailetConfig.builder()
-            .mailetName("SpamAssassin")
-            .build());
-
-        assertThat(mailet.getSpamdHost()).isEqualTo(SpamAssassin.DEFAULT_HOST);
-    }
-
-    @Test
-    void initShouldSetDefaultSpamdPortWhenNone() throws Exception {
-        mailet.init(FakeMailetConfig.builder()
-            .mailetName("SpamAssassin")
-            .build());
-
-        assertThat(mailet.getSpamdPort()).isEqualTo(SpamAssassin.DEFAULT_PORT);
-    }
-
-    @Test
-    void initShouldSetSpamdHostWhenPresent() throws Exception {
-        String spamdHost = "any.host";
-        mailet.init(FakeMailetConfig.builder()
-            .mailetName("SpamAssassin")
-            .setProperty(SpamAssassin.SPAMD_HOST, spamdHost)
-            .build());
-
-        assertThat(mailet.getSpamdHost()).isEqualTo(spamdHost);
-    }
-
-    @Test
-    void getSpamHostShouldReturnDefaultValueWhenEmpty() throws Exception {
-        mailet.init(FakeMailetConfig.builder()
-            .mailetName("SpamAssassin")
-            .setProperty(SpamAssassin.SPAMD_HOST, "")
-            .build());
-
-        assertThat(mailet.getSpamdHost()).isEqualTo(SpamAssassin.DEFAULT_HOST);
-    }
-
-    @Test
-    void initShouldSetDefaultSpamdPortWhenDefault() throws Exception {
-        mailet.init(FakeMailetConfig.builder()
-            .mailetName("SpamAssassin")
-            .build());
-
-        assertThat(mailet.getSpamdPort()).isEqualTo(SpamAssassin.DEFAULT_PORT);
-    }
-
-    @Test
-    void initShouldThrowWhenSpamdPortIsNotNumber() {
-        assertThatThrownBy(() -> mailet.init(FakeMailetConfig.builder()
-            .mailetName("SpamAssassin")
-            .setProperty(SpamAssassin.SPAMD_PORT, "noNumber")
-            .build())).isInstanceOf(MessagingException.class);
-    }
-
-    @Test
-    void initShouldThrowWhenSpamdPortIsNegative() {
-        assertThatThrownBy(() -> mailet.init(FakeMailetConfig.builder()
-            .mailetName("SpamAssassin")
-            .setProperty(SpamAssassin.SPAMD_PORT, "-1")
-            .build())).isInstanceOf(MessagingException.class);
-    }
-
-    @Test
-    void initShouldThrowWhenSpamdPortIsZero() {
-        assertThatThrownBy(() -> mailet.init(FakeMailetConfig.builder()
-            .mailetName("SpamAssassin")
-            .setProperty(SpamAssassin.SPAMD_PORT, "0")
-            .build())).isInstanceOf(MessagingException.class);
-    }
-
-    @Test
-    void initShouldThrowWhenSpamdPortTooBig() {
-        assertThatThrownBy(() -> mailet.init(FakeMailetConfig.builder()
-            .mailetName("SpamAssassin")
-            .setProperty(SpamAssassin.SPAMD_PORT,
-                String.valueOf(Port.MAX_PORT_VALUE + 1))
-            .build())).isInstanceOf(IllegalArgumentException.class);
-    }
-
-    @Test
-    void initShouldSetSpamPortWhenPresent() throws Exception {
-        int spamPort = 1000;
-        mailet.init(FakeMailetConfig.builder()
-            .mailetName("SpamAssassin")
-            .setProperty(SpamAssassin.SPAMD_PORT, String.valueOf(spamPort))
-            .build());
-
-        assertThat(mailet.getSpamdPort()).isEqualTo(spamPort);
-    }
-
-    @Test
-    void serviceShouldWriteSpamAttributeOnMail() throws Exception {
-        FakeMailetConfig mailetConfiguration = FakeMailetConfig.builder()
-            .mailetName("SpamAssassin")
-            .setProperty(SpamAssassin.SPAMD_HOST, "localhost")
-            .setProperty(SpamAssassin.SPAMD_PORT, String.valueOf(spamd.getPort()))
-            .build();
-        mailet.init(mailetConfiguration);
-
-        Mail mail = FakeMail.builder()
-            .name("name")
-            .recipient("user1@exemple.com")
-            .mimeMessage(MimeMessageBuilder.mimeMessageBuilder()
-                .addToRecipient("user1@exemple.com")
-                .addFrom("sender@exemple.com")
-                .setSubject("testing")
-                .setText("Please!")
-                .build())
-            .build();
-
-        mailet.service(mail);
-
-
-
-        assertThat(
-            mail.getPerRecipientSpecificHeaders()
-                .getHeadersByRecipient()
-                .get(new MailAddress("user1@exemple.com"))
-                .stream()
-                .map(PerRecipientHeaders.Header::getName)
-                .collect(ImmutableList.toImmutableList()))
-            .contains(SpamAssassinResult.FLAG_MAIL.asString(), SpamAssassinResult.STATUS_MAIL.asString());
-    }
-
-    @Test
-    void serviceShouldWriteMessageAsNotSpamWhenNotSpam() throws Exception {
-        FakeMailetConfig mailetConfiguration = FakeMailetConfig.builder()
-            .mailetName("SpamAssassin")
-            .setProperty(SpamAssassin.SPAMD_HOST, "localhost")
-            .setProperty(SpamAssassin.SPAMD_PORT, String.valueOf(spamd.getPort()))
-            .build();
-        mailet.init(mailetConfiguration);
-
-        Mail mail = FakeMail.builder()
-            .name("name")
-            .recipient("user1@exemple.com")
-            .mimeMessage(MimeMessageBuilder.mimeMessageBuilder()
-                .addToRecipient("user1@exemple.com")
-                .addFrom("sender@exemple.com")
-                .setSubject("testing")
-                .setText("Please!")
-                .build())
-            .build();
-
-        mailet.service(mail);
-
-        assertThat(mail.getPerRecipientSpecificHeaders())
-            .isEqualTo(new PerRecipientHeaders()
-                .addHeaderForRecipient(
-                    PerRecipientHeaders.Header.builder()
-                        .name(SpamAssassinResult.FLAG_MAIL.asString())
-                        .value("NO"),
-                    new MailAddress("user1@exemple.com"))
-                .addHeaderForRecipient(
-                    PerRecipientHeaders.Header.builder()
-                        .name(SpamAssassinResult.STATUS_MAIL.asString())
-                        .value("No, hits=3 required=5"),
-                    new MailAddress("user1@exemple.com")));
-    }
-
-    @Test
-    void serviceShouldWriteMessageAsSpamWhenSpam() throws Exception {
-        FakeMailetConfig mailetConfiguration = FakeMailetConfig.builder()
-            .mailetName("SpamAssassin")
-            .setProperty(SpamAssassin.SPAMD_HOST, "localhost")
-            .setProperty(SpamAssassin.SPAMD_PORT, String.valueOf(spamd.getPort()))
-            .build();
-        mailet.init(mailetConfiguration);
-
-        Mail mail = FakeMail.builder()
-            .name("name")
-            .recipient("user1@exemple.com")
-            .mimeMessage(MimeMessageBuilder.mimeMessageBuilder()
-                .addToRecipient("user1@exemple.com")
-                .addFrom("sender@exemple.com")
-                .setSubject(MockSpamd.GTUBE + " testing")
-                .setText("Please!")
-                .build())
-            .build();
-
-        mailet.service(mail);
-
-        assertThat(mail.getPerRecipientSpecificHeaders())
-            .isEqualTo(new PerRecipientHeaders()
-                .addHeaderForRecipient(
-                    PerRecipientHeaders.Header.builder()
-                        .name(SpamAssassinResult.FLAG_MAIL.asString())
-                        .value("YES"),
-                    new MailAddress("user1@exemple.com"))
-                .addHeaderForRecipient(
-                    PerRecipientHeaders.Header.builder()
-                        .name(SpamAssassinResult.STATUS_MAIL.asString())
-                        .value("Yes, hits=1000 required=5"),
-                    new MailAddress("user1@exemple.com")));
-    }
-
-    @Test
-    void getMailetInfoShouldReturnSpamAssasinMailetInformation() {
-        assertThat(mailet.getMailetInfo()).isEqualTo("Checks message against SpamAssassin");
-    }
-
-}
\ No newline at end of file
diff --git a/server/protocols/jmap-draft-integration-testing/jmap-draft-integration-testing-common/pom.xml b/server/protocols/jmap-draft-integration-testing/jmap-draft-integration-testing-common/pom.xml
index db703f8a28..5fa8986b93 100644
--- a/server/protocols/jmap-draft-integration-testing/jmap-draft-integration-testing-common/pom.xml
+++ b/server/protocols/jmap-draft-integration-testing/jmap-draft-integration-testing-common/pom.xml
@@ -44,12 +44,6 @@
             <artifactId>apache-james-mailbox-spamassassin</artifactId>
             <scope>test</scope>
         </dependency>
-        <dependency>
-            <groupId>${james.groupId}</groupId>
-            <artifactId>apache-james-spamassassin</artifactId>
-            <type>test-jar</type>
-            <scope>test</scope>
-        </dependency>
         <dependency>
             <groupId>${james.groupId}</groupId>
             <artifactId>backup</artifactId>
diff --git a/server/protocols/jmap-draft-integration-testing/jmap-draft-integration-testing-common/src/test/java/org/apache/james/jmap/draft/methods/integration/SpamAssassinContract.java b/server/protocols/jmap-draft-integration-testing/jmap-draft-integration-testing-common/src/test/java/org/apache/james/jmap/draft/methods/integration/SpamAssassinContract.java
deleted file mode 100644
index cb49c1728a..0000000000
--- a/server/protocols/jmap-draft-integration-testing/jmap-draft-integration-testing-common/src/test/java/org/apache/james/jmap/draft/methods/integration/SpamAssassinContract.java
+++ /dev/null
@@ -1,694 +0,0 @@
-/****************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one   *
- * or more contributor license agreements.  See the NOTICE file *
- * distributed with this work for additional information        *
- * regarding copyright ownership.  The ASF licenses this file   *
- * to you under the Apache License, Version 2.0 (the            *
- * "License"); you may not use this file except in compliance   *
- * with the License.  You may obtain a copy of the License at   *
- *                                                              *
- *   http://www.apache.org/licenses/LICENSE-2.0                 *
- *                                                              *
- * Unless required by applicable law or agreed to in writing,   *
- * software distributed under the License is distributed on an  *
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
- * KIND, either express or implied.  See the License for the    *
- * specific language governing permissions and limitations      *
- * under the License.                                           *
- ****************************************************************/
-
-package org.apache.james.jmap.draft.methods.integration;
-
-import static io.restassured.RestAssured.given;
-import static io.restassured.RestAssured.with;
-import static io.restassured.config.EncoderConfig.encoderConfig;
-import static io.restassured.config.RestAssuredConfig.newConfig;
-import static org.apache.james.jmap.HttpJmapAuthentication.authenticateJamesUser;
-import static org.apache.james.jmap.JMAPTestingConstants.ARGUMENTS;
-import static org.apache.james.jmap.JMAPTestingConstants.LOCALHOST_IP;
-import static org.apache.james.jmap.JMAPTestingConstants.NAME;
-import static org.apache.james.jmap.JMAPTestingConstants.calmlyAwait;
-import static org.apache.james.jmap.JmapURIBuilder.baseUri;
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.awaitility.Durations.ONE_MINUTE;
-import static org.hamcrest.Matchers.equalTo;
-import static org.hamcrest.Matchers.hasSize;
-
-import java.nio.charset.StandardCharsets;
-import java.util.List;
-import java.util.Map;
-
-import org.apache.james.GuiceJamesServer;
-import org.apache.james.core.Username;
-import org.apache.james.jmap.AccessToken;
-import org.apache.james.jmap.draft.JmapGuiceProbe;
-import org.apache.james.mailbox.Role;
-import org.apache.james.modules.protocols.ImapGuiceProbe;
-import org.apache.james.spamassassin.SpamAssassinExtension;
-import org.apache.james.utils.DataProbeImpl;
-import org.apache.james.utils.SpoolerProbe;
-import org.apache.james.utils.TestIMAPClient;
-import org.junit.jupiter.api.AfterEach;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-
-import io.restassured.RestAssured;
-import io.restassured.builder.RequestSpecBuilder;
-import io.restassured.http.ContentType;
-import io.restassured.parsing.Parser;
-
-public interface SpamAssassinContract {
-
-    String BOBS_DOMAIN = "spamer.com";
-    String BOB = "bob@" + BOBS_DOMAIN;
-    String BOB_PASSWORD = "bobPassword";
-    String RECIPIENTS_DOMAIN = "angels.org";
-    String ALICE = "alice@" + RECIPIENTS_DOMAIN;
-    String ALICE_PASSWORD = "alicePassword";
-    String PAUL = "paul@" + RECIPIENTS_DOMAIN;
-    String PAUL_PASSWORD = "paulPassword";
-
-    @BeforeEach
-    default void setup(GuiceJamesServer jamesServer) throws Throwable {
-        RestAssured.requestSpecification = new RequestSpecBuilder()
-                .setContentType(ContentType.JSON)
-                .setAccept(ContentType.JSON)
-                .setConfig(newConfig().encoderConfig(encoderConfig().defaultContentCharset(StandardCharsets.UTF_8)))
-                .setPort(jamesServer.getProbe(JmapGuiceProbe.class).getJmapPort().getValue())
-                .build();
-        RestAssured.defaultParser = Parser.JSON;
-
-        jamesServer.getProbe(DataProbeImpl.class)
-            .fluent()
-            .addDomain(BOBS_DOMAIN)
-            .addDomain(RECIPIENTS_DOMAIN)
-            .addUser(BOB, BOB_PASSWORD)
-            .addUser(ALICE, ALICE_PASSWORD)
-            .addUser(PAUL, PAUL_PASSWORD);
-    }
-
-    @AfterEach
-    default void tearDown(SpamAssassinExtension.SpamAssassin spamAssassin, GuiceJamesServer jamesServer) throws Exception {
-        calmlyAwait.atMost(ONE_MINUTE).untilAsserted(() -> assertEveryListenerGotCalled(jamesServer));
-        spamAssassin.clear(ALICE);
-    }
-
-    default AccessToken accessTokenFor(GuiceJamesServer james, String user, String password) {
-        return authenticateJamesUser(baseUri(james), Username.of(user), password);
-    }
-
-    @Test
-    default void spamShouldBeDeliveredInSpamMailboxWhenSameMessageHasAlreadyBeenMovedToSpam(
-        GuiceJamesServer jamesServer,
-        SpamAssassinExtension.SpamAssassin spamAssassin) throws Exception {
-
-        spamAssassin.train(ALICE);
-        AccessToken aliceAccessToken = accessTokenFor(jamesServer, ALICE, ALICE_PASSWORD);
-        AccessToken bobAccessToken = accessTokenFor(jamesServer, BOB, BOB_PASSWORD);
-
-        // Bob is sending a message to Alice
-        given()
-            .header("Authorization", bobAccessToken.asString())
-            .body(setMessageCreate(bobAccessToken))
-        .when()
-            .post("/jmap");
-
-        calmlyAwait.atMost(ONE_MINUTE).untilAsserted(() -> assertMessagesFoundInMailbox(aliceAccessToken, getInboxId(aliceAccessToken), 1));
-        calmlyAwait.atMost(ONE_MINUTE).untilAsserted(() -> assertEveryListenerGotCalled(jamesServer));
-
-        // Alice is moving this message to Spam -> learning in SpamAssassin
-        List<String> messageIds = with()
-            .header("Authorization", aliceAccessToken.asString())
-            .body("[[\"getMessageList\", {\"filter\":{\"inMailboxes\":[\"" + getInboxId(aliceAccessToken) + "\"]}}, \"#0\"]]")
-        .when()
-            .post("/jmap")
-        .then()
-            .statusCode(200)
-            .body(NAME, equalTo("messageList"))
-            .body(ARGUMENTS + ".messageIds", hasSize(1))
-            .extract()
-            .path(ARGUMENTS + ".messageIds");
-
-        messageIds
-            .forEach(messageId -> given()
-                .header("Authorization", aliceAccessToken.asString())
-                .body(String.format("[[\"setMessages\", {\"update\": {\"%s\" : { \"mailboxIds\": [\"" + getSpamId(aliceAccessToken) + "\"] } } }, \"#0\"]]", messageId))
-            .when()
-                .post("/jmap")
-            .then()
-                .statusCode(200)
-                .body(NAME, equalTo("messagesSet"))
-                .body(ARGUMENTS + ".updated", hasSize(1)));
-        calmlyAwait.atMost(ONE_MINUTE).untilAsserted(() -> assertMessagesFoundInMailbox(aliceAccessToken, getSpamId(aliceAccessToken), 1));
-
-        // Bob is sending again the same message to Alice
-        given()
-            .header("Authorization", bobAccessToken.asString())
-            .body(setMessageCreate(bobAccessToken))
-        .when()
-            .post("/jmap");
-
-        // This message is delivered in Alice Spam mailbox (she now must have 2 messages in her Spam mailbox)
-        calmlyAwait.atMost(ONE_MINUTE).untilAsserted(() -> assertMessagesFoundInMailbox(aliceAccessToken, getSpamId(aliceAccessToken), 2));
-    }
-
-    @Test
-    default void imapCopiesToSpamMailboxShouldBeConsideredAsSpam(GuiceJamesServer jamesServer,
-                                                                 SpamAssassinExtension.SpamAssassin spamAssassin) throws Exception {
-        spamAssassin.train(ALICE);
-        AccessToken aliceAccessToken = accessTokenFor(jamesServer, ALICE, ALICE_PASSWORD);
-        AccessToken bobAccessToken = accessTokenFor(jamesServer, BOB, BOB_PASSWORD);
-
-        // Bob is sending a message to Alice
-        given()
-            .header("Authorization", bobAccessToken.asString())
-            .body(setMessageCreate(bobAccessToken))
-        .when()
-            .post("/jmap");
-        calmlyAwait.atMost(ONE_MINUTE).untilAsserted(() -> assertMessagesFoundInMailbox(aliceAccessToken, getInboxId(aliceAccessToken), 1));
-        calmlyAwait.atMost(ONE_MINUTE).untilAsserted(() -> assertEveryListenerGotCalled(jamesServer));
-
-
-        // Alice is copying this message to Spam -> learning in SpamAssassin
-        try (TestIMAPClient testIMAPClient = new TestIMAPClient()) {
-            testIMAPClient.connect(LOCALHOST_IP, jamesServer.getProbe(ImapGuiceProbe.class).getImapPort())
-                .login(ALICE, ALICE_PASSWORD)
-                .select(TestIMAPClient.INBOX);
-
-            testIMAPClient.copyFirstMessage("Spam");
-        }
-        calmlyAwait.atMost(ONE_MINUTE).untilAsserted(() -> assertMessagesFoundInMailbox(aliceAccessToken, getSpamId(aliceAccessToken), 1));
-
-        // Bob is sending again the same message to Alice
-        given()
-            .header("Authorization", bobAccessToken.asString())
-            .body(setMessageCreate(bobAccessToken))
-        .when()
-            .post("/jmap");
-
-        // This message is delivered in Alice Spam mailbox (she now must have 2 messages in her Spam mailbox)
-        calmlyAwait.atMost(ONE_MINUTE).untilAsserted(() -> assertMessagesFoundInMailbox(aliceAccessToken, getSpamId(aliceAccessToken), 2));
-    }
-
-    @Test
-    default void imapMovesToSpamMailboxShouldBeConsideredAsSpam(GuiceJamesServer jamesServer,
-                                                                SpamAssassinExtension.SpamAssassin spamAssassin) throws Exception {
-        spamAssassin.train(ALICE);
-        AccessToken aliceAccessToken = accessTokenFor(jamesServer, ALICE, ALICE_PASSWORD);
-        AccessToken bobAccessToken = accessTokenFor(jamesServer, BOB, BOB_PASSWORD);
-
-        // Bob is sending a message to Alice
-        given()
-            .header("Authorization", bobAccessToken.asString())
-            .body(setMessageCreate(bobAccessToken))
-        .when()
-            .post("/jmap");
-        calmlyAwait.atMost(ONE_MINUTE).untilAsserted(() -> assertMessagesFoundInMailbox(aliceAccessToken, getInboxId(aliceAccessToken), 1));
-        calmlyAwait.atMost(ONE_MINUTE).untilAsserted(() -> assertEveryListenerGotCalled(jamesServer));
-
-        try (TestIMAPClient testIMAPClient = new TestIMAPClient()) {
-            testIMAPClient.connect(LOCALHOST_IP, jamesServer.getProbe(ImapGuiceProbe.class).getImapPort())
-                .login(ALICE, ALICE_PASSWORD)
-                .select(TestIMAPClient.INBOX);
-
-            testIMAPClient.moveFirstMessage("Spam");
-        }
-        calmlyAwait.atMost(ONE_MINUTE).untilAsserted(() -> assertMessagesFoundInMailbox(aliceAccessToken, getSpamId(aliceAccessToken), 1));
-
-        // Bob is sending again the same message to Alice
-        given()
-            .header("Authorization", bobAccessToken.asString())
-            .body(setMessageCreate(bobAccessToken))
-        .when()
-            .post("/jmap");
-
-        // This message is delivered in Alice Spam mailbox (she now must have 2 messages in her Spam mailbox)
-        calmlyAwait.atMost(ONE_MINUTE).untilAsserted(() -> assertMessagesFoundInMailbox(aliceAccessToken, getSpamId(aliceAccessToken), 2));
-    }
-
-    @Test
-    default void spamAssassinShouldForgetMessagesMovedOutOfSpamFolderUsingJMAP(GuiceJamesServer jamesServer,
-                                                                               SpamAssassinExtension.SpamAssassin spamAssassin) throws Exception {
-        spamAssassin.train(ALICE);
-        AccessToken aliceAccessToken = accessTokenFor(jamesServer, ALICE, ALICE_PASSWORD);
-        AccessToken bobAccessToken = accessTokenFor(jamesServer, BOB, BOB_PASSWORD);
-
-        // Bob is sending a message to Alice
-        given()
-            .header("Authorization", bobAccessToken.asString())
-            .body(setMessageCreate(bobAccessToken))
-            .when()
-            .post("/jmap");
-        calmlyAwait.atMost(ONE_MINUTE).untilAsserted(() -> assertMessagesFoundInMailbox(aliceAccessToken, getInboxId(aliceAccessToken), 1));
-        calmlyAwait.atMost(ONE_MINUTE).untilAsserted(() -> assertEveryListenerGotCalled(jamesServer));
-
-        // Alice is moving this message to Spam -> learning in SpamAssassin
-        List<String> messageIds = with()
-            .header("Authorization", aliceAccessToken.asString())
-            .body("[[\"getMessageList\", {\"filter\":{\"inMailboxes\":[\"" + getInboxId(aliceAccessToken) + "\"]}}, \"#0\"]]")
-        .when()
-            .post("/jmap")
-        .then()
-            .statusCode(200)
-            .body(NAME, equalTo("messageList"))
-            .body(ARGUMENTS + ".messageIds", hasSize(1))
-            .extract()
-            .path(ARGUMENTS + ".messageIds");
-
-        messageIds
-            .forEach(messageId -> given()
-                .header("Authorization", aliceAccessToken.asString())
-                .body(String.format("[[\"setMessages\", {\"update\": {\"%s\" : { \"mailboxIds\": [\"" + getSpamId(aliceAccessToken) + "\"] } } }, \"#0\"]]", messageId))
-            .when()
-                .post("/jmap")
-            .then()
-                .statusCode(200)
-                .body(NAME, equalTo("messagesSet"))
-                .body(ARGUMENTS + ".updated", hasSize(1)));
-        calmlyAwait.atMost(ONE_MINUTE).untilAsserted(() -> assertMessagesFoundInMailbox(aliceAccessToken, getSpamId(aliceAccessToken), 1));
-
-        // Alice is moving this message out of Spam -> forgetting in SpamAssassin
-        messageIds
-            .forEach(messageId -> given()
-                .header("Authorization", aliceAccessToken.asString())
-                .body(String.format("[[\"setMessages\", {\"update\": {\"%s\" : { \"mailboxIds\": [\"" + getInboxId(aliceAccessToken) + "\"] } } }, \"#0\"]]", messageId))
-            .when()
-                .post("/jmap")
-            .then()
-                .statusCode(200)
-                .body(NAME, equalTo("messagesSet"))
-                .body(ARGUMENTS + ".updated", hasSize(1)));
-        calmlyAwait.atMost(ONE_MINUTE).untilAsserted(() -> assertMessagesFoundInMailbox(aliceAccessToken, getInboxId(aliceAccessToken), 1));
-
-        // Bob is sending again the same message to Alice
-        given()
-            .header("Authorization", bobAccessToken.asString())
-            .body(setMessageCreate(bobAccessToken))
-        .when()
-            .post("/jmap");
-
-        // This message is delivered in Alice INBOX mailbox (she now must have 2 messages in her Inbox mailbox)
-        calmlyAwait.atMost(ONE_MINUTE).untilAsserted(() -> assertMessagesFoundInMailbox(aliceAccessToken, getInboxId(aliceAccessToken), 2));
-    }
-
-    @Test
-    default void movingAMailToTrashShouldNotImpactSpamassassinLearning(GuiceJamesServer jamesServer,
-                                                                       SpamAssassinExtension.SpamAssassin spamAssassin) throws Exception {
-        spamAssassin.train(ALICE);
-        AccessToken aliceAccessToken = accessTokenFor(jamesServer, ALICE, ALICE_PASSWORD);
-        AccessToken bobAccessToken = accessTokenFor(jamesServer, BOB, BOB_PASSWORD);
-
-        // Bob is sending a message to Alice
-        given()
-            .header("Authorization", bobAccessToken.asString())
-            .body(setMessageCreate(bobAccessToken))
-            .when()
-            .post("/jmap");
-        calmlyAwait.atMost(ONE_MINUTE).untilAsserted(() -> assertMessagesFoundInMailbox(aliceAccessToken, getInboxId(aliceAccessToken), 1));
-        calmlyAwait.atMost(ONE_MINUTE).untilAsserted(() -> assertEveryListenerGotCalled(jamesServer));
-
-        // Alice is moving this message to Spam -> learning in SpamAssassin
-        List<String> messageIds = with()
-            .header("Authorization", aliceAccessToken.asString())
-            .body("[[\"getMessageList\", {\"filter\":{\"inMailboxes\":[\"" + getInboxId(aliceAccessToken) + "\"]}}, \"#0\"]]")
-        .when()
-            .post("/jmap")
-        .then()
-            .statusCode(200)
-            .body(NAME, equalTo("messageList"))
-            .body(ARGUMENTS + ".messageIds", hasSize(1))
-            .extract()
-            .path(ARGUMENTS + ".messageIds");
-
-        messageIds
-            .forEach(messageId -> given()
-                .header("Authorization", aliceAccessToken.asString())
-                .body(String.format("[[\"setMessages\", {\"update\": {\"%s\" : { \"mailboxIds\": [\"" + getSpamId(aliceAccessToken) + "\"] } } }, \"#0\"]]", messageId))
-            .when()
-                .post("/jmap")
-            .then()
-                .statusCode(200)
-                .body(NAME, equalTo("messagesSet"))
-                .body(ARGUMENTS + ".updated", hasSize(1)));
-        calmlyAwait.atMost(ONE_MINUTE).untilAsserted(() -> assertMessagesFoundInMailbox(aliceAccessToken, getSpamId(aliceAccessToken), 1));
-
-        // Alice is moving this message to trash
-        messageIds
-            .forEach(messageId -> given()
-                .header("Authorization", aliceAccessToken.asString())
-                .body(String.format("[[\"setMessages\", {\"update\": {\"%s\" : { \"mailboxIds\": [\"" + getTrashId(aliceAccessToken) + "\"] } } }, \"#0\"]]", messageId))
-            .when()
-                .post("/jmap")
-            .then()
-                .statusCode(200)
-                .body(NAME, equalTo("messagesSet"))
-                .body(ARGUMENTS + ".updated", hasSize(1)));
-        calmlyAwait.atMost(ONE_MINUTE).untilAsserted(() -> assertMessagesFoundInMailbox(aliceAccessToken, getTrashId(aliceAccessToken), 1));
-
-        // Bob is sending again the same message to Alice
-        given()
-            .header("Authorization", bobAccessToken.asString())
-            .body(setMessageCreate(bobAccessToken))
-        .when()
-            .post("/jmap");
-
-        // This message is delivered in Alice Spam mailbox (she now must have 1 messages in her Spam mailbox)
-        calmlyAwait.atMost(ONE_MINUTE).untilAsserted(() -> assertMessagesFoundInMailbox(aliceAccessToken, getSpamId(aliceAccessToken), 1));
-    }
-
-    @Test
-    default void spamAssassinShouldForgetMessagesMovedOutOfSpamFolderUsingIMAP(GuiceJamesServer jamesServer,
-                                                                               SpamAssassinExtension.SpamAssassin spamAssassin) throws Exception {
-        spamAssassin.train(ALICE);
-        AccessToken aliceAccessToken = accessTokenFor(jamesServer, ALICE, ALICE_PASSWORD);
-        AccessToken bobAccessToken = accessTokenFor(jamesServer, BOB, BOB_PASSWORD);
-
-        // Bob is sending a message to Alice
-        given()
-            .header("Authorization", bobAccessToken.asString())
-            .body(setMessageCreate(bobAccessToken))
-            .when()
-            .post("/jmap");
-        calmlyAwait.atMost(ONE_MINUTE).untilAsserted(() -> assertMessagesFoundInMailbox(aliceAccessToken, getInboxId(aliceAccessToken), 1));
-        calmlyAwait.atMost(ONE_MINUTE).untilAsserted(() -> assertEveryListenerGotCalled(jamesServer));
-
-        // Alice is moving this message to Spam -> learning in SpamAssassin
-        List<String> messageIds = with()
-            .header("Authorization", aliceAccessToken.asString())
-            .body("[[\"getMessageList\", {\"filter\":{\"inMailboxes\":[\"" + getInboxId(aliceAccessToken) + "\"]}}, \"#0\"]]")
-        .when()
-            .post("/jmap")
-        .then()
-            .statusCode(200)
-            .body(NAME, equalTo("messageList"))
-            .body(ARGUMENTS + ".messageIds", hasSize(1))
-            .extract()
-            .path(ARGUMENTS + ".messageIds");
-
-        messageIds
-            .forEach(messageId -> given()
-                .header("Authorization", aliceAccessToken.asString())
-                .body(String.format("[[\"setMessages\", {\"update\": {\"%s\" : { \"mailboxIds\": [\"" + getSpamId(aliceAccessToken) + "\"] } } }, \"#0\"]]", messageId))
-            .when()
-                .post("/jmap")
-            .then()
-                .statusCode(200)
-                .body(NAME, equalTo("messagesSet"))
-                .body(ARGUMENTS + ".updated", hasSize(1)));
-        calmlyAwait.atMost(ONE_MINUTE).untilAsserted(() -> assertMessagesFoundInMailbox(aliceAccessToken, getSpamId(aliceAccessToken), 1));
-
-        // Alice is moving this message out of Spam -> forgetting in SpamAssassin
-        try (TestIMAPClient testIMAPClient = new TestIMAPClient()) {
-            testIMAPClient.connect(LOCALHOST_IP, jamesServer.getProbe(ImapGuiceProbe.class).getImapPort())
-                .login(ALICE, ALICE_PASSWORD)
-                .select("Spam");
-
-            testIMAPClient.moveFirstMessage(TestIMAPClient.INBOX);
-        }
-        calmlyAwait.atMost(ONE_MINUTE).untilAsserted(() -> assertMessagesFoundInMailbox(aliceAccessToken, getInboxId(aliceAccessToken), 1));
-
-        // Bob is sending again the same message to Alice
-        given()
-            .header("Authorization", bobAccessToken.asString())
-            .body(setMessageCreate(bobAccessToken))
-        .when()
-            .post("/jmap");
-
-        // This message is delivered in Alice INBOX mailbox (she now must have 2 messages in her Inbox mailbox)
-        calmlyAwait.atMost(ONE_MINUTE).untilAsserted(() -> assertMessagesFoundInMailbox(aliceAccessToken, getInboxId(aliceAccessToken), 2));
-    }
-
-    @Test
-    default void expungingSpamMessageShouldNotImpactSpamAssassinState(GuiceJamesServer jamesServer,
-                                                                      SpamAssassinExtension.SpamAssassin spamAssassin) throws Exception {
-        spamAssassin.train(ALICE);
-        AccessToken aliceAccessToken = accessTokenFor(jamesServer, ALICE, ALICE_PASSWORD);
-        AccessToken bobAccessToken = accessTokenFor(jamesServer, BOB, BOB_PASSWORD);
-
-        // Bob is sending a message to Alice
-        given()
-            .header("Authorization", bobAccessToken.asString())
-            .body(setMessageCreate(bobAccessToken))
-            .when()
-            .post("/jmap");
-        calmlyAwait.atMost(ONE_MINUTE).untilAsserted(() -> assertMessagesFoundInMailbox(aliceAccessToken, getInboxId(aliceAccessToken), 1));
-        calmlyAwait.atMost(ONE_MINUTE).untilAsserted(() -> assertEveryListenerGotCalled(jamesServer));
-
-        // Alice is moving this message to Spam -> learning in SpamAssassin
-        List<String> messageIds = with()
-            .header("Authorization", aliceAccessToken.asString())
-            .body("[[\"getMessageList\", {\"filter\":{\"inMailboxes\":[\"" + getInboxId(aliceAccessToken) + "\"]}}, \"#0\"]]")
-        .when()
-            .post("/jmap")
-        .then()
-            .statusCode(200)
-            .body(NAME, equalTo("messageList"))
-            .body(ARGUMENTS + ".messageIds", hasSize(1))
-            .extract()
-            .path(ARGUMENTS + ".messageIds");
-
-        messageIds
-            .forEach(messageId -> given()
-                .header("Authorization", aliceAccessToken.asString())
-                .body(String.format("[[\"setMessages\", {\"update\": {\"%s\" : { \"mailboxIds\": [\"" + getSpamId(aliceAccessToken) + "\"] } } }, \"#0\"]]", messageId))
-            .when()
-                .post("/jmap")
-            .then()
-                .statusCode(200)
-                .body(NAME, equalTo("messagesSet"))
-                .body(ARGUMENTS + ".updated", hasSize(1)));
-        calmlyAwait.atMost(ONE_MINUTE).untilAsserted(() -> assertMessagesFoundInMailbox(aliceAccessToken, getSpamId(aliceAccessToken), 1));
-
-        // Alice is deleting this message
-        try (TestIMAPClient testIMAPClient = new TestIMAPClient()) {
-            testIMAPClient.connect(LOCALHOST_IP, jamesServer.getProbe(ImapGuiceProbe.class).getImapPort())
-                .login(ALICE, ALICE_PASSWORD)
-                .select("Spam");
-
-            testIMAPClient.setFlagsForAllMessagesInMailbox("\\Deleted");
-            testIMAPClient.expunge();
-        }
-        calmlyAwait.atMost(ONE_MINUTE).untilAsserted(() -> assertMessagesFoundInMailbox(aliceAccessToken, getSpamId(aliceAccessToken), 0));
-
-        // Bob is sending again the same message to Alice
-        given()
-            .header("Authorization", bobAccessToken.asString())
-            .body(setMessageCreate(bobAccessToken))
-        .when()
-            .post("/jmap");
-
-        // This message is delivered in Alice SPAM mailbox (she now must have 1 messages in her Spam mailbox)
-        calmlyAwait.atMost(ONE_MINUTE).untilAsserted(() -> assertMessagesFoundInMailbox(aliceAccessToken, getSpamId(aliceAccessToken), 1));
-    }
-
-    @Test
-    default void deletingSpamMessageShouldNotImpactSpamAssassinState(GuiceJamesServer jamesServer,
-                                                                     SpamAssassinExtension.SpamAssassin spamAssassin) throws Exception {
-        spamAssassin.train(ALICE);
-        AccessToken aliceAccessToken = accessTokenFor(jamesServer, ALICE, ALICE_PASSWORD);
-        AccessToken bobAccessToken = accessTokenFor(jamesServer, BOB, BOB_PASSWORD);
-
-        // Bob is sending a message to Alice
-        given()
-            .header("Authorization", bobAccessToken.asString())
-            .body(setMessageCreate(bobAccessToken))
-            .when()
-            .post("/jmap");
-        calmlyAwait.atMost(ONE_MINUTE).untilAsserted(() -> assertMessagesFoundInMailbox(aliceAccessToken, getInboxId(aliceAccessToken), 1));
-        calmlyAwait.atMost(ONE_MINUTE).untilAsserted(() -> assertEveryListenerGotCalled(jamesServer));
-
-        // Alice is moving this message to Spam -> learning in SpamAssassin
-        List<String> messageIds = with()
-            .header("Authorization", aliceAccessToken.asString())
-            .body("[[\"getMessageList\", {\"filter\":{\"inMailboxes\":[\"" + getInboxId(aliceAccessToken) + "\"]}}, \"#0\"]]")
-        .when()
-            .post("/jmap")
-        .then()
-            .statusCode(200)
-            .body(NAME, equalTo("messageList"))
-            .body(ARGUMENTS + ".messageIds", hasSize(1))
-            .extract()
-            .path(ARGUMENTS + ".messageIds");
-
-        messageIds
-            .forEach(messageId -> given()
-                .header("Authorization", aliceAccessToken.asString())
-                .body(String.format("[[\"setMessages\", {\"update\": {\"%s\" : { \"mailboxIds\": [\"" + getSpamId(aliceAccessToken) + "\"] } } }, \"#0\"]]", messageId))
-            .when()
-                .post("/jmap")
-            .then()
-                .statusCode(200)
-                .body(NAME, equalTo("messagesSet"))
-                .body(ARGUMENTS + ".updated", hasSize(1)));
-        calmlyAwait.atMost(ONE_MINUTE).untilAsserted(() -> assertMessagesFoundInMailbox(aliceAccessToken, getSpamId(aliceAccessToken), 1));
-
-        // Alice is deleting this message
-        messageIds
-            .forEach(messageId -> given()
-                .header("Authorization", aliceAccessToken.asString())
-                .body(String.format("[[\"setMessages\", {\"destroy\": [\"%s\"] }, \"#0\"]]", messageId))
-            .when()
-                .post("/jmap")
-            .then()
-                .statusCode(200)
-                .body(NAME, equalTo("messagesSet"))
-                .body(ARGUMENTS + ".destroyed", hasSize(1)));
-        calmlyAwait.atMost(ONE_MINUTE).untilAsserted(() -> assertMessagesFoundInMailbox(aliceAccessToken, getSpamId(aliceAccessToken), 0));
-
-        // Bob is sending again the same message to Alice
-        given()
-            .header("Authorization", bobAccessToken.asString())
-            .body(setMessageCreate(bobAccessToken))
-        .when()
-            .post("/jmap");
-
-        // This message is delivered in Alice SPAM mailbox (she now must have 1 messages in her Spam mailbox)
-        calmlyAwait.atMost(ONE_MINUTE).untilAsserted(() -> assertMessagesFoundInMailbox(aliceAccessToken, getSpamId(aliceAccessToken), 1));
-    }
-
-    default String setMessageCreate(AccessToken accessToken) {
-        return "[" +
-            "  [" +
-            "    \"setMessages\"," +
-            "    {" +
-            "      \"create\": { \"creationId1337\" : {" +
-            "        \"from\": { \"email\": \"" + BOB + "\"}," +
-            "        \"to\": [{ \"name\": \"recipient\", \"email\": \"" + ALICE + "\"}]," +
-            "        \"subject\": \"Happy News\"," +
-            "        \"textBody\": \"This is a SPAM!!!\r\n\r\n\"," +
-            "        \"mailboxIds\": [\"" + getOutboxId(accessToken) + "\"]" +
-            "      }}" +
-            "    }," +
-            "    \"#0\"" +
-            "  ]" +
-            "]";
-    }
-
-    @Test
-    default void spamShouldBeDeliveredInSpamMailboxOrInboxWhenMultipleRecipientsConfigurations(GuiceJamesServer jamesServer,
-                                                                                               SpamAssassinExtension.SpamAssassin spamAssassin) throws Exception {
-        spamAssassin.train(ALICE);
-        AccessToken aliceAccessToken = accessTokenFor(jamesServer, ALICE, ALICE_PASSWORD);
-        AccessToken bobAccessToken = accessTokenFor(jamesServer, BOB, BOB_PASSWORD);
-        AccessToken paulAccessToken = accessTokenFor(jamesServer, PAUL, PAUL_PASSWORD);
-
-        // Bob is sending a message to Alice & Paul
-        given()
-            .header("Authorization", bobAccessToken.asString())
-            .body(setMessageCreateToMultipleRecipients(bobAccessToken))
-        .when()
-            .post("/jmap");
-        calmlyAwait.atMost(ONE_MINUTE).untilAsserted(() -> assertMessagesFoundInMailbox(aliceAccessToken, getInboxId(aliceAccessToken), 1));
-        calmlyAwait.atMost(ONE_MINUTE).untilAsserted(() -> assertMessagesFoundInMailbox(paulAccessToken, getInboxId(paulAccessToken), 1));
-
-        // Alice is moving this message to Spam -> learning in SpamAssassin
-        List<String> messageIds = with()
-            .header("Authorization", aliceAccessToken.asString())
-            .body("[[\"getMessageList\", {\"filter\":{\"inMailboxes\":[\"" + getInboxId(aliceAccessToken) + "\"]}}, \"#0\"]]")
-        .when()
-            .post("/jmap")
-        .then()
-            .statusCode(200)
-            .body(NAME, equalTo("messageList"))
-            .body(ARGUMENTS + ".messageIds", hasSize(1))
-            .extract()
-            .path(ARGUMENTS + ".messageIds");
-
-        messageIds
-            .forEach(messageId -> given()
-                .header("Authorization", aliceAccessToken.asString())
-                .body(String.format("[[\"setMessages\", {\"update\": {\"%s\" : { \"mailboxIds\": [\"" + getSpamId(aliceAccessToken) + "\"] } } }, \"#0\"]]", messageId))
-            .when()
-                .post("/jmap")
-            .then()
-                .statusCode(200)
-                .body(NAME, equalTo("messagesSet"))
-                .body(ARGUMENTS + ".updated", hasSize(1)));
-        calmlyAwait.atMost(ONE_MINUTE).untilAsserted(() -> assertMessagesFoundInMailbox(aliceAccessToken, getSpamId(aliceAccessToken), 1));
-
-        // Bob is sending again the same message to Alice & Paul
-        given()
-            .header("Authorization", bobAccessToken.asString())
-            .body(setMessageCreateToMultipleRecipients(bobAccessToken))
-        .when()
-            .post("/jmap");
-
-        // This message is delivered in Alice Spam mailbox (she now must have 2 messages in her Spam mailbox)
-        calmlyAwait.atMost(ONE_MINUTE).untilAsserted(() -> assertMessagesFoundInMailbox(aliceAccessToken, getSpamId(aliceAccessToken), 2));
-        calmlyAwait.atMost(ONE_MINUTE).untilAsserted(() -> assertMessagesFoundInMailbox(aliceAccessToken, getInboxId(aliceAccessToken), 0));
-        // This message is delivered in Paul Inbox (he now must have 2 messages in his Inbox)
-        calmlyAwait.atMost(ONE_MINUTE).untilAsserted(() -> assertMessagesFoundInMailbox(paulAccessToken, getInboxId(paulAccessToken), 2));
-        calmlyAwait.atMost(ONE_MINUTE).untilAsserted(() -> assertMessagesFoundInMailbox(paulAccessToken, getSpamId(paulAccessToken), 0));
-    }
-
-    default String setMessageCreateToMultipleRecipients(AccessToken accessToken) {
-        return "[" +
-            "  [" +
-            "    \"setMessages\"," +
-            "    {" +
-            "      \"create\": { \"creationId1337\" : {" +
-            "        \"from\": { \"email\": \"" + BOB + "\"}," +
-            "        \"to\": [{ \"name\": \"alice\", \"email\": \"" + ALICE + "\"}, " +
-            "                 { \"name\": \"paul\", \"email\": \"" + PAUL + "\"}]," +
-            "        \"subject\": \"Happy News\"," +
-            "        \"textBody\": \"This is a SPAM!!!\r\n\r\n\"," +
-            "        \"mailboxIds\": [\"" + getOutboxId(accessToken) + "\"]" +
-            "      }}" +
-            "    }," +
-            "    \"#0\"" +
-            "  ]" +
-            "]";
-    }
-
-    default void assertMessagesFoundInMailbox(AccessToken accessToken, String mailboxId, int expectedNumberOfMessages) {
-        with()
-            .header("Authorization", accessToken.asString())
-            .body("[[\"getMessageList\", {\"filter\":{\"inMailboxes\":[\"" + mailboxId + "\"]}}, \"#0\"]]")
-        .when()
-            .post("/jmap")
-        .then()
-            .statusCode(200)
-            .body(NAME, equalTo("messageList"))
-            .body(ARGUMENTS + ".messageIds", hasSize(expectedNumberOfMessages));
-    }
-
-    default String getMailboxId(AccessToken accessToken, Role role) {
-        return getAllMailboxesIds(accessToken).stream()
-            .filter(x -> x.get("role").equalsIgnoreCase(role.serialize()))
-            .map(x -> x.get("id"))
-            .findFirst().get();
-    }
-
-    default List<Map<String, String>> getAllMailboxesIds(AccessToken accessToken) {
-        return with()
-            .header("Authorization", accessToken.asString())
-            .body("[[\"getMailboxes\", {\"properties\": [\"role\", \"id\"]}, \"#0\"]]")
-        .post("/jmap")
-            .andReturn()
-            .body()
-            .jsonPath()
-            .getList(ARGUMENTS + ".list");
-    }
-
-    default String getInboxId(AccessToken accessToken) {
-        return getMailboxId(accessToken, Role.INBOX);
-    }
-
-    default String getOutboxId(AccessToken accessToken) {
-        return getMailboxId(accessToken, Role.OUTBOX);
-    }
-
-    default String getSpamId(AccessToken accessToken) {
-        return getMailboxId(accessToken, Role.SPAM);
-    }
-
-    default String getTrashId(AccessToken accessToken) {
-        return getMailboxId(accessToken, Role.TRASH);
-    }
-
-    default void assertEveryListenerGotCalled(GuiceJamesServer jamesServer) {
-        assertThat(jamesServer.getProbe(SpoolerProbe.class).processingFinished())
-            .describedAs("waiting that every listener get called")
-            .isTrue();
-    }
-}
diff --git a/server/protocols/jmap-draft-integration-testing/jmap-draft-integration-testing-common/src/test/java/org/apache/james/jmap/draft/methods/integration/SpamAssassinModule.java b/server/protocols/jmap-draft-integration-testing/jmap-draft-integration-testing-common/src/test/java/org/apache/james/jmap/draft/methods/integration/SpamAssassinModule.java
deleted file mode 100644
index 801e804ca0..0000000000
--- a/server/protocols/jmap-draft-integration-testing/jmap-draft-integration-testing-common/src/test/java/org/apache/james/jmap/draft/methods/integration/SpamAssassinModule.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/****************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one   *
- * or more contributor license agreements.  See the NOTICE file *
- * distributed with this work for additional information        *
- * regarding copyright ownership.  The ASF licenses this file   *
- * to you under the Apache License, Version 2.0 (the            *
- * "License"); you may not use this file except in compliance   *
- * with the License.  You may obtain a copy of the License at   *
- *                                                              *
- *   http://www.apache.org/licenses/LICENSE-2.0                 *
- *                                                              *
- * Unless required by applicable law or agreed to in writing,   *
- * software distributed under the License is distributed on an  *
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
- * KIND, either express or implied.  See the License for the    *
- * specific language governing permissions and limitations      *
- * under the License.                                           *
- ****************************************************************/
-package org.apache.james.jmap.draft.methods.integration;
-
-import java.util.Optional;
-
-import javax.inject.Singleton;
-
-import org.apache.commons.configuration2.BaseConfiguration;
-import org.apache.james.mailbox.spamassassin.SpamAssassinConfiguration;
-import org.apache.james.mailbox.spamassassin.SpamAssassinListener;
-import org.apache.james.mailetcontainer.impl.MailetConfigImpl;
-import org.apache.james.modules.mailbox.ListenerConfiguration;
-import org.apache.james.modules.mailbox.ListenersConfiguration;
-import org.apache.james.spamassassin.SpamAssassinExtension;
-import org.apache.james.util.Host;
-import org.apache.james.utils.MailetConfigurationOverride;
-
-import com.google.inject.AbstractModule;
-import com.google.inject.Provides;
-import com.google.inject.multibindings.Multibinder;
-
-public class SpamAssassinModule extends AbstractModule {
-
-    private final SpamAssassinExtension spamAssassinExtension;
-
-    public SpamAssassinModule(SpamAssassinExtension spamAssassinExtension) {
-        this.spamAssassinExtension = spamAssassinExtension;
-    }
-
-    @Override
-    protected void configure() {
-        Multibinder.newSetBinder(binder(), MailetConfigurationOverride.class)
-            .addBinding()
-            .toInstance(
-                new MailetConfigurationOverride(
-                    org.apache.james.transport.mailets.SpamAssassin.class,
-                    spamAssassinMailetConfig()));
-
-        bind(ListenersConfiguration.class)
-            .toInstance(ListenersConfiguration.of(
-                ListenerConfiguration.forClass(SpamAssassinListener.class.getCanonicalName())));
-    }
-
-    @Provides
-    @Singleton
-    private SpamAssassinConfiguration getSpamAssassinConfiguration() {
-        SpamAssassinExtension.SpamAssassin spamAssassin = spamAssassinExtension.getSpamAssassin();
-        return new SpamAssassinConfiguration(Optional.of(Host.from(spamAssassin.getIp(), spamAssassin.getBindingPort())));
-    }
-
-    private MailetConfigImpl spamAssassinMailetConfig() {
-        BaseConfiguration baseConfiguration = new BaseConfiguration();
-        Host host = Host.from(spamAssassinExtension.getSpamAssassin().getIp(), spamAssassinExtension.getSpamAssassin().getBindingPort());
-        baseConfiguration.addProperty(org.apache.james.transport.mailets.SpamAssassin.SPAMD_HOST, host.getHostName());
-        baseConfiguration.addProperty(org.apache.james.transport.mailets.SpamAssassin.SPAMD_PORT, host.getPort());
-
-        MailetConfigImpl mailetConfig = new MailetConfigImpl();
-        mailetConfig.setConfiguration(baseConfiguration);
-        return mailetConfig;
-    }
-
-}
diff --git a/server/protocols/jmap-draft-integration-testing/jmap-draft-integration-testing-common/src/test/java/org/apache/james/jmap/draft/methods/integration/SpamAssassinModuleExtension.java b/server/protocols/jmap-draft-integration-testing/jmap-draft-integration-testing-common/src/test/java/org/apache/james/jmap/draft/methods/integration/SpamAssassinModuleExtension.java
deleted file mode 100644
index f302932f11..0000000000
--- a/server/protocols/jmap-draft-integration-testing/jmap-draft-integration-testing-common/src/test/java/org/apache/james/jmap/draft/methods/integration/SpamAssassinModuleExtension.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/****************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one   *
- * or more contributor license agreements.  See the NOTICE file *
- * distributed with this work for additional information        *
- * regarding copyright ownership.  The ASF licenses this file   *
- * to you under the Apache License, Version 2.0 (the            *
- * "License"); you may not use this file except in compliance   *
- * with the License.  You may obtain a copy of the License at   *
- *                                                              *
- *   http://www.apache.org/licenses/LICENSE-2.0                 *
- *                                                              *
- * Unless required by applicable law or agreed to in writing,   *
- * software distributed under the License is distributed on an  *
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
- * KIND, either express or implied.  See the License for the    *
- * specific language governing permissions and limitations      *
- * under the License.                                           *
- ****************************************************************/
-
-package org.apache.james.jmap.draft.methods.integration;
-
-import java.util.Optional;
-
-import org.apache.james.GuiceModuleTestExtension;
-import org.apache.james.spamassassin.SpamAssassinExtension;
-import org.junit.jupiter.api.extension.ExtensionContext;
-import org.junit.jupiter.api.extension.ParameterContext;
-import org.junit.jupiter.api.extension.ParameterResolutionException;
-
-import com.google.inject.Module;
-
-public class SpamAssassinModuleExtension implements GuiceModuleTestExtension {
-
-    private final SpamAssassinExtension spamAssassin;
-
-    public SpamAssassinModuleExtension() {
-        this.spamAssassin = new org.apache.james.spamassassin.SpamAssassinExtension();
-    }
-
-    @Override
-    public void beforeAll(ExtensionContext extensionContext) {
-        spamAssassin.beforeAll(extensionContext);
-    }
-
-    @Override
-    public void afterAll(ExtensionContext extensionContext) {
-        spamAssassin.afterAll(extensionContext);
-    }
-
-    @Override
-    public Module getModule() {
-        return new SpamAssassinModule(spamAssassin);
-    }
-
-    @Override
-    public Optional<Class<?>> supportedParameterClass() {
-        return Optional.of(SpamAssassinExtension.SpamAssassin.class);
-    }
-
-    @Override
-    public Object resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext) throws ParameterResolutionException {
-        return spamAssassin.getSpamAssassin();
-    }
-}
diff --git a/server/protocols/jmap-draft-integration-testing/jmap-draft-integration-testing-common/src/test/resources/spamassassin_db/ham/ham1 b/server/protocols/jmap-draft-integration-testing/jmap-draft-integration-testing-common/src/test/resources/spamassassin_db/ham/ham1
deleted file mode 100644
index c50bb11c0a..0000000000
--- a/server/protocols/jmap-draft-integration-testing/jmap-draft-integration-testing-common/src/test/resources/spamassassin_db/ham/ham1
+++ /dev/null
@@ -1,113 +0,0 @@
-From exmh-workers-admin@redhat.com  Thu Aug 22 12:36:23 2002
-Return-Path: <ex...@spamassassin.taint.org>
-Delivered-To: zzzz@localhost.netnoteinc.com
-Received: from localhost (localhost [127.0.0.1])
-	by phobos.labs.netnoteinc.com (Postfix) with ESMTP id D03E543C36
-	for <zz...@localhost>; Thu, 22 Aug 2002 07:36:16 -0400 (EDT)
-Received: from phobos [127.0.0.1]
-	by localhost with IMAP (fetchmail-5.9.0)
-	for zzzz@localhost (single-drop); Thu, 22 Aug 2002 12:36:16 +0100 (IST)
-Received: from listman.spamassassin.taint.org (listman.spamassassin.taint.org [66.187.233.211]) by
-    dogma.slashnull.org (8.11.6/8.11.6) with ESMTP id g7MBYrZ04811 for
-    <zz...@spamassassin.taint.org>; Thu, 22 Aug 2002 12:34:53 +0100
-Received: from listman.spamassassin.taint.org (localhost.localdomain [127.0.0.1]) by
-    listman.redhat.com (Postfix) with ESMTP id 8386540858; Thu, 22 Aug 2002
-    07:35:02 -0400 (EDT)
-Delivered-To: exmh-workers@listman.spamassassin.taint.org
-Received: from int-mx1.corp.spamassassin.taint.org (int-mx1.corp.spamassassin.taint.org
-    [172.16.52.254]) by listman.redhat.com (Postfix) with ESMTP id 10CF8406D7
-    for <ex...@listman.redhat.com>; Thu, 22 Aug 2002 07:34:10 -0400
-    (EDT)
-Received: (from mail@localhost) by int-mx1.corp.spamassassin.taint.org (8.11.6/8.11.6)
-    id g7MBY7g11259 for exmh-workers@listman.redhat.com; Thu, 22 Aug 2002
-    07:34:07 -0400
-Received: from mx1.spamassassin.taint.org (mx1.spamassassin.taint.org [172.16.48.31]) by
-    int-mx1.corp.redhat.com (8.11.6/8.11.6) with SMTP id g7MBY7Y11255 for
-    <ex...@redhat.com>; Thu, 22 Aug 2002 07:34:07 -0400
-Received: from ratree.psu.ac.th ([202.28.97.6]) by mx1.spamassassin.taint.org
-    (8.11.6/8.11.6) with SMTP id g7MBIhl25223 for <ex...@redhat.com>;
-    Thu, 22 Aug 2002 07:18:55 -0400
-Received: from delta.cs.mu.OZ.AU (delta.coe.psu.ac.th [172.30.0.98]) by
-    ratree.psu.ac.th (8.11.6/8.11.6) with ESMTP id g7MBWel29762;
-    Thu, 22 Aug 2002 18:32:40 +0700 (ICT)
-Received: from munnari.OZ.AU (localhost [127.0.0.1]) by delta.cs.mu.OZ.AU
-    (8.11.6/8.11.6) with ESMTP id g7MBQPW13260; Thu, 22 Aug 2002 18:26:25
-    +0700 (ICT)
-From: Robert Elz <kr...@munnari.OZ.AU>
-To: Chris Garrigues <cw...@DeepEddy.Com>
-Cc: exmh-workers@spamassassin.taint.org
-Subject: Re: New Sequences Window
-In-Reply-To: <10...@deepeddy.vircio.com>
-References: <10...@deepeddy.vircio.com>
-    <10...@deepeddy.vircio.com> <96...@munnari.OZ.AU>
-    <10...@deepeddy.vircio.com>
-    <10...@deepeddy.vircio.com>
-MIME-Version: 1.0
-Content-Type: text/plain; charset=us-ascii
-Message-Id: <13...@munnari.OZ.AU>
-X-Loop: exmh-workers@spamassassin.taint.org
-Sender: exmh-workers-admin@spamassassin.taint.org
-Errors-To: exmh-workers-admin@spamassassin.taint.org
-X-Beenthere: exmh-workers@spamassassin.taint.org
-X-Mailman-Version: 2.0.1
-Precedence: bulk
-List-Help: <mailto:exmh-workers-request@spamassassin.taint.org?subject=help>
-List-Post: <ma...@spamassassin.taint.org>
-List-Subscribe: <https://listman.spamassassin.taint.org/mailman/listinfo/exmh-workers>,
-    <mailto:exmh-workers-request@redhat.com?subject=subscribe>
-List-Id: Discussion list for EXMH developers <exmh-workers.spamassassin.taint.org>
-List-Unsubscribe: <https://listman.spamassassin.taint.org/mailman/listinfo/exmh-workers>,
-    <mailto:exmh-workers-request@redhat.com?subject=unsubscribe>
-List-Archive: <https://listman.spamassassin.taint.org/mailman/private/exmh-workers/>
-Date: Thu, 22 Aug 2002 18:26:25 +0700
-
-    Date:        Wed, 21 Aug 2002 10:54:46 -0500
-    From:        Chris Garrigues <cw...@DeepEddy.Com>
-    Message-ID:  <10...@deepeddy.vircio.com>
-
-
-  | I can't reproduce this error.
-
-For me it is very repeatable... (like every time, without fail).
-
-This is the debug log of the pick happening ...
-
-18:19:03 Pick_It {exec pick +inbox -list -lbrace -lbrace -subject ftp -rbrace -rbrace} {4852-4852 -sequence mercury}
-18:19:03 exec pick +inbox -list -lbrace -lbrace -subject ftp -rbrace -rbrace 4852-4852 -sequence mercury
-18:19:04 Ftoc_PickMsgs {{1 hit}}
-18:19:04 Marking 1 hits
-18:19:04 tkerror: syntax error in expression "int ...
-
-Note, if I run the pick command by hand ...
-
-delta$ pick +inbox -list -lbrace -lbrace -subject ftp -rbrace -rbrace  4852-4852 -sequence mercury
-1 hit
-
-That's where the "1 hit" comes from (obviously).  The version of nmh I'm
-using is ...
-
-delta$ pick -version
-pick -- nmh-1.0.4 [compiled on fuchsia.cs.mu.OZ.AU at Sun Mar 17 14:55:56 ICT 2002]
-
-And the relevant part of my .mh_profile ...
-
-delta$ mhparam pick
--seq sel -list
-
-
-Since the pick command works, the sequence (actually, both of them, the
-one that's explicit on the command line, from the search popup, and the
-one that comes from .mh_profile) do get created.
-
-kre
-
-ps: this is still using the version of the code form a day ago, I haven't
-been able to reach the cvs repository today (local routing issue I think).
-
-
-
-_______________________________________________
-Exmh-workers mailing list
-Exmh-workers@redhat.com
-https://listman.redhat.com/mailman/listinfo/exmh-workers
-
diff --git a/server/protocols/jmap-draft-integration-testing/jmap-draft-integration-testing-common/src/test/resources/spamassassin_db/ham/ham2 b/server/protocols/jmap-draft-integration-testing/jmap-draft-integration-testing-common/src/test/resources/spamassassin_db/ham/ham2
deleted file mode 100644
index 7a5b23a497..0000000000
--- a/server/protocols/jmap-draft-integration-testing/jmap-draft-integration-testing-common/src/test/resources/spamassassin_db/ham/ham2
+++ /dev/null
@@ -1,73 +0,0 @@
-From Steve_Burt@cursor-system.com  Thu Aug 22 12:46:39 2002
-Return-Path: <St...@cursor-system.com>
-Delivered-To: zzzz@localhost.netnoteinc.com
-Received: from localhost (localhost [127.0.0.1])
-	by phobos.labs.netnoteinc.com (Postfix) with ESMTP id BE12E43C34
-	for <zz...@localhost>; Thu, 22 Aug 2002 07:46:38 -0400 (EDT)
-Received: from phobos [127.0.0.1]
-	by localhost with IMAP (fetchmail-5.9.0)
-	for zzzz@localhost (single-drop); Thu, 22 Aug 2002 12:46:38 +0100 (IST)
-Received: from n20.grp.scd.yahoo.com (n20.grp.scd.yahoo.com
-    [66.218.66.76]) by dogma.slashnull.org (8.11.6/8.11.6) with SMTP id
-    g7MBkTZ05087 for <zz...@spamassassin.taint.org>; Thu, 22 Aug 2002 12:46:29 +0100
-X-Egroups-Return: sentto-2242572-52726-1030016790-zzzz=spamassassin.taint.org@returns.groups.yahoo.com
-Received: from [66.218.67.196] by n20.grp.scd.yahoo.com with NNFMP;
-    22 Aug 2002 11:46:30 -0000
-X-Sender: steve.burt@cursor-system.com
-X-Apparently-To: zzzzteana@yahoogroups.com
-Received: (EGP: mail-8_1_0_1); 22 Aug 2002 11:46:29 -0000
-Received: (qmail 11764 invoked from network); 22 Aug 2002 11:46:29 -0000
-Received: from unknown (66.218.66.217) by m3.grp.scd.yahoo.com with QMQP;
-    22 Aug 2002 11:46:29 -0000
-Received: from unknown (HELO mailgateway.cursor-system.com) (62.189.7.27)
-    by mta2.grp.scd.yahoo.com with SMTP; 22 Aug 2002 11:46:29 -0000
-Received: from exchange1.cps.local (unverified) by
-    mailgateway.cursor-system.com (Content Technologies SMTPRS 4.2.10) with
-    ESMTP id <T5...@mailgateway.cursor-system.com> for
-    <fo...@yahoogroups.com>; Thu, 22 Aug 2002 13:14:10 +0100
-Received: by exchange1.cps.local with Internet Mail Service (5.5.2653.19)
-    id <PXX6AT23>; Thu, 22 Aug 2002 12:46:27 +0100
-Message-Id: <5E...@exchange1.cps.local>
-To: "'zzzzteana@yahoogroups.com'" <zz...@yahoogroups.com>
-X-Mailer: Internet Mail Service (5.5.2653.19)
-X-Egroups-From: Steve Burt <st...@cursor-system.com>
-From: Steve Burt <St...@cursor-system.com>
-X-Yahoo-Profile: pyruse
-MIME-Version: 1.0
-Mailing-List: list zzzzteana@yahoogroups.com; contact
-    forteana-owner@yahoogroups.com
-Delivered-To: mailing list zzzzteana@yahoogroups.com
-Precedence: bulk
-List-Unsubscribe: <ma...@yahoogroups.com>
-Date: Thu, 22 Aug 2002 12:46:18 +0100
-Subject: [zzzzteana] RE: Alexander
-Reply-To: zzzzteana@yahoogroups.com
-Content-Type: text/plain; charset=US-ASCII
-Content-Transfer-Encoding: 7bit
-
-Martin A posted:
-Tassos Papadopoulos, the Greek sculptor behind the plan, judged that the
- limestone of Mount Kerdylio, 70 miles east of Salonika and not far from the
- Mount Athos monastic community, was ideal for the patriotic sculpture. 
- 
- As well as Alexander's granite features, 240 ft high and 170 ft wide, a
- museum, a restored amphitheatre and car park for admiring crowds are
-planned
----------------------
-So is this mountain limestone or granite?
-If it's limestone, it'll weather pretty fast.
-
------------------------- Yahoo! Groups Sponsor ---------------------~-->
-4 DVDs Free +s&p Join Now
-http://us.click.yahoo.com/pt6YBB/NXiEAA/mG3HAA/7gSolB/TM
----------------------------------------------------------------------~->
-
-To unsubscribe from this group, send an email to:
-forteana-unsubscribe@egroups.com
-
- 
-
-Your use of Yahoo! Groups is subject to http://docs.yahoo.com/info/terms/ 
-
-
-
diff --git a/server/protocols/jmap-draft-integration-testing/jmap-draft-integration-testing-common/src/test/resources/spamassassin_db/ham/ham3 b/server/protocols/jmap-draft-integration-testing/jmap-draft-integration-testing-common/src/test/resources/spamassassin_db/ham/ham3
deleted file mode 100644
index c7cfbc84d7..0000000000
--- a/server/protocols/jmap-draft-integration-testing/jmap-draft-integration-testing-common/src/test/resources/spamassassin_db/ham/ham3
+++ /dev/null
@@ -1,82 +0,0 @@
-From timc@2ubh.com  Thu Aug 22 13:52:59 2002
-Return-Path: <ti...@2ubh.com>
-Delivered-To: zzzz@localhost.netnoteinc.com
-Received: from localhost (localhost [127.0.0.1])
-	by phobos.labs.netnoteinc.com (Postfix) with ESMTP id 0314547C66
-	for <zz...@localhost>; Thu, 22 Aug 2002 08:52:58 -0400 (EDT)
-Received: from phobos [127.0.0.1]
-	by localhost with IMAP (fetchmail-5.9.0)
-	for zzzz@localhost (single-drop); Thu, 22 Aug 2002 13:52:59 +0100 (IST)
-Received: from n16.grp.scd.yahoo.com (n16.grp.scd.yahoo.com
-    [66.218.66.71]) by dogma.slashnull.org (8.11.6/8.11.6) with SMTP id
-    g7MCrdZ07070 for <zz...@spamassassin.taint.org>; Thu, 22 Aug 2002 13:53:39 +0100
-X-Egroups-Return: sentto-2242572-52733-1030020820-zzzz=spamassassin.taint.org@returns.groups.yahoo.com
-Received: from [66.218.67.198] by n16.grp.scd.yahoo.com with NNFMP;
-    22 Aug 2002 12:53:40 -0000
-X-Sender: timc@2ubh.com
-X-Apparently-To: zzzzteana@yahoogroups.com
-Received: (EGP: mail-8_1_0_1); 22 Aug 2002 12:53:39 -0000
-Received: (qmail 76099 invoked from network); 22 Aug 2002 12:53:39 -0000
-Received: from unknown (66.218.66.218) by m5.grp.scd.yahoo.com with QMQP;
-    22 Aug 2002 12:53:39 -0000
-Received: from unknown (HELO rhenium.btinternet.com) (194.73.73.93) by
-    mta3.grp.scd.yahoo.com with SMTP; 22 Aug 2002 12:53:39 -0000
-Received: from host217-36-23-185.in-addr.btopenworld.com ([217.36.23.185])
-    by rhenium.btinternet.com with esmtp (Exim 3.22 #8) id 17hrT0-0004gj-00
-    for forteana@yahoogroups.com; Thu, 22 Aug 2002 13:53:38 +0100
-X-Mailer: Microsoft Outlook Express Macintosh Edition - 4.5 (0410)
-To: zzzzteana <zz...@yahoogroups.com>
-X-Priority: 3
-Message-Id: <E1...@rhenium.btinternet.com>
-From: "Tim Chapman" <ti...@2ubh.com>
-X-Yahoo-Profile: tim2ubh
-MIME-Version: 1.0
-Mailing-List: list zzzzteana@yahoogroups.com; contact
-    forteana-owner@yahoogroups.com
-Delivered-To: mailing list zzzzteana@yahoogroups.com
-Precedence: bulk
-List-Unsubscribe: <ma...@yahoogroups.com>
-Date: Thu, 22 Aug 2002 13:52:38 +0100
-Subject: [zzzzteana] Moscow bomber
-Reply-To: zzzzteana@yahoogroups.com
-Content-Type: text/plain; charset=US-ASCII
-Content-Transfer-Encoding: 7bit
-
-Man Threatens Explosion In Moscow 
-
-Thursday August 22, 2002 1:40 PM
-MOSCOW (AP) - Security officers on Thursday seized an unidentified man who
-said he was armed with explosives and threatened to blow up his truck in
-front of Russia's Federal Security Services headquarters in Moscow, NTV
-television reported.
-The officers seized an automatic rifle the man was carrying, then the man
-got out of the truck and was taken into custody, NTV said. No other details
-were immediately available.
-The man had demanded talks with high government officials, the Interfax and
-ITAR-Tass news agencies said. Ekho Moskvy radio reported that he wanted to
-talk with Russian President Vladimir Putin.
-Police and security forces rushed to the Security Service building, within
-blocks of the Kremlin, Red Square and the Bolshoi Ballet, and surrounded the
-man, who claimed to have one and a half tons of explosives, the news
-agencies said. Negotiations continued for about one and a half hours outside
-the building, ITAR-Tass and Interfax reported, citing witnesses.
-The man later drove away from the building, under police escort, and drove
-to a street near Moscow's Olympic Penta Hotel, where authorities held
-further negotiations with him, the Moscow police press service said. The
-move appeared to be an attempt by security services to get him to a more
-secure location. 
-
------------------------- Yahoo! Groups Sponsor ---------------------~-->
-4 DVDs Free +s&p Join Now
-http://us.click.yahoo.com/pt6YBB/NXiEAA/mG3HAA/7gSolB/TM
----------------------------------------------------------------------~->
-
-To unsubscribe from this group, send an email to:
-forteana-unsubscribe@egroups.com
-
- 
-
-Your use of Yahoo! Groups is subject to http://docs.yahoo.com/info/terms/ 
-
-
-
diff --git a/server/protocols/jmap-draft-integration-testing/jmap-draft-integration-testing-common/src/test/resources/spamassassin_db/spam/spam1 b/server/protocols/jmap-draft-integration-testing/jmap-draft-integration-testing-common/src/test/resources/spamassassin_db/spam/spam1
deleted file mode 100644
index 8bad7877e3..0000000000
--- a/server/protocols/jmap-draft-integration-testing/jmap-draft-integration-testing-common/src/test/resources/spamassassin_db/spam/spam1
+++ /dev/null
@@ -1,108 +0,0 @@
-From ilug-admin@linux.ie  Tue Aug  6 11:51:02 2002
-Return-Path: <il...@linux.ie>
-Delivered-To: yyyy@localhost.netnoteinc.com
-Received: from localhost (localhost [127.0.0.1])
-	by phobos.labs.netnoteinc.com (Postfix) with ESMTP id 9E1F5441DD
-	for <jm...@localhost>; Tue,  6 Aug 2002 06:48:09 -0400 (EDT)
-Received: from phobos [127.0.0.1]
-	by localhost with IMAP (fetchmail-5.9.0)
-	for jm@localhost (single-drop); Tue, 06 Aug 2002 11:48:09 +0100 (IST)
-Received: from lugh.tuatha.org (root@lugh.tuatha.org [194.125.145.45]) by
-    dogma.slashnull.org (8.11.6/8.11.6) with ESMTP id g72LqWv13294 for
-    <jm...@jmason.org>; Fri, 2 Aug 2002 22:52:32 +0100
-Received: from lugh (root@localhost [127.0.0.1]) by lugh.tuatha.org
-    (8.9.3/8.9.3) with ESMTP id WAA31224; Fri, 2 Aug 2002 22:50:17 +0100
-Received: from bettyjagessar.com (w142.z064000057.nyc-ny.dsl.cnc.net
-    [64.0.57.142]) by lugh.tuatha.org (8.9.3/8.9.3) with ESMTP id WAA31201 for
-    <il...@linux.ie>; Fri, 2 Aug 2002 22:50:11 +0100
-X-Authentication-Warning: lugh.tuatha.org: Host w142.z064000057.nyc-ny.dsl.cnc.net
-    [64.0.57.142] claimed to be bettyjagessar.com
-Received: from 64.0.57.142 [202.63.165.34] by bettyjagessar.com
-    (SMTPD32-7.06 EVAL) id A42A7FC01F2; Fri, 02 Aug 2002 02:18:18 -0400
-Message-Id: <10...@0.57.142>
-Date: Fri, 02 Aug 2002 23:37:59 0530
-To: ilug@linux.ie
-From: "Start Now" <st...@hotmail.com>
-MIME-Version: 1.0
-Content-Type: text/plain; charset="US-ASCII"; format=flowed
-Subject: [ILUG] STOP THE MLM INSANITY
-Sender: ilug-admin@linux.ie
-Errors-To: ilug-admin@linux.ie
-X-Mailman-Version: 1.1
-Precedence: bulk
-List-Id: Irish Linux Users' Group <ilug.linux.ie>
-X-Beenthere: ilug@linux.ie
-
-Greetings!
-
-You are receiving this letter because you have expressed an interest in 
-receiving information about online business opportunities. If this is 
-erroneous then please accept my most sincere apology. This is a one-time 
-mailing, so no removal is necessary.
-
-If you've been burned, betrayed, and back-stabbed by multi-level marketing, 
-MLM, then please read this letter. It could be the most important one that 
-has ever landed in your Inbox.
-
-MULTI-LEVEL MARKETING IS A HUGE MISTAKE FOR MOST PEOPLE
-
-MLM has failed to deliver on its promises for the past 50 years. The pursuit 
-of the "MLM Dream" has cost hundreds of thousands of people their friends, 
-their fortunes and their sacred honor. The fact is that MLM is fatally 
-flawed, meaning that it CANNOT work for most people.
-
-The companies and the few who earn the big money in MLM are NOT going to 
-tell you the real story. FINALLY, there is someone who has the courage to 
-cut through the hype and lies and tell the TRUTH about MLM.
-
-HERE'S GOOD NEWS
-
-There IS an alternative to MLM that WORKS, and works BIG! If you haven't yet 
-abandoned your dreams, then you need to see this. Earning the kind of income 
-you've dreamed about is easier than you think!
-
-With your permission, I'd like to send you a brief letter that will tell you 
-WHY MLM doesn't work for most people and will then introduce you to 
-something so new and refreshing that you'll wonder why you haven't heard of 
-this before.
-
-I promise that there will be NO unwanted follow up, NO sales pitch, no one 
-will call you, and your email address will only be used to send you the 
-information. Period.
-
-To receive this free, life-changing information, simply click Reply, type 
-"Send Info" in the Subject box and hit Send. I'll get the information to you 
-within 24 hours. Just look for the words MLM WALL OF SHAME in your Inbox.
-
-Cordially,
-
-Siddhi
-
-P.S. Someone recently sent the letter to me and it has been the most 
-eye-opening, financially beneficial information I have ever received. I 
-honestly believe that you will feel the same way once you've read it. And 
-it's FREE!
-
-
-------------------------------------------------------------
-This email is NEVER sent unsolicited.  THIS IS NOT "SPAM". You are receiving 
-this email because you EXPLICITLY signed yourself up to our list with our 
-online signup form or through use of our FFA Links Page and E-MailDOM 
-systems, which have EXPLICIT terms of use which state that through its use 
-you agree to receive our emailings.  You may also be a member of a Altra 
-Computer Systems list or one of many numerous FREE Marketing Services and as 
-such you agreed when you signed up for such list that you would also be 
-receiving this emailing.
-Due to the above, this email message cannot be considered unsolicitated, or 
-spam.
------------------------------------------------------------
-
-
-
-
--- 
-Irish Linux Users' Group: ilug@linux.ie
-http://www.linux.ie/mailman/listinfo/ilug for (un)subscription information.
-List maintainer: listmaster@linux.ie
-
-
diff --git a/server/protocols/jmap-draft-integration-testing/jmap-draft-integration-testing-common/src/test/resources/spamassassin_db/spam/spam2 b/server/protocols/jmap-draft-integration-testing/jmap-draft-integration-testing-common/src/test/resources/spamassassin_db/spam/spam2
deleted file mode 100644
index 88a809eb5f..0000000000
--- a/server/protocols/jmap-draft-integration-testing/jmap-draft-integration-testing-common/src/test/resources/spamassassin_db/spam/spam2
+++ /dev/null
@@ -1,186 +0,0 @@
-From lmrn@mailexcite.com  Mon Jun 24 17:03:24 2002
-Return-Path: merchantsworld2001@juno.com
-Delivery-Date: Mon May 13 04:46:13 2002
-Received: from mandark.labs.netnoteinc.com ([213.105.180.140]) by
-    dogma.slashnull.org (8.11.6/8.11.6) with ESMTP id g4D3kCe15097 for
-    <jm...@jmason.org>; Mon, 13 May 2002 04:46:12 +0100
-Received: from 203.129.205.5.205.129.203.in-addr.arpa ([203.129.205.5]) by
-    mandark.labs.netnoteinc.com (8.11.2/8.11.2) with SMTP id g4D3k2D12605 for
-    <jm...@netnoteinc.com>; Mon, 13 May 2002 04:46:04 +0100
-Received: from html (unverified [207.95.174.49]) by
-    203.129.205.5.205.129.203.in-addr.arpa (EMWAC SMTPRS 0.83) with SMTP id
-    <B0...@203.129.205.5.205.129.203.in-addr.arpa>; Mon, 13 May 2002
-    09:04:46 +0530
-Message-Id: <B0...@203.129.205.5.205.129.203.in-addr.arpa>
-From: lmrn@mailexcite.com
-To: ranmoore@cybertime.net
-Subject: Real Protection, Stun Guns!  Free Shipping! Time:2:01:35 PM
-Date: Mon, 28 Jul 1980 14:01:35
-MIME-Version: 1.0
-X-Keywords: 
-Content-Type: text/html; charset="DEFAULT"
-
-<html>
-<body>
-<center>
-<h3>
-<font color="blue">
-<b>
-The Need For Safety Is Real In 2002, You Might Only Get One Chance - Be Ready!
-<p>
-Free Shipping & Handling Within The (USA) If You Order Before May 25, 2002! 
-<p>
-3 Day Super Sale, Now Until May 7, 2002!  Save Up To $30.00 On Some Items!
-
-</b>
-</font>
-</h3>
-</center>
-<p>
-IT'S GETTING TO BE SPRING AGAIN, PROTECT YOURSELF AS YOU WALK,<br>
-JOG AND EXERCISE OUTSIDE.  ALSO PROTECT YOUR LOVED ONES AS<br>
-THEY RETURN HOME FROM COLLEGE!<br>
-<p>
-*     LEGAL PROTECTION FOR COLLEGE STUDENTS!<br>
-*     GREAT UP'COMING OUTDOOR PROTECTION GIFTS!<br>
-*     THERE IS NOTHING WORTH MORE PROTECTING THAN LIFE!<br>
-*     OUR STUN DEVICES & PEPPER PRODUCTS ARE LEGAL PROTECTION!
-<p>
-<b>
-<font color="red">
-JOIN THE WAR ON CRIME!
-</b>
-</font>
-<p>
-
-STUN GUNS AND BATONS 
-<p>
-EFFECTIVE - SAFE - NONLETHAL
-<p>
-PROTECT YOUR LOVED ONES AND YOURSELF
-<p>
-No matter who you are, no matter what City or Town you live in,<br>
-if you live in America, you will be touched by crime.
-<p>
-You hear about it on TV.  You read about it in the newspaper.<br>
-It's no secret that crime is a major problem in the U.S. today.<br>
-Criminals are finding it easier to commit crimes all the time.
-<p>
-Weapons are readily available.  Our cities' police forces have<br>
-more work than they can handle.  Even if these criminal are<br>
-caught, they won't be spending long in our nation's overcrowded<br>
-jails.  And while lawmakers are well aware of the crime problem,<br>
-they don't seem to have any effective answers.
-<p>
-Our Email Address:  <a
-href="mailto:Merchants4all@aol.com">Merchants4all@aol.com</a>
-<p>
-INTERESTED:
-<p>
-You will be protecting yourself within 7 days!  Don't Wait,<br>
-visit our web page below, and join The War On Crime!
-<p>
-*****************<br>
-<a
-href="http://www.geocities.com/realprotection_20022003/">http://www.geocities.com/realprotection_20022003/</a><br>
-*****************
-<p>
-Well, there is an effective answer.  Take responsibility for<br>
-your own security.  Our site has a variety of quality personal<br>
-security products.  Visit our site, choose the personal security<br>
-products that are right for you.  Use them, and join the war on
-crime!
-<p>
-FREE PEPPER SPRAY WITH ANY STUN UNIT PURCHASE.<br>
-(A Value of $15.95)
-<p>
-We Ship Orders Within 5 To 7 Days, To Every State In The U.S.A.<br>
-by UPS, FEDEX, or U.S. POSTAL SERVICE.  Visa, MasterCard, American<br>
-Express & Debt Card Gladly Accepted.
-<p>
-Ask yourself this question, if you don't help your loved ones,
-who will?
-<p>
-INTERESTED:
-<p>
-*****************<br>
-<a
-href="http://www.geocities.com/realprotection_20022003/">http://www.geocities.com/realprotection_20022003/</a><br>
-*****************
-<p>
-___The Stun Monster 625,000 Volts ($86.95)<br>
-___The Z-Force Slim Style 300,000 Volts ($64.95)<br>
-___The StunMaster 300,000 Volts Straight ($59.95)<br>
-___The StunMaster 300,000 Volts Curb ($59.95)<br>
-___The StunMaster 200,000 Volts Straight ($49.95)<br>
-___The StunMaster 200,000 Volts Curb ($49.95)<br>
-___The StunBaton 500,000 Volts ($89.95)<br>
-___The StunBaton 300,000 Volts ($79.95)<br>
-___Pen Knife (One $12.50, Two Or More $9.00)<br>
-___Wildfire Pepper Spray  (One $15.95, Two Or More $11.75)
-<p>
-___Add $5.75 For Shipping & Handling Charge.
-<p>
-
-To Order by postal mail, please send to the below address.<br>
-Make payable to Mega Safety Technology.
-<p>
-Mega Safety Technology<br>
-3215 Merrimac Ave.<br>
-Dayton, Ohio  45405<br>
-Our Email Address:  <a
-href="mailto:Merchants4all@aol.com">Merchants4all@aol.com</a>
-<p>
-Order by 24 Hour Fax!!!  775-257-6657.
-<p>
-*****<br>
-<b><font color="red">Important Credit Card Information! Please Read Below!</b></font>
- <br><br>
-*     Credit Card Address, City, State and Zip Code, must match
-      billing address to be processed. 
-<br><br>
-
-CHECK____  MONEYORDER____  VISA____ MASTERCARD____ AmericanExpress___
-Debt Card___
-<br><br>
-Name_______________________________________________________<br>
-(As it appears on Check or Credit Card)
-<br><br>
-Address____________________________________________________<br>
-(As it appears on Check or Credit Card)
-<br><br>
-___________________________________________________<br>
-City,State,Zip(As it appears on Check or Credit Card)
-<br><br>
-___________________________________________________<br>
-Country
-<br><br>
-___________________________________________________<br>
-(Credit Card Number)
-<br><br>
-Expiration Month_____  Year_____
-<br><br>
-___________________________________________________<br>
-Authorized Signature
-<br><br>
-<b>
-*****IMPORTANT NOTE*****
-</b>
-<br><br>
-If Shipping Address Is Different From The Billing Address Above,
-Please Fill Out Information Below.
-<br><br>
-Shipping Name______________________________________________
-<br><br>
-Shipping Address___________________________________________
-<br><br>
-___________________________________________________________<br>
-Shipping City,State,Zip
-<br><br>
-___________________________________________________________<br>
-Country
-<br><br>
-___________________________________________________________<br>
-Email Address & Phone Number(Please Write Neat)
-</body>
-</html>
diff --git a/server/protocols/jmap-draft-integration-testing/jmap-draft-integration-testing-common/src/test/resources/spamassassin_db/spam/spam3 b/server/protocols/jmap-draft-integration-testing/jmap-draft-integration-testing-common/src/test/resources/spamassassin_db/spam/spam3
deleted file mode 100644
index e828804aa0..0000000000
--- a/server/protocols/jmap-draft-integration-testing/jmap-draft-integration-testing-common/src/test/resources/spamassassin_db/spam/spam3
+++ /dev/null
@@ -1,211 +0,0 @@
-From amknight@mailexcite.com  Mon Jun 24 17:03:49 2002
-Return-Path: merchantsworld2001@juno.com
-Delivery-Date: Wed May 15 08:58:23 2002
-Received: from mandark.labs.netnoteinc.com ([213.105.180.140]) by
-    dogma.slashnull.org (8.11.6/8.11.6) with ESMTP id g4F7wIe23864 for
-    <jm...@jmason.org>; Wed, 15 May 2002 08:58:18 +0100
-Received: from webcust2.hightowertech.com (webcust2.hightowertech.com
-    [216.41.166.100]) by mandark.labs.netnoteinc.com (8.11.2/8.11.2) with
-    ESMTP id g4F7wGD24120 for <jm...@netnoteinc.com>; Wed, 15 May 2002 08:58:17
-    +0100
-Received: from html ([206.216.197.214]) by webcust2.hightowertech.com with
-    Microsoft SMTPSVC(5.5.1877.197.19); Wed, 15 May 2002 00:55:53 -0700
-From: amknight@mailexcite.com
-To: cbmark@cbmark.com
-Subject: New Improved Fat Burners, Now With TV Fat Absorbers! Time:6:25:49 PM
-Date: Wed, 30 Jul 1980 18:25:49
-MIME-Version: 1.0
-Message-Id: <08...@webcust2.hightowertech.com>
-X-Keywords: 
-Content-Type: text/html; charset="DEFAULT"
-
-<html>
-<body>
-<center>
-<b>
-<font color="blue">
-*****Bonus Fat Absorbers As Seen On TV, Included Free With Purchase Of 2 Or More Bottle, $24.95 Value*****
-</font>
-<br>
-<br>
-***TAKE $10.00 OFF 2 & 3 MONTH SUPPLY ORDERS, $5.00 OFF 1 MONTH SUPPLY!
-***AND STILL GET YOUR BONUS!  PRICE WILL BE DEDUCTED DURING PROCESSING.
-<br>
-<br>
-***FAT ABSORBERS ARE GREAT FOR THOSE WHO WANT TO LOSE WEIGHT,  BUT CAN'T STAY ON A DIET***
-<br>
-<br>
-***OFFER GOOD UNTIL MAY 27, 2002!  FOREIGN ORDERS INCLUDED!
-<br>
-<br>
-
-<font color="blue">
-
-LOSE 30 POUNDS  IN 30 DAYS... GUARANTEED!!!
-<br>
-<br>
-
-All Natural Weight-Loss Program, Speeds Up The Metabolism Safely
-Rated #1 In Both Categories of SAFETY & EFFECTIVENESS In<br>
-(THE United States Today)
-<br><br>
-WE'LL HELP YOU GET THINNER!
-WE'RE GOING TO HELP YOU LOOK GOOD, FEEL GOOD AND TAKE CONTROL IN
-2002
-<br>
-<br>
-</b>
-</font color="blue">
-</center>
-
-Why Use Our Amazing Weight Loss Capsules?
-<br><br>
-*  They act like a natural magnet to attract fat.<br>
-*  Stimulates the body's natural metabolism. <br>
-*  Controls appetite naturally and makes it easier to
-   eat the right foods consistently.<br>
-*  Reduces craving for sweets.<br>
-*  Aids in the absorption of fat and in overall digestion.<br>
-*  Inhibits bad cholesterol and boosts good cholesterol.<br>
-*  Aids in the process of weight loss and long-term weight management.<br>
-*  Completely safe, UltraTrim New Century contains no banned
-   substances and has no known side effects.<br>
-<br>
-What Makes UltraTrim New Century Unique?
-<br><br>
-A scientifically designed combination of natural ingredients that
-provide long-term weight management in a safe and effective manner.
-<br><br>
-*****<br>
-Receive A Bonus Supply Of Ultra Trim New Century & A Bottle Of Fat Absorbers Listed Above, 
-With Every Order Of 2 Or More Bottles. Offer Good Until May. 27, 2002! <br>
-*****
-<br><br>
-WE GLADLY SHIP TO ALL FOREIGN COUNTRIES! 
-<br><br>
-You will be losing by tomorrow!  Don't Wait, visit our web
-page below, and order now!
-<br><br>
-Email Address:   <a
-href="mailto:ultratrimnow2001@aol.com">ultratrimnow2001@aol.com</a>
-<br><br>
-Order by 24 Hour Fax!!!  775-257-6657.<br>
-<br>
-*****************<br>
-<a
-href="http://www.geocities.com/ultra_weightloss_2002/">http://www.geocities.com/ultra_weightloss_2002/</a><br>
-*****************
-<br><br>
-This is the easiest, fastest, and most effective way to lose both
-pounds and inches permanently!!!  This weight loss program is
-designed specifically to "boost" weight-loss efforts by assisting
-body metabolism, and helping the body's ability to manage weight.
-A powerful, safe, 30 Day Program.  This is one program you won't
-feel starved on.  Complete program for one amazing low price!
-Program includes: <b>BONUS AMAZING FAT ABSORBER CAPSULES, 30 DAY -
-WEIGHT
-REDUCTION PLAN, PROGRESS REPORT!</b>
-<br><br>
-SPECIAL BONUS..."FAT ABSORBERS", AS SEEN ON TV
-With every order...AMAZING MELT AWAY FAT ABSORBER CAPSULES with
-directions ( Absolutely Free ) ...With these capsules
-you can eat what you enjoy, without the worry of fat in your diet.
-2 to 3 capsules 15 minutes before eating or snack, and the fat will be
-absorbed and passed through the body without the digestion of fat into
-the body. 
-<br><br>
-You will be losing by tomorrow!  Don't Wait, visit our web
-page below, and order now!
-<br><br>
-Email Address:  <a href="mailto:ultratrimnow2001@aol.com">ultratrimnow2001@aol.com</a>
-<br><br>
-
-Order by 24 Hour Fax!!!  775-257-6657.<br>
-<br>
-*****************<br>
-<a
-href="http://www.geocities.com/ultra_weightloss_2002/">http://www.geocities.com/ultra_weightloss_2002/</a><br>
-*****************
-<br><br>
-___1 Month Supply $32.95 plus $4.75 S & H, 100 Amazing MegaTrim
-     Capsules.
-<br><br>
-___2 Month Supply $54.95 plus $4.75 S & H, 200 Amazing MegaTrim
-     Capsules.  (A $10.95 Savings, Free Bottle)!
-<br><br>
-___3 Month Supply $69.95,  Plus $4.75 S & H, 300 Amazing MegaTrim
-     Capsules.  (A $28.90 Savings, Free Bottle)!
-<br><br>
-To Order by postal mail, please send to the below address.
-Make payable to UltraTrim 2002.
-<br><br>
-Ultra Trim 2002<br>
-4132 Pompton Ct.<br>
-Dayton, Ohio  45405<br>
-(937) 567-9807<br>
-<br>
-Order by 24 Hour Voice/Fax!!!  775-257-6657.<br>
-<br>
-*****<br>
-<b><font color="red">Important Credit Card Information! Please Read Below!</b></font>
- <br><br>
-*     Credit Card Address, City, State and Zip Code, must match
-      billing address to be processed. 
-<br><br>
-
-___Check<br>
-___MoneyOrder<br>
-___Visa<br>
-___MasterCard<br>
-___AmericanExpress<br>
-___Debt Card
-<br><br>
-Name_______________________________________________________<br>
-(As it appears on Check or Credit Card)
-<br><br>
-Address____________________________________________________<br>
-(As it appears on Check or Credit Card)
-<br><br>
-___________________________________________________<br>
-City,State,Zip(As it appears on Check or Credit Card)
-<br><br>
-___________________________________________________<br>
-Country
-<br><br>
-___________________________________________________<br>
-(Credit Card Number)
-<br><br>
-Expiration Month_____  Year_____
-<br><br>
-___________________________________________________<br>
-Authorized Signature
-<br><br>
-<b>
-*****IMPORTANT NOTE*****
-</b>
-<br><br>
-If Shipping Address Is Different From The Billing Address Above,
-Please Fill Out Information Below.
-<br><br>
-Shipping Name______________________________________________
-<br><br>
-Shipping Address___________________________________________
-<br><br>
-___________________________________________________________<br>
-Shipping City,State,Zip
-<br><br>
-___________________________________________________________<br>
-Country
-<br><br>
-___________________________________________________________<br>
-Email Address & Phone Number(Please Write Neat)
-<br>
-<br>
-<center>
-<a
-href="mailto:ultratrim2002dontsend@yahoo.com">To Be Removed From Our Mail List, Click Here And Put The Word Remove In The Subject Line.</a>
-</center>
-<br>
-<br>
-</body>
-</html>
diff --git a/server/protocols/jmap-draft-integration-testing/memory-jmap-draft-integration-testing/pom.xml b/server/protocols/jmap-draft-integration-testing/memory-jmap-draft-integration-testing/pom.xml
index 722e18a945..c0d841e38b 100644
--- a/server/protocols/jmap-draft-integration-testing/memory-jmap-draft-integration-testing/pom.xml
+++ b/server/protocols/jmap-draft-integration-testing/memory-jmap-draft-integration-testing/pom.xml
@@ -50,12 +50,6 @@
             <artifactId>apache-james-mailbox-spamassassin</artifactId>
             <scope>test</scope>
         </dependency>
-        <dependency>
-            <groupId>${james.groupId}</groupId>
-            <artifactId>apache-james-spamassassin</artifactId>
-            <type>test-jar</type>
-            <scope>test</scope>
-        </dependency>
         <dependency>
             <groupId>${james.groupId}</groupId>
             <artifactId>apache-mailet-base</artifactId>
diff --git a/server/protocols/jmap-draft-integration-testing/memory-jmap-draft-integration-testing/src/test/java/org/apache/james/jmap/memory/MemorySpamAssassinContractTest.java b/server/protocols/jmap-draft-integration-testing/memory-jmap-draft-integration-testing/src/test/java/org/apache/james/jmap/memory/MemorySpamAssassinContractTest.java
deleted file mode 100644
index 50a783d8a2..0000000000
--- a/server/protocols/jmap-draft-integration-testing/memory-jmap-draft-integration-testing/src/test/java/org/apache/james/jmap/memory/MemorySpamAssassinContractTest.java
+++ /dev/null
@@ -1,90 +0,0 @@
-/****************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one   *
- * or more contributor license agreements.  See the NOTICE file *
- * distributed with this work for additional information        *
- * regarding copyright ownership.  The ASF licenses this file   *
- * to you under the Apache License, Version 2.0 (the            *
- * "License"); you may not use this file except in compliance   *
- * with the License.  You may obtain a copy of the License at   *
- *                                                              *
- *   http://www.apache.org/licenses/LICENSE-2.0                 *
- *                                                              *
- * Unless required by applicable law or agreed to in writing,   *
- * software distributed under the License is distributed on an  *
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
- * KIND, either express or implied.  See the License for the    *
- * specific language governing permissions and limitations      *
- * under the License.                                           *
- ****************************************************************/
-package org.apache.james.jmap.memory;
-
-import static org.apache.james.data.UsersRepositoryModuleChooser.Implementation.DEFAULT;
-
-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.jmap.draft.methods.integration.SpamAssassinContract;
-import org.apache.james.jmap.draft.methods.integration.SpamAssassinModuleExtension;
-import org.apache.james.junit.categories.Unstable;
-import org.apache.james.modules.TestJMAPServerModule;
-import org.apache.james.spamassassin.SpamAssassinExtension;
-import org.junit.jupiter.api.Tag;
-import org.junit.jupiter.api.extension.RegisterExtension;
-
-class MemorySpamAssassinContractTest implements SpamAssassinContract {
-    @RegisterExtension
-    static JamesServerExtension testExtension = new JamesServerBuilder<MemoryJamesConfiguration>(tmpDir ->
-        MemoryJamesConfiguration.builder()
-            .workingDirectory(tmpDir)
-            .configurationFromClasspath()
-            .usersRepository(DEFAULT)
-            .build())
-        .extension(new SpamAssassinModuleExtension())
-        .server(configuration -> MemoryJamesServerMain.createServer(configuration)
-            .overrideWith(new TestJMAPServerModule()))
-        .build();
-
-    @Override
-    @Tag(Unstable.TAG)
-    public void spamShouldBeDeliveredInSpamMailboxWhenSameMessageHasAlreadyBeenMovedToSpam(GuiceJamesServer jamesServer, SpamAssassinExtension.SpamAssassin spamAssassin) throws Exception {
-        SpamAssassinContract.super.spamShouldBeDeliveredInSpamMailboxWhenSameMessageHasAlreadyBeenMovedToSpam(jamesServer, spamAssassin);
-    }
-
-    @Override
-    @Tag(Unstable.TAG)
-    public void spamShouldBeDeliveredInSpamMailboxOrInboxWhenMultipleRecipientsConfigurations(GuiceJamesServer jamesServer, SpamAssassinExtension.SpamAssassin spamAssassin) throws Exception {
-        SpamAssassinContract.super.spamShouldBeDeliveredInSpamMailboxOrInboxWhenMultipleRecipientsConfigurations(jamesServer, spamAssassin);
-    }
-
-    @Override
-    @Tag(Unstable.TAG)
-    public void movingAMailToTrashShouldNotImpactSpamassassinLearning(GuiceJamesServer jamesServer, SpamAssassinExtension.SpamAssassin spamAssassin) throws Exception {
-        SpamAssassinContract.super.movingAMailToTrashShouldNotImpactSpamassassinLearning(jamesServer, spamAssassin);
-    }
-
-    @Override
-    @Tag(Unstable.TAG)
-    public void expungingSpamMessageShouldNotImpactSpamAssassinState(GuiceJamesServer jamesServer, SpamAssassinExtension.SpamAssassin spamAssassin) throws Exception {
-        SpamAssassinContract.super.expungingSpamMessageShouldNotImpactSpamAssassinState(jamesServer, spamAssassin);
-    }
-
-    @Override
-    @Tag(Unstable.TAG)
-    public void imapMovesToSpamMailboxShouldBeConsideredAsSpam(GuiceJamesServer jamesServer, SpamAssassinExtension.SpamAssassin spamAssassin) throws Exception {
-        SpamAssassinContract.super.imapMovesToSpamMailboxShouldBeConsideredAsSpam(jamesServer, spamAssassin);
-    }
-
-    @Override
-    @Tag(Unstable.TAG)
-    public void imapCopiesToSpamMailboxShouldBeConsideredAsSpam(GuiceJamesServer jamesServer, SpamAssassinExtension.SpamAssassin spamAssassin) throws Exception {
-        SpamAssassinContract.super.imapCopiesToSpamMailboxShouldBeConsideredAsSpam(jamesServer, spamAssassin);
-    }
-
-    @Override
-    @Tag(Unstable.TAG)
-    public void deletingSpamMessageShouldNotImpactSpamAssassinState(GuiceJamesServer jamesServer, SpamAssassinExtension.SpamAssassin spamAssassin) throws Exception {
-        SpamAssassinContract.super.deletingSpamMessageShouldNotImpactSpamAssassinState(jamesServer, spamAssassin);
-    }
-}
diff --git a/server/protocols/jmap-draft-integration-testing/memory-jmap-draft-integration-testing/src/test/resources/mailetcontainer.xml b/server/protocols/jmap-draft-integration-testing/memory-jmap-draft-integration-testing/src/test/resources/mailetcontainer.xml
index 3815150de2..68dfa629c9 100644
--- a/server/protocols/jmap-draft-integration-testing/memory-jmap-draft-integration-testing/src/test/resources/mailetcontainer.xml
+++ b/server/protocols/jmap-draft-integration-testing/memory-jmap-draft-integration-testing/src/test/resources/mailetcontainer.xml
@@ -71,14 +71,6 @@
                 <onMailetException>ignore</onMailetException>
             </mailet>
             <mailet match="RecipientIsLocal" class="Sieve"/>
-            <mailet match="RecipientIsLocal" class="SpamAssassin">
-                <onMailetException>ignore</onMailetException>
-                <spamdHost>localhost</spamdHost>
-                <spamdPort>783</spamdPort>
-            </mailet>
-            <mailet match="IsMarkedAsSpam" class="WithStorageDirective">
-                <targetFolderName>Spam</targetFolderName>
-            </mailet>
             <mailet match="RecipientIsLocal" class="org.apache.james.jmap.mailet.filter.JMAPFiltering"/>
             <mailet match="RecipientIsLocal" class="LocalDelivery"/>
             <mailet match="HostIsLocal" class="ToProcessor">
diff --git a/server/protocols/jmap-draft-integration-testing/memory-jmap-draft-integration-testing/src/test/resources/spamassassin_db b/server/protocols/jmap-draft-integration-testing/memory-jmap-draft-integration-testing/src/test/resources/spamassassin_db
deleted file mode 120000
index 144a9b2d2f..0000000000
--- a/server/protocols/jmap-draft-integration-testing/memory-jmap-draft-integration-testing/src/test/resources/spamassassin_db
+++ /dev/null
@@ -1 +0,0 @@
-../../../../jmap-draft-integration-testing-common/src/test/resources/spamassassin_db
\ No newline at end of file
diff --git a/server/protocols/jmap-draft-integration-testing/rabbitmq-jmap-draft-integration-testing/pom.xml b/server/protocols/jmap-draft-integration-testing/rabbitmq-jmap-draft-integration-testing/pom.xml
index 4304f3daa7..67ebf34cc9 100644
--- a/server/protocols/jmap-draft-integration-testing/rabbitmq-jmap-draft-integration-testing/pom.xml
+++ b/server/protocols/jmap-draft-integration-testing/rabbitmq-jmap-draft-integration-testing/pom.xml
@@ -45,12 +45,6 @@
             <type>test-jar</type>
             <scope>test</scope>
         </dependency>
-        <dependency>
-            <groupId>${james.groupId}</groupId>
-            <artifactId>apache-james-spamassassin</artifactId>
-            <type>test-jar</type>
-            <scope>test</scope>
-        </dependency>
         <dependency>
             <groupId>${james.groupId}</groupId>
             <artifactId>blob-s3</artifactId>
diff --git a/server/protocols/jmap-draft-integration-testing/rabbitmq-jmap-draft-integration-testing/src/test/java/org/apache/james/jmap/rabbitmq/RabbitMQAwsS3SpamAssassinContractTest.java b/server/protocols/jmap-draft-integration-testing/rabbitmq-jmap-draft-integration-testing/src/test/java/org/apache/james/jmap/rabbitmq/RabbitMQAwsS3SpamAssassinContractTest.java
deleted file mode 100644
index 1d74754cb6..0000000000
--- a/server/protocols/jmap-draft-integration-testing/rabbitmq-jmap-draft-integration-testing/src/test/java/org/apache/james/jmap/rabbitmq/RabbitMQAwsS3SpamAssassinContractTest.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/****************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one   *
- * or more contributor license agreements.  See the NOTICE file *
- * distributed with this work for additional information        *
- * regarding copyright ownership.  The ASF licenses this file   *
- * to you under the Apache License, Version 2.0 (the            *
- * "License"); you may not use this file except in compliance   *
- * with the License.  You may obtain a copy of the License at   *
- *                                                              *
- *   http://www.apache.org/licenses/LICENSE-2.0                 *
- *                                                              *
- * Unless required by applicable law or agreed to in writing,   *
- * software distributed under the License is distributed on an  *
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
- * KIND, either express or implied.  See the License for the    *
- * specific language governing permissions and limitations      *
- * under the License.                                           *
- ****************************************************************/
-package org.apache.james.jmap.rabbitmq;
-
-import org.apache.james.CassandraExtension;
-import org.apache.james.CassandraRabbitMQJamesConfiguration;
-import org.apache.james.CassandraRabbitMQJamesServerMain;
-import org.apache.james.DockerElasticSearchExtension;
-import org.apache.james.JamesServerBuilder;
-import org.apache.james.JamesServerExtension;
-import org.apache.james.SearchConfiguration;
-import org.apache.james.jmap.draft.methods.integration.SpamAssassinContract;
-import org.apache.james.jmap.draft.methods.integration.SpamAssassinModuleExtension;
-import org.apache.james.modules.AwsS3BlobStoreExtension;
-import org.apache.james.modules.RabbitMQExtension;
-import org.apache.james.modules.TestJMAPServerModule;
-import org.apache.james.modules.blobstore.BlobStoreConfiguration;
-import org.junit.jupiter.api.extension.RegisterExtension;
-
-class RabbitMQAwsS3SpamAssassinContractTest implements SpamAssassinContract {
-
-    private static final SpamAssassinModuleExtension spamAssassinExtension = new SpamAssassinModuleExtension();
-    @RegisterExtension
-    static JamesServerExtension testExtension = new JamesServerBuilder<CassandraRabbitMQJamesConfiguration>(tmpDir ->
-        CassandraRabbitMQJamesConfiguration.builder()
-            .workingDirectory(tmpDir)
-            .configurationFromClasspath()
-            .blobStore(BlobStoreConfiguration.builder()
-                    .s3()
-                    .disableCache()
-                    .deduplication()
-                    .noCryptoConfig())
-            .searchConfiguration(SearchConfiguration.elasticSearch())
-            .build())
-        .extension(new DockerElasticSearchExtension())
-        .extension(new CassandraExtension())
-        .extension(new RabbitMQExtension())
-        .extension(new AwsS3BlobStoreExtension())
-        .extension(spamAssassinExtension)
-        .server(configuration -> CassandraRabbitMQJamesServerMain.createServer(configuration)
-            .overrideWith(new TestJMAPServerModule()))
-        .build();
-}
-
diff --git a/server/protocols/jmap-draft-integration-testing/rabbitmq-jmap-draft-integration-testing/src/test/resources/mailetcontainer.xml b/server/protocols/jmap-draft-integration-testing/rabbitmq-jmap-draft-integration-testing/src/test/resources/mailetcontainer.xml
index 37817e8f8a..3ded9e249c 100644
--- a/server/protocols/jmap-draft-integration-testing/rabbitmq-jmap-draft-integration-testing/src/test/resources/mailetcontainer.xml
+++ b/server/protocols/jmap-draft-integration-testing/rabbitmq-jmap-draft-integration-testing/src/test/resources/mailetcontainer.xml
@@ -70,14 +70,6 @@
                 <onMailetException>ignore</onMailetException>
             </mailet>
             <mailet match="RecipientIsLocal" class="Sieve"/>
-            <mailet match="RecipientIsLocal" class="SpamAssassin">
-                <onMailetException>ignore</onMailetException>
-                <spamdHost>localhost</spamdHost>
-                <spamdPort>783</spamdPort>
-            </mailet>
-            <mailet match="IsMarkedAsSpam" class="WithStorageDirective">
-                <targetFolderName>Spam</targetFolderName>
-            </mailet>
             <mailet match="RecipientIsLocal" class="org.apache.james.jmap.mailet.filter.JMAPFiltering"/>
             <mailet match="RecipientIsLocal" class="LocalDelivery"/>
             <mailet match="HostIsLocal" class="ToProcessor">
diff --git a/server/protocols/jmap-draft-integration-testing/rabbitmq-jmap-draft-integration-testing/src/test/resources/spamassassin_db b/server/protocols/jmap-draft-integration-testing/rabbitmq-jmap-draft-integration-testing/src/test/resources/spamassassin_db
deleted file mode 120000
index 144a9b2d2f..0000000000
--- a/server/protocols/jmap-draft-integration-testing/rabbitmq-jmap-draft-integration-testing/src/test/resources/spamassassin_db
+++ /dev/null
@@ -1 +0,0 @@
-../../../../jmap-draft-integration-testing-common/src/test/resources/spamassassin_db
\ No newline at end of file
diff --git a/server/protocols/jmap-rfc-8621-integration-tests/distributed-jmap-rfc-8621-integration-tests/src/test/resources/mailetcontainer.xml b/server/protocols/jmap-rfc-8621-integration-tests/distributed-jmap-rfc-8621-integration-tests/src/test/resources/mailetcontainer.xml
index f34443a6d7..a30c7cf6b1 100644
--- a/server/protocols/jmap-rfc-8621-integration-tests/distributed-jmap-rfc-8621-integration-tests/src/test/resources/mailetcontainer.xml
+++ b/server/protocols/jmap-rfc-8621-integration-tests/distributed-jmap-rfc-8621-integration-tests/src/test/resources/mailetcontainer.xml
@@ -74,14 +74,6 @@
             <mailet match="RecipientIsLocal" class="Sieve">
                 <onMailetException>ignore</onMailetException>
             </mailet>
-            <mailet match="RecipientIsLocal" class="SpamAssassin">
-                <onMailetException>ignore</onMailetException>
-                <spamdHost>localhost</spamdHost>
-                <spamdPort>783</spamdPort>
-            </mailet>
-            <mailet match="IsMarkedAsSpam" class="WithStorageDirective">
-                <targetFolderName>Spam</targetFolderName>
-            </mailet>
             <mailet match="RecipientIsLocal" class="org.apache.james.jmap.mailet.filter.JMAPFiltering">
                 <onMailetException>ignore</onMailetException>
             </mailet>
diff --git a/server/protocols/protocols-smtp/pom.xml b/server/protocols/protocols-smtp/pom.xml
index 2ee04b70e3..ee4757ed48 100644
--- a/server/protocols/protocols-smtp/pom.xml
+++ b/server/protocols/protocols-smtp/pom.xml
@@ -33,16 +33,6 @@
     <name>Apache James :: Server :: SMTP</name>
 
     <dependencies>
-        <dependency>
-            <groupId>${james.groupId}</groupId>
-            <artifactId>apache-james-spamassassin</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>${james.groupId}</groupId>
-            <artifactId>apache-james-spamassassin</artifactId>
-            <type>test-jar</type>
-            <scope>test</scope>
-        </dependency>
         <dependency>
             <groupId>${james.groupId}</groupId>
             <artifactId>apache-mailet-api</artifactId>
diff --git a/third-party/spamassassin/src/test/resources/spamassassin_db/ham/ham4 b/third-party/spamassassin/src/test/resources/spamassassin_db/ham/ham4
deleted file mode 100644
index 9a726c245f..0000000000
--- a/third-party/spamassassin/src/test/resources/spamassassin_db/ham/ham4
+++ /dev/null
@@ -1,78 +0,0 @@
-From irregulars-admin@tb.tf  Thu Aug 22 14:23:39 2002
-Return-Path: <ir...@tb.tf>
-Delivered-To: zzzz@localhost.netnoteinc.com
-Received: from localhost (localhost [127.0.0.1])
-	by phobos.labs.netnoteinc.com (Postfix) with ESMTP id 9DAE147C66
-	for <zz...@localhost>; Thu, 22 Aug 2002 09:23:38 -0400 (EDT)
-Received: from phobos [127.0.0.1]
-	by localhost with IMAP (fetchmail-5.9.0)
-	for zzzz@localhost (single-drop); Thu, 22 Aug 2002 14:23:38 +0100 (IST)
-Received: from web.tb.tf (route-64-131-126-36.telocity.com
-    [64.131.126.36]) by dogma.slashnull.org (8.11.6/8.11.6) with ESMTP id
-    g7MDGOZ07922 for <zz...@spamassassin.taint.org>; Thu, 22 Aug 2002 14:16:24 +0100
-Received: from web.tb.tf (localhost.localdomain [127.0.0.1]) by web.tb.tf
-    (8.11.6/8.11.6) with ESMTP id g7MDP9I16418; Thu, 22 Aug 2002 09:25:09
-    -0400
-Received: from red.harvee.home (red [192.168.25.1] (may be forged)) by
-    web.tb.tf (8.11.6/8.11.6) with ESMTP id g7MDO4I16408 for
-    <ir...@tb.tf>; Thu, 22 Aug 2002 09:24:04 -0400
-Received: from prserv.net (out4.prserv.net [32.97.166.34]) by
-    red.harvee.home (8.11.6/8.11.6) with ESMTP id g7MDFBD29237 for
-    <ir...@tb.tf>; Thu, 22 Aug 2002 09:15:12 -0400
-Received: from [209.202.248.109]
-    (slip-32-103-249-10.ma.us.prserv.net[32.103.249.10]) by prserv.net (out4)
-    with ESMTP id <2002082213150220405qu8jce>; Thu, 22 Aug 2002 13:15:07 +0000
-MIME-Version: 1.0
-X-Sender: @ (Unverified)
-Message-Id: <p04330137b98a941c58a8@[209.202.248.109]>
-To: undisclosed-recipient: ;
-From: Monty Solomon <mo...@roscom.com>
-Content-Type: text/plain; charset="us-ascii"
-Subject: [IRR] Klez: The Virus That  Won't Die
-Sender: irregulars-admin@tb.tf
-Errors-To: irregulars-admin@tb.tf
-X-Beenthere: irregulars@tb.tf
-X-Mailman-Version: 2.0.6
-Precedence: bulk
-List-Help: <mailto:irregulars-request@tb.tf?subject=help>
-List-Post: <ma...@tb.tf>
-List-Subscribe: <http://tb.tf/mailman/listinfo/irregulars>,
-    <mailto:irregulars-request@tb.tf?subject=subscribe>
-List-Id: New home of the TBTF Irregulars mailing list <irregulars.tb.tf>
-List-Unsubscribe: <http://tb.tf/mailman/listinfo/irregulars>,
-    <mailto:irregulars-request@tb.tf?subject=unsubscribe>
-List-Archive: <http://tb.tf/mailman/private/irregulars/>
-Date: Thu, 22 Aug 2002 09:15:25 -0400
-
-Klez: The Virus That Won't Die
- 
-Already the most prolific virus ever, Klez continues to wreak havoc.
-
-Andrew Brandt
->>From the September 2002 issue of PC World magazine
-Posted Thursday, August 01, 2002
-
-
-The Klez worm is approaching its seventh month of wriggling across 
-the Web, making it one of the most persistent viruses ever. And 
-experts warn that it may be a harbinger of new viruses that use a 
-combination of pernicious approaches to go from PC to PC.
-
-Antivirus software makers Symantec and McAfee both report more than 
-2000 new infections daily, with no sign of letup at press time. The 
-British security firm MessageLabs estimates that 1 in every 300 
-e-mail messages holds a variation of the Klez virus, and says that 
-Klez has already surpassed last summer's SirCam as the most prolific 
-virus ever.
-
-And some newer Klez variants aren't merely nuisances--they can carry 
-other viruses in them that corrupt your data.
-
-...
-
-http://www.pcworld.com/news/article/0,aid,103259,00.asp
-_______________________________________________
-Irregulars mailing list
-Irregulars@tb.tf
-http://tb.tf/mailman/listinfo/irregulars
-
diff --git a/third-party/spamassassin/src/test/resources/spamassassin_db/ham/ham5 b/third-party/spamassassin/src/test/resources/spamassassin_db/ham/ham5
deleted file mode 100644
index 57b68015c2..0000000000
--- a/third-party/spamassassin/src/test/resources/spamassassin_db/ham/ham5
+++ /dev/null
@@ -1,77 +0,0 @@
-From Stewart.Smith@ee.ed.ac.uk  Thu Aug 22 14:44:26 2002
-Return-Path: <St...@ee.ed.ac.uk>
-Delivered-To: zzzz@localhost.netnoteinc.com
-Received: from localhost (localhost [127.0.0.1])
-	by phobos.labs.netnoteinc.com (Postfix) with ESMTP id EC69D47C66
-	for <zz...@localhost>; Thu, 22 Aug 2002 09:44:25 -0400 (EDT)
-Received: from phobos [127.0.0.1]
-	by localhost with IMAP (fetchmail-5.9.0)
-	for zzzz@localhost (single-drop); Thu, 22 Aug 2002 14:44:25 +0100 (IST)
-Received: from n6.grp.scd.yahoo.com (n6.grp.scd.yahoo.com [66.218.66.90])
-    by dogma.slashnull.org (8.11.6/8.11.6) with SMTP id g7MDcOZ08504 for
-    <zz...@spamassassin.taint.org>; Thu, 22 Aug 2002 14:38:25 +0100
-X-Egroups-Return: sentto-2242572-52736-1030023506-zzzz=spamassassin.taint.org@returns.groups.yahoo.com
-Received: from [66.218.67.192] by n6.grp.scd.yahoo.com with NNFMP;
-    22 Aug 2002 13:38:26 -0000
-X-Sender: Stewart.Smith@ee.ed.ac.uk
-X-Apparently-To: zzzzteana@yahoogroups.com
-Received: (EGP: mail-8_1_0_1); 22 Aug 2002 13:38:25 -0000
-Received: (qmail 48882 invoked from network); 22 Aug 2002 13:38:25 -0000
-Received: from unknown (66.218.66.218) by m10.grp.scd.yahoo.com with QMQP;
-    22 Aug 2002 13:38:25 -0000
-Received: from unknown (HELO postbox.ee.ed.ac.uk) (129.215.80.253) by
-    mta3.grp.scd.yahoo.com with SMTP; 22 Aug 2002 13:38:24 -0000
-Received: from ee.ed.ac.uk (sxs@dunblane [129.215.34.86]) by
-    postbox.ee.ed.ac.uk (8.11.0/8.11.0) with ESMTP id g7MDcNi28645 for
-    <fo...@yahoogroups.com>; Thu, 22 Aug 2002 14:38:23 +0100 (BST)
-Message-Id: <3D...@ee.ed.ac.uk>
-Organization: Scottish Microelectronics Centre
-User-Agent: Mozilla/5.0 (X11; U; SunOS sun4u; en-US; rv:1.1b) Gecko/20020628
-X-Accept-Language: en, en-us
-To: zzzzteana@yahoogroups.com
-References: <3D...@localhost>
-From: Stewart Smith <St...@ee.ed.ac.uk>
-X-Yahoo-Profile: stochasticus
-MIME-Version: 1.0
-Mailing-List: list zzzzteana@yahoogroups.com; contact
-    forteana-owner@yahoogroups.com
-Delivered-To: mailing list zzzzteana@yahoogroups.com
-Precedence: bulk
-List-Unsubscribe: <ma...@yahoogroups.com>
-Date: Thu, 22 Aug 2002 14:38:22 +0100
-Subject: Re: [zzzzteana] Nothing like mama used to make
-Reply-To: zzzzteana@yahoogroups.com
-Content-Type: text/plain; charset=US-ASCII
-Content-Transfer-Encoding: 7bit
-
->  in adding cream to spaghetti carbonara, which has the same effect on pasta as
->  making a pizza a deep-pie; 
-
-I just had to jump in here as Carbonara is one of my favourites to make and ask 
-what the hell are you supposed to use instead of cream?  I've never seen a 
-recipe that hasn't used this.  Personally I use low fat creme fraiche because it 
-works quite nicely but the only time I've seen an supposedly authentic recipe 
-for carbonara  it was identical to mine (cream, eggs and lots of fresh parmesan) 
-except for the creme fraiche.
-
-Stew
--- 
-Stewart Smith
-Scottish Microelectronics Centre, University of Edinburgh.
-http://www.ee.ed.ac.uk/~sxs/
-
-
------------------------- Yahoo! Groups Sponsor ---------------------~-->
-4 DVDs Free +s&p Join Now
-http://us.click.yahoo.com/pt6YBB/NXiEAA/mG3HAA/7gSolB/TM
----------------------------------------------------------------------~->
-
-To unsubscribe from this group, send an email to:
-forteana-unsubscribe@egroups.com
-
- 
-
-Your use of Yahoo! Groups is subject to http://docs.yahoo.com/info/terms/ 
-
-
-
diff --git a/third-party/spamassassin/src/test/resources/spamassassin_db/ham/ham6 b/third-party/spamassassin/src/test/resources/spamassassin_db/ham/ham6
deleted file mode 100644
index f3231fe4de..0000000000
--- a/third-party/spamassassin/src/test/resources/spamassassin_db/ham/ham6
+++ /dev/null
@@ -1,74 +0,0 @@
-From martin@srv0.ems.ed.ac.uk  Thu Aug 22 14:54:39 2002
-Return-Path: <ma...@srv0.ems.ed.ac.uk>
-Delivered-To: zzzz@localhost.netnoteinc.com
-Received: from localhost (localhost [127.0.0.1])
-	by phobos.labs.netnoteinc.com (Postfix) with ESMTP id 16FC743F99
-	for <zz...@localhost>; Thu, 22 Aug 2002 09:54:38 -0400 (EDT)
-Received: from phobos [127.0.0.1]
-	by localhost with IMAP (fetchmail-5.9.0)
-	for zzzz@localhost (single-drop); Thu, 22 Aug 2002 14:54:39 +0100 (IST)
-Received: from n14.grp.scd.yahoo.com (n14.grp.scd.yahoo.com
-    [66.218.66.69]) by dogma.slashnull.org (8.11.6/8.11.6) with SMTP id
-    g7MDoxZ08960 for <zz...@spamassassin.taint.org>; Thu, 22 Aug 2002 14:50:59 +0100
-X-Egroups-Return: sentto-2242572-52737-1030024261-zzzz=spamassassin.taint.org@returns.groups.yahoo.com
-Received: from [66.218.66.95] by n14.grp.scd.yahoo.com with NNFMP;
-    22 Aug 2002 13:51:01 -0000
-X-Sender: martin@srv0.ems.ed.ac.uk
-X-Apparently-To: zzzzteana@yahoogroups.com
-Received: (EGP: mail-8_1_0_1); 22 Aug 2002 13:51:00 -0000
-Received: (qmail 71894 invoked from network); 22 Aug 2002 13:51:00 -0000
-Received: from unknown (66.218.66.218) by m7.grp.scd.yahoo.com with QMQP;
-    22 Aug 2002 13:51:00 -0000
-Received: from unknown (HELO haymarket.ed.ac.uk) (129.215.128.53) by
-    mta3.grp.scd.yahoo.com with SMTP; 22 Aug 2002 13:51:00 -0000
-Received: from srv0.ems.ed.ac.uk (srv0.ems.ed.ac.uk [129.215.117.0]) by
-    haymarket.ed.ac.uk (8.11.6/8.11.6) with ESMTP id g7MDow310334 for
-    <fo...@yahoogroups.com>; Thu, 22 Aug 2002 14:50:59 +0100 (BST)
-Received: from EMS-SRV0/SpoolDir by srv0.ems.ed.ac.uk (Mercury 1.44);
-    22 Aug 02 14:50:58 +0000
-Received: from SpoolDir by EMS-SRV0 (Mercury 1.44); 22 Aug 02 14:50:31 +0000
-Organization: Management School
-To: zzzzteana@yahoogroups.com
-Message-Id: <3D...@localhost>
-Priority: normal
-In-Reply-To: <3D...@ee.ed.ac.uk>
-X-Mailer: Pegasus Mail for Windows (v4.01)
-Content-Description: Mail message body
-From: "Martin Adamson" <ma...@srv0.ems.ed.ac.uk>
-MIME-Version: 1.0
-Mailing-List: list zzzzteana@yahoogroups.com; contact
-    forteana-owner@yahoogroups.com
-Delivered-To: mailing list zzzzteana@yahoogroups.com
-Precedence: bulk
-List-Unsubscribe: <ma...@yahoogroups.com>
-Date: Thu, 22 Aug 2002 14:50:31 +0100
-Subject: Re: [zzzzteana] Nothing like mama used to make
-Reply-To: zzzzteana@yahoogroups.com
-Content-Type: text/plain; charset=US-ASCII
-Content-Transfer-Encoding: 7bit
-
-
-> I just had to jump in here as Carbonara is one of my favourites to make and 
-> ask 
-> what the hell are you supposed to use instead of cream? 
-
-Isn't it just basically a mixture of beaten egg and bacon (or pancetta, 
-really)? You mix in the raw egg to the cooked pasta and the heat of the pasta 
-cooks the egg. That's my understanding.
-
-Martin
-
------------------------- Yahoo! Groups Sponsor ---------------------~-->
-4 DVDs Free +s&p Join Now
-http://us.click.yahoo.com/pt6YBB/NXiEAA/mG3HAA/7gSolB/TM
----------------------------------------------------------------------~->
-
-To unsubscribe from this group, send an email to:
-forteana-unsubscribe@egroups.com
-
- 
-
-Your use of Yahoo! Groups is subject to http://docs.yahoo.com/info/terms/ 
-
-
-
diff --git a/third-party/spamassassin/src/test/resources/spamassassin_db/ham/ham7 b/third-party/spamassassin/src/test/resources/spamassassin_db/ham/ham7
deleted file mode 100644
index a65f9b4c11..0000000000
--- a/third-party/spamassassin/src/test/resources/spamassassin_db/ham/ham7
+++ /dev/null
@@ -1,88 +0,0 @@
-From martin@srv0.ems.ed.ac.uk  Thu Aug 22 14:54:40 2002
-Return-Path: <ma...@srv0.ems.ed.ac.uk>
-Delivered-To: zzzz@localhost.netnoteinc.com
-Received: from localhost (localhost [127.0.0.1])
-	by phobos.labs.netnoteinc.com (Postfix) with ESMTP id E3D7B47C66
-	for <zz...@localhost>; Thu, 22 Aug 2002 09:54:39 -0400 (EDT)
-Received: from phobos [127.0.0.1]
-	by localhost with IMAP (fetchmail-5.9.0)
-	for zzzz@localhost (single-drop); Thu, 22 Aug 2002 14:54:40 +0100 (IST)
-Received: from n11.grp.scd.yahoo.com (n11.grp.scd.yahoo.com
-    [66.218.66.66]) by dogma.slashnull.org (8.11.6/8.11.6) with SMTP id
-    g7MDt8Z09193 for <zz...@spamassassin.taint.org>; Thu, 22 Aug 2002 14:55:10 +0100
-X-Egroups-Return: sentto-2242572-52738-1030024499-zzzz=spamassassin.taint.org@returns.groups.yahoo.com
-Received: from [66.218.66.94] by n11.grp.scd.yahoo.com with NNFMP;
-    22 Aug 2002 13:55:03 -0000
-X-Sender: martin@srv0.ems.ed.ac.uk
-X-Apparently-To: zzzzteana@yahoogroups.com
-Received: (EGP: mail-8_1_0_1); 22 Aug 2002 13:54:59 -0000
-Received: (qmail 43039 invoked from network); 22 Aug 2002 13:54:58 -0000
-Received: from unknown (66.218.66.216) by m1.grp.scd.yahoo.com with QMQP;
-    22 Aug 2002 13:54:58 -0000
-Received: from unknown (HELO haymarket.ed.ac.uk) (129.215.128.53) by
-    mta1.grp.scd.yahoo.com with SMTP; 22 Aug 2002 13:54:58 -0000
-Received: from srv0.ems.ed.ac.uk (srv0.ems.ed.ac.uk [129.215.117.0]) by
-    haymarket.ed.ac.uk (8.11.6/8.11.6) with ESMTP id g7MDsv311745 for
-    <fo...@yahoogroups.com>; Thu, 22 Aug 2002 14:54:57 +0100 (BST)
-Received: from EMS-SRV0/SpoolDir by srv0.ems.ed.ac.uk (Mercury 1.44);
-    22 Aug 02 14:54:56 +0000
-Received: from SpoolDir by EMS-SRV0 (Mercury 1.44); 22 Aug 02 14:54:29 +0000
-Organization: Management School
-To: zzzzteana@yahoogroups.com
-Message-Id: <3D...@localhost>
-Priority: normal
-X-Mailer: Pegasus Mail for Windows (v4.01)
-Content-Description: Mail message body
-From: "Martin Adamson" <ma...@srv0.ems.ed.ac.uk>
-MIME-Version: 1.0
-Mailing-List: list zzzzteana@yahoogroups.com; contact
-    forteana-owner@yahoogroups.com
-Delivered-To: mailing list zzzzteana@yahoogroups.com
-Precedence: bulk
-List-Unsubscribe: <ma...@yahoogroups.com>
-Date: Thu, 22 Aug 2002 14:54:25 +0100
-Subject: [zzzzteana] Playboy wants to go out with a bang
-Reply-To: zzzzteana@yahoogroups.com
-Content-Type: text/plain; charset=ISO-8859-1
-Content-Transfer-Encoding: 8bit
-X-MIME-Autoconverted: from quoted-printable to 8bit by dogma.slashnull.org
-    id g7MDt8Z09193
-
-The Scotsman - 22 August 2002
-
- Playboy wants to go out with a bang 
- 
- 
- AN AGEING Berlin playboy has come up with an unusual offer to lure women into
- his bed - by promising the last woman he sleeps with an inheritance of 250,000
- (�160,000). 
- 
- Rolf Eden, 72, a Berlin disco owner famous for his countless sex partners,
- said he could imagine no better way to die than in the arms of an attractive
- young woman - preferably under 30. 
- 
- "I put it all in my last will and testament - the last woman who sleeps with
- me gets all the money," Mr Eden told Bild newspaper. 
- 
- "I want to pass away in the most beautiful moment of my life. First a lot of
- fun with a beautiful woman, then wild sex, a final orgasm - and it will all
- end with a heart attack and then I�m gone." 
- 
- Mr Eden, who is selling his nightclub this year, said applications should be
- sent in quickly because of his age. "It could end very soon," he said.
-
-
------------------------- Yahoo! Groups Sponsor ---------------------~-->
-4 DVDs Free +s&p Join Now
-http://us.click.yahoo.com/pt6YBB/NXiEAA/mG3HAA/7gSolB/TM
----------------------------------------------------------------------~->
-
-To unsubscribe from this group, send an email to:
-forteana-unsubscribe@egroups.com
-
- 
-
-Your use of Yahoo! Groups is subject to http://docs.yahoo.com/info/terms/ 
-
-
-
diff --git a/third-party/spamassassin/src/test/resources/spamassassin_db/ham/ham8 b/third-party/spamassassin/src/test/resources/spamassassin_db/ham/ham8
deleted file mode 100644
index c245926dcd..0000000000
--- a/third-party/spamassassin/src/test/resources/spamassassin_db/ham/ham8
+++ /dev/null
@@ -1,85 +0,0 @@
-From Stewart.Smith@ee.ed.ac.uk  Thu Aug 22 15:05:07 2002
-Return-Path: <St...@ee.ed.ac.uk>
-Delivered-To: zzzz@localhost.netnoteinc.com
-Received: from localhost (localhost [127.0.0.1])
-	by phobos.labs.netnoteinc.com (Postfix) with ESMTP id EF86747C67
-	for <zz...@localhost>; Thu, 22 Aug 2002 10:05:00 -0400 (EDT)
-Received: from phobos [127.0.0.1]
-	by localhost with IMAP (fetchmail-5.9.0)
-	for zzzz@localhost (single-drop); Thu, 22 Aug 2002 15:05:01 +0100 (IST)
-Received: from n34.grp.scd.yahoo.com (n34.grp.scd.yahoo.com
-    [66.218.66.102]) by dogma.slashnull.org (8.11.6/8.11.6) with SMTP id
-    g7ME1MZ09279 for <zz...@spamassassin.taint.org>; Thu, 22 Aug 2002 15:01:22 +0100
-X-Egroups-Return: sentto-2242572-52739-1030024883-zzzz=spamassassin.taint.org@returns.groups.yahoo.com
-Received: from [66.218.67.195] by n34.grp.scd.yahoo.com with NNFMP;
-    22 Aug 2002 14:01:23 -0000
-X-Sender: Stewart.Smith@ee.ed.ac.uk
-X-Apparently-To: zzzzteana@yahoogroups.com
-Received: (EGP: mail-8_1_0_1); 22 Aug 2002 14:01:23 -0000
-Received: (qmail 45116 invoked from network); 22 Aug 2002 14:01:22 -0000
-Received: from unknown (66.218.66.218) by m2.grp.scd.yahoo.com with QMQP;
-    22 Aug 2002 14:01:22 -0000
-Received: from unknown (HELO postbox.ee.ed.ac.uk) (129.215.80.253) by
-    mta3.grp.scd.yahoo.com with SMTP; 22 Aug 2002 14:01:22 -0000
-Received: from ee.ed.ac.uk (sxs@dunblane [129.215.34.86]) by
-    postbox.ee.ed.ac.uk (8.11.0/8.11.0) with ESMTP id g7ME1Li02942 for
-    <fo...@yahoogroups.com>; Thu, 22 Aug 2002 15:01:21 +0100 (BST)
-Message-Id: <3D...@ee.ed.ac.uk>
-Organization: Scottish Microelectronics Centre
-User-Agent: Mozilla/5.0 (X11; U; SunOS sun4u; en-US; rv:1.1b) Gecko/20020628
-X-Accept-Language: en, en-us
-To: zzzzteana@yahoogroups.com
-References: <3D...@localhost>
-From: Stewart Smith <St...@ee.ed.ac.uk>
-X-Yahoo-Profile: stochasticus
-MIME-Version: 1.0
-Mailing-List: list zzzzteana@yahoogroups.com; contact
-    forteana-owner@yahoogroups.com
-Delivered-To: mailing list zzzzteana@yahoogroups.com
-Precedence: bulk
-List-Unsubscribe: <ma...@yahoogroups.com>
-Date: Thu, 22 Aug 2002 15:01:20 +0100
-Subject: Re: [zzzzteana] Nothing like mama used to make
-Reply-To: zzzzteana@yahoogroups.com
-Content-Type: text/plain; charset=US-ASCII
-Content-Transfer-Encoding: 7bit
-
-Martin Adamson wrote:
-> 
-> Isn't it just basically a mixture of beaten egg and bacon (or pancetta, 
-> really)? You mix in the raw egg to the cooked pasta and the heat of the pasta 
-> cooks the egg. That's my understanding.
-> 
-
-You're probably right, mine's just the same but with the cream added to the 
-eggs.  I guess I should try it without.  Actually looking on the internet for a 
-recipe I found this one from possibly one of the scariest people I've ever seen, 
-and he's a US Congressman:
-<http://www.virtualcities.com/ons/me/gov/megvjb1.htm>
-
-That's one of the worst non-smiles ever.
-
-Stew
-ps. Apologies if any of the list's Maine residents voted for this man, you won't 
-do it again once you've seen this pic.
-
--- 
-Stewart Smith
-Scottish Microelectronics Centre, University of Edinburgh.
-http://www.ee.ed.ac.uk/~sxs/
-
-
------------------------- Yahoo! Groups Sponsor ---------------------~-->
-4 DVDs Free +s&p Join Now
-http://us.click.yahoo.com/pt6YBB/NXiEAA/mG3HAA/7gSolB/TM
----------------------------------------------------------------------~->
-
-To unsubscribe from this group, send an email to:
-forteana-unsubscribe@egroups.com
-
- 
-
-Your use of Yahoo! Groups is subject to http://docs.yahoo.com/info/terms/ 
-
-
-
diff --git a/third-party/spamassassin/src/test/resources/spamassassin_db/ham/ham9 b/third-party/spamassassin/src/test/resources/spamassassin_db/ham/ham9
deleted file mode 100644
index df071f62c3..0000000000
--- a/third-party/spamassassin/src/test/resources/spamassassin_db/ham/ham9
+++ /dev/null
@@ -1,176 +0,0 @@
-From martin@srv0.ems.ed.ac.uk  Thu Aug 22 15:05:07 2002
-Return-Path: <ma...@srv0.ems.ed.ac.uk>
-Delivered-To: zzzz@localhost.netnoteinc.com
-Received: from localhost (localhost [127.0.0.1])
-	by phobos.labs.netnoteinc.com (Postfix) with ESMTP id 7A0C347C68
-	for <zz...@localhost>; Thu, 22 Aug 2002 10:05:03 -0400 (EDT)
-Received: from phobos [127.0.0.1]
-	by localhost with IMAP (fetchmail-5.9.0)
-	for zzzz@localhost (single-drop); Thu, 22 Aug 2002 15:05:03 +0100 (IST)
-Received: from n34.grp.scd.yahoo.com (n34.grp.scd.yahoo.com
-    [66.218.66.102]) by dogma.slashnull.org (8.11.6/8.11.6) with SMTP id
-    g7ME1rZ09290 for <zz...@spamassassin.taint.org>; Thu, 22 Aug 2002 15:01:54 +0100
-X-Egroups-Return: sentto-2242572-52740-1030024915-zzzz=spamassassin.taint.org@returns.groups.yahoo.com
-Received: from [66.218.67.194] by n34.grp.scd.yahoo.com with NNFMP;
-    22 Aug 2002 14:01:55 -0000
-X-Sender: martin@srv0.ems.ed.ac.uk
-X-Apparently-To: zzzzteana@yahoogroups.com
-Received: (EGP: mail-8_1_0_1); 22 Aug 2002 14:01:55 -0000
-Received: (qmail 59494 invoked from network); 22 Aug 2002 14:01:55 -0000
-Received: from unknown (66.218.66.218) by m12.grp.scd.yahoo.com with QMQP;
-    22 Aug 2002 14:01:55 -0000
-Received: from unknown (HELO haymarket.ed.ac.uk) (129.215.128.53) by
-    mta3.grp.scd.yahoo.com with SMTP; 22 Aug 2002 14:01:54 -0000
-Received: from srv0.ems.ed.ac.uk (srv0.ems.ed.ac.uk [129.215.117.0]) by
-    haymarket.ed.ac.uk (8.11.6/8.11.6) with ESMTP id g7ME1r313981 for
-    <fo...@yahoogroups.com>; Thu, 22 Aug 2002 15:01:53 +0100 (BST)
-Received: from EMS-SRV0/SpoolDir by srv0.ems.ed.ac.uk (Mercury 1.44);
-    22 Aug 02 15:01:52 +0000
-Received: from SpoolDir by EMS-SRV0 (Mercury 1.44); 22 Aug 02 15:01:34 +0000
-Organization: Management School
-To: zzzzteana@yahoogroups.com
-Message-Id: <3D...@localhost>
-Priority: normal
-X-Mailer: Pegasus Mail for Windows (v4.01)
-Content-Description: Mail message body
-From: "Martin Adamson" <ma...@srv0.ems.ed.ac.uk>
-MIME-Version: 1.0
-Mailing-List: list zzzzteana@yahoogroups.com; contact
-    forteana-owner@yahoogroups.com
-Delivered-To: mailing list zzzzteana@yahoogroups.com
-Precedence: bulk
-List-Unsubscribe: <ma...@yahoogroups.com>
-Date: Thu, 22 Aug 2002 15:01:33 +0100
-Subject: [zzzzteana] Meaningful sentences
-Reply-To: zzzzteana@yahoogroups.com
-Content-Type: text/plain; charset=ISO-8859-1
-Content-Transfer-Encoding: 8bit
-X-MIME-Autoconverted: from quoted-printable to 8bit by dogma.slashnull.org
-    id g7ME1rZ09290
-
-The Scotsman
-
- Thu 22 Aug 2002 
-
- Meaningful sentences 
- 
- Tracey Lawson 
- 
- 
- If you ever wanted to look like "one of the most dangerous inmates in prison
- history", as one judge described Charles Bronson, now�s your chance. Bronson -
- the serial hostage taker, not the movie star - has written a health and
- fitness guide in which he shares some of the secrets behind his legendary
- muscle power. 
- 
- Solitary Fitness - a title which bears testament to the fact that Bronson, 48,
- has spent 24 of his 28 prison years in solitary confinement - explains how he
- has turned himself into a lean, mean, fitness machine while living 23 hours a
- day in a space just 12 feet by eight feet, on a diet of scrubs grub and at
- virtually no cost. 
- 
- The book is aimed at those who want to get fabulously fit without spending a
- fortune on gym memberships, protein supplements or designer trainers, and
- starts with a fierce attack on some of the expensive myths churned out by the
- exercise industry. 
- 
- "I pick up a fitness mag, I start to laugh and I wipe my arse with it," is the
- opening paragraph penned by Bronson. "It�s a joke and a big con and they call
- me a criminal!" You can�t help feeling he has a point. 
- 
- This is not the first book that Bronson has written from behind bars, having
- already published Birdman Opens His Mind, which features drawings and poems
- created by Bronson while in prison. And he is not the first prisoner to
- discover creative expression while residing at Her Majesty�s pleasure. 
- 
- Jimmy Boyle, the Scots sculptor and novelist, discovered his artistic talents
- when he was sent to Barlinnie Prison�s famous special unit, which aimed to
- help inmates put their violent pasts behind them by teaching them how to
- express their emotions artistically. Boyle was sentenced to life for the
- murder of "Babs" Rooney in 1967. Once released, he moved to Edinburgh where he
- has become a respected artist. His first novel, Hero of the Underworld, was
- published in 1999 and his autobiography, A Sense of Freedom, was made into an
- award-winning film. 
- 
- Hugh Collins was jailed for life in 1977 for the murder of William Mooney in
- Glasgow, and in his first year in Barlinnie prison stabbed three prison
- officers, earning him an extra seven-year sentence. But, after being
- transferred to the same unit that Boyle attended, he learned to sculpt and
- developed an interest in art. He later published Autobiography of a Murderer,
- a frank account of Glasgow�s criminal culture in the 1960s, which received
- critical praise. 
- 
- And Lord Archer doesn�t seem to have had trouble continuing to write the books
- that have made him millions while in jail. He recently signed a three-book
- deal with Macmillan publishers worth a reported �10 million, and is no doubt
- scribbling away as we speak. 
- 
- So why is it that men like Collins, Bronson and Boyle, who can be so
- destructive towards society on the outside, can become so creative once stuck
- on the inside? Steve Richards, Bronson�s publisher, has published many books
- about criminal figures and believes the roots of this phenomenon are both
- pragmatic and profound. 
- 
- He says: "Prison is sometimes the first time some criminals will ever have
- known a stable environment, and this can be the first time they have the
- chance to focus on their creative skills. 
- 
- "It may also be the first time that they have really had the chance of an
- education, if their early years have been hard. It could be the first time
- anyone has offered them the chance to explore their creative talents." 
- 
- However, Richards believes the reasons are also deeper than that. He says:
- "Once they are behind bars, the cold light of day hits them, and they examine
- the very essence of who they are. 
- 
- "They ask themselves, am I a man who wants to be remembered for violence? Or
- am I a man who can contribute to society, who can be remembered for something
- good?" 
- 
- Bronson - who was born Michael Gordon Peterson, but changed his name to that
- of the Hollywood star of the Death Wish films - has, so far, been remembered
- mainly for things bad. He was originally jailed for seven years for armed
- robbery in 1974, and has had a series of sentences added to his original term
- over the years as a result of attacking people in prison. In 2000 he was
- jailed for life after being convicted of holding a teacher hostage for nearly
- two days during a jail siege. 
- 
- Standing five feet ten and a half inches tall and weighing 210lbs, he is
- renowned for his strength. He has bent metal cell doors with his bare hands
- and does up to 3,000 - yes, 3,000 - press-ups a day. As he puts it: "I can hit
- a man 20 times in four seconds, I can push 132 press ups in 60 seconds." 
- 
- But judging by our current obsession with health and exercise, Solitary
- Fitness might be the book which will see Bronson�s face sitting on every
- coffee table in the land. He might be the man to give us the dream body which
- so many so-called fitness gurus promise but fail to motivate us into. Because
- Bronson has learned to use words as powerfully as he can use his fists. 
- 
- "All this crap about high-protein drinks, pills, diets, it�s just a load of
- bollocks and a multi-million-pound racket," he writes, in what can only be
- described as a refreshingly honest style. "We can all be fat lazy bastards,
- it�s our choice, I�m sick of hearing and reading about excuses, if you stuff
- your face with shit you become shit, that�s logical to me." 
- 
- As motivational mantras go, that might be just the kick up the, er, backside
- we all needed. 
- 
- 
- Solitary Fitness by Charles Bronson is published by Mirage Publishing and will
- be available in bookstores from October at �7.99
-
-
------------------------- Yahoo! Groups Sponsor ---------------------~-->
-4 DVDs Free +s&p Join Now
-http://us.click.yahoo.com/pt6YBB/NXiEAA/mG3HAA/7gSolB/TM
----------------------------------------------------------------------~->
-
-To unsubscribe from this group, send an email to:
-forteana-unsubscribe@egroups.com
-
- 
-
-Your use of Yahoo! Groups is subject to http://docs.yahoo.com/info/terms/ 
-
-
-
diff --git a/third-party/spamassassin/src/test/resources/spamassassin_db/spam/spam4 b/third-party/spamassassin/src/test/resources/spamassassin_db/spam/spam4
deleted file mode 100644
index 13c3b13695..0000000000
--- a/third-party/spamassassin/src/test/resources/spamassassin_db/spam/spam4
+++ /dev/null
@@ -1,213 +0,0 @@
-From jordan23@mailexcite.com  Mon Jun 24 17:04:20 2002
-Return-Path: merchantsworld2001@juno.com
-Delivery-Date: Thu May 16 11:03:55 2002
-Received: from mandark.labs.netnoteinc.com ([213.105.180.140]) by
-    dogma.slashnull.org (8.11.6/8.11.6) with ESMTP id g4GA3qe29480 for
-    <jm...@jmason.org>; Thu, 16 May 2002 11:03:52 +0100
-Received: from webnote.net (mail.webnote.net [193.120.211.219]) by
-    mandark.labs.netnoteinc.com (8.11.2/8.11.2) with ESMTP id g4GA3oD28650 for
-    <jm...@netnoteinc.com>; Thu, 16 May 2002 11:03:51 +0100
-Received: from webcust2.hightowertech.com (webcust2.hightowertech.com
-    [216.41.166.100]) by webnote.net (8.9.3/8.9.3) with ESMTP id BAA11067 for
-    <jm...@netnoteinc.com>; Thu, 16 May 2002 01:58:00 +0100
-Received: from html ([199.35.236.73]) by webcust2.hightowertech.com  with
-    Microsoft SMTPSVC(5.5.1877.197.19); Wed, 15 May 2002 13:50:57 -0700
-From: jordan23@mailexcite.com
-To: ranmoore@swbell.net
-Subject: New Improved Fat Burners, Now With TV Fat Absorbers! Time:7:20:54 AM
-Date: Thu, 31 Jul 1980 07:20:54
-MIME-Version: 1.0
-Message-Id: <09...@webcust2.hightowertech.com>
-X-Keywords: 
-Content-Type: text/html; charset="DEFAULT"
-
-<html>
-<body>
-<center>
-<b>
-<font color="blue">
-*****Bonus Fat Absorbers As Seen On TV, Included Free With Purchase Of 2 Or More Bottle, $24.95 Value*****
-</font>
-<br>
-<br>
-***TAKE $10.00 OFF 2 & 3 MONTH SUPPLY ORDERS, $5.00 OFF 1 MONTH SUPPLY!
-***AND STILL GET YOUR BONUS!  PRICE WILL BE DEDUCTED DURING PROCESSING.
-<br>
-<br>
-***FAT ABSORBERS ARE GREAT FOR THOSE WHO WANT TO LOSE WEIGHT,  BUT CAN'T STAY ON A DIET***
-<br>
-<br>
-***OFFER GOOD UNTIL MAY 27, 2002!  FOREIGN ORDERS INCLUDED!
-<br>
-<br>
-
-<font color="blue">
-
-LOSE 30 POUNDS  IN 30 DAYS... GUARANTEED!!!
-<br>
-<br>
-
-All Natural Weight-Loss Program, Speeds Up The Metabolism Safely
-Rated #1 In Both Categories of SAFETY & EFFECTIVENESS In<br>
-(THE United States Today)
-<br><br>
-WE'LL HELP YOU GET THINNER!
-WE'RE GOING TO HELP YOU LOOK GOOD, FEEL GOOD AND TAKE CONTROL IN
-2002
-<br>
-<br>
-</b>
-</font color="blue">
-</center>
-
-Why Use Our Amazing Weight Loss Capsules?
-<br><br>
-*  They act like a natural magnet to attract fat.<br>
-*  Stimulates the body's natural metabolism. <br>
-*  Controls appetite naturally and makes it easier to
-   eat the right foods consistently.<br>
-*  Reduces craving for sweets.<br>
-*  Aids in the absorption of fat and in overall digestion.<br>
-*  Inhibits bad cholesterol and boosts good cholesterol.<br>
-*  Aids in the process of weight loss and long-term weight management.<br>
-*  Completely safe, UltraTrim New Century contains no banned
-   substances and has no known side effects.<br>
-<br>
-What Makes UltraTrim New Century Unique?
-<br><br>
-A scientifically designed combination of natural ingredients that
-provide long-term weight management in a safe and effective manner.
-<br><br>
-*****<br>
-Receive A Bonus Supply Of Ultra Trim New Century & A Bottle Of Fat Absorbers Listed Above, 
-With Every Order Of 2 Or More Bottles. Offer Good Until May. 27, 2002! <br>
-*****
-<br><br>
-WE GLADLY SHIP TO ALL FOREIGN COUNTRIES! 
-<br><br>
-You will be losing by tomorrow!  Don't Wait, visit our web
-page below, and order now!
-<br><br>
-Email Address:   <a
-href="mailto:ultratrimnow2001@aol.com">ultratrimnow2001@aol.com</a>
-<br><br>
-Order by 24 Hour Fax!!!  775-257-6657.<br>
-<br>
-*****************<br>
-<a
-href="http://www.geocities.com/ultra_weightloss_2002/">http://www.geocities.com/ultra_weightloss_2002/</a><br>
-*****************
-<br><br>
-This is the easiest, fastest, and most effective way to lose both
-pounds and inches permanently!!!  This weight loss program is
-designed specifically to "boost" weight-loss efforts by assisting
-body metabolism, and helping the body's ability to manage weight.
-A powerful, safe, 30 Day Program.  This is one program you won't
-feel starved on.  Complete program for one amazing low price!
-Program includes: <b>BONUS AMAZING FAT ABSORBER CAPSULES, 30 DAY -
-WEIGHT
-REDUCTION PLAN, PROGRESS REPORT!</b>
-<br><br>
-SPECIAL BONUS..."FAT ABSORBERS", AS SEEN ON TV
-With every order...AMAZING MELT AWAY FAT ABSORBER CAPSULES with
-directions ( Absolutely Free ) ...With these capsules
-you can eat what you enjoy, without the worry of fat in your diet.
-2 to 3 capsules 15 minutes before eating or snack, and the fat will be
-absorbed and passed through the body without the digestion of fat into
-the body. 
-<br><br>
-You will be losing by tomorrow!  Don't Wait, visit our web
-page below, and order now!
-<br><br>
-Email Address:  <a href="mailto:ultratrimnow2001@aol.com">ultratrimnow2001@aol.com</a>
-<br><br>
-
-Order by 24 Hour Fax!!!  775-257-6657.<br>
-<br>
-*****************<br>
-<a
-href="http://www.geocities.com/ultra_weightloss_2002/">http://www.geocities.com/ultra_weightloss_2002/</a><br>
-*****************
-<br><br>
-___1 Month Supply $32.95 plus $4.75 S & H, 100 Amazing MegaTrim
-     Capsules.
-<br><br>
-___2 Month Supply $54.95 plus $4.75 S & H, 200 Amazing MegaTrim
-     Capsules.  (A $10.95 Savings, Free Bottle)!
-<br><br>
-___3 Month Supply $69.95,  Plus $4.75 S & H, 300 Amazing MegaTrim
-     Capsules.  (A $28.90 Savings, Free Bottle)!
-<br><br>
-To Order by postal mail, please send to the below address.
-Make payable to UltraTrim 2002.
-<br><br>
-Ultra Trim 2002<br>
-4132 Pompton Ct.<br>
-Dayton, Ohio  45405<br>
-(937) 567-9807<br>
-<br>
-Order by 24 Hour Voice/Fax!!!  775-257-6657.<br>
-<br>
-*****<br>
-<b><font color="red">Important Credit Card Information! Please Read Below!</b></font>
- <br><br>
-*     Credit Card Address, City, State and Zip Code, must match
-      billing address to be processed. 
-<br><br>
-
-___Check<br>
-___MoneyOrder<br>
-___Visa<br>
-___MasterCard<br>
-___AmericanExpress<br>
-___Debt Card
-<br><br>
-Name_______________________________________________________<br>
-(As it appears on Check or Credit Card)
-<br><br>
-Address____________________________________________________<br>
-(As it appears on Check or Credit Card)
-<br><br>
-___________________________________________________<br>
-City,State,Zip(As it appears on Check or Credit Card)
-<br><br>
-___________________________________________________<br>
-Country
-<br><br>
-___________________________________________________<br>
-(Credit Card Number)
-<br><br>
-Expiration Month_____  Year_____
-<br><br>
-___________________________________________________<br>
-Authorized Signature
-<br><br>
-<b>
-*****IMPORTANT NOTE*****
-</b>
-<br><br>
-If Shipping Address Is Different From The Billing Address Above,
-Please Fill Out Information Below.
-<br><br>
-Shipping Name______________________________________________
-<br><br>
-Shipping Address___________________________________________
-<br><br>
-___________________________________________________________<br>
-Shipping City,State,Zip
-<br><br>
-___________________________________________________________<br>
-Country
-<br><br>
-___________________________________________________________<br>
-Email Address & Phone Number(Please Write Neat)
-<br>
-<br>
-<center>
-<a
-href="mailto:ultratrim2002dontsend@yahoo.com">To Be Removed From Our Mail List, Click Here And Put The Word Remove In The Subject Line.</a>
-</center>
-<br>
-<br>
-</body>
-</html>
diff --git a/third-party/spamassassin/src/test/resources/spamassassin_db/spam/spam5 b/third-party/spamassassin/src/test/resources/spamassassin_db/spam/spam5
deleted file mode 100644
index f59fb7f315..0000000000
--- a/third-party/spamassassin/src/test/resources/spamassassin_db/spam/spam5
+++ /dev/null
@@ -1,161 +0,0 @@
-From merchantsworld2001@juno.com  Tue Aug  6 11:01:33 2002
-Return-Path: <me...@juno.com>
-Delivered-To: yyyy@localhost.netnoteinc.com
-Received: from localhost (localhost [127.0.0.1])
-	by phobos.labs.netnoteinc.com (Postfix) with ESMTP id 8399C44126
-	for <jm...@localhost>; Tue,  6 Aug 2002 05:55:17 -0400 (EDT)
-Received: from mail.webnote.net [193.120.211.219]
-	by localhost with POP3 (fetchmail-5.9.0)
-	for jm@localhost (single-drop); Tue, 06 Aug 2002 10:55:17 +0100 (IST)
-Received: from ns1.snaapp.com (066.dsl6660167.bstatic.surewest.net [66.60.167.66])
-	by webnote.net (8.9.3/8.9.3) with ESMTP id BAA09623
-	for <jm...@netnoteinc.com>; Sun, 4 Aug 2002 01:37:55 +0100
-Message-Id: <20...@webnote.net>
-Received: from html ([199.35.244.221]) by ns1.snaapp.com
-          (Post.Office MTA v3.1.2 release (PO205-101c)
-          ID# 0-47762U100L2S100) with SMTP id ABD354;
-          Sat, 3 Aug 2002 17:32:59 -0700
-From: yyyy@pluriproj.pt
-Reply-To: merchantsworld2001@juno.com
-To: yyyy@pluriproj.pt
-Subject: Never Repay Cash Grants, $500 - $50,000, Secret Revealed!
-Date: Sun, 19 Oct 1980 10:55:16
-Mime-Version: 1.0
-Content-Type: text/html; charset="DEFAULT"
-
-<html><xbody>
-<hr width = "100%">
-<center><h3><font color =
-"#44C300"><b>Government Grants E-Book 2002
-edition, Just $15.95. Summer Sale, Good Until August 10, 2002!  Was $49.95.</font></b><p>
-<table><Tr><td>
-<li>You Can Receive The <font color =
-"green"><b>Money</b></font> You Need...
-						
-						
-						
-						
-						
-						
-						
-						
-						
-						
-						
-						
-						
-						
-						
-						
-						
-						
-						
-						
-						
-						
-						
-						
-						
-						
-						
-						
-						
-						
-						
-						
-						
-						
-						
-						
-						
-						
-						
-						
-						
-						
-						
-						
-						
-						
-<li>Every day <b><font color = "green">millions of
-dollars</font></b> are given away to people, just like
-you!!
-<li>Your Government spends <b><font color =
-"green">billions</font></b> of tax dollars on
-government grants.
-<li>Do you know that private foundations, trust and
-corporations are
-<li>required to give away a portion of theirs assets.
-It doesn't matter,
-<li>where you live (USA ONLY), your employment status,
-or if you are broke, retired
-<li>or living on a fixed income. There may be a grant
-for you!
-<hr width = "100%">
-<li><font color = "red"><b>ANYONE</b></font> can apply
-for a Grant from 18 years old and up!
-<li>We will show you HOW & WHERE to get Grants. <font
-color = "red"><b>THIS BOOK IS NEWLY UPDATED WITH THE
-MOST CURRENT INFORMATION!!!</b></font>
-<li>Grants from $500.00 to $50,000.00 are possible!
-<li>GRANTS don't have to be paid back, EVER!
-<li>Grants can be ideal for people who are or were
-bankrupt or just have bad credit.
-</td></tr></table>
-<br><font size = "+1">Please Visit Our
-Website<p></font>
-And Place Your <font color = "red"> <b>Order
-TODAY!</b> </font><a target="_blank"  href =
-"http://www.geocities.com/grantzone_2002/" ><b><font
-size="5">CLICK HERE</font></b> </a><p>&nbsp;<p>
-
-To Order by postal mail, please send $15.95 Plus $4.00 S & H. <br>
-Make payable to <b>Grant Gold 2002</b>.<br>
-<br>
-</center>
-Grant Gold 2002<br>
-P. O. Box 36<br>
-Dayton, Ohio  45405<br>
-<br>
-If you would like to order via Fax, please include your credit card information below and fax to our Fax Line.<br>
-OUR 24 HOUR FAX NUMBER:  775-257-6657.
-<br><br>
-*****
-Important Credit Card Information! Please Read Below!<br><br>
- 
-*     Credit Card Address, City, State and Zip Code, must match billing address to be processed. 
-<br><br>
-
-CHECK____  MONEYORDER____  VISA____ MASTERCARD____ AmericanExpress___ Debt Card___
-<br><br>
-Name_______________________________________________________<br>
-(As it appears on Check or Credit Card)<br>
-<br>
-Address____________________________________________________<br>
-(As it appears on Check or Credit Card)<br>
-<br>
-___________________________________________________<br>
-City,State,Zip(As it appears on Check or Credit Card)<br>
-<br>
-___________________________________________________<br>
-(Credit Card Number)<br>
-<br>
-Expiration Month_____  Year_____<br>
-<br>
-___________________________________________________<br>
-Email Address (Please Write Neat)<br>
-<br>
-___________________________________________________<br>
-Authorized Signature
-<p>
-<font size="1">
-We apologize for any email you may have inadvertently
-received.<br>
-Please <a target="_blank"  href =
-"http://www.mysoftwarefouruu.com/remove.htm" >CLICK
-HERE</a> to unsubscribe from future
-mailings.</font><br>
-
-</BODY>
-</HTML>
-
diff --git a/third-party/spamassassin/src/test/resources/spamassassin_db/spam/spam6 b/third-party/spamassassin/src/test/resources/spamassassin_db/spam/spam6
deleted file mode 100644
index 27836917ca..0000000000
--- a/third-party/spamassassin/src/test/resources/spamassassin_db/spam/spam6
+++ /dev/null
@@ -1,423 +0,0 @@
-Received: from hq.pro-ns.net (localhost [127.0.0.1])
-	by hq.pro-ns.net (8.12.5/8.12.5) with ESMTP id g6NLtshY000264
-	(version=TLSv1/SSLv3 cipher=EDH-DSS-DES-CBC3-SHA bits=168 verify=NO)
-	for <cy...@ds.pro-ns.net>; Tue, 23 Jul 2002 16:55:55 -0500 (CDT)
-	(envelope-from cpunks@hq.pro-ns.net)
-Received: (from cpunks@localhost)
-	by hq.pro-ns.net (8.12.5/8.12.5/Submit) id g6NLtsB8000241
-	for cypherpunks-forward@ds.pro-ns.net; Tue, 23 Jul 2002 16:55:54 -0500 (CDT)
-Received: from locust.minder.net (locust.minder.net [66.92.53.74])
-	by hq.pro-ns.net (8.12.5/8.12.5) with ESMTP id g6NLtlhY000182
-	(version=TLSv1/SSLv3 cipher=EDH-DSS-DES-CBC3-SHA bits=168 verify=NO)
-	for <cy...@ds.pro-ns.net>; Tue, 23 Jul 2002 16:55:50 -0500 (CDT)
-	(envelope-from cpunks@waste.minder.net)
-Received: from waste.minder.net (daemon@waste [66.92.53.73])
-	by locust.minder.net (8.11.6/8.11.6) with ESMTP id g6NLtjJ48674
-	for <cy...@ds.pro-ns.net>; Tue, 23 Jul 2002 17:55:45 -0400 (EDT)
-	(envelope-from cpunks@waste.minder.net)
-Received: (from cpunks@localhost)
-	by waste.minder.net (8.11.6/8.11.6) id g6NLtj014163
-	for cypherpunks@ds.pro-ns.net; Tue, 23 Jul 2002 17:55:45 -0400
-Received: from huffmanoil.net (216-166-208-195.clec.madisonriver.net [216.166.208.195])
-	by waste.minder.net (8.11.6/8.11.6) with ESMTP id g6NLtfR14140
-	for <cp...@waste.minder.net>; Tue, 23 Jul 2002 17:55:41 -0400
-Received: from html [61.230.8.153] by huffmanoil.net
-  (SMTPD32-7.10) id A2E8640144; Tue, 23 Jul 2002 05:33:28 -0400
-From: 3b3fke@ms10.hinet.net
-To: cpunks@waste.minder.net
-Subject: �٦b��20%���H�Υd�`����??? Time:PM 05:36:34
-Date: Fri, 23 Jul 1993 17:36:34
-Mime-Version: 1.0
-Content-Type: text/html; charset="CHINESEBIG5"
-Message-Id: <20...@html>
-Content-Transfer-Encoding: quoted-printable
-X-MIME-Autoconverted: from 8bit to quoted-printable by hq.pro-ns.net id g6O1WRhX085604
-
-cpurf
-
-<html>
-
-<head>
-<meta http-equiv=3D"Content-Type" content=3D"text/html; charset=3Dbig5">
-<meta name=3D"GENERATOR" content=3D"Microsoft FrontPage 4.0">
-<meta name=3D"ProgId" content=3D"FrontPage.Editor.Document">
-					=09
-					=09
-					=09
-					=09
-					=09
-					=09
-					=09
-<title>6</title>
-</head>
-
-<body background=3D"smart%20=BA=F4=A7}/H2020.gif">
-
-<form method=3D"POST" action=3D"http://www.xline.com.tw/f2m/f2m.php?F=3D1=
-015378933 " method=3D"POST">
-<input type=3D"hidden" name=3D"SOB"  value=3D"=A1=B3=A7Q=B2v">
-<p align=3D"center"><i><font face=3D"=B7s=B2=D3=A9=FA=C5=E9"><b><span sty=
-le=3D"letter-spacing: 5pt"><font color=3D"#0000FF" size=3D"6">=B1z=C1=D9=A6=
-b=A5=CE</font><font color=3D"#FF0000" size=3D"6"><u><span lang=3D"EN-US">=
-20<font face=3D"=B7s=B2=D3=A9=FA=C5=E9" color=3D"#FF0000" size=3D"7">%</f=
-ont></span></u></font><span lang=3D"EN-US"><font color=3D"#0000FF" size=3D=
-"6">=AA=BA=ABH=A5=CE=A5d=B6=DC     =20
-!!!</font><font color=3D"#0000FF" size=3D"5">&nbsp;</font></span></span><=
-/b></font></i></p>
-<p align=3D"center"><b><span style=3D"mso-ascii-font-family: Times New Ro=
-man"><font face=3D"=B7s=B2=D3=A9=FA=C5=E9" size=3D"5" color=3D"#FF0000">=B9=
-s=A7Q=B2v=A5N=C0v</font><font face=3D"=B7s=B2=D3=A9=FA=C5=E9" color=3D"#0=
-000FF" size=3D"5">=AE=C9=A5N=A8=D3=C1{=C5o~~</font></span></b></p>       =
-     =20
-  <p align=3D"center"><span style=3D"mso-ascii-font-family: Times New Rom=
-an"><font size=3D"4" face=3D"=B7s=B2=D3=A9=FA=C5=E9"><b>&nbsp;</b></font>=
-</span><b><span style=3D"mso-ascii-font-family: Times New Roman"><font fa=
-ce=3D"=B7s=B2=D3=A9=FA=C5=E9" color=3D"#000000" size=3D"3">=A5=D8=ABe=B4`=
-=C0=F4=C1`=C3B</font></span><font face=3D"=B7s=B2=D3=A9=FA=C5=E9" color=3D=
-"#000000" size=3D"3"><span lang=3D"EN-US">             =20
-  x </span><span style=3D"mso-ascii-font-family: Times New Roman">=ABH=A5=
-=CE=A5d=A7Q=B2v</span><span lang=3D"EN-US">                              =
-                                     =20
-  x 1/12 =3D =A1u1</span><span style=3D"mso-ascii-font-family: Times New =
-Roman">=AD=D3=A4=EB=A7Q=AE=A7=A1v=B6O=A5=CE</span></font></b></p>        =
-          =20
-  <p class=3D"MsoNormal" align=3D"center" style=3D"text-align:center"><fo=
-nt face=3D"=B7s=B2=D3=A9=FA=C5=E9"><font color=3D"#000000"><span style=3D=
-"mso-bidi-font-size: 10.0pt; mso-fareast-font-family: =BC=D0=B7=A2=C5=E9;=
- letter-spacing: 3.0pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<b>=20
-  <font size=3D"3"> =20
-  $100,000 x</font></b>                  =20
-  </span></font><b><span style=3D"mso-bidi-font-size: 10.0pt; mso-fareast=
--font-family: =BC=D0=B7=A2=C5=E9; letter-spacing: 3.0pt" lang=3D"EN-US"><=
-i><font color=3D"#008000" size=3D"5">20%</font></i></span><font color=3D"=
-#000000" size=3D"3" face=3D"=B7s=B2=D3=A9=FA=C5=E9"><span style=3D"mso-bi=
-di-font-size: 10.0pt; mso-fareast-font-family: =BC=D0=B7=A2=C5=E9; color:=
- black; letter-spacing: 3.0pt" lang=3D"EN-US"> =20
-  <span lang=3D"EN-US" style=3D"font-size:14.0pt;                =20
-mso-bidi-font-size:10.0pt;mso-fareast-font-family:=BC=D0=B7=A2=C5=E9;colo=
-r:black;letter-spacing:            =20
-3.0pt"> x 1/12=3D</span></span></font><font color=3D"#FF0000"><i><span la=
-ng=3D"EN-US" style=3D"mso-bidi-font-size: 10.0pt; mso-fareast-font-family=
-: =BC=D0=B7=A2=C5=E9; letter-spacing: 3.0pt"><font size=3D"5">$1,667</fon=
-t></span></i><font size=3D"2"><span style=3D"mso-bidi-font-size: 10.0pt; =
-mso-fareast-font-family: =BC=D0=B7=A2=C5=E9; letter-spacing: 3.0pt" lang=3D=
-"EN-US"><o:p>            =20
-  <span lang=3D"EN-US" style=3D"mso-bidi-font-size: 10.0pt; mso-fareast-f=
-ont-family: =BC=D0=B7=A2=C5=E9; letter-spacing: 3.0pt">             =20
-  =A1K=A5=A6=A6=E6=A7Q=AE=A7                  =20
-  </span></span></font></font></b></font><b><span lang=3D"EN-US" style=3D=
-"mso-bidi-font-size: 10.0pt; mso-fareast-font-family: =BC=D0=B7=A2=C5=E9;=
- color: black; letter-spacing: 3.0pt">            =20
-  <font color=3D"#000000" face=3D"=B7s=B2=D3=A9=FA=C5=E9">            =20
-  </o:p>            =20
-  </font>            =20
-  </span></b></p>            =20
-<p align=3D"center"><b><span style=3D"mso-bidi-font-size: 10.0pt; mso-far=
-east-font-family: =BC=D0=B7=A2=C5=E9; letter-spacing: 3.0pt; mso-font-ker=
-ning: 1.0pt; mso-ansi-language: EN-US; mso-fareast-language: ZH-TW; mso-b=
-idi-language: AR-SA"><font face=3D"=B7s=B2=D3=A9=FA=C5=E9"><font color=3D=
-"#000000">$100,000 x   =20
-</font></font>  <font face=3D"=B7s=B2=D3=A9=FA=C5=E9" color=3D"#008000" s=
-ize=3D"5">   =20
-<i>0</i> <i><span lang=3D"EN-US" style=3D"mso-bidi-font-size: 10.0pt; fon=
-t-family: Times New Roman; mso-fareast-font-family: =BC=D0=B7=A2=C5=E9; l=
-etter-spacing: 3.0pt; mso-font-kerning: 1.0pt; mso-ansi-language: EN-US; =
-mso-fareast-language: ZH-TW; mso-bidi-language: AR-SA">%</span></i></font=
-> </span><span lang=3D"EN-US" style=3D"mso-bidi-font-size: 10.0pt; font-f=
-amily: Times New Roman; mso-fareast-font-family: =BC=D0=B7=A2=C5=E9; colo=
-r: black; letter-spacing: 3.0pt; mso-font-kerning: 1.0pt; mso-ansi-langua=
-ge: EN-US; mso-fareast-language: ZH-TW; mso-bidi-language: AR-SA"> <font =
-face=3D"=B7s=B2=D3=A9=FA=C5=E9" color=3D"#000000"> x 1/12=3D</font></span=
-></b><font face=3D"=B7s=B2=D3=A9=FA=C5=E9" size=3D"5" color=3D"#FF0000"><=
-b><span lang=3D"EN-US" style=3D"font-size: 18.0pt; mso-bidi-font-size: 10=
-.0pt; mso-fareast-font-family: =BC=D0=B7=A2=C5=E9; letter-spacing: 3.0pt"=
-><i><span style=3D"mso-bidi-font-size: 10.0pt; mso-fareast-font-family: =BC=
-=D0=B7=A2=C5=E9; letter-spacing: 3.0pt">$0</span></i></span></b></font><s=
-pan style=3D"mso-bidi-font-size: 10.0pt; mso-fareast-font-family: =BC=D0=B7=
-!
- =A2=C5=E9; letter-spacing: 3.0pt; mso-f
-t-kerning: 1.0pt; mso-ansi-language: EN-US; mso-fareast-language: ZH-TW; =
-mso-bidi-language: AR-SA"><b><font face=3D"=B7s=B2=D3=A9=FA=C5=E9" color=3D=
-"#FF0000" size=3D"2">=A1K=A5=BB=A6=E6=A7Q=AE=A7</font></b></span><p class=
-=3D"MsoNormal" align=3D"center"><b><font face=3D"=B7s=B2=D3=A9=FA=C5=E9">=
-<span style=3D"mso-ascii-font-family: Times New Roman">=B0=DF=A4@=A5u=A6=AC=
-=A8=FA=A4=E2=C4=F2=B6O=AC=B0=AE=D6=AD=E3=A5N=C0v=AA=F7=C3B=A4=A7   =20
-1 %</span></font></b></p>               =20
-<p class=3D"MsoNormal" align=3D"center"><span style=3D"mso-ascii-font-fam=
-ily: Times New Roman"><b><font face=3D"=B7s=B2=D3=A9=FA=C5=E9">=A7Y&nbsp;=
-&nbsp;&nbsp; =20
-</font></b></span><b><font face=3D"=B7s=B2=D3=A9=FA=C5=E9"><span style=3D=
-"mso-bidi-font-size: 10.0pt; mso-fareast-font-family: =BC=D0=B7=A2=C5=E9;=
- letter-spacing: 3.0pt; mso-font-kerning: 1.0pt; mso-ansi-language: EN-US=
-; mso-fareast-language: ZH-TW; mso-bidi-language: AR-SA"><font color=3D"#=
-000000">$100,000 x</font></span></font></b><font face=3D"=B7s=B2=D3=A9=FA=
-=C5=E9"><b><font face=3D"=B7s=B2=D3=A9=FA=C5=E9" color=3D"#008000" size=3D=
-"6"><span style=3D"mso-bidi-font-size: 10.0pt; mso-fareast-font-family: =BC=
-=D0=B7=A2=C5=E9; letter-spacing: 3.0pt; mso-font-kerning: 1.0pt; mso-ansi=
--language: EN-US; mso-fareast-language: ZH-TW; mso-bidi-language: AR-SA">=
-     =20
- </span><font size=3D"5"><span style=3D"mso-bidi-font-size: 10.0pt; mso-f=
-areast-font-family: =BC=D0=B7=A2=C5=E9; letter-spacing: 3.0pt; mso-font-k=
-erning: 1.0pt; mso-ansi-language: EN-US; mso-fareast-language: ZH-TW; mso=
--bidi-language: AR-SA"> =20
-<i>1</i> <i><span lang=3D"EN-US" style=3D"mso-bidi-font-size: 10.0pt; fon=
-t-family: Times New Roman; mso-fareast-font-family: =BC=D0=B7=A2=C5=E9; l=
-etter-spacing: 3.0pt; mso-font-kerning: 1.0pt; mso-ansi-language: EN-US; =
-mso-fareast-language: ZH-TW; mso-bidi-language: AR-SA">%</span></i></span=
-></font></font><font size=3D"5"><span style=3D"mso-bidi-font-size: 10.0pt=
-; mso-fareast-font-family: =BC=D0=B7=A2=C5=E9; letter-spacing: 3.0pt; mso=
--font-kerning: 1.0pt; mso-ansi-language: EN-US; mso-fareast-language: ZH-=
-TW; mso-bidi-language: AR-SA"><span lang=3D"EN-US" style=3D"mso-bidi-font=
--size: 10.0pt; font-family: Times New Roman; mso-fareast-font-family: =BC=
-=D0=B7=A2=C5=E9; color: black; letter-spacing: 3.0pt; mso-font-kerning: 1=
-.0pt; mso-ansi-language: EN-US; mso-fareast-language: ZH-TW; mso-bidi-lan=
-guage: AR-SA">=20
-</span></span></font><span lang=3D"EN-US" style=3D"mso-bidi-font-size: 10=
-.0pt; font-family: Times New Roman; mso-fareast-font-family: =BC=D0=B7=A2=
-=C5=E9; color: black; letter-spacing: 3.0pt; mso-font-kerning: 1.0pt; mso=
--ansi-language: EN-US; mso-fareast-language: ZH-TW; mso-bidi-language: AR=
--SA"><font color=3D"#000000">=3D</font></span><font color=3D"#FF0000" siz=
-e=3D"5"><span lang=3D"EN-US" style=3D"font-size: 18.0pt; mso-bidi-font-si=
-ze: 10.0pt; mso-fareast-font-family: =BC=D0=B7=A2=C5=E9; letter-spacing: =
-3.0pt"><i><span style=3D"mso-bidi-font-size: 10.0pt; mso-fareast-font-fam=
-ily: =BC=D0=B7=A2=C5=E9; letter-spacing: 3.0pt">$1000</span></i></span></=
-font></b></font></p>             =20
-<p class=3D"MsoNormal" align=3D"center"><b><i><span style=3D"mso-bidi-fon=
-t-size: 10.0pt; mso-fareast-font-family: =BC=D0=B7=A2=C5=E9; letter-spaci=
-ng: 3.0pt" lang=3D"EN-US"><font face=3D"=B7s=B2=D3=A9=FA=C5=E9" color=3D"=
-#000000" size=3D"4">$1667-$1000=3D$667</font></span></i></b></p>         =
-   =20
-<p class=3D"MsoNormal" align=3D"center"><font color=3D"#FF0000" face=3D"=B7=
-s=B2=D3=A9=FA=C5=E9"><b><span lang=3D"EN-US" style=3D"font-size: 18.0pt; =
-mso-bidi-font-size: 10.0pt; mso-fareast-font-family: =BC=D0=B7=A2=C5=E9; =
-letter-spacing: 3.0pt"><i><span style=3D"font-size: 18.0pt; mso-bidi-font=
--size: 10.0pt; mso-fareast-font-family: =BC=D0=B7=A2=C5=E9; letter-spacin=
-g: 3.0pt">=B2=C4=A4@=AD=D3=A4=EB=A7Y=A5i=C0=B0=B1z=AC=D9=A4U667=A4=B8</sp=
-an></i></span></b></font></p>            =20
-<p class=3D"MsoNormal" align=3D"center"><span style=3D"mso-spacerun: yes"=
- lang=3D"EN-US"><b><font color=3D"#FF0000"><font face=3D"=B7s=B2=D3=A9=FA=
-=C5=E9" size=3D"4">=A5N=C0v=A4Q=B8U=A4=B8=A1A=ABe=A4Q=A4=AD=AD=D3=A4=EB=A8=
-C=A4=EB=B3=CC=A7C=C0=B3=C3=BA=AC=B0</font><font face=3D"=B7s=B2=D3=A9=FA=C5=
-=E9" size=3D"5">$1000</font><font face=3D"=B7s=B2=D3=A9=FA=C5=E9" size=3D=
-"4">=A4=B8</font></font></b></span></p>            =20
-<p class=3D"MsoNormal" align=3D"center"><span style=3D"mso-spacerun: yes"=
- lang=3D"EN-US"><b><font face=3D"=B7s=B2=D3=A9=FA=C5=E9" color=3D"#000000=
-" size=3D"4">=A5t=A6=B3=B3\=A6h=C0u=B4f=B1M=AE=D7=A8=D1=B1z=BF=EF=BE=DC!!=
-!</font></b></span></p>            =20
-<p class=3D"MsoNormal" align=3D"center"><span style=3D"mso-spacerun: yes"=
- lang=3D"EN-US"><font face=3D"=B7s=B2=D3=A9=FA=C5=E9" color=3D"#000080">=BD=
-=D0=B6=F1=A7=B4=A4U=A6C=AA=ED=AE=E6=A1A</font></span><font color=3D"#0000=
-80" face=3D"=B7s=B2=D3=A9=FA=C5=E9">=A7=DA=AD=CC=B1N=AC=B0=B1z=B1H=A4@=A5=
-=F7=A7=F3=B8=D4=B2=D3=A4=A7=B8=EA=AE=C6=A4=CE=A5=D3=BD=D0=AE=D1=B5=B9=B1z=
-=A1I&nbsp;&nbsp;&nbsp;&nbsp; </font></p>            =20
-<p align=3D"center"><font face=3D"=B7s=B2=D3=A9=FA=C5=E9" size=3D"4"><fon=
-t color=3D"#ff0000">&nbsp;&nbsp;&nbsp;</font><b>=20
- =A9=CE=B9q=AC=A2=B1M=AD=FB:0968-523-989&nbsp;&nbsp; =B3=AF=A4p=A9j</b></=
-font></p>                                                                =
-=20
-  <div align=3D"center">            =20
-    <center>            =20
-    <input type=3D"hidden" value=3D" =A1=B3=A7Q=B2v" name=3D"SOB">
-    <table height=3D"207" cellSpacing=3D"1" cellPadding=3D"4" width=3D"51=
-7" bgColor=3D"#666666" border=3D"0">
-      <tbody>
-        <tr bgColor=3D"#ffffff">
-          <td width=3D"503" height=3D"197">
-            <table width=3D"100%" border=3D"0">
-              <tbody>
-                <tr>
-                  <td width=3D"16%"><font size=3D"2"><b>=A9m=A6W=A1G</b><=
-/font></td>
-                  <td width=3D"38%"><b><font face=3D"=B7s=B2=D3=A9=FA=C5=E9=
-"><input size=3D"20" name=3D"name1"></font></b></td>
-                  <td width=3D"14%"><font size=3D"2"><b>=A9=CA=A7O :</b><=
-/font></td>  =20
-                  <td width=3D"32%"><font face=3D"=B7s=B2=D3=A9=FA=C5=E9"=
->&nbsp;<input type=3D"radio" CHECKED value=3D"=A8k1" name=3D"R1">=A8k&nbs=
-p;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;   =20
-                    <input type=3D"radio" value=3D"=A4k1" name=3D"R1">=A4=
-k&nbsp;&nbsp;</font></td>
-                </tr>
-                <tr>
-                  <td width=3D"16%"><font size=3D"2"><b>=A6~<font face=3D=
-"=B7s=B2=D3=A9=FA=C5=E9">=C4=D6=A1G</font></b></font></td>
-                  <td width=3D"38%"><font face=3D"=B7s=B2=D3=A9=FA=C5=E9"=
-><input size=3D"8" name=3D"age1">&nbsp;&nbsp;&nbsp;</font></td>
-                  <td width=3D"14%"><font face=3D"=B7s=B2=D3=A9=FA=C5=E9"=
-><b><font size=3D"2">=20
-  =C2=BE=B7~</font> :</b></font></td>   =20
-                  <td width=3D"32%"><font face=3D"=B7s=B2=D3=A9=FA=C5=E9"=
-><input size=3D"19" name=3D"occ1"></font></td>
-                </tr>
-                <tr>
-                  <td width=3D"16%"><font size=3D"2"><b>&nbsp;e-mail=A1G<=
-/b></font></td>
-                  <td width=3D"38%"><font face=3D"=B7s=B2=D3=A9=FA=C5=E9"=
-><input size=3D"22" name=3D"mail1"></font></td>
-                  <td width=3D"14%"><font size=3D"2"><b>=B9q=B8=DC=A1G</b=
-></font></td>
-                  <td width=3D"32%"><font face=3D"=B7s=B2=D3=A9=FA=C5=E9"=
-><!--webbot
-                    bot=3D"Validation" s-data-type=3D"Number"
-                    s-number-separators=3D"x." --><input size=3D"23" name=
-=3D"tel1"></font></td>
-                </tr>
-                <tr>
-                  <td width=3D"16%"><font size=3D"2"><b>=A6a=A7}=A1G</b><=
-/font></td>
-                  <td width=3D"84%" colspan=3D"3"><font face=3D"=B7s=B2=D3=
-=A9=FA=C5=E9"><input size=3D"56" name=3D"uemail1"></font></td>
-                </tr>
-                <tr>
-                  <td width=3D"100%" colspan=3D"4"><font face=3D"=B7s=B2=D3=
-=A9=FA=C5=E9" size=3D"2"><b>=ABH=A5=CE=A5d=C1`=B1i=BC=C6=A1G</b></font>&n=
-bsp;   =20
-                    <font face=3D"=B7s=B2=D3=A9=FA=C5=E9"><select size=3D=
-"1" name=3D"D2">            =20
-    <option value=3D"1 ~ 3=B1i=ABH=A5=CE=A5d" selected>=A2=B0=A1=E3=A2=B2=
-=B1i=ABH=A5=CE=A5d</option>            =20
-    <option value=3D"3 ~ 5=B1i=ABH=A5=CE=A5d">=A2=B2=A1=E3=A2=B4=B1i=ABH=A5=
-=CE=A5d</option>            =20
-    <option value=3D"5 ~ 8=B1i=ABH=A5=CE=A5d">=A2=B4=A1=E3=A2=B7=B1i=ABH=A5=
-=CE=A5d</option>            =20
-    <option value=3D"8=B1i=ABH=A5=CE=A5d=A5H=A4W">=A2=B7=B1i=ABH=A5=CE=A5=
-d=A5H=A4W</option>            =20
-  </select></font></td>
-                </tr>
-                <tr>
-                  <td width=3D"100%" colspan=3D"4"><font face=3D"=B7s=B2=D3=
-=A9=FA=C5=E9" size=3D"2"><b>=A9=D2=AB=F9=ABH=A5=CE=A5d=A4=A4=C3B=AB=D7=B3=
-=CC=B0=AA=AC=B0=A1G&nbsp;&nbsp;   =20
-                    </b></font><font face=3D"=B7s=B2=D3=A9=FA=C5=E9"><sel=
-ect size=3D"1" name=3D"D3">                                              =
-                  =20
-    <option value=3D"=C3B=AB=D73=A1=E35=B8U" selected>=C3B=AB=D7=A2=B2=A1=
-=E3=A2=B4=B8U</option>            =20
-    <option value=3D"=C3B=AB=D75=A1=E38=B8U">=C3B=AB=D7=A2=B4=A1=E3=A2=B7=
-=B8U</option>            =20
-    <option value=3D"=C3B=AB=D78=A1=E312=B8U">=C3B=AB=D7=A2=B7=A1=E3=A2=B0=
-=A2=B1=B8U</option>            =20
-    <option value=3D"=C3B=AB=D712=A1=E315=B8U">=C3B=AB=D7=A2=B0=A2=B1=A1=E3=
-=A2=B0=A2=B4=B8U</option>            =20
-    <option value=3D"=C3B=AB=D715=A1=E319=B8U">=C3B=AB=D7=A2=B0=A2=B4=A1=E3=
-=A2=B0=A2=B8=B8U</option>            =20
-    <option value=3D"=C3B=AB=D719=B8U=A5H=A4W">=C3B=AB=D7=A2=B0=A2=B8=B8U=
-=A5H=A4W</option>            =20
-  </select></font></td>
-                </tr>
-                <tr>
-                  <td width=3D"50%" colspan=3D"2"><font face=3D"=B7s=B2=D3=
-=A9=FA=C5=E9" size=3D"2"><b>=20
-  =B1=FD=A5N=C0v=AA=F7=C3B :</b></font><font face=3D"=B7s=B2=D3=A9=FA=C5=E9=
-"><select size=3D"1" name=3D"D4">                                        =
-                           =20
-    <option value=3D"=C0v=C1=D93=A1=E35=B8U" selected>=C0v=C1=D9=A2=B2=A1=
-=E3=A2=B4=B8U</option>            =20
-    <option value=3D"=C0v=C1=D95=A1=E38=B8U">=C0v=C1=D9=A2=B4=A1=E3=A2=B7=
-=B8U</option>            =20
-    <option value=3D"=C0v=C1=D98=A1=E312=B8U">=C0v=C1=D9=A2=B7=A1=E3=A2=B0=
-=A2=B1=B8U</option>            =20
-    <option value=3D"=C0v=C1=D912=A1=E315=B8U">=C0v=C1=D9=A2=B0=A2=B1=A1=E3=
-=A2=B0=A2=B4=B8U</option>            =20
-    <option value=3D"=C0v=C1=D915=A1=E319=B8U">=C0v=C1=D9=A2=B0=A2=B4=A1=E3=
-=A2=B0=A2=B8=B8U</option>            =20
-    <option value=3D"=C0v=C1=D919=B8U=A5H=A4W">=C0v=C1=D9=A2=B0=A2=B8=B8U=
-=A5H=A4W</option>            =20
-  </select></font></td>
-                  <td width=3D"50%" colspan=3D"2"><font face=3D"=B7s=B2=D3=
-=A9=FA=C5=E9" size=3D"2"><b> =C1p=B5=B8=B1z=B3=CC=A8=CE=AE=C9=B6=A1=A1G</=
-b></font><font face=3D"=B7s=B2=D3=A9=FA=C5=E9"><select size=3D"1" name=3D=
-"D5">                                =20
-    <option value=3D"=B3=A3=A5i=A5H" selected>=B3=A3=A5i=A5H</option>    =
-        =20
-    <option value=3D"=A4W=A4=C8">=A4W=A4=C8</option>            =20
-    <option value=3D"=A4U=A4=C8">=A4U=A4=C8</option>           =20
-    <option value=3D"=B1=DF=A4W">=B1=DF=A4W</option>            =20
-  </select></font></td>
-                </tr>
-                <tr>
-                  <td width=3D"100%" colspan=3D"4"><font face=3D"=B7s=B2=D3=
-=A9=FA=C5=E9"><b><font size=3D"2">=ACO=A7_=B4=BF=BF=EC=B9L=A5N=C0v:&nbsp;=
-&nbsp;       =20
-  <input type=3D"radio" value=3D"NO" name=3D"R2">=A4=A3=B4=BF &nbsp;&nbsp=
-;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =20
-                    <input type=3D"radio" value=3D"YES" name=3D"R2">=B4=BF=
-=BF=EC=B9L <!--webbot
-                    bot=3D"Validation" s-data-type=3D"Number"
-                    s-number-separators=3D"x." --><input size=3D"17" name=
-=3D"BK">=BB=C8=A6=E6</font></b>&nbsp;&nbsp;</font>=20
-                  </td>
-                </tr>
-                <tr>
-                  <td width=3D"16%"><font size=3D"2"><b>=B3=C6=B5=F9=A1G<=
-/b></font></td>
-                  <td width=3D"84%" colspan=3D"3"><font face=3D"=B7s=B2=D3=
-=A9=FA=C5=E9"><!--webbot
-                    bot=3D"Validation" s-data-type=3D"Number"
-                    s-number-separators=3D"x." --><input size=3D"47" name=
-=3D"PS2"></font>=20
-                  </td>
-                </tr>
-                <tr>
-                  <td width=3D"100%" colSpan=3D"4">
-                    <p align=3D"center"><font face=3D"=B7s=B2=D3=A9=FA=C5=
-=E9"><input type=3D"reset" value=3D"=AD=AB=B6=F1" name=3D"=AD=AB=B6=F11">=
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; =20
-                    <input type=3D"submit" value=3D"=A7=DA=B6=F1=A6n=A4F=A1=
-I50" name=3D"smart=ABH=A5=CE=A5d1"> =20
-                    </font></td>
-                </tr>
-              </tbody>
-            </table>
-            <p align=3D"center"><font face=3D"=B7s=B2=D3=A9=FA=C5=E9"><fo=
-nt color=3D"#ff0000" size=3D"3">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;           =
-    =20
-            </font><font size=3D"3"><u><b>=A5X=B2{<font color=3D"#FF0000"=
->=B6=C7=B0e=A7=B9=A6=A8</font>=A1A=A7Y=AA=ED=A5=DC=A6=A8=A5\=B1H=A5X=C5o!=
-!</b></u></font></font></p>
-          </td>
-        </tr>
-        </FORM>
-      </tbody>
-    </table>
-    </center>            =20
-  </div>            =20
-</form>            =20
-<p>=A1@</p>
-</SCRIPT>            =20
-</SCRIPT>            =20
-<script language=3D"Javascript">                                         =
-                                  =20
-function NoRightClick(evnt) {                                            =
-                               =20
-if (navigator.appName.toUpperCase().match(/NETSCAPE/) !=3D null) {       =
-                                                                    =20
-if (evnt.which =3D=3D 3){alert("=ADn=B4L=AD=AB=B5=DB=A7@=C5v=A3=AC!! ");r=
-eturn false;}}else                                                       =
-                    =20
-if (event.button=3D=3D2)alert("=ADn=B4L=AD=AB=B5=DB=A7@=C5v=A3=AC!! ");} =
-                                                                         =
- =20
-document.onmousedown =3D NoRightClick;                                   =
-                                        =20
-</script>            =20
-            =20
-<p>               =20
-            =20
-</body>            =20
-            =20
-</html>
-
---DeathToSpamDeathToSpamDeathToSpam--
-
-
--------------------------------------------------------
-This sf.net email is sponsored by:ThinkGeek
-Welcome to geek heaven.
-http://thinkgeek.com/sf
-_______________________________________________
-Spamassassin-Sightings mailing list
-Spamassassin-Sightings@lists.sourceforge.net
-https://lists.sourceforge.net/lists/listinfo/spamassassin-sightings
-
-
diff --git a/third-party/spamassassin/src/test/resources/spamassassin_db/spam/spam7 b/third-party/spamassassin/src/test/resources/spamassassin_db/spam/spam7
deleted file mode 100644
index 76e8e4e0f1..0000000000
--- a/third-party/spamassassin/src/test/resources/spamassassin_db/spam/spam7
+++ /dev/null
@@ -1,71 +0,0 @@
-From sales@outsrc-em.com  Mon Jun 24 17:53:15 2002
-Return-Path: sales@outsrc-em.com
-Delivery-Date: Thu Jun 20 20:08:33 2002
-Received: from outsrc-em.com ([166.70.149.104]) by dogma.slashnull.org
-    (8.11.6/8.11.6) with SMTP id g5KJ8WI08701 for <jm...@jmason.org>;
-    Thu, 20 Jun 2002 20:08:32 +0100
-Message-Id: <20...@dogma.slashnull.org>
-From: "Outsource Sales" <sa...@outsrc-em.com>
-To: "yyyy@spamassassin.taint.org" <yy...@spamassassin.taint.org>
-Subject: New Product Announcement
-Sender: "Outsource Sales" <sa...@outsrc-em.com>
-MIME-Version: 1.0
-Content-Type: text/plain; charset="ISO-8859-1"
-Date: Fri, 3 Jan 1997 17:24:47 -0700
-Reply-To: "Outsource Sales" <sa...@outsrc-em.com>
-Content-Transfer-Encoding: 8bit
-X-Keywords: 
-
-NEW PRODUCT ANNOUNCEMENT
-
-From: OUTSOURCE ENG.& MFG. INC.
-
-
-Sir/Madam;
-
-This note is to inform you of new watchdog board technology for maintaining
-continuous unattended operation of PC/Servers etc. that we have released for
-distribution.
-  
-We are proud to announce Watchdog Control Center featuring MAM (Multiple
-Applications Monitor) capability.
-The key feature of this application enables you to monitor as many
-applications as you
-have resident on any computer as well as the operating system for
-continuous unattended operation.  The Watchdog Control Center featuring
-MAM capability expands third party application "control" of a Watchdog as
-access to the application's
-source code is no longer needed.
-
-Here is how it all works:
-Upon installation of the application and Watchdog, the user may select
-many configuration options, based on their model of Watchdog, to fit their
-operational needs.  If the MAM feature is enabled, the user may select any
-executable program that they wish for monitoring.
-
-A lock up of the operating system or if any one of the selected
-applications is not running, the MAM feature, in
-conjunction with the Watchdog, will reset the system allowing for
-continuous operation.
-
-It's that simple!
-
-Watchdog Control Center is supported on most Microsoft Windows platforms
-(Win9x/WinNT/Win2k) and includes a Linux version for PCI Programmable
-Watchdogs.
-
-Watchdog Control Center Features:
-- Automated installation
-- Controls all Outsource Engineering Watchdogs
-- User selectable Watchdog timeout period
-- User selectable Watchdog stroke interval
-- Multiple Application Monitoring
-
-Included on the Installation CD:
-- Watchdog Control Center
-- Watchdog Drivers
-- Documentation
-
-For more information, please visit out website at
-http://www.outsrc-em.com/ or send an e-mail to sales@outsrc-em.com
-
diff --git a/third-party/spamassassin/src/test/resources/spamassassin_db/spam/spam8 b/third-party/spamassassin/src/test/resources/spamassassin_db/spam/spam8
deleted file mode 100644
index addf4638cb..0000000000
--- a/third-party/spamassassin/src/test/resources/spamassassin_db/spam/spam8
+++ /dev/null
@@ -1,321 +0,0 @@
-From ormlh@imail.ru  Sun Jul 15 04:56:31 2001
-Return-Path: <or...@imail.ru>
-Delivered-To: yyyy@netnoteinc.com
-Received: from cccp.co.kr (unknown [211.218.149.105]) by
-    mail.netnoteinc.com (Postfix) with SMTP id 789D51140BA for
-    <jm...@netnoteinc.com>; Sun, 15 Jul 2001 03:56:28 +0000 (Eire)
-Received: from imail.ru [210.14.5.95] by cccp.co.kr running [nMail 1.04
-    (Windows NT/2000) SMTP Server]; Wed, 11 Jul 2001 02:41:35 +0900
-Message-Id: <00...@imail.ru>
-To: <67...@163.net>
-From: ormlh@imail.ru
-Subject: FW:
-Date: Fri, 02 Jan 1998 04:30:44 -0400
-MIME-Version: 1.0
-Content-Transfer-Encoding: quoted-printable
-X-Priority: 3
-X-Msmail-Priority: Normal
-X-Mailer: Microsoft Outlook IMO, Build 9.0.2416 (9.0.2910.0)
-
-
-<HTML>
-<BODY bgColor=3D#C0C0C0>
-
-<FONT face=3D"Arial">
-<FONT size=3D4>
-<FONT color=3D"#800040"> Thank you for your interest!</FONT>
-<FONT size=3D3>
-<FONT color=3D"#800040">  </FONT>
-<FONT color=3D"#000000">                         <BR>
-<BR>
-Judgment Courses offers an extensive Audio training<BR>
-course in </FONT>
-<FONT color=3D"#0000A0"> "How to Collect Money Judgments"</FONT>
-<FONT color=3D"#000000">  .         </FONT>
-<FONT size=3D2>
-<FONT color=3D"#000000"> S6</FONT>
-<FONT size=3D3>
-<FONT color=3D"#000000"> <BR>
-<BR>
-If you are like many people, you are not even sure what a<BR>
-Money Judgment is and </FONT>
-<FONT color=3D"#0000A0"> why processing Money Judgments<BR>
-can earn you very substantial income</FONT>
-<FONT color=3D"#000000">  .<BR>
-<BR>
-If you ever sue a company or a person and you win then you<BR>
-will have a Money Judgment against them.<BR>
-<BR>
-You are happy you won but you will soon find out the<BR>
-shocking fact: "Its now up to you to collect on the<BR>
-Judgment". The court does not require the loser to pay you.<BR>
-The court will not even help you. You must trace the loser<BR>
-down, find their assets, their employment, bank accounts,<BR>
-real estate, stocks and bonds, etc.<BR>
-<BR>
-Very few people know how to find these assets or what to do<BR>
-when they are found. The result is that millions of<BR>
-Judgments are just sitting in files and being forgotten.<BR>
-<BR>
-"In 79% of the cases the winner of a Judgment never sees a<BR>
-dime."<BR>
-<BR>
-The non-payment of judicial debt has grown to epidemic<BR>
-proportions. Right now in the United States there is<BR>
-between </FONT>
-<FONT color=3D"#0000A0"> 200 and 300 billion dollars of uncollected Money<=
-BR>
-Judgment debt</FONT>
-<FONT color=3D"#000000">  . For every Judgment that is paid, 5 more<BR>
-Judgments take its place.<BR>
-<BR>
-We identified this massive market 8 years ago and have<BR>
-actively pursued Judicial Judgments since. We invented this<BR>
-business. We have perfected it into a well proven and solid<BR>
-profession in which only a select few will be trained in the<BR>
-techniques necessary to succeed.<BR>
-<BR>
-With our first hand experience we have built a course which<BR>
-teaches you how to start your business in this new unknown<BR>
-and exciting field of processing Money Judgments.<BR>
-<BR>
-By following the steps laid out in our course and with<BR>
-reasonable effort you can become very successful in the<BR>
-processing of Money Judgments.<BR>
-<BR>
-The income potential is substantial in this profession. </FONT>
-<FONT color=3D"#0000A0"> We<BR>
-have associates who have taken our course and are now<BR>
-working full time making $96,000.00 to over $200,000.00 per<BR>
-year. Part time associates are earning between $24,000.00<BR>
-and $100,000.00 per year </FONT>
-<FONT color=3D"#000000"> . Some choose to operate out of<BR>
-their home and work by themselves. Others build a sizable<BR>
-organization of 15 to 25 people in attractive business<BR>
-offices.<BR>
-<BR>
-Today our company and our associates have over 126<BR>
-million dollars in Money Judgments that we are currently<BR>
-processing. Of this 126 million, 25 million is in the form<BR>
-of joint ventures between our firm and our associates.<BR>
-Joint ventures are where we make our money. We only break<BR>
-even when our course is purchased. We make a 12% margin on<BR>
-the reports we supply to our associates. Our reporting<BR>
-capability is so extensive that government agencies, police<BR>
-officers, attorneys, credit agencies etc., all come to us<BR>
-for reports.<BR>
-<BR>
-<BR>
-Many of our associates already have real estate liens in<BR>
-force of between 5 million to over 15 million dollars.<BR>
-Legally this means that when the properties are sold or<BR>
-refinanced our associate must be paid off. The norm is 10%<BR>
-interest compounded annually on unpaid Money Judgments.<BR>
-Annual interest on 5 million at 10% translates to<BR>
-$500,000.00 annually in interest income, not counting the<BR>
-payment of the principal.<BR>
-<BR>
-Our associates earn half of this amount or $250,000.00 per<BR>
-year. This is just for interest, not counting principle<BR>
-and not counting the compounding of the interest which can<BR>
-add substantial additional income. Typically companies are<BR>
-sold for 10 times earnings. Just based on simple interest<BR>
-an associate with 5 million in real estate liens could sell<BR>
-their business for approximately 2.5 million dollars.<BR>
-<BR>
-</FONT>
-<FONT color=3D"#0000A0"> 92% of all of our associates work out of their ho=
-me; 43%<BR>
-are women and 36% are part time</FONT>
-<FONT color=3D"#000000">  .<BR>
-<BR>
-One of the benefits of working in this field is that you are<BR>
-not under any kind of time frame. If you decide to take off<BR>
-for a month on vacation then go. The Judgments you are<BR>
-working on will be there when you return. The Judgments<BR>
-are still in force, they do not disappear.<BR>
-<BR>
-The way we train you is non-confrontational. You use your<BR>
-computer and telephone to do most of the processing. You<BR>
-never confront the debtor. The debtor doesn't know who you<BR>
-are. You are not a collection agency.<BR>
-<BR>
-Simply stated the steps to successful Money Processing<BR>
-are as follows:<BR>
-<BR>
-Mail our recommended letter to companies and individuals<BR>
-with Money Judgments. (We train you how to find out who<BR>
-to write to)<BR>
-<BR>
-8% to 11% of the firms and people you write will call you<BR>
-and ask for your help. They call you, you don't call them<BR>
-unless you want to.<BR>
-<BR>
-You send them an agreement (supplied in the course) to<BR>
-sign which splits every dollar you collect 50% to you and<BR>
-50% to them. This applies no matter if the judgment is for<BR>
-$2,000.00 or $2,000,000.00.<BR>
-<BR>
-You then go on-line to our computers to find the debtor<BR>
-and their assets. We offer over 120 powerful reports to<BR>
-assist you. They range from credit reports from all three<BR>
-credit bureaus, to bank account locates, employment<BR>
-locates, skip traces and locating stocks and bonds, etc.<BR>
-The prices of our reports are very low. Typically 1/2 to<BR>
-1/3 of what other firms charge. For example we charge<BR>
-$6.00 for an individuals credit report when some other<BR>
-companies charge $25.00.<BR>
-<BR>
-Once you find the debtor and their assets you file<BR>
-garnishments and liens on the assets you have located.<BR>
-(Standard fill in the blanks forms are included in the<BR>
-course)<BR>
-<BR>
-When you receive the assets you keep 50% and send 50% to<BR>
-the original Judgment holder.<BR>
-<BR>
-Once the Judgment is fully paid you mail a Satisfaction of<BR>
-Judgment to the court. (Included in the course)<BR>
-<BR>
-Quote's from several of our students:<BR>
-<BR>
-Thomas in area code 516 writes us: "I just wanted to drop<BR>
-you a short note thanking you for your excellent course. </FONT>
-<FONT color=3D"#0000A0"> My<BR>
-first week, part time, will net me 3,700.00 dollars</FONT>
-<FONT color=3D"#000000">  . Your<BR>
-professionalism in both the manual and the video opened<BR>
-doors for me in the future. There's no stopping me now.<BR>
-Recently Thomas states he has over $8,500,000 worth of<BR>
-judgments he is working on.<BR>
-<BR>
-After only having this course for four months, Larry S. in<BR>
-area code 314 stated to us: " </FONT>
-<FONT color=3D"#0000A0"> I am now making $2,000.00 per<BR>
-week </FONT>
-<FONT color=3D"#000000"> and expect this to grow to twice this amount with=
-in the<BR>
-next year. I am having a ball. I have over $250,000 in<BR>
-judgments I am collecting on now."<BR>
-<BR>
-After having our course for 7 months Larry S. in 314 stated<BR>
-" </FONT>
-<FONT color=3D"#0000A0"> I am now making $12,000.00</FONT>
-<FONT color=3D"#000000">  per month and have approximately<BR>
-$500,000.00 in judgments I am collecting on. Looks like I<BR>
-will have to hire someone to help out"<BR>
-<BR>
-Marshal in area code 407 states to us "I feel bad, you only<BR>
-charged me $259.00 for this course and it is a goldmine. I<BR>
-have added 3 full time people to help me after only having<BR>
-your course for 5 months"<BR>
-<BR>
->From the above information and actual results you can see<BR>
-why we can state the following:<BR>
-<BR>
-With our course you can own your own successful business.<BR>
-A business which earns you substantial income now and one<BR>
-which could be sold in 3-5 years, paying you enough to<BR>
-retire on and travel the world. A business which is<BR>
-extremely interesting to be in. A Business in which every<BR>
-day is new and exciting.<BR>
-<BR>
-None of your days will be hum-drum. Your brain is<BR>
-Challenged. A business, which protects you from Corporate<BR>
-Downsizing. A business which you can start part time from<BR>
-your home and later, if you so desire, you can work in full<BR>
-time. A business, which is your ticket to freedom from<BR>
-others telling you what to do. A business, which lets you<BR>
-control your own destiny. Our training has made this happen<BR>
-for many others already. Make it happen for you!<BR>
-<BR>
-If the above sounds interesting to you then its time for you<BR>
-to talk to a real live human being, no cost or obligation<BR>
-on your part.<BR>
-<BR>
-</FONT>
-<FONT color=3D"#800040"> Please call us at 1_406_652_0194 </FONT>
-<FONT color=3D"#000000"> .<BR>
-<BR>
-We have </FONT>
-<FONT color=3D"#800040"> Customer Support staff available to you from 8:00=
-am to<BR>
-9:00pm (Mountain Time) 7 days a week</FONT>
-<FONT color=3D"#000000">  . If you call this number<BR>
-you can talk to one of our experienced Customer Support personnel.<BR>
-They can answer any questions you may have - with no obligation.<BR>
-Sometimes we run special pricing on our courses and combinations<BR>
-of courses. When you call our Customer Support line they can let<BR>
-you know of any specials we may be running. If you like what you<BR>
-read and hear about our courses, then the Customer Support person<BR>
-can work with you to place your order. We are very low key. We<BR>
-merely give you the facts and you can then decide if you want to<BR>
-work with us or not.<BR>
-<BR>
-Thank you for your time and interest.<BR>
-<BR>
-<BR>
-<BR>
-<BR>
-<BR>
-<BR>
-<BR>
-<BR>
-<BR>
-<BR>
-<BR>
-<BR>
-<BR>
-<BR>
-<BR>
-</FONT>
-<FONT face=3D"Courier New">
-<FONT size=3D2>
-<FONT color=3D"#000000"> .................................................=
-....................<BR>
-T h i s message i s produced a n d sent out by:<BR>
-Universal S.y.s.t.e.m.s.<BR>
-To be dropped form our mailing list please email us at <BR>
-james77@mail.asia-links.com call us toll free at 1=3D888=3D605=3D2485<BR>
-and  g i v e us y o u r email a d d r e s s  or w r i t e  us a t:<BR>
-*Central*DB*Processing, PO: Box:1200, O r a n j e s t a d, Aruba<BR>
-.....................................................................<BR>
-</FONT>
-<FONT face=3D"Arial">
-<FONT size=3D3>
-<FONT color=3D"#000000"> <BR>
-<BR>
-</FONT>
-<FONT size=3D3>
-<FONT color=3D"#000000"> <BR>
-<BR>
-</FONT>
-<FONT size=3D3>
-<FONT color=3D"#000000"> <BR>
-<BR>
-<BR>
-<BR>
-<BR>
-</FONT>
-<FONT size=3D2>
-<FONT color=3D"#000000"> <BR>
-''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''=
-''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''=
-''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''=
-''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''=
-''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''=
-''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''=
-''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''=
-''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''=
-''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''=
-''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''=
-'''''''''''<BR>
-</FONT>
-<FONT size=3D3>
-<FONT color=3D"#000000"> <BR>
-</FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FONT></FO=
-NT></FONT></FONT></BODY></HTML>
-
-
-
-
diff --git a/third-party/spamassassin/src/test/resources/spamassassin_db/spam/spam9 b/third-party/spamassassin/src/test/resources/spamassassin_db/spam/spam9
deleted file mode 100644
index 163bde8c84..0000000000
--- a/third-party/spamassassin/src/test/resources/spamassassin_db/spam/spam9
+++ /dev/null
@@ -1,142 +0,0 @@
-From spamassassin-sightings-admin@lists.sourceforge.net  Tue Jul  2 13:04:23 2002
-Return-Path: <sp...@example.sourceforge.net>
-Delivered-To: yyyy@localhost.labs.netnoteinc.com
-Received: from localhost (localhost [127.0.0.1])
-	by phobos.labs.netnoteinc.com (Postfix on SuSE Linux 8.0 (i386)) with ESMTP id BB16E14F914
-	for <jm...@localhost>; Tue,  2 Jul 2002 12:56:51 +0100 (IST)
-Received: from dogma.slashnull.org [212.17.35.15]
-	by localhost with IMAP (fetchmail-5.9.0)
-	for jm@localhost (single-drop); Tue, 02 Jul 2002 12:56:51 +0100 (IST)
-Received: from usw-sf-list2.sourceforge.net (usw-sf-fw2.sourceforge.net
-    [216.136.171.252]) by dogma.slashnull.org (8.11.6/8.11.6) with ESMTP id
-    g61Iat611966 for <jm...@jmason.org>; Mon, 1 Jul 2002 19:36:56
-    +0100
-Received: from usw-sf-list1-b.sourceforge.net ([10.3.1.13]
-    helo=usw-sf-list1.sourceforge.net) by usw-sf-list2.sourceforge.net with
-    esmtp (Exim 3.31-VA-mm2 #1 (Debian)) id 17P62B-0000rw-00; Mon,
-    01 Jul 2002 11:36:23 -0700
-Received: from [64.86.155.148] (helo=ok61655.com) by
-    usw-sf-list1.sourceforge.net with smtp (Exim 3.31-VA-mm2 #1 (Debian)) id
-    17P60P-0006ds-00 for <sp...@lists.sourceforge.net>;
-    Mon, 01 Jul 2002 11:34:34 -0700
-From: "MR.DOUGLAS  AND PRINCESS M." <do...@yahoo.co.uk>
-Reply-To: princessmar001@yahoo.com
-To: spamassassin-sightings@example.sourceforge.net
-X-Mailer: Microsoft Outlook Express 5.00.2919.6900 DM
-MIME-Version: 1.0
-Message-Id: <E1...@usw-sf-list1.sourceforge.net>
-Subject: [SA] URGENT HELP..............
-Sender: spamassassin-sightings-admin@example.sourceforge.net
-Errors-To: spamassassin-sightings-admin@example.sourceforge.net
-X-Beenthere: spamassassin-sightings@example.sourceforge.net
-X-Mailman-Version: 2.0.9-sf.net
-Precedence: bulk
-List-Help: <mailto:spamassassin-sightings-request@example.sourceforge.net?subject=help>
-List-Post: <ma...@example.sourceforge.net>
-List-Subscribe: <https://example.sourceforge.net/lists/listinfo/spamassassin-sightings>,
-    <mailto:spamassassin-sightings-request@lists.sourceforge.net?subject=subscribe>
-List-Id: <spamassassin-sightings.example.sourceforge.net>
-List-Unsubscribe: <https://example.sourceforge.net/lists/listinfo/spamassassin-sightings>,
-    <mailto:spamassassin-sightings-request@lists.sourceforge.net?subject=unsubscribe>
-List-Archive: <http://www.geocrawler.com/redir-sf.php3?list=spamassassin-sightings>
-X-Original-Date: Mon, 5 Apr 1999 20:38:02 +0100
-Date: Mon, 5 Apr 1999 20:38:02 +0100
-Content-Type: multipart/mixed; boundary="===_SecAtt_000_1fnapngoonxcrm"
-
---===_SecAtt_000_1fnapngoonxcrm
-Content-Type: text/plain; charset="us-ascii"
-Content-Transfer-Encoding: quoted-printable
-
-
-DEAR SIR=2C
-URGENT AND CONFIDENTIAL=3A
-
-Re=3ATransfer of $50=2C000=2E000=2E00 USD=5BFIFTY MILLION UNITED
-STATES DOLLARS=5D=2E
-
-WE WANT TO TRANSFER TO OVERSEAS=5B$50=2C000=2E000=2E00=5BFIFTY
-MILLION UNITED STATES DOLLARS=5DFROM A SECURITY COMPANY
-IN SPAIN=2CI WANT TO ASK YOU TO QUIETLY LOOK FOR A
-RELIABLE AND HONEST PERSON WHO WILL BE CAPABLE AND FIT
-TO PROVIDE EITHER AN EXISTING BANK ACCOUNT OR TO SET
-UP A NEW BANK ACCOUNT IMMEDIATELY TO RECEIVE THIS
-MONEY=2CEVEN AN EMPTY ACCOUNT CAN SERVE TO RECEIVE THIS
-MONEY=2CAS LONG AS YOU WILL REMAIN HONEST TO ME TILL THE
-END OF THIS IMPORTANT BUSINESS TRANSACTION=2EI WANT TO
-BELIEVE THAT YOU WILL NEVER LET ME DOWN EITHER NOW OR
-IN FUTURE=2E
-
-I AM DOUGLAS SMITH=2CTHE AUDITOR GENERAL OF MAGNUM TRUST
-INC=2E MADRID SPAIN DURING THE COURSE OF OUR AUDITING=2CI DISCOVERED A
-FLOATING FUND IN AN ACCOUNT OPENED IN THE SECURITY
-COMPANY IN 1990 AND SINCE 1993 NOBODY HAS OPERATED ON
-THIS ACCOUNT AGAIN=2C AFTER GOING THROUGH SOME OLD FILES
-IN THE RECORDS I DISCOVERED THAT THE OWNER OF THE
-ACCOUNT DIED WITHOUT A HEIR HENCE THE MONEY IS
-FLOATING AND IF I DO NOT REMIT THIS MONEY OUT
-URGENTLY=2CIT WILL BE FORFEITED FOR NOTHING=2E
-
-THE OWNER OF THIS ACCOUNT WAS =22MR=2EALLAN P=2E SEAMAN=22=2CA FOREIGNER AND AN INDUSTRIALIST=2CAND HE DIED SINCE 1993 AND NO OTHER PERSON KNOWS ABOUT THIS ACCOUNT OR ANYTHING CONCERNING IT=2CTHE ACCOUNT HAS NO BENEFICIARY AND MY INVESTIGATION PROVED TO ME AS WELL THAT ALLAN=2EP SEAMAN UNTILL HIS DEATH WAS THE MANAGER DIAMOND SAFARI=5BPTY=5DS=2EA=2E
-
-WE WILL START THE FIRST TRANSFER WITH $20 MILLION
-DOLLARS=5BTWENTY MILLION DOLLARS=5DUPON SUCCESSFUL
-TRANSFER WITHOUT ANY DISAPPOINTMENT FROM YOUR SIDE=2CWE
-SHALL RE-APPLY FOR THE TRANSFER OF THE REMAINING $30
-MILLION USA DOLLARS=5BTHIRTY MILLION UNITED STATES
-DOLLARS=5DINTO YOUR ACCOUNT BRINGING THE SUM TOTAL TO
-$50=2C000=2E000=2E00=5BFIFTY MILLION DOLLARS=5D=2E
-
-I AM CONTACTING YOU AS A FOREIGNER BECAUSE THIS MONEY
-CAN ONLY BE APPROVED TO A FOREIGNER WITH VALID
-INTERNATIONAL PASSPORT=2CDRIVERS LICENCE AND FOREIGN
-ACCOUNT BECAUSE THE MONEY IS IN USA DOLLARS AND THE
-FORMER OWNER OF THE ACCOUNT=22MR=2EALLAN P=2ESEAMAN IS A
-FOREIGNER=2EI WILL LIKE US TO MEET FACE TO FACE TO SIGN
-A BINDING AGREEMENT THAT WILL BIND US TOGETHER IN THE
-BUSINESS=2CI AM REVEALING ALL THESE TO YOU WITH THE
-BELIEF THAT YOU WILL NEVER LET ME DOWN IN THIS
-BUSINESS=2CYOU ARE THE FIRST AND ONLY PERSON I AM
-CONTACTING FOR THE BUSINESS=2CSO PLEASE REPLY URGENTLY
-FOR ME TO TELL YOU THE NEXT STEP TO TAKE=2EYOU SHOULD
-FORWARD YOUR TELEPHONE AND FAX NUMBERS AND YOUR BANK
-ACCOUNT DETAILS THAT WILL BE USED IN TRANSFERING THE
-MONEY=2E
-
-YOU WILL HAVE TO GIVE ME THE ASSURANCE WHEN WE
-MEET THAT THIS MONEY WILL BE INTACT PENDING OUR
-PHYSICAL ARRIVAL IN YOUR COUNTRY FOR SHARING AND
-DISBURSEMENT OF THE FUND WHICH WILL BE 35% FOR YOUR
-ASSISTANCE=2C60% WILL BE FOR US WHILE 5% WILL  BE SET
-ASIDE TO TAKE CARE OF ALL THE EXPENSES THAT WILL BE
-INCURRED BY BOTH PARTIES DURING THE COURSE OF THE
-TRANSFER=2E
-
-I LOOK FORWARD TO YOUR EARLIEST RESPONSE=2CALL
-CORRESPONDENCE FOR NOW SHOULD BE EMAIL FOR SECURITY
-REASONS=2E
-
-BEST REGARDS=2E
-
-DOUGLAS SMITH  =28PLEASE  CONTACT ME THROUGH  MY WIFE EMAIL=28princessmar001=40yahoo=2Ecom=29FOR CONFIDENCAIL
-
-
-
---===_SecAtt_000_1fnapngoonxcrm
-Content-Type: application/octet-stream; name="aaaaaaa.txt"
-Content-Transfer-Encoding: base64
-Content-Disposition: attachment; filename="aaaaaaa.txt"
-
-
---===_SecAtt_000_1fnapngoonxcrm
-
-
-
--------------------------------------------------------
-This sf.net email is sponsored by:ThinkGeek
-Welcome to geek heaven.
-http://thinkgeek.com/sf
-_______________________________________________
-Spamassassin-Sightings mailing list
-Spamassassin-Sightings@lists.sourceforge.net
-https://lists.sourceforge.net/lists/listinfo/spamassassin-sightings
-


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