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

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

commit cf0897bff90cef3df94e483b648d1eb3eaabd30d
Author: Benoit Tellier <[email protected]>
AuthorDate: Tue Jul 4 00:21:14 2023 +0700

    JAMES-3920 SPF integration test
    
    Check gmail is recognised as spoofed
---
 .../apache/james/mailets/SPFIntegrationTests.java  | 113 +++++++++++++++++++++
 .../org/apache/james/transport/mailets/SPF.java    |   4 +-
 .../apache/james/transport/mailets/SPFTest.java    |  21 ++--
 3 files changed, 123 insertions(+), 15 deletions(-)

diff --git 
a/server/mailet/integration-testing/src/test/java/org/apache/james/mailets/SPFIntegrationTests.java
 
b/server/mailet/integration-testing/src/test/java/org/apache/james/mailets/SPFIntegrationTests.java
new file mode 100644
index 0000000000..3f1d71ff44
--- /dev/null
+++ 
b/server/mailet/integration-testing/src/test/java/org/apache/james/mailets/SPFIntegrationTests.java
@@ -0,0 +1,113 @@
+/****************************************************************
+ * 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.mailets;
+
+import static 
org.apache.james.mailets.configuration.CommonProcessors.ERROR_REPOSITORY;
+import static org.apache.james.mailets.configuration.Constants.DEFAULT_DOMAIN;
+import static org.apache.james.mailets.configuration.Constants.FROM;
+import static org.apache.james.mailets.configuration.Constants.LOCALHOST_IP;
+import static org.apache.james.mailets.configuration.Constants.PASSWORD;
+import static org.apache.james.mailets.configuration.Constants.RECIPIENT;
+import static 
org.apache.james.mailets.configuration.Constants.awaitAtMostOneMinute;
+
+import java.io.File;
+
+import org.apache.james.MemoryJamesServerMain;
+import org.apache.james.mailbox.model.MailboxConstants;
+import org.apache.james.mailets.configuration.CommonProcessors;
+import org.apache.james.mailets.configuration.MailetConfiguration;
+import org.apache.james.mailets.configuration.MailetContainer;
+import org.apache.james.mailets.configuration.ProcessorConfiguration;
+import org.apache.james.modules.MailboxProbeImpl;
+import org.apache.james.modules.protocols.ImapGuiceProbe;
+import org.apache.james.modules.protocols.SieveProbeImpl;
+import org.apache.james.modules.protocols.SmtpGuiceProbe;
+import org.apache.james.probe.DataProbe;
+import org.apache.james.transport.mailets.SPF;
+import org.apache.james.transport.mailets.ToRepository;
+import org.apache.james.transport.matchers.All;
+import org.apache.james.transport.matchers.HasMailAttribute;
+import org.apache.james.transport.matchers.HasMailAttributeWithValue;
+import org.apache.james.transport.matchers.SizeGreaterThan;
+import org.apache.james.utils.DataProbeImpl;
+import org.apache.james.utils.MailRepositoryProbeImpl;
+import org.apache.james.utils.SMTPMessageSender;
+import org.apache.james.utils.TestIMAPClient;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.RegisterExtension;
+import org.junit.jupiter.api.io.TempDir;
+
+class SPFIntegrationTests {
+    public static final String FROM = "[email protected]";
+    public static final String POSTMASTER = "postmaster@" + DEFAULT_DOMAIN;
+
+    @RegisterExtension
+    public TestIMAPClient testIMAPClient = new TestIMAPClient();
+    @RegisterExtension
+    public SMTPMessageSender messageSender = new 
SMTPMessageSender(DEFAULT_DOMAIN);
+
+    private TemporaryJamesServer jamesServer;
+
+    @BeforeEach
+    void setup(@TempDir File temporaryFolder) throws Exception {
+        jamesServer = TemporaryJamesServer.builder()
+                .withBase(MemoryJamesServerMain.SMTP_AND_IMAP_MODULE)
+                .withMailetContainer(
+                        generateMailetContainerConfiguration())
+                .build(temporaryFolder);
+        jamesServer.start();
+
+        DataProbe dataProbe = jamesServer.getProbe(DataProbeImpl.class);
+        dataProbe.addDomain(DEFAULT_DOMAIN);
+        dataProbe.addUser(RECIPIENT, PASSWORD);
+    }
+
+    @AfterEach
+    void tearDown() {
+        jamesServer.shutdown();
+    }
+
+    @Test
+    void shouldRejectSpoofedEmail() throws Exception {
+        messageSender.connect(LOCALHOST_IP, 
jamesServer.getProbe(SmtpGuiceProbe.class).getSmtpPort())
+            .sendMessage(FROM, RECIPIENT);
+
+        awaitAtMostOneMinute.until(() -> 
jamesServer.getProbe(MailRepositoryProbeImpl.class).getRepositoryMailCount(ERROR_REPOSITORY)
 == 1);
+    }
+
+    private MailetContainer.Builder generateMailetContainerConfiguration() {
+        return TemporaryJamesServer.defaultMailetContainerConfiguration()
+                .postmaster(POSTMASTER)
+                .putProcessor(ProcessorConfiguration.transport()
+                        .addMailet(MailetConfiguration.builder()
+                                .matcher(All.class)
+                                .mailet(SPF.class)
+                                .addProperty("checkLocalIps", "true"))
+                        .addMailet(MailetConfiguration.builder()
+                                .matcher(HasMailAttributeWithValue.class)
+                                
.matcherCondition("org.apache.james.transport.mailets.spf.result, softfail")
+                                .mailet(ToRepository.class)
+                                .addProperty("repositoryPath", 
ERROR_REPOSITORY.asString())
+                                .addProperty("passThrough", "false"))
+                        
.addMailetsFrom(CommonProcessors.deliverOnlyTransport()));
+    }
+}
diff --git 
a/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/SPF.java
 
b/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/SPF.java
index 381c46daa3..1bda369912 100644
--- 
a/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/SPF.java
+++ 
b/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/SPF.java
@@ -67,6 +67,7 @@ public class SPF extends GenericMailet {
 
     private boolean debug = false;
     private boolean addHeader = false;
+    private boolean ignoreLocalIps = false;
     private org.apache.james.jspf.impl.SPF spf;
     public static final AttributeName EXPLANATION_ATTRIBUTE = 
AttributeName.of("org.apache.james.transport.mailets.spf.explanation");
     public static final AttributeName RESULT_ATTRIBUTE = 
AttributeName.of("org.apache.james.transport.mailets.spf.result");
@@ -91,6 +92,7 @@ public class SPF extends GenericMailet {
     public void init() {
         debug = Boolean.parseBoolean(getInitParameter("debug", "false"));
         addHeader = Boolean.parseBoolean(getInitParameter("addHeader", 
"false"));
+        addHeader = Boolean.parseBoolean(getInitParameter("checkLocalIps", 
"false"));
 
         if (spfDnsService == null) {
             spf = new DefaultSPF();
@@ -111,7 +113,7 @@ public class SPF extends GenericMailet {
     public void service(Mail mail) throws MessagingException {
         String remoteAddr = mail.getRemoteAddr();
 
-        if (netMatcher.matchInetNetwork(remoteAddr)) {
+        if (ignoreLocalIps || netMatcher.matchInetNetwork(remoteAddr)) {
             LOGGER.debug("ignore SPF check for ip:{}", remoteAddr);
         } else {
             String helo = AttributeUtils.getValueAndCastFromMail(mail, 
Mail.SMTP_HELO, String.class).orElse(mail.getRemoteHost());
diff --git 
a/server/mailet/mailets/src/test/java/org/apache/james/transport/mailets/SPFTest.java
 
b/server/mailet/mailets/src/test/java/org/apache/james/transport/mailets/SPFTest.java
index f05fb34259..c7e378d731 100644
--- 
a/server/mailet/mailets/src/test/java/org/apache/james/transport/mailets/SPFTest.java
+++ 
b/server/mailet/mailets/src/test/java/org/apache/james/transport/mailets/SPFTest.java
@@ -23,7 +23,6 @@ import java.net.InetAddress;
 import java.net.UnknownHostException;
 import java.util.ArrayList;
 import java.util.List;
-import java.util.concurrent.CompletableFuture;
 
 import javax.mail.MessagingException;
 
@@ -105,7 +104,7 @@ public class SPFTest {
         Mailet mailet = testMailet(false, false, "10.0.0.0/8");
 
         mailet.service(mail);
-        assertThat(mail.getAttribute(RESULT_ATTRIBUTE).isEmpty()).isTrue();
+        assertThat(mail.getAttribute(RESULT_ATTRIBUTE)).isEmpty();
     }
 
     @Test
@@ -114,8 +113,7 @@ public class SPFTest {
         Mailet mailet = testMailet();
 
         mailet.service(mail);
-        assertThat(AttributeUtils.getValueAndCastFromMail(mail, 
RESULT_ATTRIBUTE, String.class)
-            .orElse(null)).isEqualTo("none");
+        assertThat(AttributeUtils.getValueAndCastFromMail(mail, 
RESULT_ATTRIBUTE, String.class)).contains("none");
     }
 
     @Test
@@ -124,8 +122,7 @@ public class SPFTest {
         Mailet mailet = testMailet();
 
         mailet.service(mail);
-        assertThat(AttributeUtils.getValueAndCastFromMail(mail, 
RESULT_ATTRIBUTE, String.class)
-            .orElse(null)).isEqualTo("pass");
+        assertThat(AttributeUtils.getValueAndCastFromMail(mail, 
RESULT_ATTRIBUTE, String.class)).contains("pass");
     }
 
     @Test
@@ -134,8 +131,7 @@ public class SPFTest {
         Mailet mailet = testMailet();
 
         mailet.service(mail);
-        assertThat(AttributeUtils.getValueAndCastFromMail(mail, 
RESULT_ATTRIBUTE, String.class)
-            .orElse(null)).isEqualTo("fail");
+        assertThat(AttributeUtils.getValueAndCastFromMail(mail, 
RESULT_ATTRIBUTE, String.class)).contains("fail");
     }
 
     @Test
@@ -144,8 +140,7 @@ public class SPFTest {
         Mailet mailet = testMailet();
 
         mailet.service(mail);
-        assertThat(AttributeUtils.getValueAndCastFromMail(mail, 
RESULT_ATTRIBUTE, String.class)
-            .orElse(null)).isEqualTo("softfail");
+        assertThat(AttributeUtils.getValueAndCastFromMail(mail, 
RESULT_ATTRIBUTE, String.class)).contains("softfail");
     }
 
     @Test
@@ -154,8 +149,7 @@ public class SPFTest {
         Mailet mailet = testMailet();
 
         mailet.service(mail);
-        assertThat(AttributeUtils.getValueAndCastFromMail(mail, 
RESULT_ATTRIBUTE, String.class)
-            .orElse(null)).isEqualTo("permerror");
+        assertThat(AttributeUtils.getValueAndCastFromMail(mail, 
RESULT_ATTRIBUTE, String.class)).contains("permerror");
     }
 
     @Test
@@ -164,8 +158,7 @@ public class SPFTest {
         Mailet mailet = testMailet();
 
         mailet.service(mail);
-        assertThat(AttributeUtils.getValueAndCastFromMail(mail, 
RESULT_ATTRIBUTE, String.class)
-            .orElse(null)).isEqualTo("temperror");
+        assertThat(AttributeUtils.getValueAndCastFromMail(mail, 
RESULT_ATTRIBUTE, String.class)).contains("temperror");
     }
 
     private Mailet testMailet() throws MessagingException {


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to