diff --git a/Jenkinsfile b/Jenkinsfile
index 2e0293778d9..20f086c84ed 100644
--- a/Jenkinsfile
+++ b/Jenkinsfile
@@ -85,7 +85,7 @@ pipeline {
stage('Build') {
steps {
echo 'Building'
- sh 'mvn -U -B -e clean install -DskipTests -T1C ${MVN_SHOW_TIMESTAMPS} ${MVN_LOCAL_REPO_OPT}'
+ sh 'mvn -U -B -e clean install -DskipTests -Djib.skip -T1C ${MVN_SHOW_TIMESTAMPS} ${MVN_LOCAL_REPO_OPT}'
}
}
diff --git a/backends-common/cassandra/src/test/java/org/apache/james/backends/cassandra/CassandraWaitStrategy.java b/backends-common/cassandra/src/test/java/org/apache/james/backends/cassandra/CassandraWaitStrategy.java
index 3e56fdf7562..f3bd034ac41 100644
--- a/backends-common/cassandra/src/test/java/org/apache/james/backends/cassandra/CassandraWaitStrategy.java
+++ b/backends-common/cassandra/src/test/java/org/apache/james/backends/cassandra/CassandraWaitStrategy.java
@@ -52,7 +52,7 @@ public void waitUntilReady(WaitStrategyTarget waitStrategyTarget) {
Unreliables.retryUntilTrue(Ints.checkedCast(timeout.getSeconds()), TimeUnit.SECONDS, () -> {
try {
ClusterFactory.createWithoutKeyspace(ClusterConfiguration.builder()
- .host(Host.from(cassandraContainer.getContainerIpAddress(), cassandraContainer.getMappedPort(9042)))
+ .host(Host.from(cassandraContainer.getHost(), cassandraContainer.getMappedPort(9042)))
.username("cassandra")
.password("cassandra")
.maxRetry(1)
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..c27957bd1ef 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));
@@ -223,7 +224,7 @@ public Host getHost() {
}
public String getIp() {
- return cassandraContainer.getContainerIpAddress();
+ return cassandraContainer.getHost();
}
public int getBindingPort() {
diff --git a/backends-common/opensearch/pom.xml b/backends-common/opensearch/pom.xml
index 55782b45bca..c7c0c196b02 100644
--- a/backends-common/opensearch/pom.xml
+++ b/backends-common/opensearch/pom.xml
@@ -74,7 +74,7 @@
org.apache.logging.log4j
log4j-to-slf4j
- 2.19.0
+ ${log4j2.version}
org.awaitility
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/backends-common/pulsar/pom.xml b/backends-common/pulsar/pom.xml
index c53d57e7f4f..c1b923c88fb 100644
--- a/backends-common/pulsar/pom.xml
+++ b/backends-common/pulsar/pom.xml
@@ -32,6 +32,8 @@
2.11.0
2.9.0
+ 0.40.17
+ 2.8.3
@@ -86,13 +88,13 @@
com.dimafeng
testcontainers-scala-pulsar_${scala.base}
- 0.40.10
+ ${testcontainer-pulsar.version}
test
com.dimafeng
testcontainers-scala-scalatest_${scala.base}
- 0.40.10
+ ${testcontainer-pulsar.version}
test
@@ -102,12 +104,12 @@
com.typesafe.akka
akka-stream-typed_${scala.base}
- 2.6.20
+ ${akka-stream.version}
com.typesafe.akka
akka-stream_${scala.base}
- 2.6.20
+ ${akka-stream.version}
javax.annotation
diff --git a/backends-common/rabbitmq/src/test/java/org/apache/james/backends/rabbitmq/DockerRabbitMQ.java b/backends-common/rabbitmq/src/test/java/org/apache/james/backends/rabbitmq/DockerRabbitMQ.java
index e776056a327..e2abe1a9ba8 100644
--- a/backends-common/rabbitmq/src/test/java/org/apache/james/backends/rabbitmq/DockerRabbitMQ.java
+++ b/backends-common/rabbitmq/src/test/java/org/apache/james/backends/rabbitmq/DockerRabbitMQ.java
@@ -109,7 +109,7 @@ private String hostName(Optional hostNamePrefix) {
}
private String getHostIp() {
- return container.getContainerIpAddress();
+ return container.getHost();
}
private Integer getPort() {
diff --git a/examples/custom-healthcheck/pom.xml b/examples/custom-healthcheck/pom.xml
index 172aa2da8c2..afb422c4ca8 100644
--- a/examples/custom-healthcheck/pom.xml
+++ b/examples/custom-healthcheck/pom.xml
@@ -39,7 +39,7 @@
io.projectreactor
reactor-core
- 3.4.18
+ 3.5.8
provided
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..51d785d1aec 100644
--- a/examples/custom-imap/pom.xml
+++ b/examples/custom-imap/pom.xml
@@ -71,7 +71,7 @@
com.google.inject
guice
- 5.1.0
+ 6.0.0
provided
@@ -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/README.md b/examples/custom-james-assembly/README.md
index c26525e053b..81b3bd65675 100644
--- a/examples/custom-james-assembly/README.md
+++ b/examples/custom-james-assembly/README.md
@@ -71,7 +71,7 @@ We do provide in this example [JIB](https://github.com/GoogleContainerTools/jib/
com.google.cloud.tools
jib-maven-plugin
- 2.7.1
+ 3.3.2
adoptopenjdk:11-jdk-hotspot
diff --git a/examples/custom-james-assembly/pom.xml b/examples/custom-james-assembly/pom.xml
index d49138accb6..374806e268e 100644
--- a/examples/custom-james-assembly/pom.xml
+++ b/examples/custom-james-assembly/pom.xml
@@ -51,10 +51,10 @@
com.google.cloud.tools
jib-maven-plugin
- 2.7.1
+ 3.3.2
- 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..5119148668f 100644
--- a/examples/metrics-graphite/pom.xml
+++ b/examples/metrics-graphite/pom.xml
@@ -31,12 +31,12 @@
io.dropwizard.metrics
metrics-graphite
- 4.2.15
+ 4.2.19
com.google.inject
guice
- 5.1.0
+ 6.0.0
provided
@@ -75,6 +75,7 @@
jar-with-dependencies
+ metrics-graphite
diff --git a/examples/pom.xml b/examples/pom.xml
index c8681fe9c2f..f4ea85b9ca0 100644
--- a/examples/pom.xml
+++ b/examples/pom.xml
@@ -73,6 +73,16 @@
+
+ io.github.git-commit-id
+ git-commit-id-maven-plugin
+
+
+ get-the-git-infos
+ none
+
+
+
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/mailbox/api/pom.xml b/mailbox/api/pom.xml
index cbd95d54286..5c8abab5695 100644
--- a/mailbox/api/pom.xml
+++ b/mailbox/api/pom.xml
@@ -76,10 +76,6 @@
com.sun.mail
javax.mail
-
- commons-io
- commons-io
-
io.projectreactor
reactor-core
diff --git a/mailbox/event/json/pom.xml b/mailbox/event/json/pom.xml
index 3f929bff4bf..6aafd95ac47 100644
--- a/mailbox/event/json/pom.xml
+++ b/mailbox/event/json/pom.xml
@@ -59,7 +59,7 @@
com.beachape
enumeratum_${scala.base}
- 1.7.0
+ 1.7.2
com.chuusai
diff --git a/mailbox/store/pom.xml b/mailbox/store/pom.xml
index 7bf36d590a3..21e04fd007d 100644
--- a/mailbox/store/pom.xml
+++ b/mailbox/store/pom.xml
@@ -90,10 +90,6 @@
com.sun.mail
javax.mail
-
- commons-io
- commons-io
-
javax.inject
javax.inject
diff --git a/mailbox/store/src/main/java/org/apache/james/mailbox/store/StoreMessageManager.java b/mailbox/store/src/main/java/org/apache/james/mailbox/store/StoreMessageManager.java
index a5fe322689d..e60a583f972 100644
--- a/mailbox/store/src/main/java/org/apache/james/mailbox/store/StoreMessageManager.java
+++ b/mailbox/store/src/main/java/org/apache/james/mailbox/store/StoreMessageManager.java
@@ -46,6 +46,8 @@
import javax.mail.Flags.Flag;
import org.apache.commons.io.input.TeeInputStream;
+import org.apache.commons.io.input.UnsynchronizedBufferedInputStream;
+import org.apache.commons.io.input.UnsynchronizedFilterInputStream;
import org.apache.commons.lang3.tuple.ImmutablePair;
import org.apache.commons.lang3.tuple.Pair;
import org.apache.james.events.EventBus;
@@ -107,7 +109,6 @@
import org.apache.james.mime4j.stream.RecursionMode;
import org.apache.james.util.io.BodyOffsetInputStream;
import org.apache.james.util.io.InputStreamConsummer;
-import org.apache.james.util.io.UnsynchronizedBufferedInputStream;
import org.apache.james.util.streams.Iterators;
import org.reactivestreams.Publisher;
@@ -358,7 +359,9 @@ public AppendResult appendMessage(InputStream msgIn, Date internalDate, final Ma
file = Files.createTempFile("imap", ".msg").toFile();
try (FileOutputStream out = new FileOutputStream(file);
BufferedOutputStream bufferedOut = new BufferedOutputStream(out);
- UnsynchronizedBufferedInputStream tmpMsgIn = new UnsynchronizedBufferedInputStream(new TeeInputStream(msgIn, bufferedOut));
+ UnsynchronizedFilterInputStream tmpMsgIn = UnsynchronizedBufferedInputStream.builder()
+ .setInputStream(new TeeInputStream(msgIn, bufferedOut))
+ .get();
BodyOffsetInputStream bIn = new BodyOffsetInputStream(tmpMsgIn)) {
Pair pair = parseProperties(bIn);
PropertyBuilder propertyBuilder = pair.getLeft();
@@ -405,8 +408,10 @@ private Mono appendMessage(Content msgIn, Date internalDate, final
}
try (InputStream contentStream = msgIn.getInputStream();
- UnsynchronizedBufferedInputStream bufferedContentStream = new UnsynchronizedBufferedInputStream(contentStream);
- BodyOffsetInputStream bIn = new BodyOffsetInputStream(bufferedContentStream)) {
+ UnsynchronizedFilterInputStream bufferedContentStream = UnsynchronizedBufferedInputStream.builder()
+ .setInputStream(contentStream)
+ .get();
+ BodyOffsetInputStream bIn = new BodyOffsetInputStream(bufferedContentStream)) {
Pair pair = parseProperties(bIn);
PropertyBuilder propertyBuilder = pair.getLeft();
HeaderImpl headers = pair.getRight();
diff --git a/mailet/amqp/pom.xml b/mailet/amqp/pom.xml
index 1f3c30a4c4b..1ef17b43e5e 100644
--- a/mailet/amqp/pom.xml
+++ b/mailet/amqp/pom.xml
@@ -83,10 +83,6 @@
com.sun.mail
javax.mail
-
- commons-io
- commons-io
-
javax.annotation
javax.annotation-api
diff --git a/mailet/crypto/pom.xml b/mailet/crypto/pom.xml
index d7b5bc4f4a1..2d75b733830 100644
--- a/mailet/crypto/pom.xml
+++ b/mailet/crypto/pom.xml
@@ -54,10 +54,6 @@
com.sun.mail
javax.mail
-
- commons-io
- commons-io
-
javax.inject
javax.inject
diff --git a/mailet/crypto/src/main/java/org/apache/james/transport/KeyStoreHolder.java b/mailet/crypto/src/main/java/org/apache/james/transport/KeyStoreHolder.java
index 0142293e1b5..7d2dc57012f 100644
--- a/mailet/crypto/src/main/java/org/apache/james/transport/KeyStoreHolder.java
+++ b/mailet/crypto/src/main/java/org/apache/james/transport/KeyStoreHolder.java
@@ -46,7 +46,7 @@
import javax.mail.MessagingException;
-import org.apache.james.util.io.UnsynchronizedBufferedInputStream;
+import org.apache.commons.io.input.UnsynchronizedBufferedInputStream;
import org.bouncycastle.cert.jcajce.JcaCertStoreBuilder;
import org.bouncycastle.cert.selector.X509CertificateHolderSelector;
import org.bouncycastle.cert.selector.jcajce.JcaX509CertSelectorConverter;
@@ -101,7 +101,10 @@ public KeyStoreHolder(String keyStoreFileName, String keyStorePassword, String k
}
keyStore = KeyStore.getInstance(keyStoreType);
- keyStore.load(new UnsynchronizedBufferedInputStream(new FileInputStream(keyStoreFileName)), keyStorePassword.toCharArray());
+ keyStore.load(UnsynchronizedBufferedInputStream
+ .builder()
+ .setInputStream(new FileInputStream(keyStoreFileName))
+ .get(), keyStorePassword.toCharArray());
if (keyStore.size() == 0) {
throw new KeyStoreException("The keystore must be not empty");
}
diff --git a/mailet/crypto/src/main/java/org/apache/james/transport/SMIMEKeyHolder.java b/mailet/crypto/src/main/java/org/apache/james/transport/SMIMEKeyHolder.java
index 5bb18304352..020437a5d61 100644
--- a/mailet/crypto/src/main/java/org/apache/james/transport/SMIMEKeyHolder.java
+++ b/mailet/crypto/src/main/java/org/apache/james/transport/SMIMEKeyHolder.java
@@ -45,7 +45,7 @@
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
-import org.apache.james.util.io.UnsynchronizedBufferedInputStream;
+import org.apache.commons.io.input.UnsynchronizedBufferedInputStream;
import org.bouncycastle.cert.jcajce.JcaCertStore;
import org.bouncycastle.cms.SignerInfoGenerator;
import org.bouncycastle.cms.jcajce.JcaSimpleSignerInfoGeneratorBuilder;
@@ -128,7 +128,11 @@ public SMIMEKeyHolder(String keyStoreFileName, String keyStorePassword, String k
}
KeyStore keyStore = KeyStore.getInstance(keyStoreType);
- keyStore.load(new UnsynchronizedBufferedInputStream(new FileInputStream(keyStoreFileName)), keyStorePassword.toCharArray());
+
+ keyStore.load(UnsynchronizedBufferedInputStream.builder()
+ .setInputStream(new FileInputStream(keyStoreFileName))
+ .get(),
+ keyStorePassword.toCharArray());
Enumeration aliases = keyStore.aliases();
if (keyAlias == null) {
diff --git a/mailet/icalendar/pom.xml b/mailet/icalendar/pom.xml
index 10a17b255b7..0ac4dd410d2 100644
--- a/mailet/icalendar/pom.xml
+++ b/mailet/icalendar/pom.xml
@@ -64,11 +64,6 @@
com.google.guava
guava
-
- commons-io
- commons-io
- test
-
net.javacrumbs.json-unit
json-unit-assertj
diff --git a/mailet/mailetdocs-maven-plugin/pom.xml b/mailet/mailetdocs-maven-plugin/pom.xml
index 332e0290c4d..e4300c1dcd0 100644
--- a/mailet/mailetdocs-maven-plugin/pom.xml
+++ b/mailet/mailetdocs-maven-plugin/pom.xml
@@ -34,7 +34,9 @@
information available from implementation source.
http://james.apache.org/mailet/maven-mailetdocs-plugin/
2008
-
+
+ 1.12.0
+
${james.groupId}
@@ -64,12 +66,12 @@
org.apache.maven.doxia
doxia-core
- 1.11.1
+ ${doxia.version}
org.apache.maven.doxia
doxia-sink-api
- 1.11.1
+ ${doxia.version}
org.apache.maven.plugin-tools
diff --git a/mailet/standard/pom.xml b/mailet/standard/pom.xml
index 3b3d09684c9..b2104cc5693 100644
--- a/mailet/standard/pom.xml
+++ b/mailet/standard/pom.xml
@@ -76,10 +76,6 @@
com.sun.mail
javax.mail
-
- commons-io
- commons-io
-
javax.annotation
javax.annotation-api
diff --git a/mailet/standard/src/main/java/org/apache/james/transport/mailets/RecoverAttachment.java b/mailet/standard/src/main/java/org/apache/james/transport/mailets/RecoverAttachment.java
index 87a898bc8f9..1c5a3d862b8 100644
--- a/mailet/standard/src/main/java/org/apache/james/transport/mailets/RecoverAttachment.java
+++ b/mailet/standard/src/main/java/org/apache/james/transport/mailets/RecoverAttachment.java
@@ -30,7 +30,7 @@
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
-import org.apache.james.util.io.UnsynchronizedBufferedInputStream;
+import org.apache.commons.io.input.UnsynchronizedBufferedInputStream;
import org.apache.mailet.AttributeName;
import org.apache.mailet.AttributeUtils;
import org.apache.mailet.AttributeValue;
@@ -119,8 +119,9 @@ private void processAttachment(Mail mail, Map> attach
continue;
}
byte[] bytes = (byte[]) i.next().getValue();
- InputStream is = new UnsynchronizedBufferedInputStream(
- new ByteArrayInputStream(bytes));
+ InputStream is = UnsynchronizedBufferedInputStream.builder()
+ .setInputStream(new ByteArrayInputStream(bytes))
+ .get();
MimeBodyPart p = new MimeBodyPart(is);
if (!(message.isMimeType("multipart/*") && (message
.getContent() instanceof MimeMultipart))) {
diff --git a/pom.xml b/pom.xml
index bbea10ea761..2dbfa527efd 100644
--- a/pom.xml
+++ b/pom.xml
@@ -598,51 +598,51 @@
org.apache.james
${james.groupId}.protocols
- 5.17.3
+ 5.18.2
0.8.9
3.2.0
10.14.2.0
- 2.19.0
+ 2.20.0
1
javax.activation
activation
0.8
4.3.25.RELEASE
- 2.27.1
+ 2.29.0
1.0.3
1.5.4
1.1.1
- 2.0.6
+ 2.0.7
3.5.2
- 5.8.2
- 1.8.2
- 5.8.2
+ 5.9.3
+ 1.9.3
+ 5.9.3
1.3.4
- 4.21
+ 4.23
4.1.94.Final
2.4.0
1.6.4
- 2.14.1
- 2.14.1
- 11.10
+ 2.15.2
+ 2.15.2
+ 12.4
3.8.0
0.11.5
- 4.2.15
- 1.17.6
+ 4.2.19
+ 1.18.3
2.2.1
6.0.0-RC3
- 31.1-jre
+ 32.1.1-jre
1.0.0
- 4.5.13
+ 4.5.14
3.0-alpha-1
- 3.6.4
- 3.8.5
+ 3.9.0
+ 3.9.3
3.1.0
- 3.0
+ 3.1.1
2.0.3
javax.activation
activation
@@ -650,19 +650,20 @@
2.3.1
3.6.2
1.9.3
- 5.1.0
- 1.4.5
- 1.7.0
+ 6.0.0
+ 1.4.8
+ 1.9.0
6.2.4.RELEASE
1.70
2.13
- ${scala.base}.10
+ ${scala.base}.11
5.0.0
none
- 4.8.0
+ 5.2.0
0.8.9
+ 2.38.0
@@ -2122,7 +2123,7 @@
com.github.ben-manes.caffeine
caffeine
- 3.1.2
+ 3.1.6
com.github.dpaukov
@@ -2196,7 +2197,7 @@
com.jayway.jsonpath
json-path
- 2.7.0
+ 2.8.0
com.jcraft
@@ -2252,12 +2253,12 @@
com.typesafe.play
play-json_${scala.base}
- 2.9.3
+ 2.9.4
com.unboundid
unboundid-ldapsdk
- 6.0.7
+ 6.0.9
commons-beanutils
@@ -2278,7 +2279,7 @@
commons-daemon
commons-daemon
- 1.3.3
+ 1.3.4
commons-dbcp
@@ -2294,7 +2295,7 @@
commons-io
commons-io
- 2.11.0
+ 2.13.0
commons-net
@@ -2314,7 +2315,7 @@
eu.timepit
refined_${scala.base}
- 0.10.3
+ 0.11.0
io.cucumber
@@ -2354,7 +2355,7 @@
io.github.hakky54
sslcontext-kickstart-for-pem
- 7.4.7
+ 8.1.2
io.github.openfeign
@@ -2436,7 +2437,7 @@
io.projectreactor
reactor-bom
- 2022.0.8
+ 2022.0.9
pom
import
@@ -2453,7 +2454,7 @@
io.rest-assured
rest-assured
- 5.3.0
+ 5.3.1
commons-logging
@@ -2496,15 +2497,20 @@
jaxb-api
${jaxb.version}
+
+ net.javacrumbs.json-unit
+ json-unit
+ ${javacrumbs.json-unit.version}
+
net.javacrumbs.json-unit
json-unit-assertj
- 2.36.0
+ ${javacrumbs.json-unit.version}
nl.jqno.equalsverifier
equalsverifier
- 3.10.1
+ 3.15
org.apache.activemq
@@ -2541,7 +2547,7 @@
org.apache.ant
ant
- 1.10.12
+ 1.10.13
org.apache.commons
@@ -2551,12 +2557,12 @@
org.apache.commons
commons-compress
- 1.22
+ 1.23.0
org.apache.commons
commons-configuration2
- 2.8.0
+ 2.9.0
commons-logging
@@ -2679,7 +2685,7 @@
org.apache.pdfbox
pdfbox
- 2.0.27
+ 2.0.29
commons-logging
@@ -2705,7 +2711,7 @@
org.assertj
assertj-core
- 3.23.1
+ 3.24.2
org.awaitility
@@ -2741,7 +2747,7 @@
org.jsoup
jsoup
- 1.15.3
+ 1.16.1
org.julienrf
@@ -2781,7 +2787,7 @@
org.mock-server
mockserver-netty
- 5.14.0
+ 5.15.0
io.netty
@@ -2817,7 +2823,7 @@
org.scalatest
scalatest_${scala.base}
- 3.2.14
+ 3.2.16
org.slf4j
@@ -2949,15 +2955,10 @@
${project.version}
-
- com.coderplus.maven.plugins
- copy-rename-maven-plugin
- 1.0
-
com.github.ekryd.sortpom
sortpom-maven-plugin
- 3.1.2
+ 3.2.1
false
false
@@ -2999,7 +3000,7 @@
com.google.cloud.tools
jib-maven-plugin
- 3.2.1
+ 3.3.2
io.github.evis
@@ -3034,7 +3035,7 @@
org.scalatest
scalatest-maven-plugin
- 2.0.2
+ 2.2.0
${project.build.directory}/surefire-reports
.
@@ -3075,7 +3076,7 @@
org.scalameta
semanticdb-scalac_${scala.version}
- 4.6.0
+ 4.8.4
@@ -3105,7 +3106,7 @@
org.apache.maven.plugins
maven-assembly-plugin
- 3.1.1
+ 3.6.0
org.apache.maven.plugins
@@ -3121,17 +3122,12 @@
org.apache.maven.plugins
maven-checkstyle-plugin
- 3.1.2
-
-
- org.apache.maven.plugins
- maven-clean-plugin
- 3.1.0
+ 3.3.0
org.apache.maven.plugins
maven-compiler-plugin
- 3.8.1
+ 3.11.0
true
${target.jdk}
@@ -3191,15 +3187,10 @@
-
- org.apache.maven.plugins
- maven-eclipse-plugin
- 2.10
-
org.apache.maven.plugins
maven-jar-plugin
- 3.2.2
+ 3.3.0
org.apache.maven.plugins
@@ -3229,42 +3220,16 @@
-
- org.apache.maven.plugins
- maven-gpg-plugin
- 1.6
-
org.apache.maven.plugins
maven-jxr-plugin
- 3.2.0
-
- true
-
+ 3.3.0
org.apache.maven.plugins
maven-plugin-plugin
3.6.4
-
- org.apache.maven.plugins
- maven-pmd-plugin
- 3.15.0
-
- true
- ${target.jdk}
-
- /rulesets/basic.xml
- /rulesets/unusedcode.xml
- /rulesets/imports.xml
-
- xml
- true
- utf-8
- 100
-
-
org.apache.maven.plugins
maven-project-info-reports-plugin
@@ -3308,7 +3273,7 @@
org.apache.maven.wagon
wagon-ssh
- 3.5.2
+ 3.5.3
@@ -3323,7 +3288,7 @@
org.apache.maven.plugins
maven-surefire-plugin
- 2.22.2
+ 3.1.2
@@ -3342,7 +3307,7 @@
org.apache.maven.plugins
maven-surefire-report-plugin
- 2.22.2
+ 3.1.2
true
@@ -3409,15 +3374,10 @@
javacc-maven-plugin
2.6
-
- org.codehaus.mojo
- taglist-maven-plugin
- 3.0.0
-
org.codehaus.mojo
versions-maven-plugin
- 2.11.0
+ 2.16.0
org.eclipse.m2e
@@ -3493,9 +3453,9 @@
- pl.project13.maven
- git-commit-id-plugin
- 4.9.10
+ io.github.git-commit-id
+ git-commit-id-maven-plugin
+ 6.0.0
@@ -3600,7 +3560,7 @@
org.apache.maven.doxia
doxia-module-markdown
- 1.9.1
+ 1.12.0
@@ -3618,7 +3578,7 @@
com.puppycrawl.tools
checkstyle
- 10.3.4
+ 10.12.1
@@ -3632,8 +3592,8 @@
- pl.project13.maven
- git-commit-id-plugin
+ io.github.git-commit-id
+ git-commit-id-maven-plugin
${project.basedir}/.git
git
@@ -3665,6 +3625,19 @@
+
+ org.apache.maven.plugins
+ maven-surefire-report-plugin
+
+
+ build-surefire-report
+
+ report-only
+
+ post-integration-test
+
+
+
@@ -3698,13 +3671,6 @@
org.apache.rat
apache-rat-plugin
-
org.apache.maven.plugins
maven-javadoc-plugin
@@ -3783,7 +3749,7 @@
org.apache.maven.plugins
maven-surefire-plugin
- 2.22.2
+ 3.1.2
unstable
@@ -3971,8 +3937,8 @@
- pl.project13.maven
- git-commit-id-plugin
+ io.github.git-commit-id
+ git-commit-id-maven-plugin
get-the-git-infos
diff --git a/protocols/imap/pom.xml b/protocols/imap/pom.xml
index b70e5523481..b11ec65fcc6 100644
--- a/protocols/imap/pom.xml
+++ b/protocols/imap/pom.xml
@@ -110,7 +110,7 @@
it.unimi.dsi
fastutil-core
- 8.5.9
+ 8.5.12
org.apache.commons
diff --git a/protocols/managesieve/pom.xml b/protocols/managesieve/pom.xml
index 0b2b1092ea2..d7616bfbbf5 100644
--- a/protocols/managesieve/pom.xml
+++ b/protocols/managesieve/pom.xml
@@ -50,10 +50,6 @@
com.google.guava
guava
-
- commons-io
- commons-io
-
javax.annotation
javax.annotation-api
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..90784e8fd33 100644
--- a/server/apps/cassandra-app/pom.xml
+++ b/server/apps/cassandra-app/pom.xml
@@ -300,10 +300,10 @@
package
- https://github.com/glowroot/glowroot/releases/download/v0.13.4/glowroot-0.13.4-dist.zip
+ https://github.com/glowroot/glowroot/releases/download/v0.14.0/glowroot-0.14.0-dist.zip
true
${project.build.directory}
- 93d472281a67ab8404033a88280c23c9
+ 16073f10204751cd71d3b4ea93be2649
@@ -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..313c0c9b790 100644
--- a/server/apps/distributed-app/pom.xml
+++ b/server/apps/distributed-app/pom.xml
@@ -344,10 +344,10 @@
package
- https://github.com/glowroot/glowroot/releases/download/v0.13.6/glowroot-0.13.6-dist.zip
+ https://github.com/glowroot/glowroot/releases/download/v0.14.0/glowroot-0.14.0-dist.zip
true
${project.build.directory}
- f9026dbab1fbade067ca549913802fcc
+ 16073f10204751cd71d3b4ea93be2649
@@ -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..ad2ec4df8b9 100644
--- a/server/apps/distributed-pop3-app/pom.xml
+++ b/server/apps/distributed-pop3-app/pom.xml
@@ -352,10 +352,10 @@
package
- https://github.com/glowroot/glowroot/releases/download/v0.13.6/glowroot-0.13.6-dist.zip
+ https://github.com/glowroot/glowroot/releases/download/v0.14.0/glowroot-0.14.0-dist.zip
true
${project.build.directory}
- f9026dbab1fbade067ca549913802fcc
+ 16073f10204751cd71d3b4ea93be2649
@@ -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..5d8e063e747 100644
--- a/server/apps/jpa-app/pom.xml
+++ b/server/apps/jpa-app/pom.xml
@@ -233,10 +233,10 @@
package
- https://github.com/glowroot/glowroot/releases/download/v0.13.6/glowroot-0.13.6-dist.zip
+ https://github.com/glowroot/glowroot/releases/download/v0.14.0/glowroot-0.14.0-dist.zip
true
${project.build.directory}
- f9026dbab1fbade067ca549913802fcc
+ 16073f10204751cd71d3b4ea93be2649
@@ -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..3f9cae5ecaa 100644
--- a/server/apps/jpa-smtp-app/pom.xml
+++ b/server/apps/jpa-smtp-app/pom.xml
@@ -204,10 +204,10 @@
package
- https://github.com/glowroot/glowroot/releases/download/v0.13.6/glowroot-0.13.6-dist.zip
+ https://github.com/glowroot/glowroot/releases/download/v0.14.0/glowroot-0.14.0-dist.zip
true
${project.build.directory}
- f9026dbab1fbade067ca549913802fcc
+ 16073f10204751cd71d3b4ea93be2649
@@ -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..bbc4b384f0b 100644
--- a/server/apps/memory-app/pom.xml
+++ b/server/apps/memory-app/pom.xml
@@ -232,10 +232,10 @@
package
- https://github.com/glowroot/glowroot/releases/download/v0.13.6/glowroot-0.13.6-dist.zip
+ https://github.com/glowroot/glowroot/releases/download/v0.14.0/glowroot-0.14.0-dist.zip
true
${project.build.directory}
- f9026dbab1fbade067ca549913802fcc
+ 16073f10204751cd71d3b4ea93be2649
@@ -267,7 +267,7 @@
jib-maven-plugin
- eclipse-temurin:11-jre-focal
+ eclipse-temurin:11-jre-jammy
apache/james
diff --git a/server/apps/webadmin-cli/pom.xml b/server/apps/webadmin-cli/pom.xml
index b794c650a4d..14ef613d610 100644
--- a/server/apps/webadmin-cli/pom.xml
+++ b/server/apps/webadmin-cli/pom.xml
@@ -67,10 +67,6 @@
testing-base
test
-
- commons-io
- commons-io
-
info.picocli
picocli
diff --git a/server/blob/blob-aes/pom.xml b/server/blob/blob-aes/pom.xml
index f24a3cbf25a..3de703d6afe 100644
--- a/server/blob/blob-aes/pom.xml
+++ b/server/blob/blob-aes/pom.xml
@@ -62,10 +62,6 @@
com.google.guava
guava
-
- commons-io
- commons-io
-
io.projectreactor
reactor-core
diff --git a/server/blob/blob-api/pom.xml b/server/blob/blob-api/pom.xml
index 5613a52e172..4e15cfebd94 100644
--- a/server/blob/blob-api/pom.xml
+++ b/server/blob/blob-api/pom.xml
@@ -60,11 +60,6 @@
com.google.guava
guava
-
- commons-io
- commons-io
- test
-
io.projectreactor.addons
reactor-extra
diff --git a/server/blob/blob-s3/pom.xml b/server/blob/blob-s3/pom.xml
index 951301625f1..668ec999ca8 100644
--- a/server/blob/blob-s3/pom.xml
+++ b/server/blob/blob-s3/pom.xml
@@ -33,7 +33,7 @@
Apache James :: Server :: Blob :: S3
- 2.20.98
+ 2.20.103
@@ -69,10 +69,6 @@
testing-base
test
-
- commons-io
- commons-io
-
io.netty
netty-codec
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/container/core/src/main/java/org/apache/james/server/core/MimeMessageInputStreamSource.java b/server/container/core/src/main/java/org/apache/james/server/core/MimeMessageInputStreamSource.java
index 4ba872108da..58f4d4e1c6f 100644
--- a/server/container/core/src/main/java/org/apache/james/server/core/MimeMessageInputStreamSource.java
+++ b/server/container/core/src/main/java/org/apache/james/server/core/MimeMessageInputStreamSource.java
@@ -33,10 +33,10 @@
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
+import org.apache.commons.io.input.UnsynchronizedBufferedInputStream;
import org.apache.commons.io.output.DeferredFileOutputStream;
import org.apache.james.lifecycle.api.Disposable;
import org.apache.james.util.SizeFormat;
-import org.apache.james.util.io.UnsynchronizedBufferedInputStream;
/**
* Takes an input stream and creates a repeatable input stream source for a
@@ -186,7 +186,10 @@ public InputStream getInputStream() throws IOException {
if (getResource().getOut().isInMemory()) {
return new ByteArrayInputStream(getResource().getOut().getData());
} else {
- InputStream in = new UnsynchronizedBufferedInputStream(new FileInputStream(getResource().getOut().getFile()), 2048);
+ InputStream in = UnsynchronizedBufferedInputStream.builder()
+ .setInputStream(new FileInputStream(getResource().getOut().getFile()))
+ .setBufferSize(2048)
+ .get();
getResource().streams.add(in);
return in;
}
diff --git a/server/container/filesystem-api/pom.xml b/server/container/filesystem-api/pom.xml
index 8a9b8c49ac9..45ddafe090d 100644
--- a/server/container/filesystem-api/pom.xml
+++ b/server/container/filesystem-api/pom.xml
@@ -43,10 +43,6 @@
spark-core
test
-
- commons-io
- commons-io
-
pl.pragmatists
JUnitParams
diff --git a/server/container/filesystem-api/src/test/java/org/apache/james/filesystem/api/AbstractFileSystemTest.java b/server/container/filesystem-api/src/test/java/org/apache/james/filesystem/api/AbstractFileSystemTest.java
index 34972dcad5f..5ba49f7723e 100644
--- a/server/container/filesystem-api/src/test/java/org/apache/james/filesystem/api/AbstractFileSystemTest.java
+++ b/server/container/filesystem-api/src/test/java/org/apache/james/filesystem/api/AbstractFileSystemTest.java
@@ -22,12 +22,11 @@
import java.io.File;
import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
-import org.apache.commons.io.FileUtils;
-import org.apache.commons.io.IOUtils;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
@@ -74,7 +73,9 @@ public void setUp() throws Exception {
private void createSubFolderWithAFileIn(String folderName, String fileName, String fileContent) throws IOException {
File folder = tmpFolder.newFolder(folderName);
File file = new File(folder.getAbsolutePath() + "/" + fileName);
- FileUtils.writeStringToFile(file, fileContent, StandardCharsets.UTF_8);
+ try (var out = new FileOutputStream(file)) {
+ out.write(fileContent.getBytes(StandardCharsets.UTF_8));
+ }
}
@After
@@ -185,7 +186,7 @@ public static Object[] provide() {
public final void availableInputStreamShouldReturnANonEmptyStream(String url) throws Exception {
url = replacePort(url);
try (InputStream inputStream = fileSystem.getResource(url)) {
- assertThat(IOUtils.toByteArray(inputStream).length).isGreaterThan(0);
+ assertThat(inputStream.readAllBytes().length).isGreaterThan(0);
}
}
@@ -231,7 +232,7 @@ public final void createdFilesShouldExistWhenAccessedWithTwoSlashes(String name,
public final void createdFilesAsInputStreamShouldBeAvailable(String name, String extension) throws Exception {
File temp = createTempFile(name, extension);
try (InputStream inputStream = fileSystem.getResource("file:" + temp.getAbsolutePath())) {
- assertThat(IOUtils.toString(inputStream, StandardCharsets.UTF_8)).isEqualTo("content");
+ assertThat(new String(inputStream.readAllBytes(), StandardCharsets.UTF_8)).isEqualTo("content");
} finally {
temp.delete();
}
@@ -242,7 +243,7 @@ public final void createdFilesAsInputStreamShouldBeAvailable(String name, String
public final void createdFilesAsInputStreamShouldBeAvailableWhenAccessedWithTwoSlashes(String name, String extension) throws Exception {
File temp = createTempFile(name, extension);
try (InputStream inputStream = fileSystem.getResource("file://" + temp.getAbsolutePath())) {
- assertThat(IOUtils.toString(inputStream, StandardCharsets.UTF_8)).isEqualTo("content");
+ assertThat(new String(inputStream.readAllBytes(), StandardCharsets.UTF_8)).isEqualTo("content");
} finally {
temp.delete();
}
@@ -250,7 +251,9 @@ public final void createdFilesAsInputStreamShouldBeAvailableWhenAccessedWithTwoS
private File createTempFile(String name, String extension) throws IOException {
File temp = File.createTempFile(name, extension);
- FileUtils.write(temp, "content", StandardCharsets.UTF_8);
+ try (var out = new FileOutputStream(temp)) {
+ out.write("content".getBytes(StandardCharsets.UTF_8));
+ }
return temp;
}
diff --git a/server/container/util/pom.xml b/server/container/util/pom.xml
index 979d6fde256..d57bb50eb98 100644
--- a/server/container/util/pom.xml
+++ b/server/container/util/pom.xml
@@ -55,10 +55,6 @@
com.sun.mail
javax.mail
-
- commons-io
- commons-io
-
io.projectreactor
reactor-core
diff --git a/server/container/util/src/main/java/org/apache/james/util/io/UnsynchronizedBufferedInputStream.java b/server/container/util/src/main/java/org/apache/james/util/io/UnsynchronizedBufferedInputStream.java
deleted file mode 100644
index cab709cc83b..00000000000
--- a/server/container/util/src/main/java/org/apache/james/util/io/UnsynchronizedBufferedInputStream.java
+++ /dev/null
@@ -1,238 +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.util.io;
-
-import java.io.FilterInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-
-/**
- * Copied from {@link java.io.BufferedInputStream} with the following modifications:
- * - Removal of 'synchronized' keyword
- * - Removal of 'volatile' keyword
- * - Removal of Unsafe usages
- *
- * See https://issues.apache.org/jira/projects/IO/issues/IO-786 for rationals
- */
-public class UnsynchronizedBufferedInputStream extends FilterInputStream {
- private static int DEFAULT_BUFFER_SIZE = 8192;
- private static int MAX_BUFFER_SIZE = 2147483639;
- protected byte[] buf;
- protected int count;
- protected int pos;
- protected int markpos;
- protected int marklimit;
-
- private InputStream getInIfOpen() throws IOException {
- InputStream input = this.in;
- if (input == null) {
- throw new IOException("Stream closed");
- } else {
- return input;
- }
- }
-
- private byte[] getBufIfOpen() throws IOException {
- byte[] buffer = this.buf;
- if (buffer == null) {
- throw new IOException("Stream closed");
- } else {
- return buffer;
- }
- }
-
- public UnsynchronizedBufferedInputStream(InputStream in) {
- this(in, DEFAULT_BUFFER_SIZE);
- }
-
- public UnsynchronizedBufferedInputStream(InputStream in, int size) {
- super(in);
- this.markpos = -1;
- if (size <= 0) {
- throw new IllegalArgumentException("Buffer size <= 0");
- } else {
- this.buf = new byte[size];
- }
- }
-
- private void fill() throws IOException {
- byte[] buffer = this.getBufIfOpen();
- int nsz;
- if (this.markpos < 0) {
- this.pos = 0;
- } else if (this.pos >= buffer.length) {
- if (this.markpos > 0) {
- nsz = this.pos - this.markpos;
- System.arraycopy(buffer, this.markpos, buffer, 0, nsz);
- this.pos = nsz;
- this.markpos = 0;
- } else if (buffer.length >= this.marklimit) {
- this.markpos = -1;
- this.pos = 0;
- } else {
- if (buffer.length >= MAX_BUFFER_SIZE) {
- throw new OutOfMemoryError("Required array size too large");
- }
-
- nsz = this.pos <= MAX_BUFFER_SIZE - this.pos ? this.pos * 2 : MAX_BUFFER_SIZE;
- if (nsz > this.marklimit) {
- nsz = this.marklimit;
- }
-
- byte[] nbuf = new byte[nsz];
- System.arraycopy(buffer, 0, nbuf, 0, this.pos);
-
- buffer = nbuf;
- }
- }
-
- this.count = this.pos;
- nsz = this.getInIfOpen().read(buffer, this.pos, buffer.length - this.pos);
- if (nsz > 0) {
- this.count = nsz + this.pos;
- }
-
- }
-
- public int read() throws IOException {
- if (this.pos >= this.count) {
- this.fill();
- if (this.pos >= this.count) {
- return -1;
- }
- }
-
- return this.getBufIfOpen()[this.pos++] & 255;
- }
-
- private int read1(byte[] b, int off, int len) throws IOException {
- int avail = this.count - this.pos;
- if (avail <= 0) {
- if (len >= this.getBufIfOpen().length && this.markpos < 0) {
- return this.getInIfOpen().read(b, off, len);
- }
-
- this.fill();
- avail = this.count - this.pos;
- if (avail <= 0) {
- return -1;
- }
- }
-
- int cnt = avail < len ? avail : len;
- System.arraycopy(this.getBufIfOpen(), this.pos, b, off, cnt);
- this.pos += cnt;
- return cnt;
- }
-
- public int read(byte[] b, int off, int len) throws IOException {
- this.getBufIfOpen();
- if ((off | len | off + len | b.length - (off + len)) < 0) {
- throw new IndexOutOfBoundsException();
- } else if (len == 0) {
- return 0;
- } else {
- int n = 0;
-
- InputStream input;
- do {
- int nread = this.read1(b, off + n, len - n);
- if (nread <= 0) {
- return n == 0 ? nread : n;
- }
-
- n += nread;
- if (n >= len) {
- return n;
- }
-
- input = this.in;
- } while (input == null || input.available() > 0);
-
- return n;
- }
- }
-
- public long skip(long n) throws IOException {
- this.getBufIfOpen();
- if (n <= 0L) {
- return 0L;
- } else {
- long avail = (long)(this.count - this.pos);
- if (avail <= 0L) {
- if (this.markpos < 0) {
- return this.getInIfOpen().skip(n);
- }
-
- this.fill();
- avail = (long)(this.count - this.pos);
- if (avail <= 0L) {
- return 0L;
- }
- }
-
- long skipped = avail < n ? avail : n;
- this.pos = (int)((long)this.pos + skipped);
- return skipped;
- }
- }
-
- public int available() throws IOException {
- int n = this.count - this.pos;
- int avail = this.getInIfOpen().available();
- return n > 2147483647 - avail ? 2147483647 : n + avail;
- }
-
- public void mark(int readlimit) {
- this.marklimit = readlimit;
- this.markpos = this.pos;
- }
-
- public void reset() throws IOException {
- this.getBufIfOpen();
- if (this.markpos < 0) {
- throw new IOException("Resetting to invalid mark");
- } else {
- this.pos = this.markpos;
- }
- }
-
- public boolean markSupported() {
- return true;
- }
-
- public void close() throws IOException {
- while (true) {
- byte[] buffer;
- if ((buffer = this.buf) != null) {
-
- InputStream input = this.in;
- this.in = null;
- if (input != null) {
- input.close();
- }
-
- return;
- }
-
- return;
- }
- }
-}
diff --git a/server/mailet/integration-testing/pom.xml b/server/mailet/integration-testing/pom.xml
index 521a3e5daeb..bde166d48a1 100644
--- a/server/mailet/integration-testing/pom.xml
+++ b/server/mailet/integration-testing/pom.xml
@@ -32,6 +32,10 @@
Apache James :: Server :: Mailet :: Integration Testing
+
+ 2.9.1
+
+
${james.groupId}
@@ -138,12 +142,12 @@
org.xmlunit
xmlunit-core
- 2.9.0
+ ${xmlunit.version}
org.xmlunit
xmlunit-matchers
- 2.9.0
+ ${xmlunit.version}
diff --git a/server/mailet/mailets/pom.xml b/server/mailet/mailets/pom.xml
index b415acb5624..16cdc776f59 100644
--- a/server/mailet/mailets/pom.xml
+++ b/server/mailet/mailets/pom.xml
@@ -33,7 +33,7 @@
Apache James :: Server :: Mailets
- 4.17.0
+ 4.20.0
diff --git a/server/mailet/mock-smtp-server/pom.xml b/server/mailet/mock-smtp-server/pom.xml
index d868aff45b0..a583247b65b 100644
--- a/server/mailet/mock-smtp-server/pom.xml
+++ b/server/mailet/mock-smtp-server/pom.xml
@@ -121,10 +121,9 @@
com.google.cloud.tools
jib-maven-plugin
- 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/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 10d8c064d21..a03e2edc84b 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
@@ -175,7 +175,6 @@
org.apache.maven.plugins
maven-surefire-plugin
- 2.22.2
org.apache.james.junit.categories.Unstable
diff --git a/server/protocols/jmap-draft/pom.xml b/server/protocols/jmap-draft/pom.xml
index d6f1525d758..00e4378c284 100644
--- a/server/protocols/jmap-draft/pom.xml
+++ b/server/protocols/jmap-draft/pom.xml
@@ -266,7 +266,7 @@
org.jgrapht
jgrapht-core
- 1.5.1
+ 1.5.2
org.jsoup
diff --git a/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/crypto/SecurityKeyLoader.java b/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/crypto/SecurityKeyLoader.java
index e1b4660591e..b3fd1022002 100644
--- a/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/crypto/SecurityKeyLoader.java
+++ b/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/crypto/SecurityKeyLoader.java
@@ -40,9 +40,9 @@
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Preconditions;
-import nl.altindag.ssl.exception.CertificateParseException;
+import nl.altindag.ssl.pem.exception.PemParseException;
+import nl.altindag.ssl.pem.util.PemUtils;
import nl.altindag.ssl.util.KeyStoreUtils;
-import nl.altindag.ssl.util.PemUtils;
public class SecurityKeyLoader {
private static final String ALIAS = "james";
@@ -104,7 +104,7 @@ private PublicKey loadPublicKey() throws IOException {
fileSystem.getResource(jmapDraftConfiguration.getCertificates().get()))
.get(0);
return certificate.getPublicKey();
- } catch (CertificateParseException e) {
+ } catch (PemParseException e) {
String publicKeyAsString = IOUtils.toString(fileSystem.getResource(jmapDraftConfiguration.getCertificates().get()), StandardCharsets.US_ASCII);
return new PublicKeyReader()
.fromPEM(publicKeyAsString)
diff --git a/server/protocols/jmap-rfc-8621-integration-tests/distributed-jmap-rfc-8621-integration-tests/pom.xml b/server/protocols/jmap-rfc-8621-integration-tests/distributed-jmap-rfc-8621-integration-tests/pom.xml
index 7a3ed08c214..f82e7570fee 100644
--- a/server/protocols/jmap-rfc-8621-integration-tests/distributed-jmap-rfc-8621-integration-tests/pom.xml
+++ b/server/protocols/jmap-rfc-8621-integration-tests/distributed-jmap-rfc-8621-integration-tests/pom.xml
@@ -146,7 +146,6 @@
org.apache.maven.plugins
maven-surefire-plugin
- 2.22.2
unstable
diff --git a/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/pom.xml b/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/pom.xml
index ef6b172cbeb..35d750d7b32 100644
--- a/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/pom.xml
+++ b/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/pom.xml
@@ -65,7 +65,7 @@
com.softwaremill.sttp.client3
okhttp-backend_${scala.base}
- 3.6.2
+ 3.8.16
com.typesafe.play
diff --git a/server/protocols/jmap-rfc-8621/pom.xml b/server/protocols/jmap-rfc-8621/pom.xml
index c5594234231..72fd65a56b9 100644
--- a/server/protocols/jmap-rfc-8621/pom.xml
+++ b/server/protocols/jmap-rfc-8621/pom.xml
@@ -185,7 +185,7 @@
org.typelevel
cats-core_${scala.base}
- 2.8.0
+ 2.9.0
diff --git a/server/protocols/jwt/pom.xml b/server/protocols/jwt/pom.xml
index d664bcc3f57..4ba4aa91446 100644
--- a/server/protocols/jwt/pom.xml
+++ b/server/protocols/jwt/pom.xml
@@ -40,7 +40,7 @@
com.auth0
jwks-rsa
- 0.21.1
+ 0.22.0
com.fasterxml.jackson.core
diff --git a/server/protocols/protocols-imap4/pom.xml b/server/protocols/protocols-imap4/pom.xml
index dc104407941..4c3b829372a 100644
--- a/server/protocols/protocols-imap4/pom.xml
+++ b/server/protocols/protocols-imap4/pom.xml
@@ -122,10 +122,6 @@
com.jcraft
jzlib
-
- commons-io
- commons-io
-
io.github.hakky54
sslcontext-kickstart-for-pem
diff --git a/server/protocols/protocols-imap4/src/test/java/org/apache/james/imapserver/netty/IMAPServerTest.java b/server/protocols/protocols-imap4/src/test/java/org/apache/james/imapserver/netty/IMAPServerTest.java
index 551e0e34326..c05aa98d88c 100644
--- a/server/protocols/protocols-imap4/src/test/java/org/apache/james/imapserver/netty/IMAPServerTest.java
+++ b/server/protocols/protocols-imap4/src/test/java/org/apache/james/imapserver/netty/IMAPServerTest.java
@@ -124,7 +124,7 @@
import io.netty.handler.codec.compression.ZlibWrapper;
import io.netty.handler.ssl.SslContextBuilder;
import nl.altindag.ssl.exception.GenericKeyStoreException;
-import nl.altindag.ssl.exception.PrivateKeyParseException;
+import nl.altindag.ssl.pem.exception.PrivateKeyParseException;
import reactor.core.publisher.Mono;
import reactor.core.scheduler.Schedulers;
import reactor.netty.Connection;
diff --git a/server/protocols/protocols-library/src/main/java/org/apache/james/protocols/lib/LegacyJavaEncryptionFactory.java b/server/protocols/protocols-library/src/main/java/org/apache/james/protocols/lib/LegacyJavaEncryptionFactory.java
index 206a64f7c9f..491653ce426 100644
--- a/server/protocols/protocols-library/src/main/java/org/apache/james/protocols/lib/LegacyJavaEncryptionFactory.java
+++ b/server/protocols/protocols-library/src/main/java/org/apache/james/protocols/lib/LegacyJavaEncryptionFactory.java
@@ -40,8 +40,8 @@
import com.github.fge.lambdas.Throwing;
import nl.altindag.ssl.SSLFactory;
-import nl.altindag.ssl.trustmanager.TrustStoreTrustOptions;
-import nl.altindag.ssl.util.PemUtils;
+import nl.altindag.ssl.pem.util.PemUtils;
+import nl.altindag.ssl.trustmanager.trustoptions.TrustStoreTrustOptions;
public class LegacyJavaEncryptionFactory implements Encryption.Factory {
private static final Logger LOGGER = LoggerFactory.getLogger(AbstractConfigurableAsyncServer.class);
diff --git a/server/protocols/webadmin-integration-test/distributed-webadmin-integration-test/pom.xml b/server/protocols/webadmin-integration-test/distributed-webadmin-integration-test/pom.xml
index f8b8a98ad36..16259ef9c31 100644
--- a/server/protocols/webadmin-integration-test/distributed-webadmin-integration-test/pom.xml
+++ b/server/protocols/webadmin-integration-test/distributed-webadmin-integration-test/pom.xml
@@ -122,7 +122,6 @@
org.apache.maven.plugins
maven-surefire-plugin
- 2.22.2
unstable
diff --git a/server/protocols/webadmin/webadmin-data/src/test/java/org/apache/james/webadmin/routes/VacationRoutesTest.java b/server/protocols/webadmin/webadmin-data/src/test/java/org/apache/james/webadmin/routes/VacationRoutesTest.java
index 6aa94768651..15a2e781a0e 100755
--- a/server/protocols/webadmin/webadmin-data/src/test/java/org/apache/james/webadmin/routes/VacationRoutesTest.java
+++ b/server/protocols/webadmin/webadmin-data/src/test/java/org/apache/james/webadmin/routes/VacationRoutesTest.java
@@ -148,8 +148,8 @@ void postVacationCreates() {
SoftAssertions.assertSoftly(softly -> {
softly.assertThat(vacation).isNotNull();
softly.assertThat(vacation.isEnabled()).isTrue();
- softly.assertThat(vacation.getFromDate()).isEqualTo(Optional.of(ZonedDateTime.parse("2021-09-20T10:00:00Z[UTC]")));
- softly.assertThat(vacation.getToDate()).isEqualTo(Optional.of(ZonedDateTime.parse("2021-09-27T18:00:00Z[UTC]")));
+ softly.assertThat(vacation.getFromDate()).isEqualTo(Optional.of(ZonedDateTime.parse("2021-09-20T10:00:00Z")));
+ softly.assertThat(vacation.getToDate()).isEqualTo(Optional.of(ZonedDateTime.parse("2021-09-27T18:00:00Z")));
softly.assertThat(vacation.getSubject()).isEqualTo(Optional.of("On vacation again"));
softly.assertThat(vacation.getTextBody()).isEqualTo(Optional.of("Need more vacation!"));
softly.assertThat(vacation.getHtmlBody()).isEqualTo(Optional.of("Need more vacation!
"));
@@ -176,8 +176,8 @@ void postVacationUpdatesAll() throws Exception {
SoftAssertions.assertSoftly(softly -> {
softly.assertThat(vacation).isNotNull();
softly.assertThat(vacation.isEnabled()).isTrue();
- softly.assertThat(vacation.getFromDate()).isEqualTo(Optional.of(ZonedDateTime.parse("2021-09-20T10:00:00Z[UTC]")));
- softly.assertThat(vacation.getToDate()).isEqualTo(Optional.of(ZonedDateTime.parse("2021-09-27T18:00:00Z[UTC]")));
+ softly.assertThat(vacation.getFromDate()).isEqualTo(Optional.of(ZonedDateTime.parse("2021-09-20T10:00:00Z")));
+ softly.assertThat(vacation.getToDate()).isEqualTo(Optional.of(ZonedDateTime.parse("2021-09-27T18:00:00Z")));
softly.assertThat(vacation.getSubject()).isEqualTo(Optional.of("On vacation again"));
softly.assertThat(vacation.getTextBody()).isEqualTo(Optional.of("Need more vacation!"));
softly.assertThat(vacation.getHtmlBody()).isEqualTo(Optional.of("Need more vacation!
"));
diff --git a/server/protocols/webadmin/webadmin-dropwizard-metrics/pom.xml b/server/protocols/webadmin/webadmin-dropwizard-metrics/pom.xml
index d1d669820bc..d858521a6c4 100644
--- a/server/protocols/webadmin/webadmin-dropwizard-metrics/pom.xml
+++ b/server/protocols/webadmin/webadmin-dropwizard-metrics/pom.xml
@@ -33,6 +33,10 @@
HTTP endpoint to expose dropwizard collected metrics. This endpoint is intended to be called by
Prometheus.
+
+ 0.16.0
+
+
${james.groupId}
@@ -61,12 +65,12 @@
io.prometheus
simpleclient_dropwizard
- 0.15.0
+ ${prometheus.version}
io.prometheus
simpleclient_servlet
- 0.15.0
+ ${prometheus.version}
io.rest-assured
diff --git a/server/queue/queue-pulsar/pom.xml b/server/queue/queue-pulsar/pom.xml
index 7e9cbd7bc53..19c8c6e4771 100644
--- a/server/queue/queue-pulsar/pom.xml
+++ b/server/queue/queue-pulsar/pom.xml
@@ -101,7 +101,7 @@
com.clever-cloud.pulsar4s
pulsar4s-play-json_${scala.base}
- 2.8.1
+ 2.9.0
com.typesafe.play
diff --git a/server/testing/src/main/java/org/apache/james/util/docker/DockerContainer.java b/server/testing/src/main/java/org/apache/james/util/docker/DockerContainer.java
index c4c271e8526..af64205e63f 100644
--- a/server/testing/src/main/java/org/apache/james/util/docker/DockerContainer.java
+++ b/server/testing/src/main/java/org/apache/james/util/docker/DockerContainer.java
@@ -193,7 +193,7 @@ public String getContainerIp() {
}
public String getHostIp() {
- return container.getContainerIpAddress();
+ return container.getHost();
}
@Override
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/linshare/src/test/java/org/apache/james/linshare/Linshare.java b/third-party/linshare/src/test/java/org/apache/james/linshare/Linshare.java
index 3f9a1de59d0..0cb758a5a9d 100644
--- a/third-party/linshare/src/test/java/org/apache/james/linshare/Linshare.java
+++ b/third-party/linshare/src/test/java/org/apache/james/linshare/Linshare.java
@@ -86,7 +86,7 @@ public int getPort() {
}
public String getIp() {
- return linshareBackend.getContainerIpAddress();
+ return linshareBackend.getHost();
}
public String getUrl() {
@@ -182,7 +182,7 @@ public RequestSpecification fakeSmtpRequestSpecification() {
.setAccept(ContentType.JSON)
.setConfig(newConfig().encoderConfig(encoderConfig().defaultContentCharset(StandardCharsets.UTF_8)))
.setPort(linshareSmtp.getMappedPort(80))
- .setBaseUri("http://" + linshareSmtp.getContainerIpAddress())
+ .setBaseUri("http://" + linshareSmtp.getHost())
.build();
}
}
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..e83aff71eb7 100644
--- a/third-party/rspamd/pom.xml
+++ b/third-party/rspamd/pom.xml
@@ -106,12 +106,6 @@
${project.version}
provided
-
- ${james.groupId}
- james-server-rate-limiter-redis
- test-jar
- test
-
${james.groupId}
james-server-task-json
@@ -207,13 +201,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
deleted file mode 100644
index f2bc942c162..00000000000
--- a/third-party/rspamd/src/test/java/org/apache/james/rspamd/DockerClamAV.java
+++ /dev/null
@@ -1,54 +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.rspamd;
-
-import java.time.Duration;
-import java.util.UUID;
-
-import org.testcontainers.containers.GenericContainer;
-import org.testcontainers.containers.Network;
-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 int DEFAULT_PORT = 3310;
-
- private final GenericContainer> container;
-
- public DockerClamAV(Network network) {
- this.container = new GenericContainer<>(DEFAULT_IMAGE_NAME.withTag(DEFAULT_TAG))
- .withExposedPorts(DEFAULT_PORT)
- .withEnv("CLAMAV_NO_FRESHCLAMD", "true")
- .withEnv("CLAMAV_NO_MILTERD", "true")
- .withNetwork(network)
- .withCreateContainerCmdModifier(createContainerCmd -> createContainerCmd.withName("james-clamav-test-" + UUID.randomUUID()))
- .withNetworkAliases("clamav")
- .waitingFor(Wait.forHealthcheck()
- .withStartupTimeout(Duration.ofMinutes(2)));
- }
-
- public void start() {
- if (!container.isRunning()) {
- container.start();
- }
- }
-}
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
deleted file mode 100644
index ba8ceee0b5b..00000000000
--- a/third-party/rspamd/src/test/java/org/apache/james/rspamd/DockerRspamd.java
+++ /dev/null
@@ -1,102 +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.rspamd;
-
-import java.time.Duration;
-import java.util.UUID;
-import java.util.stream.Stream;
-
-import org.apache.james.rate.limiter.DockerRedis;
-import org.testcontainers.containers.GenericContainer;
-import org.testcontainers.containers.Network;
-import org.testcontainers.containers.wait.strategy.Wait;
-import org.testcontainers.utility.DockerImageName;
-import org.testcontainers.utility.MountableFile;
-
-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 int DEFAULT_PORT = 11334;
-
- private final DockerRedis dockerRedis;
- private final DockerClamAV dockerClamAV;
- private final GenericContainer> container;
- private final Network network;
-
- public DockerRspamd() {
- this.network = Network.newNetwork();
- this.dockerRedis = new DockerRedis(network);
- this.dockerClamAV = new DockerClamAV(network);
- this.container = createRspamd();
- }
-
- public boolean isRunning() {
- return container.isRunning();
- }
-
- private GenericContainer> createRspamd() {
- return new GenericContainer<>(DEFAULT_IMAGE_NAME.withTag(DEFAULT_TAG))
- .withExposedPorts(DEFAULT_PORT)
- .withEnv("REDIS", "redis")
- .withEnv("CLAMAV", "clamav")
- .withEnv("PASSWORD", PASSWORD)
- .withCopyFileToContainer(MountableFile.forClasspathResource("rspamd-config/antivirus.conf"), "/etc/rspamd/override.d/")
- .withCopyFileToContainer(MountableFile.forClasspathResource("rspamd-config/actions.conf"), "/etc/rspamd/")
- .withCopyFileToContainer(MountableFile.forClasspathResource("rspamd-config/statistic.conf"), "/etc/rspamd/")
- .withCreateContainerCmdModifier(createContainerCmd -> createContainerCmd.withName("james-rspamd-test-" + UUID.randomUUID()))
- .withNetwork(network)
- .waitingFor(Wait.forHealthcheck()
- .withStartupTimeout(Duration.ofMinutes(2)));
- }
-
- public Integer getPort() {
- return container.getMappedPort(DEFAULT_PORT);
- }
-
- public void start() {
- Stream.of(dockerClamAV::start, dockerRedis::start)
- .parallel()
- .forEach(Runnable::run);
-
- if (!container.isRunning()) {
- container.start();
- }
- }
-
- public void pause() {
- container.getDockerClient().pauseContainerCmd(container.getContainerId()).exec();
- }
-
- public void unPause() {
- container.getDockerClient().unpauseContainerCmd(container.getContainerId()).exec();
- }
-
- public boolean isPaused() {
- return container.getDockerClient().inspectContainerCmd(container.getContainerId())
- .exec()
- .getState()
- .getPaused();
- }
-
- public void flushAll() {
- dockerRedis.flushAll();
- }
-}
diff --git a/third-party/rspamd/src/test/java/org/apache/james/rspamd/DockerRspamdExtension.java b/third-party/rspamd/src/test/java/org/apache/james/rspamd/DockerRspamdExtension.java
deleted file mode 100644
index 92c2094893a..00000000000
--- a/third-party/rspamd/src/test/java/org/apache/james/rspamd/DockerRspamdExtension.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.rspamd;
-
-import java.net.MalformedURLException;
-import java.net.URL;
-
-import org.apache.james.GuiceModuleTestExtension;
-import org.junit.jupiter.api.extension.ExtensionContext;
-import org.junit.jupiter.api.extension.ParameterContext;
-import org.junit.jupiter.api.extension.ParameterResolutionException;
-
-public class DockerRspamdExtension implements GuiceModuleTestExtension {
- private static final DockerRspamd DOCKER_RSPAMD_SINGLETON = new DockerRspamd();
-
- @Override
- public void beforeAll(ExtensionContext extensionContext) {
- if (!DOCKER_RSPAMD_SINGLETON.isRunning()) {
- DOCKER_RSPAMD_SINGLETON.start();
- }
- }
-
- @Override
- public void beforeEach(ExtensionContext extensionContext) {
- DOCKER_RSPAMD_SINGLETON.flushAll();
- }
-
- public DockerRspamd dockerRspamd() {
- return DOCKER_RSPAMD_SINGLETON;
- }
-
- @Override
- public boolean supportsParameter(ParameterContext parameterContext, ExtensionContext extensionContext) throws ParameterResolutionException {
- return parameterContext.getParameter().getType() == DockerRspamd.class;
- }
-
- @Override
- public Object resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext) throws ParameterResolutionException {
- return dockerRspamd();
- }
-
- public URL getBaseUrl() {
- try {
- return new URL("http://127.0.0.1:" + dockerRspamd().getPort());
- } catch (MalformedURLException e) {
- throw new RuntimeException(e);
- }
- }
-}
diff --git a/third-party/rspamd/src/test/java/org/apache/james/rspamd/DockerRspamdExtensionTest.java b/third-party/rspamd/src/test/java/org/apache/james/rspamd/DockerRspamdExtensionTest.java
index 4e51ac0bc3f..f4166db0720 100644
--- a/third-party/rspamd/src/test/java/org/apache/james/rspamd/DockerRspamdExtensionTest.java
+++ b/third-party/rspamd/src/test/java/org/apache/james/rspamd/DockerRspamdExtensionTest.java
@@ -19,7 +19,7 @@
package org.apache.james.rspamd;
-import static org.apache.james.rspamd.DockerRspamd.PASSWORD;
+import static org.apache.james.rspamd.RspamdExtension.PASSWORD;
import static org.assertj.core.api.Assertions.assertThat;
import static org.hamcrest.core.Is.is;
@@ -41,11 +41,11 @@
@Tag(Unstable.TAG)
class DockerRspamdExtensionTest {
@RegisterExtension
- static DockerRspamdExtension rspamdExtension = new DockerRspamdExtension();
+ static RspamdExtension rspamdExtension = new RspamdExtension();
@Test
void dockerRspamdExtensionShouldWork() {
- RequestSpecification rspamdApi = WebAdminUtils.spec(Port.of(rspamdExtension.dockerRspamd().getPort()));
+ RequestSpecification rspamdApi = WebAdminUtils.spec(Port.of(rspamdExtension.rspamdPort()));
String response = rspamdApi
.get("ping")
@@ -61,7 +61,7 @@ void dockerRspamdExtensionShouldWork() {
@Test
void checkSpamEmailWithExactPasswordHeaderShouldWork() {
- RequestSpecification rspamdApi = WebAdminUtils.spec(Port.of(rspamdExtension.dockerRspamd().getPort()));
+ RequestSpecification rspamdApi = WebAdminUtils.spec(Port.of(rspamdExtension.rspamdPort()));
rspamdApi
.header(new Header("Password", PASSWORD))
@@ -74,7 +74,7 @@ void checkSpamEmailWithExactPasswordHeaderShouldWork() {
@Test
void checkHamEmailWithExactPasswordHeaderShouldWork() {
- RequestSpecification rspamdApi = WebAdminUtils.spec(Port.of(rspamdExtension.dockerRspamd().getPort()));
+ RequestSpecification rspamdApi = WebAdminUtils.spec(Port.of(rspamdExtension.rspamdPort()));
rspamdApi
.header(new Header("Password", PASSWORD))
.body(ClassLoader.getSystemResourceAsStream("mail/ham/ham1.eml"))
@@ -86,7 +86,7 @@ void checkHamEmailWithExactPasswordHeaderShouldWork() {
@Test
void learnSpamEmailWithExactPasswordHeaderShouldWork() {
- RequestSpecification rspamdApi = WebAdminUtils.spec(Port.of(rspamdExtension.dockerRspamd().getPort()));
+ RequestSpecification rspamdApi = WebAdminUtils.spec(Port.of(rspamdExtension.rspamdPort()));
rspamdApi
.header(new Header("Password", PASSWORD))
@@ -99,7 +99,7 @@ void learnSpamEmailWithExactPasswordHeaderShouldWork() {
@Test
void learnHamEmailWithExactPasswordHeaderShouldWork() {
- RequestSpecification rspamdApi = WebAdminUtils.spec(Port.of(rspamdExtension.dockerRspamd().getPort()));
+ RequestSpecification rspamdApi = WebAdminUtils.spec(Port.of(rspamdExtension.rspamdPort()));
rspamdApi
.header(new Header("Password", PASSWORD))
@@ -113,20 +113,20 @@ void learnHamEmailWithExactPasswordHeaderShouldWork() {
@ParameterizedTest
@ValueSource(strings = {"checkv2", "learnspam", "learnham"})
void endpointsWithWrongPasswordHeaderShouldReturnUnauthorized(String endpoint) {
- RequestSpecification rspamdApi = WebAdminUtils.spec(Port.of(rspamdExtension.dockerRspamd().getPort()));
+ RequestSpecification rspamdApi = WebAdminUtils.spec(Port.of(rspamdExtension.rspamdPort()));
rspamdApi
.header(new Header("Password", "wrongPassword"))
.body("dummy")
.post(endpoint)
.then()
- .statusCode(HttpStatus.FORBIDDEN_403)
+ .statusCode(HttpStatus.UNAUTHORIZED_401)
.body("error", is("Unauthorized"));
}
@Test
void checkVirusEmailWithExactPasswordHeaderShouldReturnClamVirusSymbol() {
- RequestSpecification rspamdApi = WebAdminUtils.spec(Port.of(rspamdExtension.dockerRspamd().getPort()));
+ RequestSpecification rspamdApi = WebAdminUtils.spec(Port.of(rspamdExtension.rspamdPort()));
rspamdApi
.header(new Header("Password", PASSWORD))
@@ -140,7 +140,7 @@ void checkVirusEmailWithExactPasswordHeaderShouldReturnClamVirusSymbol() {
@Test
void checkNonVirusEmailWithExactPasswordHeaderShouldNotReturnClamVirusSymbol() {
- RequestSpecification rspamdApi = WebAdminUtils.spec(Port.of(rspamdExtension.dockerRspamd().getPort()));
+ RequestSpecification rspamdApi = WebAdminUtils.spec(Port.of(rspamdExtension.rspamdPort()));
rspamdApi
.header(new Header("Password", PASSWORD))
diff --git a/third-party/rspamd/src/test/java/org/apache/james/rspamd/RspamdExtension.java b/third-party/rspamd/src/test/java/org/apache/james/rspamd/RspamdExtension.java
new file mode 100644
index 00000000000..ab12fe54f11
--- /dev/null
+++ b/third-party/rspamd/src/test/java/org/apache/james/rspamd/RspamdExtension.java
@@ -0,0 +1,156 @@
+/****************************************************************
+ * 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.rspamd;
+
+import java.io.IOException;
+import java.net.URL;
+import java.time.Duration;
+import java.util.UUID;
+
+import org.apache.james.GuiceModuleTestExtension;
+import org.apache.james.util.Runnables;
+import org.junit.jupiter.api.extension.ExtensionContext;
+import org.testcontainers.containers.GenericContainer;
+import org.testcontainers.containers.Network;
+import org.testcontainers.containers.wait.strategy.Wait;
+import org.testcontainers.utility.DockerImageName;
+import org.testcontainers.utility.MountableFile;
+
+import com.github.fge.lambdas.Throwing;
+
+public class RspamdExtension implements GuiceModuleTestExtension {
+ public static final Duration STARTUP_TIMEOUT = Duration.ofMinutes(5);
+ public static final String PASSWORD = "admin";
+
+ private static final DockerImageName RSPAMD_IMAGE = DockerImageName.parse("a16bitsysop/rspamd").withTag("3.5-r7-alpine3.18.2-r0");
+ private static final DockerImageName REDIS_IMAGE = DockerImageName.parse("redis").withTag("7.0.12");
+ private static final DockerImageName CLAMAV_IMAGE = DockerImageName.parse("clamav/clamav").withTag("1.1");
+ private static final int RSPAMD_DEFAULT_PORT = 11334;
+ private static final int REDIS_DEFAULT_PORT = 6379;
+ private static final int CLAMAV_DEFAULT_PORT = 3310;
+
+ private final GenericContainer> rspamdContainer;
+ private final GenericContainer> redisContainer;
+ private final GenericContainer> clamAVContainer;
+ private final Network network;
+
+ public RspamdExtension() {
+ this.network = Network.newNetwork();
+ this.redisContainer = redisContainer(network);
+ this.clamAVContainer = clamAVContainer(network);
+ this.rspamdContainer = rspamdContainer(network);
+ }
+
+ @Override
+ public void beforeAll(ExtensionContext extensionContext) {
+ if (!rspamdContainer.isRunning()) {
+ rspamdContainer.start();
+ }
+ }
+
+ @Override
+ public void afterAll(ExtensionContext extensionContext) {
+ rspamdContainer.stop();
+ Runnables.runParallel(redisContainer::stop, clamAVContainer::stop);
+ }
+
+ @Override
+ public void beforeEach(ExtensionContext extensionContext) {
+ redisFlushAll();
+ }
+
+ public GenericContainer> rspamdContainer(Network network) {
+ return new GenericContainer<>(RSPAMD_IMAGE)
+ .withExposedPorts(RSPAMD_DEFAULT_PORT)
+ .withEnv("REDIS", "redis")
+ .withEnv("CLAMAV", "clamav")
+ .withEnv("PASSWORD", PASSWORD)
+ .withCopyFileToContainer(MountableFile.forClasspathResource("rspamd-config/antivirus.conf"), "/etc/rspamd/override.d/")
+ .withCopyFileToContainer(MountableFile.forClasspathResource("rspamd-config/actions.conf"), "/etc/rspamd/")
+ .withCopyFileToContainer(MountableFile.forClasspathResource("rspamd-config/statistic.conf"), "/etc/rspamd/")
+ .withCreateContainerCmdModifier(createContainerCmd -> createContainerCmd.withName("james-rspamd-test-" + UUID.randomUUID()))
+ .withNetwork(network)
+ .dependsOn(redisContainer, clamAVContainer)
+ .waitingFor(Wait.forHealthcheck())
+ .withStartupTimeout(STARTUP_TIMEOUT);
+ }
+
+
+ public GenericContainer> redisContainer(Network network) {
+ return new GenericContainer<>(REDIS_IMAGE)
+ .withExposedPorts(REDIS_DEFAULT_PORT)
+ .withNetwork(network)
+ .withCreateContainerCmdModifier(createContainerCmd -> createContainerCmd.withName("james-redis-test-" + UUID.randomUUID()))
+ .withNetworkAliases("redis");
+ }
+
+ public GenericContainer> clamAVContainer(Network network) {
+ return new GenericContainer<>(CLAMAV_IMAGE)
+ .withExposedPorts(CLAMAV_DEFAULT_PORT)
+ .withEnv("CLAMAV_NO_FRESHCLAMD", "true")
+ .withEnv("CLAMAV_NO_MILTERD", "true")
+ .withNetwork(network)
+ .withCreateContainerCmdModifier(createContainerCmd -> createContainerCmd.withName("james-clamav-test-" + UUID.randomUUID()))
+ .withNetworkAliases("clamav")
+ .waitingFor(Wait.forHealthcheck())
+ .withStartupTimeout(STARTUP_TIMEOUT);
+ }
+
+
+ public void redisFlushAll() {
+ try {
+ redisContainer.execInContainer("redis-cli", "flushall");
+ } catch (IOException | InterruptedException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public URL rspamdURL() {
+ return Throwing.supplier(() -> new URL("http",
+ rspamdContainer.getHost(),
+ rspamdContainer.getMappedPort(RSPAMD_DEFAULT_PORT),
+ "/")).get();
+ }
+
+ public URL getBaseUrl() {
+ return rspamdURL();
+ }
+
+ public int rspamdPort() {
+ return rspamdContainer.getMappedPort(RSPAMD_DEFAULT_PORT);
+ }
+
+
+ public void pause() {
+ rspamdContainer.getDockerClient().pauseContainerCmd(rspamdContainer.getContainerId()).exec();
+ }
+
+ public void unPause() {
+ rspamdContainer.getDockerClient().unpauseContainerCmd(rspamdContainer.getContainerId()).exec();
+ }
+
+ public boolean isPaused() {
+ return rspamdContainer.getDockerClient().inspectContainerCmd(rspamdContainer.getContainerId())
+ .exec()
+ .getState()
+ .getPaused();
+ }
+
+}
diff --git a/third-party/rspamd/src/test/java/org/apache/james/rspamd/client/RspamdHttpClientTest.java b/third-party/rspamd/src/test/java/org/apache/james/rspamd/client/RspamdHttpClientTest.java
index eff8966503c..7d40490833c 100644
--- a/third-party/rspamd/src/test/java/org/apache/james/rspamd/client/RspamdHttpClientTest.java
+++ b/third-party/rspamd/src/test/java/org/apache/james/rspamd/client/RspamdHttpClientTest.java
@@ -20,7 +20,7 @@
package org.apache.james.rspamd.client;
import static org.apache.james.mailbox.model.Content.BUFFER_SIZE;
-import static org.apache.james.rspamd.DockerRspamd.PASSWORD;
+import static org.apache.james.rspamd.RspamdExtension.PASSWORD;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatCode;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
@@ -34,7 +34,7 @@
import org.apache.james.core.Username;
import org.apache.james.junit.categories.Unstable;
-import org.apache.james.rspamd.DockerRspamdExtension;
+import org.apache.james.rspamd.RspamdExtension;
import org.apache.james.rspamd.exception.UnauthorizedException;
import org.apache.james.rspamd.model.AnalysisResult;
import org.apache.james.util.MimeMessageUtil;
@@ -64,7 +64,7 @@ class RspamdHttpClientTest {
private final static Username ALICE = Username.of("alice@domain.tld");
@RegisterExtension
- static DockerRspamdExtension rspamdExtension = new DockerRspamdExtension();
+ static RspamdExtension rspamdExtension = new RspamdExtension();
private Mail spamMessage;
private Mail hamMessage;
@@ -134,7 +134,7 @@ void checkSpamMailUsingRspamdClientWithExactPasswordShouldReturnAnalysisResultAs
AnalysisResult analysisResult = client.checkV2(spamMessage).block();
assertThat(analysisResult.getAction()).isEqualTo(AnalysisResult.Action.ADD_HEADER);
- RequestSpecification rspamdApi = WebAdminUtils.spec(Port.of(rspamdExtension.dockerRspamd().getPort()));
+ RequestSpecification rspamdApi = WebAdminUtils.spec(Port.of(rspamdExtension.rspamdPort()));
rspamdApi
.header(new Header("Password", PASSWORD))
.header(new Header("IP", spamMessage.getRemoteAddr()))
@@ -160,7 +160,7 @@ void checkHamMailUsingRspamdClientWithExactPasswordShouldReturnAnalysisResultAsS
softly.assertThat(analysisResult.hasVirus()).isEqualTo(false);
});
- RequestSpecification rspamdApi = WebAdminUtils.spec(Port.of(rspamdExtension.dockerRspamd().getPort()));
+ RequestSpecification rspamdApi = WebAdminUtils.spec(Port.of(rspamdExtension.rspamdPort()));
rspamdApi
.header(new Header("Password", PASSWORD))
.body(ClassLoader.getSystemResourceAsStream(HAM_MESSAGE_PATH))
diff --git a/third-party/rspamd/src/test/java/org/apache/james/rspamd/healthcheck/RspamdHealthcheckTest.java b/third-party/rspamd/src/test/java/org/apache/james/rspamd/healthcheck/RspamdHealthcheckTest.java
index 3c7a367ee45..ee88c4293ae 100644
--- a/third-party/rspamd/src/test/java/org/apache/james/rspamd/healthcheck/RspamdHealthcheckTest.java
+++ b/third-party/rspamd/src/test/java/org/apache/james/rspamd/healthcheck/RspamdHealthcheckTest.java
@@ -25,7 +25,7 @@
import java.util.Optional;
import org.apache.james.core.healthcheck.Result;
-import org.apache.james.rspamd.DockerRspamdExtension;
+import org.apache.james.rspamd.RspamdExtension;
import org.apache.james.rspamd.client.RspamdClientConfiguration;
import org.apache.james.rspamd.client.RspamdHttpClient;
import org.junit.jupiter.api.BeforeEach;
@@ -36,14 +36,14 @@
class RspamdHealthcheckTest {
@RegisterExtension
- static DockerRspamdExtension rspamdExtension = new DockerRspamdExtension();
+ static RspamdExtension rspamdExtension = new RspamdExtension();
private RspamdHealthCheck rspamdHealthCheck;
@BeforeEach
void setUp() {
- if (rspamdExtension.dockerRspamd().isPaused()) {
- rspamdExtension.dockerRspamd().unPause();
+ if (rspamdExtension.isPaused()) {
+ rspamdExtension.unPause();
}
RspamdClientConfiguration configuration = new RspamdClientConfiguration(rspamdExtension.getBaseUrl(), "passwordDoesNotMatter", Optional.empty());
@@ -60,7 +60,7 @@ void checkShouldReturnHealthyWhenRspamdIsRunning() {
@Test
void checkShouldReturnUnhealthyWhenRspamdIsDown() {
- rspamdExtension.dockerRspamd().pause();
+ rspamdExtension.pause();
Result check = Mono.from(rspamdHealthCheck.check()).block();
assertThat(check.isUnHealthy()).isTrue();
@@ -79,8 +79,8 @@ void checkShouldReturnUnhealthyWhenWrongRspamdURL() throws Exception {
@Test
void checkShouldReturnHealthyWhenRspamdIsRecovered() {
- rspamdExtension.dockerRspamd().pause();
- rspamdExtension.dockerRspamd().unPause();
+ rspamdExtension.pause();
+ rspamdExtension.unPause();
Result check = Mono.from(rspamdHealthCheck.check()).block();
assertThat(check.isHealthy()).isTrue();
diff --git a/third-party/rspamd/src/test/java/org/apache/james/rspamd/route/FeedMessageRouteTest.java b/third-party/rspamd/src/test/java/org/apache/james/rspamd/route/FeedMessageRouteTest.java
index f06f87fd1e5..7a7d439f030 100644
--- a/third-party/rspamd/src/test/java/org/apache/james/rspamd/route/FeedMessageRouteTest.java
+++ b/third-party/rspamd/src/test/java/org/apache/james/rspamd/route/FeedMessageRouteTest.java
@@ -21,7 +21,7 @@
import static io.restassured.RestAssured.given;
import static io.restassured.http.ContentType.JSON;
-import static org.apache.james.rspamd.DockerRspamd.PASSWORD;
+import static org.apache.james.rspamd.RspamdExtension.PASSWORD;
import static org.apache.james.rspamd.route.FeedMessageRoute.BASE_PATH;
import static org.apache.james.rspamd.task.FeedHamToRspamdTaskTest.ALICE_INBOX_MAILBOX;
import static org.apache.james.rspamd.task.FeedHamToRspamdTaskTest.BOB_INBOX_MAILBOX;
@@ -62,7 +62,7 @@
import org.apache.james.mailbox.inmemory.manager.InMemoryIntegrationResources;
import org.apache.james.mailbox.model.MailboxPath;
import org.apache.james.mailbox.store.MailboxSessionMapperFactory;
-import org.apache.james.rspamd.DockerRspamdExtension;
+import org.apache.james.rspamd.RspamdExtension;
import org.apache.james.rspamd.client.RspamdClientConfiguration;
import org.apache.james.rspamd.client.RspamdHttpClient;
import org.apache.james.rspamd.task.FeedHamToRspamdTask;
@@ -98,7 +98,7 @@
@Tag(Unstable.TAG)
public class FeedMessageRouteTest {
@RegisterExtension
- static DockerRspamdExtension rspamdExtension = new DockerRspamdExtension();
+ static RspamdExtension rspamdExtension = new RspamdExtension();
private InMemoryMailboxManager mailboxManager;
private WebAdminServer webAdminServer;
diff --git a/third-party/rspamd/src/test/java/org/apache/james/rspamd/task/FeedHamToRspamdTaskTest.java b/third-party/rspamd/src/test/java/org/apache/james/rspamd/task/FeedHamToRspamdTaskTest.java
index 418799003fa..5cc995d0d97 100644
--- a/third-party/rspamd/src/test/java/org/apache/james/rspamd/task/FeedHamToRspamdTaskTest.java
+++ b/third-party/rspamd/src/test/java/org/apache/james/rspamd/task/FeedHamToRspamdTaskTest.java
@@ -19,7 +19,7 @@
package org.apache.james.rspamd.task;
-import static org.apache.james.rspamd.DockerRspamd.PASSWORD;
+import static org.apache.james.rspamd.RspamdExtension.PASSWORD;
import static org.apache.james.rspamd.task.FeedSpamToRspamdTaskTest.BOB_SPAM_MAILBOX;
import static org.apache.james.rspamd.task.RunningOptions.ALL_MESSAGES;
import static org.apache.james.rspamd.task.RunningOptions.DEFAULT_MESSAGES_PER_SECOND;
@@ -53,7 +53,7 @@
import org.apache.james.mailbox.inmemory.manager.InMemoryIntegrationResources;
import org.apache.james.mailbox.model.MailboxPath;
import org.apache.james.mailbox.store.MailboxSessionMapperFactory;
-import org.apache.james.rspamd.DockerRspamdExtension;
+import org.apache.james.rspamd.RspamdExtension;
import org.apache.james.rspamd.client.RspamdClientConfiguration;
import org.apache.james.rspamd.client.RspamdHttpClient;
import org.apache.james.task.Task;
@@ -80,7 +80,7 @@
@Tag(Unstable.TAG)
public class FeedHamToRspamdTaskTest {
@RegisterExtension
- static DockerRspamdExtension rspamdExtension = new DockerRspamdExtension();
+ static RspamdExtension rspamdExtension = new RspamdExtension();
public static final String INBOX_MAILBOX_NAME = "INBOX";
public static final Domain DOMAIN = Domain.of("domain.tld");
diff --git a/third-party/rspamd/src/test/java/org/apache/james/rspamd/task/FeedSpamToRspamdTaskTest.java b/third-party/rspamd/src/test/java/org/apache/james/rspamd/task/FeedSpamToRspamdTaskTest.java
index 80260bf311d..51887aeca2c 100644
--- a/third-party/rspamd/src/test/java/org/apache/james/rspamd/task/FeedSpamToRspamdTaskTest.java
+++ b/third-party/rspamd/src/test/java/org/apache/james/rspamd/task/FeedSpamToRspamdTaskTest.java
@@ -19,7 +19,7 @@
package org.apache.james.rspamd.task;
-import static org.apache.james.rspamd.DockerRspamd.PASSWORD;
+import static org.apache.james.rspamd.RspamdExtension.PASSWORD;
import static org.apache.james.rspamd.task.FeedSpamToRspamdTask.SPAM_MAILBOX_NAME;
import static org.apache.james.rspamd.task.RunningOptions.ALL_MESSAGES;
import static org.apache.james.rspamd.task.RunningOptions.DEFAULT_MESSAGES_PER_SECOND;
@@ -53,7 +53,7 @@
import org.apache.james.mailbox.inmemory.manager.InMemoryIntegrationResources;
import org.apache.james.mailbox.model.MailboxPath;
import org.apache.james.mailbox.store.MailboxSessionMapperFactory;
-import org.apache.james.rspamd.DockerRspamdExtension;
+import org.apache.james.rspamd.RspamdExtension;
import org.apache.james.rspamd.client.RspamdClientConfiguration;
import org.apache.james.rspamd.client.RspamdHttpClient;
import org.apache.james.task.Task;
@@ -80,7 +80,7 @@
@Tag(Unstable.TAG)
public class FeedSpamToRspamdTaskTest {
@RegisterExtension
- static DockerRspamdExtension rspamdExtension = new DockerRspamdExtension();
+ static RspamdExtension rspamdExtension = new RspamdExtension();
public static final Domain DOMAIN = Domain.of("domain.tld");
public static final Username CEDRIC = Username.fromLocalPartWithDomain("cedric", DOMAIN);
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..dd1580346ad 100644
--- a/third-party/spamassassin/pom.xml
+++ b/third-party/spamassassin/pom.xml
@@ -158,11 +158,6 @@
javax.mail
provided
-
- commons-io
- commons-io
- provided
-
org.apache.commons
commons-lang3
@@ -192,13 +187,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..8efc1038129 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,15 +94,13 @@ 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;
private SpamAssassin(GenericContainer> spamAssassinContainer) {
this.spamAssassinContainer = spamAssassinContainer;
- this.ip = spamAssassinContainer.getContainerIpAddress();
+ this.ip = spamAssassinContainer.getHost();
this.bindingPort = spamAssassinContainer.getMappedPort(SPAMASSASSIN_PORT);
}
@@ -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