diff --git a/backends-common/cassandra/src/test/java/org/apache/james/backends/cassandra/DockerCassandra.java b/backends-common/cassandra/src/test/java/org/apache/james/backends/cassandra/DockerCassandra.java index a354c5e4642..287ea77e40e 100644 --- a/backends-common/cassandra/src/test/java/org/apache/james/backends/cassandra/DockerCassandra.java +++ b/backends-common/cassandra/src/test/java/org/apache/james/backends/cassandra/DockerCassandra.java @@ -133,7 +133,7 @@ private static String buildSpecificImageDiscriminator() { @SuppressWarnings("resource") public DockerCassandra() { - this("cassandra_3_11_10-" + buildSpecificImageDiscriminator(), AdditionalDockerFileStep.IDENTITY); + this("cassandra_3_11_15-" + buildSpecificImageDiscriminator(), AdditionalDockerFileStep.IDENTITY); } private DockerCassandra(String imageName, AdditionalDockerFileStep additionalSteps) { @@ -168,7 +168,7 @@ public void close() { new ImageFromDockerfile(imageName,doNotDeleteImageAfterUsage) .withDockerfileFromBuilder(builder -> additionalSteps.applyStep(builder - .from("cassandra:3.11.10") + .from("cassandra:3.11.15") .env("CASSANDRA_CONFIG", "/etc/cassandra") .run("echo \"-Xms" + CASSANDRA_MEMORY + "M\" >> " + JVM_OPTIONS + "&& echo \"-Xmx" + CASSANDRA_MEMORY + "M\" >> " + JVM_OPTIONS @@ -183,6 +183,7 @@ public void close() { .build())) .withTmpFs(ImmutableMap.of("/var/lib/cassandra", "rw,noexec,nosuid,size=200m")) .withExposedPorts(CASSANDRA_PORT) + .withCreateContainerCmdModifier(createContainerCmd -> createContainerCmd.withName("james-cassandra-test-" + UUID.randomUUID())) .withLogConsumer(DockerCassandra::displayDockerLog); cassandraContainer .waitingFor(new CassandraWaitStrategy(cassandraContainer)); diff --git a/backends-common/opensearch/src/test/resources/auth-es/NginxDockerfile b/backends-common/opensearch/src/test/resources/auth-es/NginxDockerfile index 039b00c1bf7..f22aee94683 100644 --- a/backends-common/opensearch/src/test/resources/auth-es/NginxDockerfile +++ b/backends-common/opensearch/src/test/resources/auth-es/NginxDockerfile @@ -1,4 +1,4 @@ -FROM nginx:1.22 +FROM nginx:1.25 COPY conf/nginx-conf/ /etc/nginx/conf.d/ COPY conf/default.crt /etc/ssl/certs/default.crt diff --git a/examples/custom-imap/docker-compose.yml b/examples/custom-imap/docker-compose.yml index ac56ec29aa4..b8f1bb83862 100644 --- a/examples/custom-imap/docker-compose.yml +++ b/examples/custom-imap/docker-compose.yml @@ -6,9 +6,10 @@ services: image: apache/james:memory-latest container_name: james hostname: james.local + command: + - --generate-keystore volumes: - - ./target/custom-imap-3.8.0-SNAPSHOT-jar-with-dependencies.jar:/root/extensions-jars/custom-imap-3.8.0-SNAPSHOT-jar-with-dependencies.jar - - ./sample-configuration/keystore:/root/conf/keystore + - ./target/custom-imap-jar-with-dependencies.jar:/root/extensions-jars/custom-imap.jar - ./sample-configuration/imapserver.xml:/root/conf/imapserver.xml ports: - "143:143" diff --git a/examples/custom-imap/pom.xml b/examples/custom-imap/pom.xml index c83831796ba..3ec23666885 100644 --- a/examples/custom-imap/pom.xml +++ b/examples/custom-imap/pom.xml @@ -97,6 +97,7 @@ jar-with-dependencies + custom-imap diff --git a/examples/custom-imap/sample-configuration/keystore b/examples/custom-imap/sample-configuration/keystore deleted file mode 100644 index 361cd01f43d..00000000000 Binary files a/examples/custom-imap/sample-configuration/keystore and /dev/null differ diff --git a/examples/custom-james-assembly/pom.xml b/examples/custom-james-assembly/pom.xml index d49138accb6..a56d151b80f 100644 --- a/examples/custom-james-assembly/pom.xml +++ b/examples/custom-james-assembly/pom.xml @@ -54,7 +54,7 @@ 2.7.1 - eclipse-temurin:11-jre-focal + eclipse-temurin:11-jre-jammy apache/james diff --git a/examples/imap-autoconf/docker-compose.yml b/examples/imap-autoconf/docker-compose.yml index 999529e8dcd..f8826e9644b 100644 --- a/examples/imap-autoconf/docker-compose.yml +++ b/examples/imap-autoconf/docker-compose.yml @@ -6,8 +6,8 @@ services: image: apache/james:memory-latest container_name: james hostname: james.local - volumes: - - ./keystore:/root/conf/keystore + command: + - --generate-keystore ports: - "465:465" - "993:993" diff --git a/examples/imap-autoconf/keystore b/examples/imap-autoconf/keystore deleted file mode 100644 index 361cd01f43d..00000000000 Binary files a/examples/imap-autoconf/keystore and /dev/null differ diff --git a/examples/metrics-graphite/docker-compose.yml b/examples/metrics-graphite/docker-compose.yml index fe8894bb2ce..218dcdd57fe 100644 --- a/examples/metrics-graphite/docker-compose.yml +++ b/examples/metrics-graphite/docker-compose.yml @@ -8,9 +8,10 @@ services: image: apache/james:memory-latest container_name: james hostname: james.local + command: + - --generate-keystore volumes: - - ./james/keystore:/root/conf/keystore - - ./target/metrics-graphite-3.8.0-SNAPSHOT-jar-with-dependencies.jar:/root/extensions-jars/metrics-graphite-3.8.0-SNAPSHOT-jar-with-dependencies.jar + - ./target/metrics-graphite-jar-with-dependencies.jar:/root/extensions-jars/metrics-graphite.jar - ./james/extensions.properties:/root/conf/extensions.properties graphite: diff --git a/examples/metrics-graphite/james/keystore b/examples/metrics-graphite/james/keystore deleted file mode 100644 index 361cd01f43d..00000000000 Binary files a/examples/metrics-graphite/james/keystore and /dev/null differ diff --git a/examples/metrics-graphite/pom.xml b/examples/metrics-graphite/pom.xml index d2f80a6e055..cf791cc03e3 100644 --- a/examples/metrics-graphite/pom.xml +++ b/examples/metrics-graphite/pom.xml @@ -75,6 +75,7 @@ jar-with-dependencies + metrics-graphite diff --git a/examples/proxy-smtp/docker-compose.yml b/examples/proxy-smtp/docker-compose.yml index c175a5c7f9e..cf7545e772f 100644 --- a/examples/proxy-smtp/docker-compose.yml +++ b/examples/proxy-smtp/docker-compose.yml @@ -6,7 +6,7 @@ services: volumes: - ./haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg:ro ports: - - 25:25 + - "25:25" - 143:143 - 993:993 - 465:465 @@ -17,10 +17,11 @@ services: image: apache/james:memory-latest container_name: james hostname: james.local + command: + - --generate-keystore volumes: - ./smtpserver.xml:/root/conf/smtpserver.xml:ro - ./imapserver.xml:/root/conf/imapserver.xml:ro - - ./keystore:/root/conf/keystore helo: image: alpine:latest diff --git a/examples/proxy-smtp/keystore b/examples/proxy-smtp/keystore deleted file mode 100644 index 361cd01f43d..00000000000 Binary files a/examples/proxy-smtp/keystore and /dev/null differ diff --git a/server/apps/cassandra-app/README.adoc b/server/apps/cassandra-app/README.adoc index e5af4814e20..27c75b62481 100644 --- a/server/apps/cassandra-app/README.adoc +++ b/server/apps/cassandra-app/README.adoc @@ -21,12 +21,12 @@ Firstly, create your own user network on Docker for the James environment: Third party compulsory dependencies: - * Cassandra 3.11.10 + * Cassandra 3.11.15 * OpenSearch 2.1.0 [source] ---- -$ docker run -d --network james -p 9042:9042 --name=cassandra cassandra:3.11.10 +$ docker run -d --network james -p 9042:9042 --name=cassandra cassandra:3.11.15 $ docker run -d --network james -p 9200:9200 --name=opensearch --env 'discovery.type=single-node' opensearchproject/opensearch:2.1.0 ---- diff --git a/server/apps/cassandra-app/docker-compose.yml b/server/apps/cassandra-app/docker-compose.yml index a2627519a08..0210548d258 100644 --- a/server/apps/cassandra-app/docker-compose.yml +++ b/server/apps/cassandra-app/docker-compose.yml @@ -4,12 +4,19 @@ services: james: depends_on: - - opensearch - - cassandra - - tika + cassandra: + condition: service_healthy + opensearch: + condition: service_started + tika: + condition: service_started image: apache/james:cassandra-latest container_name: james hostname: james.local + networks: + - james + volumes: + - ${KEYSTORE_PATH}:/root/conf/keystore ports: - "80:80" - "25:25" @@ -21,6 +28,10 @@ services: - "8000:8000" opensearch: + networks: + james: + aliases: + - elasticsearch image: opensearchproject/opensearch:2.1.0 environment: - discovery.type=single-node @@ -28,10 +39,21 @@ services: - DISABLE_SECURITY_PLUGIN=true cassandra: - image: cassandra:3.11.10 + image: cassandra:3.11.15 ports: - "9042:9042" + healthcheck: + test: [ "CMD-SHELL", "[ $$(nodetool statusgossip) = running ]" ] + interval: 3s + timeout: 20s + retries: 5 + networks: + - james tika: - image: apache/tika:1.28.2 + image: apache/tika:2.8.0.0 + networks: + - james +networks: + james: diff --git a/server/apps/cassandra-app/pom.xml b/server/apps/cassandra-app/pom.xml index 8411d0356ef..46ec761c37a 100644 --- a/server/apps/cassandra-app/pom.xml +++ b/server/apps/cassandra-app/pom.xml @@ -335,7 +335,7 @@ jib-maven-plugin - eclipse-temurin:11-jre-focal + eclipse-temurin:11-jre-jammy apache/james diff --git a/server/apps/distributed-app/README.adoc b/server/apps/distributed-app/README.adoc index 72e9edb77d9..89738e8f8b0 100644 --- a/server/apps/distributed-app/README.adoc +++ b/server/apps/distributed-app/README.adoc @@ -10,17 +10,17 @@ Firstly, create your own user network on Docker for the James environment: Third party compulsory dependencies: - * Cassandra 3.11.10 + * Cassandra 3.11.15 * OpenSearch 2.1.0 * RabbitMQ-Management 3.8.18 * Zenko Cloudserver or AWS S3 [source] ---- -$ docker run -d --network james -p 9042:9042 --name=cassandra cassandra:3.11.10 +$ docker run -d --network james -p 9042:9042 --name=cassandra cassandra:3.11.15 $ docker run -d --network james -p 9200:9200 --name=opensearch --env 'discovery.type=single-node' opensearchproject/opensearch:2.1.0 -$ docker run -d --network james -p 5672:5672 -p 15672:15672 --name=rabbitmq rabbitmq:3.9.18-management -$ docker run -d --network james --env 'REMOTE_MANAGEMENT_DISABLE=1' --env 'SCALITY_ACCESS_KEY_ID=accessKey1' --env 'SCALITY_SECRET_ACCESS_KEY=secretKey1' --name=s3 zenko/cloudserver:8.2.6 +$ docker run -d --network james -p 5672:5672 -p 15672:15672 --name=rabbitmq rabbitmq:3.12.1-management +$ docker run -d --network james --env 'REMOTE_MANAGEMENT_DISABLE=1' --env 'SCALITY_ACCESS_KEY_ID=accessKey1' --env 'SCALITY_SECRET_ACCESS_KEY=secretKey1' --name=s3 registry.scality.com/cloudserver/cloudserver:8.7.25 ---- == Running diff --git a/server/apps/distributed-app/docker-compose.yml b/server/apps/distributed-app/docker-compose.yml index 70b70ec1f05..40ce9fc5d71 100644 --- a/server/apps/distributed-app/docker-compose.yml +++ b/server/apps/distributed-app/docker-compose.yml @@ -4,14 +4,23 @@ services: james: depends_on: - - opensearch - - cassandra - - tika - - rabbitmq - - s3 + cassandra: + condition: service_healthy + opensearch: + condition: service_started + tika: + condition: service_started + rabbitmq: + condition: service_started + s3: + condition: service_started image: apache/james:distributed-latest container_name: james hostname: james.local + command: + - --generate-keystore + networks: + - james ports: - "80:80" - "25:25" @@ -28,23 +37,38 @@ services: - discovery.type=single-node - DISABLE_INSTALL_DEMO_CONFIG=true - DISABLE_SECURITY_PLUGIN=true + networks: + james: + aliases: + - elasticsearch cassandra: image: cassandra:3.11.10 ports: - "9042:9042" + healthcheck: + test: [ "CMD-SHELL", "[ $$(nodetool statusgossip) = running ]" ] + interval: 3s + timeout: 20s + retries: 5 + networks: + - james tika: - image: apache/tika:1.28.2 + image: apache/tika:2.8.0.0 + networks: + - james rabbitmq: - image: rabbitmq:3.9.18-management + image: rabbitmq:3.12.1-management ports: - "5672:5672" - "15672:15672" + networks: + - james s3: - image: zenko/cloudserver:8.2.6 + image: registry.scality.com/cloudserver/cloudserver:8.7.25 container_name: s3.docker.test environment: - SCALITY_ACCESS_KEY_ID=accessKey1 @@ -52,4 +76,8 @@ services: - S3BACKEND=mem - LOG_LEVEL=trace - REMOTE_MANAGEMENT_DISABLE=1 + networks: + - james +networks: + james: \ No newline at end of file diff --git a/server/apps/distributed-app/docs/modules/ROOT/pages/operate/logging.adoc b/server/apps/distributed-app/docs/modules/ROOT/pages/operate/logging.adoc index 87f645cf4a4..b7ef18c07ee 100644 --- a/server/apps/distributed-app/docs/modules/ROOT/pages/operate/logging.adoc +++ b/server/apps/distributed-app/docs/modules/ROOT/pages/operate/logging.adoc @@ -200,18 +200,18 @@ services: - discovery.type=single-node cassandra: - image: cassandra:3.11.10 + image: cassandra:3.11.15 ports: - "9042:9042" rabbitmq: - image: rabbitmq:3.9.18-management + image: rabbitmq:3.12.1-management ports: - "5672:5672" - "15672:15672" s3: - image: zenko/cloudserver:8.2.6 + image: registry.scality.com/cloudserver/cloudserver:8.7.25 container_name: s3.docker.test environment: - SCALITY_ACCESS_KEY_ID=accessKey1 diff --git a/server/apps/distributed-app/docs/modules/ROOT/pages/run/run-docker.adoc b/server/apps/distributed-app/docs/modules/ROOT/pages/run/run-docker.adoc index b3a97f44e58..d90a10943ba 100644 --- a/server/apps/distributed-app/docs/modules/ROOT/pages/run/run-docker.adoc +++ b/server/apps/distributed-app/docs/modules/ROOT/pages/run/run-docker.adoc @@ -53,15 +53,15 @@ Firstly, create your own user network on Docker for the James environment: You need a running *cassandra* in docker which connects to *james* network. To achieve this run: - $ docker run -d --network james --name=cassandra cassandra:3.11.10 + $ docker run -d --network james --name=cassandra cassandra:3.11.15 You need a running *rabbitmq* in docker which connects to *james* network. To achieve this run: - $ docker run -d --network james --name=rabbitmq rabbitmq:3.9.18-management + $ docker run -d --network james --name=rabbitmq rabbitmq:3.12.1-management You need a running *Zenko Cloudserver* objectstorage in docker which connects to *james* network. To achieve this run: - $ docker run -d --network james --env 'REMOTE_MANAGEMENT_DISABLE=1' --env 'SCALITY_ACCESS_KEY_ID=accessKey1' --env 'SCALITY_SECRET_ACCESS_KEY=secretKey1' --name=s3 zenko/cloudserver:8.2.6 + $ docker run -d --network james --env 'REMOTE_MANAGEMENT_DISABLE=1' --env 'SCALITY_ACCESS_KEY_ID=accessKey1' --env 'SCALITY_SECRET_ACCESS_KEY=secretKey1' --name=s3 registry.scality.com/cloudserver/cloudserver:8.7.25 You need a running *OpenSearch* in docker which connects to *james* network. To achieve this run: @@ -69,7 +69,7 @@ $ docker run -d --network james -p 9200:9200 --name=opensearch --env 'discovery. If you want to use all the JMAP search capabilities, you may also need to start Tika container which connects to *james* network: - $ docker run -d --network james --name=tika apache/tika:1.28.2 + $ docker run -d --network james --name=tika apache/tika:2.8.0.0 You can find more explanation on the need of Tika in this xref:configure/tika.adoc[page]. @@ -122,7 +122,7 @@ You can handle attachment text extraction before indexing in OpenSearch. This ma Run tika connect to *james* network: - $ docker run -d --network james --name tika apache/tika:1.28.2 + $ docker run -d --network james --name tika apache/tika:2.8.0.0 Run James: diff --git a/server/apps/distributed-app/docs/modules/ROOT/pages/run/run-java.adoc b/server/apps/distributed-app/docs/modules/ROOT/pages/run/run-java.adoc index 052537523d1..6e736667e54 100644 --- a/server/apps/distributed-app/docs/modules/ROOT/pages/run/run-java.adoc +++ b/server/apps/distributed-app/docs/modules/ROOT/pages/run/run-java.adoc @@ -7,7 +7,7 @@ * Java 11 SDK * Docker ∕ OpenSearch 2.1.0, RabbitMQ Management 3.8.18, S3 compatible -ObjectStorage and Cassandra 3.11.10 +ObjectStorage and Cassandra 3.11.15 * Maven 3 === Building the artifacts @@ -29,7 +29,7 @@ mvn clean install === Requirements -* Cassandra 3.11.10 +* Cassandra 3.11.15 * OpenSearch 2.1.0 * RabbitMQ-Management 3.8.17 * Swift ObjectStorage 2.15.1 or Zenko Cloudserver or AWS S3 @@ -50,10 +50,10 @@ running. You can either install the servers or launch them via docker: [source,bash] ---- -$ docker run -d -p 9042:9042 --name=cassandra cassandra:3.11.10 +$ docker run -d -p 9042:9042 --name=cassandra cassandra:3.11.15 $ docker run -d --network james -p 9200:9200 --name=opensearch --env 'discovery.type=single-node' opensearchproject/opensearch:2.1.0 -$ docker run -d -p 5672:5672 -p 15672:15672 --name=rabbitmq rabbitmq:3.9.18-management -$ docker run -d --env 'REMOTE_MANAGEMENT_DISABLE=1' --env 'SCALITY_ACCESS_KEY_ID=accessKey1' --env 'SCALITY_SECRET_ACCESS_KEY=secretKey1' --name=s3 zenko/cloudserver:8.2.6 +$ docker run -d -p 5672:5672 -p 15672:15672 --name=rabbitmq rabbitmq:3.12.1-management +$ docker run -d --env 'REMOTE_MANAGEMENT_DISABLE=1' --env 'SCALITY_ACCESS_KEY_ID=accessKey1' --env 'SCALITY_SECRET_ACCESS_KEY=secretKey1' --name=s3 registry.scality.com/cloudserver/cloudserver:8.7.25 ---- Once everything is set up, you just have to run the jar with: diff --git a/server/apps/distributed-app/pom.xml b/server/apps/distributed-app/pom.xml index a240fd51539..e4813deb636 100644 --- a/server/apps/distributed-app/pom.xml +++ b/server/apps/distributed-app/pom.xml @@ -379,7 +379,7 @@ jib-maven-plugin - eclipse-temurin:11-jre-focal + eclipse-temurin:11-jre-jammy apache/james diff --git a/server/apps/distributed-pop3-app/README.adoc b/server/apps/distributed-pop3-app/README.adoc index add1c010d18..7b5032bfaa6 100644 --- a/server/apps/distributed-pop3-app/README.adoc +++ b/server/apps/distributed-pop3-app/README.adoc @@ -13,15 +13,15 @@ Firstly, create your own user network on Docker for the James environment: Third party compulsory dependencies: - * Cassandra 3.11.10 + * Cassandra 3.11.15 * RabbitMQ-Management 3.8.18 * Zenko Cloudserver or AWS S3 [source] ---- -$ docker run -d --network james -p 9042:9042 --name=cassandra cassandra:3.11.10 -$ docker run -d --network james -p 5672:5672 -p 15672:15672 --name=rabbitmq rabbitmq:3.9.18-management -$ docker run -d --network james --env 'REMOTE_MANAGEMENT_DISABLE=1' --env 'SCALITY_ACCESS_KEY_ID=accessKey1' --env 'SCALITY_SECRET_ACCESS_KEY=secretKey1' --name=s3 zenko/cloudserver:8.2.6 +$ docker run -d --network james -p 9042:9042 --name=cassandra cassandra:3.11.15 +$ docker run -d --network james -p 5672:5672 -p 15672:15672 --name=rabbitmq rabbitmq:3.12.1-management +$ docker run -d --network james --env 'REMOTE_MANAGEMENT_DISABLE=1' --env 'SCALITY_ACCESS_KEY_ID=accessKey1' --env 'SCALITY_SECRET_ACCESS_KEY=secretKey1' --name=s3 registry.scality.com/cloudserver/cloudserver:8.7.25 ---- == Docker distribution diff --git a/server/apps/distributed-pop3-app/docker-compose.yml b/server/apps/distributed-pop3-app/docker-compose.yml index 36e9621b2e9..c08d9417713 100644 --- a/server/apps/distributed-pop3-app/docker-compose.yml +++ b/server/apps/distributed-pop3-app/docker-compose.yml @@ -4,11 +4,16 @@ services: james: depends_on: - - opensearch - - cassandra - - tika - - rabbitmq - - s3 + cassandra: + condition: service_healthy + opensearch: + condition: service_started + tika: + condition: service_started + rabbitmq: + condition: service_started + s3: + condition: service_started image: apache/james:distributed-pop3-latest container_name: james hostname: james.local @@ -21,6 +26,10 @@ services: - "587:587" - "993:993" - "8000:8000" + command: + - --generate-keystore + networks: + - james opensearch: image: opensearchproject/opensearch:2.1.0 @@ -28,23 +37,38 @@ services: - discovery.type=single-node - DISABLE_INSTALL_DEMO_CONFIG=true - DISABLE_SECURITY_PLUGIN=true + networks: + james: + aliases: + - elasticsearch cassandra: - image: cassandra:3.11.10 + image: cassandra:3.11.15 ports: - "9042:9042" + healthcheck: + test: [ "CMD-SHELL", "[ $$(nodetool statusgossip) = running ]" ] + interval: 3s + timeout: 20s + retries: 5 + networks: + - james tika: - image: apache/tika:1.28.2 + image: apache/tika:2.8.0.0 + networks: + - james rabbitmq: - image: rabbitmq:3.9.18-management + image: rabbitmq:3.12.1-management ports: - "5672:5672" - "15672:15672" + networks: + - james s3: - image: zenko/cloudserver:8.2.6 + image: registry.scality.com/cloudserver/cloudserver:8.7.25 container_name: s3.docker.test environment: - SCALITY_ACCESS_KEY_ID=accessKey1 @@ -52,3 +76,8 @@ services: - S3BACKEND=mem - LOG_LEVEL=trace - REMOTE_MANAGEMENT_DISABLE=1 + networks: + - james + +networks: + james: \ No newline at end of file diff --git a/server/apps/distributed-pop3-app/pom.xml b/server/apps/distributed-pop3-app/pom.xml index ccb294767af..eeaf913122b 100644 --- a/server/apps/distributed-pop3-app/pom.xml +++ b/server/apps/distributed-pop3-app/pom.xml @@ -387,7 +387,7 @@ jib-maven-plugin - eclipse-temurin:11-jre-focal + eclipse-temurin:11-jre-jammy apache/james diff --git a/server/apps/distributed-pop3-app/sample-configuration/opensearch.properties b/server/apps/distributed-pop3-app/sample-configuration/opensearch.properties new file mode 100644 index 00000000000..87011f9f5ce --- /dev/null +++ b/server/apps/distributed-pop3-app/sample-configuration/opensearch.properties @@ -0,0 +1,96 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +# This template file can be used as example for James Server configuration +# DO NOT USE IT AS SUCH AND ADAPT IT TO YOUR NEEDS + +# Configuration file for OpenSearch +# Read https://james.apache.org/server/config-opensearch.html for further details + +opensearch.masterHost=opensearch +opensearch.port=9200 + +# Optional. Only http or https are accepted, default is http +# opensearch.hostScheme=http + +# Optional, default is `default` +# Choosing the SSL check strategy when using https scheme +# default: Use the default SSL TrustStore of the system. +# ignore: Ignore SSL Validation check (not recommended). +# override: Override the SSL Context to use a custom TrustStore containing ES server's certificate. +# opensearch.hostScheme.https.sslValidationStrategy=default + +# Optional. Required when using 'https' scheme and 'override' sslValidationStrategy +# Configure OpenSearch rest client to use this trustStore file to recognize nginx's ssl certificate. +# You need to specify both trustStorePath and trustStorePassword +# opensearch.hostScheme.https.trustStorePath=/file/to/trust/keystore.jks + +# Optional. Required when using 'https' scheme and 'override' sslValidationStrategy +# Configure OpenSearch rest client to use this trustStore file with the specified password. +# You need to specify both trustStorePath and trustStorePassword +# opensearch.hostScheme.https.trustStorePassword=myJKSPassword + +# Optional. default is `default` +# Configure OpenSearch rest client to use host name verifier during SSL handshake +# default: using the default hostname verifier provided by apache http client. +# accept_any_hostname: accept any host (not recommended). +# opensearch.hostScheme.https.hostNameVerifier=default + +# Optional. +# Basic auth username to access opensearch. +# Ignore opensearch.user and opensearch.password to not be using authentication (default behaviour). +# Otherwise, you need to specify both properties. +# opensearch.user=elasticsearch + +# Optional. +# Basic auth password to access opensearch. +# Ignore opensearch.user and opensearch.password to not be using authentication (default behaviour). +# Otherwise, you need to specify both properties. +# opensearch.password=secret + +# You can alternatively provide a list of hosts following this format : +# opensearch.hosts=host1:9200,host2:9200 +# opensearch.clusterName=cluster + +opensearch.nb.shards=5 +opensearch.nb.replica=1 +opensearch.index.waitForActiveShards=1 +opensearch.retryConnection.maxRetries=7 +opensearch.retryConnection.minDelay=3000 +# Index or not attachments (default value: true) +opensearch.indexAttachments=true + +# Search overrides allow resolution of predefined search queries against alternative sources of data +# and allow bypassing opensearch. This is useful to handle most resynchronisation queries that +# are simple enough to be resolved against Cassandra. +# +# Possible values are: +# - `org.apache.james.mailbox.cassandra.search.AllSearchOverride` Some IMAP clients uses SEARCH ALL to fully list messages in +# a mailbox and detect deletions. This is typically done by clients not supporting QRESYNC and from an IMAP perspective +# is considered an optimisation as less data is transmitted compared to a FETCH command. Resolving such requests against +# Cassandra is enabled by this search override and likely desirable. +# - `org.apache.james.mailbox.cassandra.search.UidSearchOverride`. Same as above but restricted by ranges. +# - `org.apache.james.mailbox.cassandra.search.DeletedSearchOverride`. Find deleted messages by looking up in the relevant Cassandra +# table. +# - `org.apache.james.mailbox.cassandra.search.DeletedWithRangeSearchOverride`. Same as above but limited by ranges. +# - `org.apache.james.mailbox.cassandra.search.NotDeletedWithRangeSearchOverride`. List non deleted messages in a given range. +# Lists all messages and filters out deleted message thus this is based on the following heuristic: most messages are not marked as deleted. +# - `org.apache.james.mailbox.cassandra.search.UnseenSearchOverride`. List unseen messages in the corresponding cassandra projection. +# +# Please note that custom overrides can be defined here. +# +# opensearch.search.overrides=org.apache.james.mailbox.cassandra.search.AllSearchOverride,org.apache.james.mailbox.cassandra.search.DeletedSearchOverride, org.apache.james.mailbox.cassandra.search.DeletedWithRangeSearchOverride,org.apache.james.mailbox.cassandra.search.NotDeletedWithRangeSearchOverride,org.apache.james.mailbox.cassandra.search.UidSearchOverride,org.apache.james.mailbox.cassandra.search.UnseenSearchOverride diff --git a/server/apps/jpa-app/pom.xml b/server/apps/jpa-app/pom.xml index d45acccc491..81366e717af 100644 --- a/server/apps/jpa-app/pom.xml +++ b/server/apps/jpa-app/pom.xml @@ -268,7 +268,7 @@ jib-maven-plugin - eclipse-temurin:11-jre-focal + eclipse-temurin:11-jre-jammy apache/james diff --git a/server/apps/jpa-smtp-app/pom.xml b/server/apps/jpa-smtp-app/pom.xml index 7e395b905fc..ee5e5361e8a 100644 --- a/server/apps/jpa-smtp-app/pom.xml +++ b/server/apps/jpa-smtp-app/pom.xml @@ -252,7 +252,7 @@ jib-maven-plugin - eclipse-temurin:11-jre-focal + eclipse-temurin:11-jre-jammy apache/james diff --git a/server/apps/memory-app/pom.xml b/server/apps/memory-app/pom.xml index dfa543bc4d1..1a0e896325e 100644 --- a/server/apps/memory-app/pom.xml +++ b/server/apps/memory-app/pom.xml @@ -267,7 +267,7 @@ jib-maven-plugin - eclipse-temurin:11-jre-focal + eclipse-temurin:11-jre-jammy apache/james diff --git a/server/blob/blob-s3/src/test/java/org/apache/james/blob/objectstorage/aws/DockerAwsS3Container.java b/server/blob/blob-s3/src/test/java/org/apache/james/blob/objectstorage/aws/DockerAwsS3Container.java index d47469054cf..2359d6220a5 100644 --- a/server/blob/blob-s3/src/test/java/org/apache/james/blob/objectstorage/aws/DockerAwsS3Container.java +++ b/server/blob/blob-s3/src/test/java/org/apache/james/blob/objectstorage/aws/DockerAwsS3Container.java @@ -20,6 +20,7 @@ package org.apache.james.blob.objectstorage.aws; import java.net.URI; +import java.util.UUID; import org.apache.james.util.Host; import org.testcontainers.containers.GenericContainer; @@ -27,8 +28,7 @@ public class DockerAwsS3Container { - - private static final String AWS_S3_DOCKER_IMAGE = "zenko/cloudserver:8.2.6"; + private static final String AWS_S3_DOCKER_IMAGE = "registry.scality.com/cloudserver/cloudserver:8.7.25"; private static final int AWS_S3_PORT = 8000; private static final int ONE_TIME = 1; @@ -40,14 +40,14 @@ public class DockerAwsS3Container { private DockerAwsS3 dockerAwsS3; public DockerAwsS3Container() { - this.awsS3Container = new GenericContainer<>(AWS_S3_DOCKER_IMAGE); - this.awsS3Container + this.awsS3Container = new GenericContainer<>(AWS_S3_DOCKER_IMAGE) .withExposedPorts(AWS_S3_PORT) .withEnv("S3BACKEND", "mem") .withEnv("SCALITY_ACCESS_KEY_ID", ACCESS_KEY_ID) .withEnv("SCALITY_SECRET_ACCESS_KEY", SECRET_ACCESS_KEY) .withEnv("LOG_LEVEL", "trace") .withEnv("REMOTE_MANAGEMENT_DISABLE", "1") + .withCreateContainerCmdModifier(createContainerCmd -> createContainerCmd.withName("james-s3-test-" + UUID.randomUUID())) .waitingFor(Wait.forLogMessage(".*\"message\":\"server started\".*\\n", ONE_TIME)); } @@ -81,7 +81,7 @@ public Host getHost() { } public String getIp() { - return awsS3Container.getContainerIpAddress(); + return awsS3Container.getHost(); } public int getPort() { diff --git a/server/mailet/mock-smtp-server/pom.xml b/server/mailet/mock-smtp-server/pom.xml index d868aff45b0..03a2afe1ebf 100644 --- a/server/mailet/mock-smtp-server/pom.xml +++ b/server/mailet/mock-smtp-server/pom.xml @@ -124,7 +124,7 @@ 2.7.0 - eclipse-temurin:11-jre-focal + eclipse-temurin:11-jre-jammy linagora/mock-smtp-server diff --git a/server/mailet/rate-limiter-redis/docker-compose.yml b/server/mailet/rate-limiter-redis/docker-compose.yml index 757396f6a8e..ce98bee9600 100644 --- a/server/mailet/rate-limiter-redis/docker-compose.yml +++ b/server/mailet/rate-limiter-redis/docker-compose.yml @@ -3,16 +3,20 @@ version: '3' services: redis: - image: redis:6.2.6 - + image: redis:7.0.12 + command: + - "--loglevel" + - "debug" james: image: apache/james:memory-latest depends_on: - redis container_name: james hostname: james.local + command: + - --generate-keystore volumes: - - $PWD/target/james-server-rate-limiter-redis-3.8.0-SNAPSHOT-jar-with-dependencies.jar:/root/extensions-jars/james-server-rate-limiter-redis.jar + - $PWD/target/james-server-rate-limiter-redis-jar-with-dependencies.jar:/root/extensions-jars/james-server-rate-limiter-redis.jar - $PWD/extensions.properties:/root/conf/extensions.properties - $PWD/redis.properties:/root/conf/redis.properties - $PWD/mailetcontainer.xml:/root/conf/mailetcontainer.xml diff --git a/server/mailet/rate-limiter-redis/pom.xml b/server/mailet/rate-limiter-redis/pom.xml index fee59985e50..6782b7022bc 100644 --- a/server/mailet/rate-limiter-redis/pom.xml +++ b/server/mailet/rate-limiter-redis/pom.xml @@ -145,13 +145,14 @@ jar-with-dependencies + james-server-rate-limiter-redis single - compile + package diff --git a/server/mailet/rate-limiter-redis/src/test/java/org/apache/james/rate/limiter/DockerRedis.java b/server/mailet/rate-limiter-redis/src/test/java/org/apache/james/rate/limiter/DockerRedis.java index 805d4dfa30d..1dc0ceb9323 100644 --- a/server/mailet/rate-limiter-redis/src/test/java/org/apache/james/rate/limiter/DockerRedis.java +++ b/server/mailet/rate-limiter-redis/src/test/java/org/apache/james/rate/limiter/DockerRedis.java @@ -20,50 +20,51 @@ package org.apache.james.rate.limiter; import java.net.URI; -import java.net.URISyntaxException; +import java.time.Duration; +import java.util.UUID; import org.apache.http.client.utils.URIBuilder; import org.testcontainers.containers.GenericContainer; import org.testcontainers.containers.Network; +import org.testcontainers.containers.wait.strategy.Wait; import org.testcontainers.utility.DockerImageName; +import com.github.fge.lambdas.Throwing; + import io.lettuce.core.RedisClient; import io.lettuce.core.api.sync.RedisCommands; public class DockerRedis { - private static final DockerImageName DEFAULT_IMAGE_NAME = DockerImageName.parse("redis"); - private static final String DEFAULT_TAG = "6.2.6"; + private static final DockerImageName DEFAULT_IMAGE_NAME = DockerImageName.parse("redis").withTag("7.0.12"); private static final int DEFAULT_PORT = 6379; private final GenericContainer container; public DockerRedis() { - this.container = new GenericContainer<>(DEFAULT_IMAGE_NAME.withTag(DEFAULT_TAG)) - .withExposedPorts(DEFAULT_PORT); + this.container = getContainer(); } public DockerRedis(Network network) { - this.container = new GenericContainer<>(DEFAULT_IMAGE_NAME.withTag(DEFAULT_TAG)) - .withExposedPorts(DEFAULT_PORT) - .withNetwork(network) - .withCreateContainerCmdModifier(createContainerCmd -> createContainerCmd.withName("james-redis-test")) - .withNetworkAliases("redis"); + this.container = getContainer() + .withNetwork(network); } - public Integer getPort() { - return container.getMappedPort(DEFAULT_PORT); + private GenericContainer getContainer() { + return new GenericContainer<>(DEFAULT_IMAGE_NAME) + .withExposedPorts(DEFAULT_PORT) + .withCreateContainerCmdModifier(createContainerCmd -> createContainerCmd.withName("james-redis-test-" + UUID.randomUUID())) + .withCommand("--loglevel", "debug") + .withNetworkAliases("redis") + .waitingFor(Wait.forLogMessage(".*Ready to accept connections.*", 1) + .withStartupTimeout(Duration.ofMinutes(2))); } public URI redisURI() { - try { - return new URIBuilder() - .setScheme("redis") - .setHost(container.getHost()) - .setPort(getPort()) - .build(); - } catch (URISyntaxException e) { - throw new RuntimeException("Error when build redis uri. ", e); - } + return Throwing.supplier(() -> new URIBuilder() + .setScheme("redis") + .setHost(container.getHost()) + .setPort(container.getMappedPort(DEFAULT_PORT)) + .build()).get(); } public void start() { diff --git a/server/mailet/rate-limiter/docker-compose.yml b/server/mailet/rate-limiter/docker-compose.yml index 63ddeb72fee..a9b158d2b07 100644 --- a/server/mailet/rate-limiter/docker-compose.yml +++ b/server/mailet/rate-limiter/docker-compose.yml @@ -6,7 +6,9 @@ services: image: apache/james:memory-latest container_name: james hostname: james.local + command: + - --generate-keystore volumes: - - $PWD/target/james-server-rate-limiter-3.8.0-SNAPSHOT-jar-with-dependencies.jar:/root/extensions-jars/james-server-rate-limiter.jar + - $PWD/target/james-server-rate-limiter-jar-with-dependencies.jar:/root/extensions-jars/james-server-rate-limiter.jar - $PWD/extensions.properties:/root/conf/extensions.properties - $PWD/mailetcontainer.xml:/root/conf/mailetcontainer.xml diff --git a/server/mailet/rate-limiter/mailetcontainer.xml b/server/mailet/rate-limiter/mailetcontainer.xml index 10aa8e3bca8..5a19d2642d0 100644 --- a/server/mailet/rate-limiter/mailetcontainer.xml +++ b/server/mailet/rate-limiter/mailetcontainer.xml @@ -121,7 +121,7 @@ 200M tooMuchMails - + myPrefix 1h 1h diff --git a/server/mailet/rate-limiter/pom.xml b/server/mailet/rate-limiter/pom.xml index 69cfc7d4681..6273a88bdaf 100644 --- a/server/mailet/rate-limiter/pom.xml +++ b/server/mailet/rate-limiter/pom.xml @@ -114,13 +114,14 @@ jar-with-dependencies + james-server-rate-limiter single - compile + package diff --git a/server/mailet/rate-limiter/src/test/scala/org/apache/james/transport/mailets/PerRecipientRateLimitTest.scala b/server/mailet/rate-limiter/src/test/scala/org/apache/james/transport/mailets/PerRecipientRateLimitTest.scala index 7eb00ff45a2..7de761d5266 100644 --- a/server/mailet/rate-limiter/src/test/scala/org/apache/james/transport/mailets/PerRecipientRateLimitTest.scala +++ b/server/mailet/rate-limiter/src/test/scala/org/apache/james/transport/mailets/PerRecipientRateLimitTest.scala @@ -42,7 +42,7 @@ class PerRecipientRateLimitTest { @Test def rateLimitingShouldBeAppliedPerRecipient(): Unit = { val mailet: PerRecipientRateLimit = testee(FakeMailetConfig.builder() - .mailetName("PerRecipientRateLimitMailet") + .mailetName("PerRecipientRateLimit") .setProperty("duration", "20s") .setProperty("precision", "1s") .setProperty("count", "1") @@ -74,7 +74,7 @@ class PerRecipientRateLimitTest { @Test def rateLimitingShouldNotBeAppliedWhenDoNotHaveRecipient() : Unit = { val mailet: PerRecipientRateLimit = testee(FakeMailetConfig.builder() - .mailetName("PerRecipientRateLimitMailet") + .mailetName("PerRecipientRateLimit") .setProperty("duration", "20s") .setProperty("precision", "1s") .setProperty("count", "1") @@ -93,7 +93,7 @@ class PerRecipientRateLimitTest { @Test def rateLimitingShouldFlowToTheIntendedProcessor() : Unit = { val mailet: PerRecipientRateLimit = testee(FakeMailetConfig.builder() - .mailetName("PerRecipientRateLimitMailet") + .mailetName("PerRecipientRateLimit") .setProperty("duration", "20s") .setProperty("precision", "1s") .setProperty("count", "1") @@ -126,7 +126,7 @@ class PerRecipientRateLimitTest { @Test def rateLimitingShouldNOTBeAppliedPerSender() : Unit = { val mailet: PerRecipientRateLimit = testee(FakeMailetConfig.builder() - .mailetName("PerRecipientRateLimitMailet") + .mailetName("PerRecipientRateLimit") .setProperty("duration", "20s") .setProperty("precision", "1s") .setProperty("count", "1") @@ -159,7 +159,7 @@ class PerRecipientRateLimitTest { @Test def shouldRateLimitSizeOfEmails(): Unit = { val mailet: PerRecipientRateLimit = testee(FakeMailetConfig.builder() - .mailetName("PerRecipientRateLimitMailet") + .mailetName("PerRecipientRateLimit") .setProperty("duration", "20s") .setProperty("precision", "1s") .setProperty("size", "100K") @@ -206,7 +206,7 @@ class PerRecipientRateLimitTest { val mailetContext = Mockito.spy(FakeMailContext.defaultContext) val mailet: PerRecipientRateLimit = testee(FakeMailetConfig.builder() - .mailetName("PerRecipientRateLimitMailet") + .mailetName("PerRecipientRateLimit") .setProperty("duration", "20s") .setProperty("precision", "1s") .setProperty("count", "1") @@ -258,7 +258,7 @@ class PerRecipientRateLimitTest { @Test def shouldRateLimitedWhenAllRecipientsExceeded(): Unit = { val mailet: PerRecipientRateLimit = testee(FakeMailetConfig.builder() - .mailetName("PerRecipientRateLimitMailet") + .mailetName("PerRecipientRateLimit") .setProperty("duration", "20s") .setProperty("precision", "1s") .setProperty("count", "1") @@ -292,7 +292,7 @@ class PerRecipientRateLimitTest { @Test def mailetShouldSupportBothCountAndSize(): Unit = { val mailet: PerRecipientRateLimit = testee(FakeMailetConfig.builder() - .mailetName("PerRecipientRateLimitMailet") + .mailetName("PerRecipientRateLimit") .setProperty("duration", "20s") .setProperty("precision", "1s") .setProperty("count", "2") @@ -354,7 +354,7 @@ class PerRecipientRateLimitTest { @Test def shouldFailWhenNoDuration(): Unit = { assertThatThrownBy(() => testee(FakeMailetConfig.builder() - .mailetName("PerRecipientRateLimitMailet") + .mailetName("PerRecipientRateLimit") .build())) .isInstanceOf(classOf[IllegalArgumentException]) } @@ -362,7 +362,7 @@ class PerRecipientRateLimitTest { @Test def shouldFailWhenEmptyDuration(): Unit = { assertThatThrownBy(() => testee(FakeMailetConfig.builder() - .mailetName("PerRecipientRateLimitMailet") + .mailetName("PerRecipientRateLimit") .setProperty("duration", "") .build())) .isInstanceOf(classOf[IllegalArgumentException]) @@ -371,7 +371,7 @@ class PerRecipientRateLimitTest { @Test def shouldFailWhenBadDuration(): Unit = { assertThatThrownBy(() => testee(FakeMailetConfig.builder() - .mailetName("PerRecipientRateLimitMailet") + .mailetName("PerRecipientRateLimit") .setProperty("duration", "bad") .build())) .isInstanceOf(classOf[IllegalArgumentException]) @@ -380,7 +380,7 @@ class PerRecipientRateLimitTest { @Test def shouldFailWhenNegativeDuration(): Unit = { assertThatThrownBy(() => testee(FakeMailetConfig.builder() - .mailetName("PerRecipientRateLimitMailet") + .mailetName("PerRecipientRateLimit") .setProperty("duration", "-3s") .build())) .isInstanceOf(classOf[IllegalArgumentException]) @@ -389,7 +389,7 @@ class PerRecipientRateLimitTest { @Test def shouldFailWhenZeroDuration(): Unit = { assertThatThrownBy(() => testee(FakeMailetConfig.builder() - .mailetName("PerRecipientRateLimitMailet") + .mailetName("PerRecipientRateLimit") .setProperty("count", "1") .setProperty("duration", "0s") .build())) @@ -399,7 +399,7 @@ class PerRecipientRateLimitTest { @Test def shouldFailWhenTooSmallDuration(): Unit = { assertThatThrownBy(() => testee(FakeMailetConfig.builder() - .mailetName("PerRecipientRateLimitMailet") + .mailetName("PerRecipientRateLimit") .setProperty("count", "1") .setProperty("duration", "10ms") .build())) @@ -410,7 +410,7 @@ class PerRecipientRateLimitTest { def durationWithNoUnitShouldDefaultToSeconds(): Unit = { assertThat( testee(FakeMailetConfig.builder() - .mailetName("PerRecipientRateLimitMailet") + .mailetName("PerRecipientRateLimit") .setProperty("duration", "10") .build()).parseDuration().getSeconds) .isEqualTo(10L) @@ -420,7 +420,7 @@ class PerRecipientRateLimitTest { def durationShouldSupportUnits(): Unit = { assertThat( testee(FakeMailetConfig.builder() - .mailetName("PerRecipientRateLimitMailet") + .mailetName("PerRecipientRateLimit") .setProperty("duration", "1h") .build()).parseDuration().getSeconds) .isEqualTo(3600L) @@ -429,7 +429,7 @@ class PerRecipientRateLimitTest { @Test def shouldFailWithEmptyCount(): Unit = { assertThatThrownBy(() => testee(FakeMailetConfig.builder() - .mailetName("PerRecipientRateLimitMailet") + .mailetName("PerRecipientRateLimit") .setProperty("count", "") .setProperty("duration", "10s") .build()).parseDuration().getSeconds) @@ -439,7 +439,7 @@ class PerRecipientRateLimitTest { @Test def shouldFailWithZeroCount(): Unit = { assertThatThrownBy(() => testee(FakeMailetConfig.builder() - .mailetName("PerRecipientRateLimitMailet") + .mailetName("PerRecipientRateLimit") .setProperty("count", "0") .setProperty("duration", "10s") .build()).parseDuration().getSeconds) @@ -449,7 +449,7 @@ class PerRecipientRateLimitTest { @Test def shouldFailWithNegativeCount(): Unit = { assertThatThrownBy(() => testee(FakeMailetConfig.builder() - .mailetName("PerRecipientRateLimitMailet") + .mailetName("PerRecipientRateLimit") .setProperty("count", "-1") .setProperty("duration", "10s") .build()).parseDuration().getSeconds) @@ -459,7 +459,7 @@ class PerRecipientRateLimitTest { @Test def shouldFailWithBadCount(): Unit = { assertThatThrownBy(() => testee(FakeMailetConfig.builder() - .mailetName("PerRecipientRateLimitMailet") + .mailetName("PerRecipientRateLimit") .setProperty("count", "bad") .setProperty("duration", "10s") .build()).parseDuration().getSeconds) @@ -469,7 +469,7 @@ class PerRecipientRateLimitTest { @Test def shouldFailWithEmptySize(): Unit = { assertThatThrownBy(() => testee(FakeMailetConfig.builder() - .mailetName("PerRecipientRateLimitMailet") + .mailetName("PerRecipientRateLimit") .setProperty("size", "") .setProperty("duration", "10s") .build()).parseDuration().getSeconds) @@ -479,7 +479,7 @@ class PerRecipientRateLimitTest { @Test def shouldFailWithZeroSize(): Unit = { assertThatThrownBy(() => testee(FakeMailetConfig.builder() - .mailetName("PerRecipientRateLimitMailet") + .mailetName("PerRecipientRateLimit") .setProperty("size", "0") .setProperty("duration", "10s") .build()).parseDuration().getSeconds) @@ -489,7 +489,7 @@ class PerRecipientRateLimitTest { @Test def shouldFailWithNegativeSize(): Unit = { assertThatThrownBy(() => testee(FakeMailetConfig.builder() - .mailetName("PerRecipientRateLimitMailet") + .mailetName("PerRecipientRateLimit") .setProperty("size", "-1000") .setProperty("duration", "10s") .build()).parseDuration().getSeconds) @@ -499,7 +499,7 @@ class PerRecipientRateLimitTest { @Test def shouldFailWithBadSize(): Unit = { assertThatThrownBy(() => testee(FakeMailetConfig.builder() - .mailetName("PerRecipientRateLimitMailet") + .mailetName("PerRecipientRateLimit") .setProperty("size", "bad") .setProperty("duration", "10s") .build()).parseDuration().getSeconds) @@ -509,7 +509,7 @@ class PerRecipientRateLimitTest { @Test def sizeShouldSupportUnits(): Unit = { assertThatCode(() => testee(FakeMailetConfig.builder() - .mailetName("PerRecipientRateLimitMailet") + .mailetName("PerRecipientRateLimit") .setProperty("size", "1k") .setProperty("duration", "10s") .build()).parseDuration().getSeconds) diff --git a/server/protocols/jmap-draft-integration-testing/jmap-draft-integration-testing-common/src/test/java/org/apache/james/jmap/ContainerTest.java b/server/protocols/jmap-draft-integration-testing/jmap-draft-integration-testing-common/src/test/java/org/apache/james/jmap/ContainerTest.java index e24e77831d9..4225e87a1ad 100644 --- a/server/protocols/jmap-draft-integration-testing/jmap-draft-integration-testing-common/src/test/java/org/apache/james/jmap/ContainerTest.java +++ b/server/protocols/jmap-draft-integration-testing/jmap-draft-integration-testing-common/src/test/java/org/apache/james/jmap/ContainerTest.java @@ -36,7 +36,7 @@ public class ContainerTest { @Rule - public DockerContainer container = DockerContainer.fromName("nginx:1.22") + public DockerContainer container = DockerContainer.fromName("nginx:1.25") .withAffinityToContainer() .withExposedPorts(80) .waitingFor(new HttpWaitStrategy() 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 fd55e976462..a14371968fe 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 @@ -21,12 +21,12 @@ public interface Images { String FAKE_SMTP = "weave/rest-smtp-sink:latest"; - String RABBITMQ = "rabbitmq:3.9.18-management"; + String RABBITMQ = "rabbitmq:3.12.1-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.4.0"; - String TIKA = "apache/tika:1.28.2"; + String TIKA = "apache/tika:2.8.0.0"; String MOCK_SMTP_SERVER = "linagora/mock-smtp-server:0.6"; String OPEN_LDAP = "osixia/openldap:1.5.0"; } diff --git a/src/site/markdown/server/install/guice-cassandra-rabbitmq-s3.md b/src/site/markdown/server/install/guice-cassandra-rabbitmq-s3.md index fc16946843c..7aee72c793e 100644 --- a/src/site/markdown/server/install/guice-cassandra-rabbitmq-s3.md +++ b/src/site/markdown/server/install/guice-cassandra-rabbitmq-s3.md @@ -5,7 +5,7 @@ ### Requirements - Java 11 SDK - - Docker ∕ OpenSearch 2.1.0, RabbitMQ Management 3.8.18, compatible S3 ObjectStorage and Cassandra 3.11.10 + - Docker ∕ OpenSearch 2.1.0, RabbitMQ Management 3.8.18, compatible S3 ObjectStorage and Cassandra 3.11.15 - Maven 3 ### Building the artifacts @@ -25,7 +25,7 @@ mvn clean install ### Requirements - * Cassandra 3.11.10 + * Cassandra 3.11.15 * OpenSearch 2.1.0 * RabbitMQ-Management 3.8.18 * Zenko Cloudserver or AWS S3 compatible API @@ -47,10 +47,10 @@ $ keytool -genkey -alias james -keyalg RSA -keystore conf/keystore You need to have a Cassandra, OpenSearch, S3 and RabbitMQ instance running. You can either install the servers or launch them via docker: ```bash -$ docker run -d -p 9042:9042 --name=cassandra cassandra:3.11.10 +$ docker run -d -p 9042:9042 --name=cassandra cassandra:3.11.15 $ docker run -d --network james -p 9200:9200 --name=opensearch --env 'discovery.type=single-node' opensearchproject/opensearch:2.1.0 -$ docker run -d -p 5672:5672 -p 15672:15672 --name=rabbitmq rabbitmq:3.9.18-management -$ docker run -d --env 'REMOTE_MANAGEMENT_DISABLE=1' --env 'SCALITY_ACCESS_KEY_ID=accessKey1' --env 'SCALITY_SECRET_ACCESS_KEY=secretKey1' --name=s3 zenko/cloudserver:8.2.6 +$ docker run -d -p 5672:5672 -p 15672:15672 --name=rabbitmq rabbitmq:3.12.1-management +$ docker run -d --env 'REMOTE_MANAGEMENT_DISABLE=1' --env 'SCALITY_ACCESS_KEY_ID=accessKey1' --env 'SCALITY_SECRET_ACCESS_KEY=secretKey1' --name=s3 registry.scality.com/cloudserver/cloudserver:8.7.25 ``` Once everything is set up, you just have to run the jar with: diff --git a/src/site/markdown/server/install/guice-cassandra.md b/src/site/markdown/server/install/guice-cassandra.md index 370da400808..9259cfd806d 100644 --- a/src/site/markdown/server/install/guice-cassandra.md +++ b/src/site/markdown/server/install/guice-cassandra.md @@ -5,7 +5,7 @@ ### Requirements - Java 11 SDK - - Docker ∕ OpenSearch 2.1.0 and Cassandra 3.11.10 + - Docker ∕ OpenSearch 2.1.0 and Cassandra 3.11.15 - Maven 3 *WARNING*: JAMES-3591 Cassandra is not made to store large binary content, its use will be suboptimal compared to @@ -28,7 +28,7 @@ mvn clean install ### Requirements - * Cassandra 3.11.10 + * Cassandra 3.11.15 * OpenSearch 2.1.0 ### James Launch @@ -48,7 +48,7 @@ $ keytool -genkey -alias james -keyalg RSA -keystore conf/keystore You need to have a Cassandra and an OpenSearch instance running. You can either install the servers or launch them via docker: ```bash -$ docker run -d -p 9042:9042 --name=cassandra cassandra:3.11.10 +$ docker run -d -p 9042:9042 --name=cassandra cassandra:3.11.15 $ docker run -d --network james -p 9200:9200 --name=opensearch --env 'discovery.type=single-node' opensearchproject/opensearch:2.1.0 ``` diff --git a/src/site/xdoc/server/quick-start-cassandra.xml b/src/site/xdoc/server/quick-start-cassandra.xml index 0c71406c219..9b750de1108 100644 --- a/src/site/xdoc/server/quick-start-cassandra.xml +++ b/src/site/xdoc/server/quick-start-cassandra.xml @@ -64,7 +64,7 @@ Step 3: Deploy 3.1. Deploy Cassandra (optional) You may skip this part if you already have a running Cassandra on your network. -$ docker run --detach=true --name=cassandra cassandra:3.11.10 +$ docker run --detach=true --name=cassandra cassandra:3.11.15 3.2. Deploy OpenSearch (optional) You may skip this part if you already have a running OpenSearch on your network. diff --git a/third-party/clamav/docker-compose.yml b/third-party/clamav/docker-compose.yml index e04e5aba556..c70f15c0039 100644 --- a/third-party/clamav/docker-compose.yml +++ b/third-party/clamav/docker-compose.yml @@ -4,18 +4,25 @@ services: james: depends_on: - - opensearch - - cassandra - - tika - - rabbitmq - - s3 - - clamav + cassandra: + condition: service_healthy + opensearch: + condition: service_started + tika: + condition: service_started + rabbitmq: + condition: service_started + s3: + condition: service_started + clamav: + condition: service_started image: apache/james:distributed-latest container_name: james hostname: james.local + command: + - --generate-keystore volumes: - - $PWD/target/apache-james-clamav-3.8.0-SNAPSHOT-jar-with-dependencies.jar:/root/extensions-jars/james-server-clamav.jar - - $PWD/sample-configuration/keystore:/root/conf/keystore + - $PWD/target/apache-james-clamav-jar-with-dependencies.jar:/root/extensions-jars/james-server-clamav.jar - $PWD/sample-configuration/mailetcontainer.xml:/root/conf/mailetcontainer.xml ports: - "80:80" @@ -26,28 +33,47 @@ services: - "587:587" - "993:993" - "8000:8000" + networks: + - james opensearch: image: opensearchproject/opensearch:2.1.0 environment: - discovery.type=single-node + - DISABLE_INSTALL_DEMO_CONFIG=true + - DISABLE_SECURITY_PLUGIN=true + networks: + james: + aliases: + - elasticsearch cassandra: - image: cassandra:3.11.10 + image: cassandra:3.11.15 ports: - "9042:9042" + healthcheck: + test: [ "CMD-SHELL", "[ $$(nodetool statusgossip) = running ]" ] + interval: 3s + timeout: 20s + retries: 5 + networks: + - james tika: - image: apache/tika:1.26 + image: apache/tika:2.8.0.0 + networks: + - james rabbitmq: - image: rabbitmq:3.8.18-management + image: rabbitmq:3.12.1-management ports: - "5672:5672" - "15672:15672" + networks: + - james s3: - image: zenko/cloudserver:8.2.6 + image: registry.scality.com/cloudserver/cloudserver:8.7.25 container_name: s3.docker.test environment: - SCALITY_ACCESS_KEY_ID=accessKey1 @@ -55,6 +81,13 @@ services: - S3BACKEND=mem - LOG_LEVEL=trace - REMOTE_MANAGEMENT_DISABLE=1 + networks: + - james clamav: - image: clamav/clamav:0.105 + image: clamav/clamav:1.1 + networks: + - james + +networks: + james: \ No newline at end of file diff --git a/third-party/clamav/pom.xml b/third-party/clamav/pom.xml index 9ba8047f1ef..4e726e19e3a 100644 --- a/third-party/clamav/pom.xml +++ b/third-party/clamav/pom.xml @@ -70,13 +70,14 @@ jar-with-dependencies + apache-james-clamav single - compile + package diff --git a/third-party/clamav/sample-configuration/mailetcontainer.xml b/third-party/clamav/sample-configuration/mailetcontainer.xml index 976a3d900ef..ad69dbd7bd6 100644 --- a/third-party/clamav/sample-configuration/mailetcontainer.xml +++ b/third-party/clamav/sample-configuration/mailetcontainer.xml @@ -31,7 +31,7 @@ 20 - memory://var/mail/error/ + cassandra://var/mail/error/ @@ -51,7 +51,7 @@ ignore - memory://var/mail/error/ + cassandra://var/mail/error/ propagate @@ -129,7 +129,7 @@ none - memory://var/mail/address-error/ + cassandra://var/mail/address-error/ @@ -141,7 +141,7 @@ none - memory://var/mail/relay-denied/ + cassandra://var/mail/relay-denied/ Warning: You are sending an e-mail to a remote server. You must be authenticated to perform such an operation @@ -157,7 +157,7 @@ - memory://var/mail/rrt-error/ + cassandra://var/mail/rrt-error/ true diff --git a/third-party/clamav/src/test/java/org/apache/james/clamav/DockerClamAV.java b/third-party/clamav/src/test/java/org/apache/james/clamav/DockerClamAV.java index c66d2783880..6fec1c9191e 100644 --- a/third-party/clamav/src/test/java/org/apache/james/clamav/DockerClamAV.java +++ b/third-party/clamav/src/test/java/org/apache/james/clamav/DockerClamAV.java @@ -20,24 +20,25 @@ package org.apache.james.clamav; import java.time.Duration; +import java.util.UUID; import org.testcontainers.containers.GenericContainer; -import org.testcontainers.containers.wait.strategy.LogMessageWaitStrategy; +import org.testcontainers.containers.wait.strategy.Wait; import org.testcontainers.utility.DockerImageName; public class DockerClamAV { - private static final DockerImageName DEFAULT_IMAGE_NAME = DockerImageName.parse("clamav/clamav"); - private static final String DEFAULT_TAG = "0.105"; + private static final DockerImageName DEFAULT_IMAGE_NAME = DockerImageName.parse("clamav/clamav").withTag("1.1"); private static final int DEFAULT_PORT = 3310; private final GenericContainer container; public DockerClamAV() { - this.container = new GenericContainer<>(DEFAULT_IMAGE_NAME.withTag(DEFAULT_TAG)) + this.container = new GenericContainer<>(DEFAULT_IMAGE_NAME) .withExposedPorts(DEFAULT_PORT) .withEnv("CLAMAV_NO_FRESHCLAMD", "true") .withEnv("CLAMAV_NO_MILTERD", "true") - .waitingFor(new LogMessageWaitStrategy().withRegEx(".*clamd started.*\\n").withTimes(1) + .withCreateContainerCmdModifier(createContainerCmd -> createContainerCmd.withName("james-clamav-test-" + UUID.randomUUID())) + .waitingFor(Wait.forHealthcheck() .withStartupTimeout(Duration.ofMinutes(5))); } diff --git a/third-party/elasticsearch/conf/keystore b/third-party/elasticsearch/conf/keystore deleted file mode 100644 index 361cd01f43d..00000000000 Binary files a/third-party/elasticsearch/conf/keystore and /dev/null differ diff --git a/third-party/elasticsearch/docker-compose.yml b/third-party/elasticsearch/docker-compose.yml index de788681b62..2fe73817e5d 100644 --- a/third-party/elasticsearch/docker-compose.yml +++ b/third-party/elasticsearch/docker-compose.yml @@ -8,9 +8,10 @@ services: image: apache/james:memory-latest container_name: james hostname: james.local + command: + - --generate-keystore volumes: - - ./conf/keystore:/root/conf/keystore - - ./target/apache-james-elasticsearch-3.8.0-SNAPSHOT-jar-with-dependencies.jar:/root/extensions-jars/apache-james-elasticsearch-3.8.0-SNAPSHOT-jar-with-dependencies.jar + - ./target/apache-james-elasticsearch-jar-with-dependencies.jar:/root/extensions-jars/apache-james-elasticsearch.jar - ./conf/extensions.properties:/root/conf/extensions.properties - ./conf/elasticsearch.properties:/root/conf/elasticsearch.properties diff --git a/third-party/elasticsearch/pom.xml b/third-party/elasticsearch/pom.xml index 8d80e8b979a..15830efcc91 100644 --- a/third-party/elasticsearch/pom.xml +++ b/third-party/elasticsearch/pom.xml @@ -130,6 +130,7 @@ jar-with-dependencies + apache-james-elasticsearch diff --git a/third-party/rspamd/docker-compose-distributed.yml b/third-party/rspamd/docker-compose-distributed.yml index 7bfe971c5d4..5bf833be81f 100644 --- a/third-party/rspamd/docker-compose-distributed.yml +++ b/third-party/rspamd/docker-compose-distributed.yml @@ -4,18 +4,25 @@ services: james: depends_on: - - elasticsearch - - cassandra - - tika - - rabbitmq - - s3 - - rspamd + cassandra: + condition: service_healthy + opensearch: + condition: service_started + tika: + condition: service_started + rabbitmq: + condition: service_started + s3: + condition: service_started + rspamd: + condition: service_healthy image: apache/james:distributed-latest container_name: james hostname: james.local + command: + - --generate-keystore volumes: - - $PWD/target/apache-james-rspamd-3.8.0-SNAPSHOT-jar-with-dependencies.jar:/root/extensions-jars/james-server-rspamd.jar - - $PWD/sample-configuration/keystore:/root/conf/keystore + - $PWD/target/apache-james-rspamd-jar-with-dependencies.jar:/root/extensions-jars/james-server-rspamd.jar - $PWD/sample-configuration/extensions.properties:/root/conf/extensions.properties - $PWD/sample-configuration/mailetcontainer_distributed.xml:/root/conf/mailetcontainer.xml - $PWD/sample-configuration/listeners.xml:/root/conf/listeners.xml @@ -31,28 +38,47 @@ services: - "587:587" - "993:993" - "8000:8000" + networks: + - james opensearch: image: opensearchproject/opensearch:2.1.0 environment: - discovery.type=single-node + - DISABLE_INSTALL_DEMO_CONFIG=true + - DISABLE_SECURITY_PLUGIN=true + networks: + james: + aliases: + - elasticsearch cassandra: - image: cassandra:3.11.10 + image: cassandra:3.11.15 ports: - "9042:9042" + healthcheck: + test: [ "CMD-SHELL", "[ $$(nodetool statusgossip) = running ]" ] + interval: 3s + timeout: 20s + retries: 5 + networks: + - james tika: - image: apache/tika:1.26 + image: apache/tika:2.8.0.0 + networks: + - james rabbitmq: - image: rabbitmq:3.8.18-management + image: rabbitmq:3.12.1-management ports: - "5672:5672" - "15672:15672" + networks: + - james s3: - image: zenko/cloudserver:8.2.6 + image: registry.scality.com/cloudserver/cloudserver:8.7.25 container_name: s3.docker.test environment: - SCALITY_ACCESS_KEY_ID=accessKey1 @@ -60,19 +86,27 @@ services: - S3BACKEND=mem - LOG_LEVEL=trace - REMOTE_MANAGEMENT_DISABLE=1 + networks: + - james redis: - image: redis:6.2.6 + image: redis:7.0.12 + networks: + - james clamav: - image: clamav/clamav:0.105 + image: clamav/clamav:1.1 + networks: + - james rspamd: depends_on: - - redis - - clamav + clamav: + condition: service_healthy + redis: + condition: service_started container_name: rspamd - image: a16bitsysop/rspamd:3.3-r0-alpine3.16.2-r0 + image: a16bitsysop/rspamd:3.5-r7-alpine3.18.2-r0 environment: - REDIS=redis - CLAMAV=clamav @@ -81,4 +115,9 @@ services: - $PWD/sample-configuration/antivirus.conf:/etc/rspamd/override.d/antivirus.conf - $PWD/sample-configuration/statistic.conf:/etc/rspamd/statistic.conf ports: - - 11334:11334 \ No newline at end of file + - 11334:11334 + networks: + - james + +networks: + james: \ No newline at end of file diff --git a/third-party/rspamd/docker-compose.yml b/third-party/rspamd/docker-compose.yml index 6efd11a8ba0..3e7a9d514fc 100644 --- a/third-party/rspamd/docker-compose.yml +++ b/third-party/rspamd/docker-compose.yml @@ -4,13 +4,15 @@ services: james: depends_on: - - rspamd + rspamd: + condition: service_healthy image: apache/james:memory-latest container_name: james hostname: james.local + command: + - --generate-keystore volumes: - - $PWD/target/apache-james-rspamd-3.8.0-SNAPSHOT-jar-with-dependencies.jar:/root/extensions-jars/james-server-rspamd.jar - - $PWD/sample-configuration/keystore:/root/conf/keystore + - $PWD/target/apache-james-rspamd-jar-with-dependencies.jar:/root/extensions-jars/james-server-rspamd.jar - $PWD/sample-configuration/extensions.properties:/root/conf/extensions.properties - $PWD/sample-configuration/mailetcontainer_memory.xml:/root/conf/mailetcontainer.xml - $PWD/sample-configuration/listeners.xml:/root/conf/listeners.xml @@ -28,17 +30,22 @@ services: - "8000:8000" redis: - image: redis:6.2.6 + image: redis:7.0.12 + command: + - "--loglevel" + - "debug" clamav: - image: clamav/clamav:0.105 + image: clamav/clamav:1.1 rspamd: depends_on: - - redis - - clamav + clamav: + condition: service_healthy + redis: + condition: service_started container_name: rspamd - image: a16bitsysop/rspamd:3.3-r0-alpine3.16.2-r0 + image: a16bitsysop/rspamd:3.5-r7-alpine3.18.2-r0 environment: - REDIS=redis - CLAMAV=clamav diff --git a/third-party/rspamd/pom.xml b/third-party/rspamd/pom.xml index 11718f0eb20..ff91ce9356c 100644 --- a/third-party/rspamd/pom.xml +++ b/third-party/rspamd/pom.xml @@ -207,13 +207,14 @@ jar-with-dependencies + apache-james-rspamd single - compile + package diff --git a/third-party/rspamd/sample-configuration/keystore b/third-party/rspamd/sample-configuration/keystore deleted file mode 100644 index 361cd01f43d..00000000000 Binary files a/third-party/rspamd/sample-configuration/keystore and /dev/null differ diff --git a/third-party/rspamd/src/test/java/org/apache/james/rspamd/DockerClamAV.java b/third-party/rspamd/src/test/java/org/apache/james/rspamd/DockerClamAV.java index f2bc942c162..5b18644ec90 100644 --- a/third-party/rspamd/src/test/java/org/apache/james/rspamd/DockerClamAV.java +++ b/third-party/rspamd/src/test/java/org/apache/james/rspamd/DockerClamAV.java @@ -28,14 +28,13 @@ import org.testcontainers.utility.DockerImageName; public class DockerClamAV { - private static final DockerImageName DEFAULT_IMAGE_NAME = DockerImageName.parse("clamav/clamav"); - private static final String DEFAULT_TAG = "0.105"; + private static final DockerImageName DEFAULT_IMAGE_NAME = DockerImageName.parse("clamav/clamav").withTag("1.1"); private static final int DEFAULT_PORT = 3310; private final GenericContainer container; public DockerClamAV(Network network) { - this.container = new GenericContainer<>(DEFAULT_IMAGE_NAME.withTag(DEFAULT_TAG)) + this.container = new GenericContainer<>(DEFAULT_IMAGE_NAME) .withExposedPorts(DEFAULT_PORT) .withEnv("CLAMAV_NO_FRESHCLAMD", "true") .withEnv("CLAMAV_NO_MILTERD", "true") diff --git a/third-party/rspamd/src/test/java/org/apache/james/rspamd/DockerRspamd.java b/third-party/rspamd/src/test/java/org/apache/james/rspamd/DockerRspamd.java index ba8ceee0b5b..1be14bd554e 100644 --- a/third-party/rspamd/src/test/java/org/apache/james/rspamd/DockerRspamd.java +++ b/third-party/rspamd/src/test/java/org/apache/james/rspamd/DockerRspamd.java @@ -33,7 +33,7 @@ public class DockerRspamd { public static final String PASSWORD = "admin"; private static final DockerImageName DEFAULT_IMAGE_NAME = DockerImageName.parse("a16bitsysop/rspamd"); - private static final String DEFAULT_TAG = "3.3-r0-alpine3.16.2-r0"; + private static final String DEFAULT_TAG = "3.5-r7-alpine3.18.2-r0"; private static final int DEFAULT_PORT = 11334; private final DockerRedis dockerRedis; diff --git a/third-party/spamassassin/docker-compose.yml b/third-party/spamassassin/docker-compose.yml index 618806afc1b..514717ef54c 100644 --- a/third-party/spamassassin/docker-compose.yml +++ b/third-party/spamassassin/docker-compose.yml @@ -8,9 +8,10 @@ services: image: apache/james:memory-latest container_name: james hostname: james.local + command: + - --generate-keystore 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/target/apache-james-spamassassin-jar-with-dependencies.jar:/root/extensions-jars/james-server-spamassassin.jar - $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 @@ -27,6 +28,6 @@ services: - "8000:8000" spamassassin: - image: instantlinux/spamassassin:3.4.6-1 + image: instantlinux/spamassassin:4.0.0-6 ports: - "783:783" \ No newline at end of file diff --git a/third-party/spamassassin/pom.xml b/third-party/spamassassin/pom.xml index e3f6dc9710a..607e84e00a3 100644 --- a/third-party/spamassassin/pom.xml +++ b/third-party/spamassassin/pom.xml @@ -192,13 +192,14 @@ jar-with-dependencies + apache-james-spamassassin single - compile + package diff --git a/third-party/spamassassin/sample-configuration/keystore b/third-party/spamassassin/sample-configuration/keystore deleted file mode 100644 index 361cd01f43d..00000000000 Binary files a/third-party/spamassassin/sample-configuration/keystore and /dev/null differ diff --git a/third-party/spamassassin/src/test/java/org/apache/james/spamassassin/SpamAssassinExtension.java b/third-party/spamassassin/src/test/java/org/apache/james/spamassassin/SpamAssassinExtension.java index a15eb2e636a..2120de5aa4e 100644 --- a/third-party/spamassassin/src/test/java/org/apache/james/spamassassin/SpamAssassinExtension.java +++ b/third-party/spamassassin/src/test/java/org/apache/james/spamassassin/SpamAssassinExtension.java @@ -38,33 +38,21 @@ import org.junit.jupiter.api.extension.ParameterResolver; import org.testcontainers.containers.GenericContainer; import org.testcontainers.containers.wait.strategy.HostPortWaitStrategy; -import org.testcontainers.images.builder.ImageFromDockerfile; -import org.testcontainers.utility.Base58; import com.github.fge.lambdas.Throwing; -import com.google.common.collect.ImmutableMap; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; import reactor.core.scheduler.Schedulers; public class SpamAssassinExtension implements BeforeAllCallback, AfterEachCallback, ParameterResolver { + public static final int SPAMASSASSIN_PORT = 783; private static final Duration STARTUP_TIMEOUT = Duration.ofMinutes(30); - private static final String UNIQUE_IDENTIFIER = Base58.randomString(16).toLowerCase(); - - private static final boolean DELETE_ON_EXIT = false; - private static final GenericContainer spamAssassinContainer = new GenericContainer<>( - new ImageFromDockerfile("james-spamassassin/" + UNIQUE_IDENTIFIER, DELETE_ON_EXIT) - .withFileFromClasspath("Dockerfile", "docker/spamassassin/Dockerfile") - .withFileFromClasspath("local.cf", "docker/spamassassin/local.cf") - .withFileFromClasspath("run.sh", "docker/spamassassin/run.sh") - .withFileFromClasspath("spamd.sh", "docker/spamassassin/spamd.sh") - .withFileFromClasspath("rule-update.sh", "docker/spamassassin/rule-update.sh") - .withFileFromClasspath("bayes_pg.sql", "docker/spamassassin/bayes_pg.sql")) - .withCreateContainerCmdModifier(cmd -> cmd.withName("spam-assassin-" + UUID.randomUUID().toString())) + private static final String SPAMASSASSIN_IMAGE = "instantlinux/spamassassin:4.0.0-6"; + private static final GenericContainer spamAssassinContainer = new GenericContainer<>(SPAMASSASSIN_IMAGE) + .withCreateContainerCmdModifier(cmd -> cmd.withName("james-spam-assassin-test-" + UUID.randomUUID())) .withStartupTimeout(STARTUP_TIMEOUT) - .withExposedPorts(783) - .withTmpFs(ImmutableMap.of("/var/lib/postgresql/data", "rw,noexec,nosuid,size=200m")) + .withExposedPorts(SPAMASSASSIN_PORT) .waitingFor(new HostPortWaitStrategy().withRateLimiter(RateLimiters.TWENTIES_PER_SECOND)); static { @@ -106,8 +94,6 @@ public SpamAssassin getSpamAssassin() { } public static class SpamAssassin { - private static final int SPAMASSASSIN_PORT = 783; - private final String ip; private final int bindingPort; private final GenericContainer spamAssassinContainer; @@ -155,7 +141,7 @@ private void train(String user, Path folder, TrainingKind trainingKind) throws I private enum TrainingKind { SPAM("--spam"), HAM("--ham"); - private String saLearnExtensionName; + private final String saLearnExtensionName; TrainingKind(String saLearnExtensionName) { this.saLearnExtensionName = saLearnExtensionName; 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 index 2578092b5a4..2583e9ef9ba 100644 --- 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 @@ -30,7 +30,6 @@ import static org.assertj.core.api.Assertions.assertThat; import java.io.File; -import java.util.UUID; import javax.mail.MessagingException; @@ -44,8 +43,6 @@ 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; @@ -55,7 +52,6 @@ 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; @@ -64,15 +60,9 @@ 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()); - + public static SpamAssassinExtension spamAssassinExtension = new SpamAssassinExtension(); @RegisterExtension public TestIMAPClient messageReader = new TestIMAPClient(); @RegisterExtension @@ -100,7 +90,7 @@ public void configure(Binder binder) { @Provides @Singleton private SpamAssassinConfiguration provideSpamAssassinConfiguration(){ - return new SpamAssassinConfiguration(Host.parseConfString("localhost", spamAssassinContainer.getMappedPort(783))); + return new SpamAssassinConfiguration(Host.parseConfString("localhost", spamAssassinExtension.getSpamAssassin().getBindingPort())); } }) .build(temporaryFolder); diff --git a/third-party/spamassassin/src/test/resources/docker/spamassassin/Dockerfile b/third-party/spamassassin/src/test/resources/docker/spamassassin/Dockerfile deleted file mode 100644 index 51ea4af10fa..00000000000 --- a/third-party/spamassassin/src/test/resources/docker/spamassassin/Dockerfile +++ /dev/null @@ -1,43 +0,0 @@ -FROM postgres:15.1 - -ENV SPAMASSASSIN_VERSION 3.4.6 - -RUN apt-get update && \ - DEBIAN_FRONTEND=noninteractive apt-get install --no-install-recommends -y \ - gpg \ - libio-socket-ip-perl \ - libmail-dkim-perl \ - libnet-ident-perl \ - libsocket-getaddrinfo-perl \ - pyzor \ - razor \ - libdbi-perl \ - libdbd-pg-perl \ - spamassassin=${SPAMASSASSIN_VERSION}* && \ - apt-get clean && \ - rm -rf /var/lib/apt/lists/* - -RUN mkdir -p /etc/spamassassin/sa-update-keys && \ - chmod 700 /etc/spamassassin/sa-update-keys && \ - chown debian-spamd:debian-spamd /etc/spamassassin/sa-update-keys && \ - mkdir -p /var/lib/spamassassin/.pyzor && \ - chmod 700 /var/lib/spamassassin/.pyzor && \ - echo "public.pyzor.org:24441" > /var/lib/spamassassin/.pyzor/servers && \ - chmod 600 /var/lib/spamassassin/.pyzor/servers && \ - chown -R debian-spamd:debian-spamd /var/lib/spamassassin/.pyzor - -RUN sed -i 's/^logfile = .*$/logfile = \/dev\/stderr/g' /etc/razor/razor-agent.conf - -COPY spamd.sh / -COPY rule-update.sh / -COPY run.sh / -RUN chmod 755 /spamd.sh /rule-update.sh /run.sh - -COPY local.cf /etc/spamassassin/ - -# Bayes database will be created automatically by Postres -COPY bayes_pg.sql /docker-entrypoint-initdb.d/ - -EXPOSE 783 - -ENTRYPOINT ["/spamd.sh"] diff --git a/third-party/spamassassin/src/test/resources/docker/spamassassin/bayes_pg.sql b/third-party/spamassassin/src/test/resources/docker/spamassassin/bayes_pg.sql deleted file mode 100644 index ef964728ff4..00000000000 --- a/third-party/spamassassin/src/test/resources/docker/spamassassin/bayes_pg.sql +++ /dev/null @@ -1,119 +0,0 @@ - -CREATE TABLE bayes_expire ( - id integer NOT NULL default '0', - runtime integer NOT NULL default '0' -) WITHOUT OIDS; - -CREATE INDEX bayes_expire_idx1 ON bayes_expire (id); - -CREATE TABLE bayes_global_vars ( - variable varchar(30) NOT NULL default '', - value varchar(200) NOT NULL default '', - PRIMARY KEY (variable) -) WITHOUT OIDS; - -INSERT INTO bayes_global_vars VALUES ('VERSION','3'); - -CREATE TABLE bayes_seen ( - id integer NOT NULL default '0', - msgid varchar(200) NOT NULL default '', - flag character(1) NOT NULL default '', - PRIMARY KEY (id,msgid) -) WITHOUT OIDS; - -CREATE TABLE bayes_token ( - id integer NOT NULL default '0', - token bytea NOT NULL default '', - spam_count integer NOT NULL default '0', - ham_count integer NOT NULL default '0', - atime integer NOT NULL default '0', - PRIMARY KEY (id,token) -) WITHOUT OIDS; - -CREATE INDEX bayes_token_idx1 ON bayes_token (token); - -ALTER TABLE bayes_token SET (fillfactor=95); - -CREATE TABLE bayes_vars ( - id serial NOT NULL, - username varchar(200) NOT NULL default '', - spam_count integer NOT NULL default '0', - ham_count integer NOT NULL default '0', - token_count integer NOT NULL default '0', - last_expire integer NOT NULL default '0', - last_atime_delta integer NOT NULL default '0', - last_expire_reduce integer NOT NULL default '0', - oldest_token_age integer NOT NULL default '2147483647', - newest_token_age integer NOT NULL default '0', - PRIMARY KEY (id) -) WITHOUT OIDS; - -CREATE UNIQUE INDEX bayes_vars_idx1 ON bayes_vars (username); - -CREATE OR REPLACE FUNCTION greatest_int (integer, integer) - RETURNS INTEGER - IMMUTABLE STRICT - AS 'SELECT CASE WHEN $1 < $2 THEN $2 ELSE $1 END;' - LANGUAGE SQL; - -CREATE OR REPLACE FUNCTION least_int (integer, integer) - RETURNS INTEGER - IMMUTABLE STRICT - AS 'SELECT CASE WHEN $1 < $2 THEN $1 ELSE $2 END;' - LANGUAGE SQL; - -CREATE OR REPLACE FUNCTION put_tokens(INTEGER, - BYTEA[], - INTEGER, - INTEGER, - INTEGER) -RETURNS VOID AS ' -DECLARE - inuserid ALIAS FOR $1; - intokenary ALIAS FOR $2; - inspam_count ALIAS FOR $3; - inham_count ALIAS FOR $4; - inatime ALIAS FOR $5; - _token BYTEA; - new_tokens INTEGER := 0; -BEGIN - for i in array_lower(intokenary, 1) .. array_upper(intokenary, 1) - LOOP - _token := intokenary[i]; - UPDATE bayes_token - SET spam_count = greatest_int(spam_count + inspam_count, 0), - ham_count = greatest_int(ham_count + inham_count, 0), - atime = greatest_int(atime, inatime) - WHERE id = inuserid - AND token = _token; - IF NOT FOUND THEN - -- we do not insert negative counts, just return true - IF NOT (inspam_count < 0 OR inham_count < 0) THEN - INSERT INTO bayes_token (id, token, spam_count, ham_count, atime) - VALUES (inuserid, _token, inspam_count, inham_count, inatime); - IF FOUND THEN - new_tokens := new_tokens + 1; - END IF; - END IF; - END IF; - END LOOP; - - IF new_tokens > 0 AND inatime > 0 THEN - UPDATE bayes_vars - SET token_count = token_count + new_tokens, - newest_token_age = greatest_int(newest_token_age, inatime), - oldest_token_age = least_int(oldest_token_age, inatime) - WHERE id = inuserid; - ELSIF new_tokens > 0 AND NOT inatime > 0 THEN - UPDATE bayes_vars - SET token_count = token_count + new_tokens - WHERE id = inuserid; - ELSIF NOT new_tokens > 0 AND inatime > 0 THEN - UPDATE bayes_vars - SET newest_token_age = greatest_int(newest_token_age, inatime), - oldest_token_age = least_int(oldest_token_age, inatime) - WHERE id = inuserid; - END IF; - RETURN; -END; -' LANGUAGE 'plpgsql'; diff --git a/third-party/spamassassin/src/test/resources/docker/spamassassin/local.cf b/third-party/spamassassin/src/test/resources/docker/spamassassin/local.cf deleted file mode 100644 index 6005e55403b..00000000000 --- a/third-party/spamassassin/src/test/resources/docker/spamassassin/local.cf +++ /dev/null @@ -1,97 +0,0 @@ -# This is the right place to customize your installation of SpamAssassin. -# -# See 'perldoc Mail::SpamAssassin::Conf' for details of what can be -# tweaked. -# -# Only a small subset of options are listed below -# -########################################################################### - -# Add *****SPAM***** to the Subject header of spam e-mails -# -# rewrite_header Subject *****SPAM***** - - -# Save spam messages as a message/rfc822 MIME attachment instead of -# modifying the original message (0: off, 2: use text/plain instead) -# -# report_safe 1 - - -# Set which networks or hosts are considered 'trusted' by your mail -# server (i.e. not spammers) -# -# trusted_networks 212.17.35. - - -# Set file-locking method (flock is not safe over NFS, but is faster) -# -# lock_method flock - - -# Set the threshold at which a message is considered spam (default: 5.0) -# -# required_score 5.0 - - -# Use Bayesian classifier (default: 1) -# -use_bayes 1 - - -# Bayesian classifier auto-learning (default: 1) -# -#bayes_auto_learn 1 - -bayes_store_module Mail::SpamAssassin::BayesStore::PgSQL - -bayes_sql_dsn DBI:Pg:dbname=postgres;host=localhost -bayes_sql_username postgres - -bayes_min_spam_num 1 -bayes_min_ham_num 1 - - -# Set headers which may provide inappropriate cues to the Bayesian -# classifier -# -# bayes_ignore_header X-Bogosity -# bayes_ignore_header X-Spam-Flag -# bayes_ignore_header X-Spam-Status - - -# Whether to decode non- UTF-8 and non-ASCII textual parts and recode -# them to UTF-8 before the text is given over to rules processing. -# -# normalize_charset 1 - -# Some shortcircuiting, if the plugin is enabled -# -ifplugin Mail::SpamAssassin::Plugin::Shortcircuit -# -# default: strongly-whitelisted mails are *really* whitelisted now, if the -# shortcircuiting plugin is active, causing early exit to save CPU load. -# Uncomment to turn this on -# -# shortcircuit USER_IN_WHITELIST on -# shortcircuit USER_IN_DEF_WHITELIST on -# shortcircuit USER_IN_ALL_SPAM_TO on -# shortcircuit SUBJECT_IN_WHITELIST on - -# the opposite; blacklisted mails can also save CPU -# -# shortcircuit USER_IN_BLACKLIST on -# shortcircuit USER_IN_BLACKLIST_TO on -# shortcircuit SUBJECT_IN_BLACKLIST on - -# if you have taken the time to correctly specify your "trusted_networks", -# this is another good way to save CPU -# -# shortcircuit ALL_TRUSTED on - -# and a well-trained bayes DB can save running rules, too -# -# shortcircuit BAYES_99 spam -# shortcircuit BAYES_00 ham - -endif # Mail::SpamAssassin::Plugin::Shortcircuit diff --git a/third-party/spamassassin/src/test/resources/docker/spamassassin/rule-update.sh b/third-party/spamassassin/src/test/resources/docker/spamassassin/rule-update.sh deleted file mode 100755 index 2867735cc4a..00000000000 --- a/third-party/spamassassin/src/test/resources/docker/spamassassin/rule-update.sh +++ /dev/null @@ -1,7 +0,0 @@ -#!/bin/bash - -while true; do - sleep 1m - su debian-spamd -c 'sa-update' && kill -HUP `cat /var/run/spamd.pid` - sleep 1d -done diff --git a/third-party/spamassassin/src/test/resources/docker/spamassassin/run.sh b/third-party/spamassassin/src/test/resources/docker/spamassassin/run.sh deleted file mode 100755 index b4a13518da3..00000000000 --- a/third-party/spamassassin/src/test/resources/docker/spamassassin/run.sh +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/bash -set -m - -/rule-update.sh & -/spamd.sh & - -pids=`jobs -p` - -wait diff --git a/third-party/spamassassin/src/test/resources/docker/spamassassin/spamd.sh b/third-party/spamassassin/src/test/resources/docker/spamassassin/spamd.sh deleted file mode 100755 index 31c22613648..00000000000 --- a/third-party/spamassassin/src/test/resources/docker/spamassassin/spamd.sh +++ /dev/null @@ -1,15 +0,0 @@ -#!/bin/sh - -echo "Run Postgres" -/usr/local/bin/docker-entrypoint.sh postgres & - -echo "Run spamd" -spamd --username debian-spamd \ - --nouser-config \ - --syslog stderr \ - --pidfile /var/run/spamd.pid \ - --helper-home-dir /var/lib/spamassassin \ - --ip-address \ - --allowed-ips 0.0.0.0/0 \ - --allow-tell \ - --debug bayes,learn