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

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


The following commit(s) were added to refs/heads/master by this push:
     new aaa5931eaf JAMES-3755 Allow RSpamDScanner to override url settings 
(#2819)
aaa5931eaf is described below

commit aaa5931eaf81d2eaec129087bc040896448ec0e6
Author: Benoit TELLIER <btell...@linagora.com>
AuthorDate: Mon Sep 22 17:29:43 2025 +0200

    JAMES-3755 Allow RSpamDScanner to override url settings (#2819)
---
 third-party/rspamd/README.md                       |  5 +++
 .../org/apache/james/rspamd/RspamdScanner.java     | 18 ++++++++--
 .../org/apache/james/rspamd/RspamdScannerTest.java | 42 ++++++++++++++++++++++
 3 files changed, 62 insertions(+), 3 deletions(-)

diff --git a/third-party/rspamd/README.md b/third-party/rspamd/README.md
index 3706c6eaeb..31c7be977f 100644
--- a/third-party/rspamd/README.md
+++ b/third-party/rspamd/README.md
@@ -86,6 +86,11 @@ If true `virusProcessor` and `rejectSpamProcessor` are 
honnered per user, at the
 </processor>
 ```
 
+`RSpamdScanner` supports addition `rspamdUrl`, `rspamdPassword`, 
`rspamdTimeout`, `perUserBayes` properties allowing to 
+override content defined in `rspamd.properties`, which allows running several 
instances on distict Rspamd instance. A 
+possible use case is to use 1 RSpamD cluster on user incoming spam, trained in 
perUserBayes mode, and another RSpamD 
+cluster configured to check outgoing email for spams with a tolerant threshold 
and a specifc configuration.
+
 - Declare the webadmin for Rspamd in `webadmin.properties`
 
 ```
diff --git 
a/third-party/rspamd/src/main/java/org/apache/james/rspamd/RspamdScanner.java 
b/third-party/rspamd/src/main/java/org/apache/james/rspamd/RspamdScanner.java
index 19a5ce13e1..63c4b8ef8e 100644
--- 
a/third-party/rspamd/src/main/java/org/apache/james/rspamd/RspamdScanner.java
+++ 
b/third-party/rspamd/src/main/java/org/apache/james/rspamd/RspamdScanner.java
@@ -20,6 +20,7 @@
 package org.apache.james.rspamd;
 
 
+import java.net.URL;
 import java.util.Collection;
 import java.util.List;
 import java.util.Optional;
@@ -63,9 +64,10 @@ public class RspamdScanner extends GenericMailet {
     public static final AttributeName FLAG_MAIL = 
AttributeName.of("org.apache.james.rspamd.flag");
     public static final AttributeName STATUS_MAIL = 
AttributeName.of("org.apache.james.rspamd.status");
 
-    private final RspamdHttpClient rspamdHttpClient;
     private final RspamdClientConfiguration configuration;
+    private RspamdHttpClient rspamdHttpClient;
     private boolean rewriteSubject;
+    private boolean perUserBayes;
     private Optional<String> virusProcessor;
     private Optional<String> rejectSpamProcessor;
 
@@ -73,18 +75,28 @@ public class RspamdScanner extends GenericMailet {
     public RspamdScanner(RspamdHttpClient rspamdHttpClient, 
RspamdClientConfiguration configuration) {
         this.rspamdHttpClient = rspamdHttpClient;
         this.configuration = configuration;
+        this.perUserBayes = configuration.usePerUserBayes();
     }
 
     @Override
     public void init() {
-        rewriteSubject = 
getBooleanParameter(getInitParameter("rewriteSubject"), false);
+        rewriteSubject = getInitParameter("rewriteSubject", false);
         virusProcessor = getInitParameterAsOptional("virusProcessor");
         rejectSpamProcessor = 
getInitParameterAsOptional("rejectSpamProcessor");
+
+        perUserBayes = getInitParameter("perUserBayes", 
configuration.usePerUserBayes());
+
+        getInitParameterAsOptional("rspamdUrl")
+            .ifPresent(Throwing.consumer(url -> this.rspamdHttpClient = new 
RspamdHttpClient(new RspamdClientConfiguration(
+                new URL(url),
+                getInitParameter("rspamdPassword", 
configuration.getPassword()),
+                
getInitParameterAsOptional("rspamdTimeout").map(Integer::parseInt).or(configuration::getTimeout),
+                perUserBayes))));
     }
 
     @Override
     public void service(Mail mail) throws MessagingException {
-        if (configuration.usePerUserBayes()) {
+        if (perUserBayes) {
             scanPerUser(mail);
         } else {
             scanAll(mail);
diff --git 
a/third-party/rspamd/src/test/java/org/apache/james/rspamd/RspamdScannerTest.java
 
b/third-party/rspamd/src/test/java/org/apache/james/rspamd/RspamdScannerTest.java
index 7485914879..57449d472a 100644
--- 
a/third-party/rspamd/src/test/java/org/apache/james/rspamd/RspamdScannerTest.java
+++ 
b/third-party/rspamd/src/test/java/org/apache/james/rspamd/RspamdScannerTest.java
@@ -23,6 +23,7 @@ import static org.assertj.core.api.Assertions.assertThat;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verifyNoInteractions;
 import static org.mockito.Mockito.when;
 
 import java.util.Collection;
@@ -313,6 +314,47 @@ class RspamdScannerTest {
         assertThat(mail.getState()).isEqualTo("spam");
     }
 
+    @Test
+    void shouldSupportCustomRSpamDURL() throws Exception {
+        RspamdHttpClient rspamdHttpClient = mock(RspamdHttpClient.class);
+        
when(rspamdHttpClient.checkV2(any(Mail.class))).thenReturn(Mono.just(AnalysisResult.builder()
+                .action(AnalysisResult.Action.REJECT)
+                .score(12.1F)
+                .requiredScore(14F)
+            .build()));
+
+        FakeMailetConfig mailetConfig = FakeMailetConfig.builder()
+            .setProperty("rejectSpamProcessor", "spam")
+            .setProperty("rspamdUrl", "http://imap.failing.com";)
+            .setProperty("rspamdPassword", "secret")
+            .setProperty("rspamdTimeout", "20000")
+            .build();
+
+        mailet = new RspamdScanner(rspamdHttpClient, configuration);
+
+        Mail mail = FakeMail.builder()
+            .name("name")
+            .state("initial")
+            .recipient("us...@exemple.com")
+            .mimeMessage(MimeMessageBuilder.mimeMessageBuilder()
+                .addToRecipient("us...@exemple.com")
+                .addFrom("sen...@exemple.com")
+                .setSubject(INIT_SUBJECT)
+                .setText("Please!")
+                .build())
+            .build();
+
+        mailet.init(mailetConfig);
+        try {
+            mailet.service(mail);
+        } catch (Exception e) {
+            // ignore
+        }
+
+        // We overloaded the mock supplied in the constructor
+        verifyNoInteractions(rspamdHttpClient);
+    }
+
     @Test
     void serviceShouldNotMoveRejetedEmailWhenNoSpamProcessor() throws 
Exception {
         RspamdHttpClient rspamdHttpClient = mock(RspamdHttpClient.class);


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

Reply via email to