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 2628a5b62e JAMES-4086 Mailet for folding long lines (#2490)
2628a5b62e is described below

commit 2628a5b62e23b89d5a4d6e1bee356f28e6c71f57
Author: hungphan227 <45198168+hungphan...@users.noreply.github.com>
AuthorDate: Mon Nov 11 17:35:29 2024 +0700

    JAMES-4086 Mailet for folding long lines (#2490)
---
 docs/modules/servers/partials/FoldLongLines.adoc   |   7 +
 .../james/transport/mailets/FoldLongLines.java     | 107 ++++++++++++
 .../apache/james/transport/mailets/MimeUtil.java   |  80 +++++++++
 .../james/transport/mailets/FoldLongLinesTest.java | 185 +++++++++++++++++++++
 .../apache/james/mailets/DKIMIntegrationTest.java  |  71 +++++++-
 5 files changed, 449 insertions(+), 1 deletion(-)

diff --git a/docs/modules/servers/partials/FoldLongLines.adoc 
b/docs/modules/servers/partials/FoldLongLines.adoc
new file mode 100644
index 0000000000..0b913d756f
--- /dev/null
+++ b/docs/modules/servers/partials/FoldLongLines.adoc
@@ -0,0 +1,7 @@
+=== FoldLongLines
+
+This mailet fold (wrap) any header lines of the mail that exceed the maximum 
number of characters. This sanitizing of EML message will prevent downstream 
server from applying it, and prevent them to break the DKIM signature 
positioned by James.
+
+It takes only one parameter:
+
+* maxCharacters: maximum number of characters. Default to 998 (This line limit 
is defined in RFC5322).
diff --git 
a/mailet/standard/src/main/java/org/apache/james/transport/mailets/FoldLongLines.java
 
b/mailet/standard/src/main/java/org/apache/james/transport/mailets/FoldLongLines.java
new file mode 100644
index 0000000000..01608c9454
--- /dev/null
+++ 
b/mailet/standard/src/main/java/org/apache/james/transport/mailets/FoldLongLines.java
@@ -0,0 +1,107 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ ****************************************************************/
+
+package org.apache.james.transport.mailets;
+
+import java.util.List;
+import java.util.Set;
+
+import jakarta.mail.Header;
+import jakarta.mail.MessagingException;
+
+import org.apache.commons.lang3.stream.Streams;
+import org.apache.mailet.Mail;
+import org.apache.mailet.base.GenericMailet;
+
+import com.github.fge.lambdas.Throwing;
+import com.google.common.base.Preconditions;
+import com.google.common.base.Splitter;
+import com.google.common.collect.ImmutableSet;
+
+/**
+ * This mailet fold (wrap) any header lines of the mail that exceed the 
maximum number of characters.
+ * <br />
+ * It takes only one parameter:
+ * <ul>
+ * <li>maxCharacters: maximum number of characters. Default to 998.
+ * </ul>
+ */
+public class FoldLongLines extends GenericMailet {
+    public static final String MAX_CHARACTERS_PARAMETER_NAME = "maxCharacters";
+    public static final String HEADER_SEPARATOR = ": ";
+
+    private static final int DEFAULT_MAX_CHARACTERS = 998;
+    private static final String SEPARATOR = "\n";
+
+    private int maxCharacters;
+
+    @Override
+    public void init() throws MessagingException {
+        int maxCharacters = 
getInitParameterAsOptional(MAX_CHARACTERS_PARAMETER_NAME).map(Integer::parseInt).orElse(DEFAULT_MAX_CHARACTERS);
+        Preconditions.checkArgument(maxCharacters > 0, "maxCharacters must be 
positive");
+        this.maxCharacters = maxCharacters;
+    }
+
+    @Override
+    public void service(Mail mail) throws MessagingException {
+        Set<String> longHeaders = getHeadersExceedingMaxCharacters(mail);
+
+        if (!longHeaders.isEmpty()) {
+            List<Header> headers = 
getHeadersWithTheSameNameAsLongHeaders(mail, longHeaders);
+
+            // remove all long headers (as well as headers with same name)
+            longHeaders.forEach(Throwing.consumer(header -> 
mail.getMessage().removeHeader(header)));
+
+            headers.forEach(Throwing.consumer(header -> {
+                if (exceedLineLimit(header)) {
+                    mail.getMessage().addHeader(header.getName(), 
fold(header));
+                } else {
+                    mail.getMessage().addHeader(header.getName(), 
header.getValue());
+                }
+            }));
+            mail.getMessage().saveChanges();
+        }
+    }
+
+    private Set<String> getHeadersExceedingMaxCharacters(Mail mail) throws 
MessagingException {
+        return Streams.of(mail.getMessage().getAllHeaders().asIterator())
+            .filter(this::exceedLineLimit)
+            .map(Header::getName)
+            .collect(ImmutableSet.toImmutableSet());
+    }
+
+    private List<Header> getHeadersWithTheSameNameAsLongHeaders(Mail mail, 
Set<String> longHeaders) throws MessagingException {
+        return Streams.of(mail.getMessage().getAllHeaders().asIterator())
+            .filter(header -> longHeaders.contains(header.getName()))
+            .toList();
+    }
+
+    private String fold(Header header) {
+        int headerNameLength = header.getName().length() + 
HEADER_SEPARATOR.length();
+        // TODO After new release of mime4j with commit 
https://github.com/apache/james-mime4j/commit/66a09219457854c7a26e5b7c0e4c9dd59b4b0c32,
 update to use MimeUtil of mime4j and remove MimeUtil class file
+        return MimeUtil.fold(header.getValue(), headerNameLength, 
maxCharacters);
+    }
+
+    private boolean exceedLineLimit(Header header) {
+        String fullHeader = header.getName() + HEADER_SEPARATOR + 
header.getValue();
+        return Splitter.on(SEPARATOR)
+            .splitToStream(fullHeader)
+            .anyMatch(line -> line.length() > maxCharacters);
+    }
+}
\ No newline at end of file
diff --git 
a/mailet/standard/src/main/java/org/apache/james/transport/mailets/MimeUtil.java
 
b/mailet/standard/src/main/java/org/apache/james/transport/mailets/MimeUtil.java
new file mode 100644
index 0000000000..ef6213a57d
--- /dev/null
+++ 
b/mailet/standard/src/main/java/org/apache/james/transport/mailets/MimeUtil.java
@@ -0,0 +1,80 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ ****************************************************************/
+
+package org.apache.james.transport.mailets;
+
+// TODO After new release of mime4j with commit 
https://github.com/apache/james-mime4j/commit/66a09219457854c7a26e5b7c0e4c9dd59b4b0c32,
 remove this class
+public class MimeUtil {
+    /**
+     * Splits the specified string into a multiple-line representation with
+     * lines no longer than the maximum number of characters (because the line 
might contain
+     * encoded words; see <a href='http://www.faqs.org/rfcs/rfc2047.html'>RFC
+     * 2047</a> section 2). If the string contains non-whitespace sequences
+     * longer than the maximum number of characters a line break is inserted 
at the whitespace
+     * character following the sequence resulting in a line longer than the 
maximum number of
+     * characters.
+     *
+     * @param s
+     *            string to split.
+     * @param usedCharacters
+     *            number of characters already used up. Usually the number of
+     *            characters for header field name plus colon and one space.
+     * @param maxCharacters
+     *            maximum number of characters
+     * @return a multiple-line representation of the given string.
+     */
+    public static String fold(String s, int usedCharacters, int maxCharacters) 
{
+        final int length = s.length();
+        if (usedCharacters + length <= maxCharacters) {
+            return s;
+        }
+
+        StringBuilder sb = new StringBuilder();
+
+        int lastLineBreak = -usedCharacters;
+        int wspIdx = indexOfWsp(s, 0);
+        while (true) {
+            if (wspIdx == length) {
+                sb.append(s.substring(Math.max(0, lastLineBreak)));
+                return sb.toString();
+            }
+
+            int nextWspIdx = indexOfWsp(s, wspIdx + 1);
+
+            if (nextWspIdx - lastLineBreak > maxCharacters) {
+                sb.append(s, Math.max(0, lastLineBreak), wspIdx);
+                sb.append("\r\n");
+                lastLineBreak = wspIdx;
+            }
+
+            wspIdx = nextWspIdx;
+        }
+    }
+
+    private static int indexOfWsp(String s, int fromIndex) {
+        final int len = s.length();
+        for (int index = fromIndex; index < len; index++) {
+            char c = s.charAt(index);
+            if (c == ' ' || c == '\t') {
+                return index;
+            }
+        }
+        return len;
+    }
+}
diff --git 
a/mailet/standard/src/test/java/org/apache/james/transport/mailets/FoldLongLinesTest.java
 
b/mailet/standard/src/test/java/org/apache/james/transport/mailets/FoldLongLinesTest.java
new file mode 100644
index 0000000000..37a15f59b6
--- /dev/null
+++ 
b/mailet/standard/src/test/java/org/apache/james/transport/mailets/FoldLongLinesTest.java
@@ -0,0 +1,185 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ ****************************************************************/
+
+package org.apache.james.transport.mailets;
+
+import static 
org.apache.james.transport.mailets.FoldLongLines.HEADER_SEPARATOR;
+import static 
org.apache.james.transport.mailets.FoldLongLines.MAX_CHARACTERS_PARAMETER_NAME;
+import static org.assertj.core.api.Assertions.assertThat;
+
+import java.util.List;
+
+import jakarta.mail.Header;
+import jakarta.mail.MessagingException;
+
+import org.apache.commons.lang3.stream.Streams;
+import org.apache.james.core.builder.MimeMessageBuilder;
+import org.apache.mailet.Mail;
+import org.apache.mailet.Mailet;
+import org.apache.mailet.MailetContext;
+import org.apache.mailet.base.test.FakeMail;
+import org.apache.mailet.base.test.FakeMailContext;
+import org.apache.mailet.base.test.FakeMailetConfig;
+import org.assertj.core.api.SoftAssertions;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+public class FoldLongLinesTest {
+    static final String HEADER_NAME = "References";
+    static final String HEADER_VALUE = "<a1@gmailcom> <a2@gmailcom> 
<a3@gmailcom>";
+    static final String FOLDED_LINE = "<a1@gmailcom> <a2@gmailcom>\r\n" +
+        " <a3@gmailcom>";
+
+    private Mailet foldMailet;
+    private MailetContext mailetContext;
+
+    @BeforeEach
+    void beforeEach() {
+        foldMailet = new FoldLongLines();
+        mailetContext = FakeMailContext.defaultContext();
+    }
+
+    @Test
+    void serviceShouldFoldLinesWhenTheyExceedMaxCharacters() throws 
MessagingException {
+        FakeMailetConfig mailetConfig = FakeMailetConfig.builder()
+            .mailetName("Test")
+            .mailetContext(mailetContext)
+            .setProperty(MAX_CHARACTERS_PARAMETER_NAME, 
String.valueOf(HEADER_NAME.length() + HEADER_SEPARATOR.length() + 
HEADER_VALUE.length() - 1))
+            .build();
+        foldMailet.init(mailetConfig);
+
+        Mail mail = FakeMail.builder()
+            
.name("mail").mimeMessage(MimeMessageBuilder.mimeMessageBuilder().addHeader(HEADER_NAME,
 HEADER_VALUE).build())
+            .build();
+        foldMailet.service(mail);
+
+        List<Header> headers = 
Streams.of(mail.getMessage().getAllHeaders()).filter(header -> 
header.getName().equals(HEADER_NAME)).toList();
+        assertThat(headers).hasSize(1);
+        assertThat(headers.getFirst().getValue()).isEqualTo(FOLDED_LINE);
+    }
+
+    @Test
+    void 
serviceShouldFoldLinesWhenTheyExceedMaxCharactersAndTheHeaderHasMultiLines() 
throws MessagingException {
+        FakeMailetConfig mailetConfig = FakeMailetConfig.builder()
+            .mailetName("Test")
+            .mailetContext(mailetContext)
+            .setProperty(MAX_CHARACTERS_PARAMETER_NAME, "30")
+            .build();
+        foldMailet.init(mailetConfig);
+
+        Mail mail = FakeMail.builder()
+            
.name("mail").mimeMessage(MimeMessageBuilder.mimeMessageBuilder().addHeader(HEADER_NAME,
 "<a1@gmailcom>\n<a2@gmailcom> <a3@gmailcom> <a4@gmailcom>").build())
+            .build();
+        foldMailet.service(mail);
+
+        List<Header> headers = 
Streams.of(mail.getMessage().getAllHeaders()).filter(header -> 
header.getName().equals(HEADER_NAME)).toList();
+        assertThat(headers).hasSize(1);
+        assertThat(headers.getFirst().getValue()).isEqualTo("<a1@gmailcom>\n" +
+            "<a2@gmailcom>\r\n" +
+            " <a3@gmailcom> <a4@gmailcom>");
+    }
+
+    @Test
+    void serviceShouldNotFoldLinesWhenTheyDoNotExceedMaxCharacters() throws 
MessagingException {
+        FakeMailetConfig mailetConfig = FakeMailetConfig.builder()
+            .mailetName("Test")
+            .mailetContext(mailetContext)
+            .setProperty(MAX_CHARACTERS_PARAMETER_NAME, "60")
+            .build();
+        foldMailet.init(mailetConfig);
+
+        Mail mail = FakeMail.builder()
+            
.name("mail").mimeMessage(MimeMessageBuilder.mimeMessageBuilder().addHeader(HEADER_NAME,
 HEADER_VALUE).build())
+            .build();
+        foldMailet.service(mail);
+
+        List<Header> headers = 
Streams.of(mail.getMessage().getAllHeaders()).filter(header -> 
header.getName().equals(HEADER_NAME)).toList();
+        assertThat(headers).hasSize(1);
+        assertThat(headers.getFirst().getValue()).isEqualTo(HEADER_VALUE);
+    }
+
+    @Test
+    void serviceShouldNotFoldLinesWhenTheirLengthEqualToMaxCharacters() throws 
MessagingException {
+        FakeMailetConfig mailetConfig = FakeMailetConfig.builder()
+            .mailetName("Test")
+            .mailetContext(mailetContext)
+            .setProperty(MAX_CHARACTERS_PARAMETER_NAME, 
String.valueOf(HEADER_NAME.length() + HEADER_SEPARATOR.length() + 
HEADER_VALUE.length()))
+            .build();
+        foldMailet.init(mailetConfig);
+
+        Mail mail = FakeMail.builder()
+            
.name("mail").mimeMessage(MimeMessageBuilder.mimeMessageBuilder().addHeader(HEADER_NAME,
 HEADER_VALUE).build())
+            .build();
+        foldMailet.service(mail);
+
+        List<Header> headers = 
Streams.of(mail.getMessage().getAllHeaders()).filter(header -> 
header.getName().equals(HEADER_NAME)).toList();
+        assertThat(headers).hasSize(1);
+        assertThat(headers.getFirst().getValue()).isEqualTo(HEADER_VALUE);
+    }
+
+    @Test
+    void 
serviceShouldNotRemoveTheHeaderThatHasTheSameNameAsHeadersWithLongLine() throws 
Exception {
+        FakeMailetConfig mailetConfig = FakeMailetConfig.builder()
+            .mailetName("Test")
+            .mailetContext(mailetContext)
+            .setProperty(MAX_CHARACTERS_PARAMETER_NAME, "40")
+            .build();
+        foldMailet.init(mailetConfig);
+
+        Mail mail = FakeMail.builder()
+            .name("mail").mimeMessage(MimeMessageBuilder.mimeMessageBuilder()
+                .addHeader(HEADER_NAME, "<b1@gmailcom>")
+                .addHeader(HEADER_NAME, HEADER_VALUE)
+                .build()
+            )
+            .build();
+        foldMailet.service(mail);
+
+        List<Header> headers = 
Streams.of(mail.getMessage().getAllHeaders()).filter(header -> 
header.getName().equals(HEADER_NAME)).toList();
+        assertThat(headers).hasSize(2);
+        SoftAssertions.assertSoftly(softly -> {
+            
assertThat(headers.getFirst().getValue()).isEqualTo("<b1@gmailcom>");
+            assertThat(headers.getLast().getValue()).isEqualTo(FOLDED_LINE);
+        });
+    }
+
+    @Test
+    void 
serviceShouldNotChangeTheRelativePositionOfTheHeaderThatHasTheSameNameAsHeadersWithLongLine()
 throws Exception {
+        FakeMailetConfig mailetConfig = FakeMailetConfig.builder()
+            .mailetName("Test")
+            .mailetContext(mailetContext)
+            .setProperty(MAX_CHARACTERS_PARAMETER_NAME, "30")
+            .build();
+        foldMailet.init(mailetConfig);
+
+        Mail mail = FakeMail.builder()
+            .name("mail").mimeMessage(MimeMessageBuilder.mimeMessageBuilder()
+                .addHeader(HEADER_NAME, HEADER_VALUE)
+                .addHeader(HEADER_NAME, "<b1@gmailcom>")
+                .addHeader(HEADER_NAME, HEADER_VALUE)
+                .build()
+            )
+            .build();
+        foldMailet.service(mail);
+
+        List<Header> headers = 
Streams.of(mail.getMessage().getAllHeaders()).filter(header -> 
header.getName().equals(HEADER_NAME)).toList();
+        assertThat(headers).hasSize(3);
+        assertThat(headers.get(1).getValue()).isEqualTo("<b1@gmailcom>");
+    }
+}
diff --git 
a/server/mailet/integration-testing/src/test/java/org/apache/james/mailets/DKIMIntegrationTest.java
 
b/server/mailet/integration-testing/src/test/java/org/apache/james/mailets/DKIMIntegrationTest.java
index 26d098b93e..920d6d78b2 100644
--- 
a/server/mailet/integration-testing/src/test/java/org/apache/james/mailets/DKIMIntegrationTest.java
+++ 
b/server/mailet/integration-testing/src/test/java/org/apache/james/mailets/DKIMIntegrationTest.java
@@ -23,6 +23,7 @@ import static 
org.apache.james.mailets.configuration.Constants.DEFAULT_DOMAIN;
 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.awaitAtMostOneMinute;
+import static 
org.apache.james.transport.mailets.FoldLongLines.MAX_CHARACTERS_PARAMETER_NAME;
 import static org.assertj.core.api.Assertions.assertThat;
 
 import java.io.File;
@@ -43,6 +44,7 @@ import org.apache.james.modules.protocols.ImapGuiceProbe;
 import org.apache.james.modules.protocols.SmtpGuiceProbe;
 import org.apache.james.probe.DataProbe;
 import org.apache.james.transport.mailets.ExtractAttributeStub;
+import org.apache.james.transport.mailets.FoldLongLines;
 import org.apache.james.transport.matchers.All;
 import org.apache.james.utils.DataProbeImpl;
 import org.apache.james.utils.SMTPMessageSender;
@@ -100,6 +102,12 @@ class DKIMIntegrationTest {
         .addProperty("attributeName", DKIMVerify.DKIM_AUTH_RESULT.asString())
         .build();
 
+    private static final MailetConfiguration FOLD_LONG_LINES_MAILET = 
MailetConfiguration.builder()
+        .matcher(All.class)
+        .mailet(FoldLongLines.class)
+        .addProperty(MAX_CHARACTERS_PARAMETER_NAME, "78")
+        .build();
+
     private static final PublicKeyRecordRetriever 
MOCK_PUBLIC_KEY_RECORD_RETRIEVER = new MockPublicKeyRecordRetriever(
             "v=DKIM1; k=rsa; 
p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDYDaYKXzwVYwqWbLhmuJ66aTAN8wmDR+rfHE8HfnkSOax0oIoTM5zquZrTLo30870YMfYzxwfB6j/Nz3QdwrUD/t0YMYJiUKyWJnCKfZXHJBJ+yfRHr7oW+UW3cVo9CG2bBfIxsInwYe175g9UjyntJpWueqdEIo1c2bhv9Mp66QIDAQAB;",
             "selector", "example.com");
@@ -231,13 +239,64 @@ class DKIMIntegrationTest {
             .hasValueSatisfying(result -> 
assertThat(result).startsWith("fail"));
     }
 
-    private void initJamesServer(File temporaryFolder, Module... 
overrideGuiceModules) throws Exception {
+    @Test
+    void 
incomingMessageShouldPassDKIMVerificationWhenLongHeadersAreFoldedBeforeSigning(@TempDir
 File temporaryFolder) throws Exception {
         MailetContainer.Builder mailetContainer = 
TemporaryJamesServer.simpleMailetContainerConfiguration()
             .putProcessor(ProcessorConfiguration.transport()
+                .addMailet(FOLD_LONG_LINES_MAILET)
                 .addMailet(DKIMSIGN_MAILET)
                 .addMailet(DKIMVERIFY_MAILET)
                 .addMailet(STUB_MAILET)
                 .addMailetsFrom(CommonProcessors.transport()));
+        initJamesServer(mailetContainer, temporaryFolder, binder -> 
binder.bind(PublicKeyRecordRetriever.class).toInstance(MOCK_PUBLIC_KEY_RECORD_RETRIEVER));
+
+        messageSender.connect(LOCALHOST_IP, 
jamesServer.getProbe(SmtpGuiceProbe.class).getSmtpPort())
+            .authenticate(FROM, PASSWORD)
+            .sendMessageWithHeaders(FROM, ImmutableList.of(RECIPIENT), 
"Return-Path: <btell...@linagora.com>\n" +
+                "Content-Type: multipart/mixed; 
boundary=\"------------dsVZbfyUhMRjfuWnqQ80tHvc\"\n" +
+                "Message-ID: 
<a7a376a1-cadb-45bc-9deb-39f749f62...@linagora.com>\n" +
+                "Date: Tue, 7 Nov 2023 12:14:47 +0100\n" +
+                "MIME-Version: 1.0\n" +
+                "User-Agent: Mozilla Thunderbird\n" +
+                "Content-Language: en-US\n" +
+                "To: btell...@linagora.com\n" +
+                "From: \"btell...@linagora.com\" <btell...@linagora.com>\n" +
+                "References: <a...@gmail.com> <a...@gmail.com> 
<a...@gmail.com> <a...@gmail.com> <a...@gmail.com> <a...@gmail.com> 
<a...@gmail.com> <a...@gmail.com>\n" +
+                "Subject: Simple message\n" +
+                "\n" +
+                "This is a multi-part message in MIME format.\n" +
+                "--------------dsVZbfyUhMRjfuWnqQ80tHvc\n" +
+                "Content-Type: text/plain; charset=UTF-8; format=flowed\n" +
+                "Content-Transfer-Encoding: 7bit\n" +
+                "\n" +
+                "Simple body\n" +
+                "\n" +
+                "--------------dsVZbfyUhMRjfuWnqQ80tHvc\n" +
+                "Content-Type: message/rfc822; name=\"BNPP ADVICE 
LOLO.eml\"\n" +
+                "Content-Disposition: attachment; filename=\"BNPP.eml\"\n" +
+                "\n" +
+                "\n" +
+                "--------------dsVZbfyUhMRjfuWnqQ80tHvc--");
+
+        testIMAPClient.connect(LOCALHOST_IP, 
jamesServer.getProbe(ImapGuiceProbe.class).getImapPort())
+            .login(RECIPIENT, PASSWORD)
+            .select(TestIMAPClient.INBOX)
+            .awaitMessage(awaitAtMostOneMinute);
+
+        assertThat(dkimAuthResults)
+            .hasSize(1);
+        assertThat(dkimAuthResults.get(0))
+            .hasValueSatisfying(result -> 
assertThat(result).startsWith("pass"));
+
+        assertThat(testIMAPClient.readFirstMessageHeaders())
+            .contains("DKIM-Signature");
+
+        assertThat(testIMAPClient.readFirstMessageHeaders())
+            .contains("References: <a...@gmail.com> <a...@gmail.com> 
<a...@gmail.com> <a...@gmail.com>\r\n" +
+                " <a...@gmail.com> <a...@gmail.com> <a...@gmail.com> 
<a...@gmail.com>");
+    }
+
+    private void initJamesServer(MailetContainer.Builder mailetContainer, File 
temporaryFolder, Module... overrideGuiceModules) throws Exception {
         jamesServer = TemporaryJamesServer
             .builder()
             .withBase(MemoryJamesServerMain.IN_MEMORY_SERVER_AGGREGATE_MODULE)
@@ -251,4 +310,14 @@ class DKIMIntegrationTest {
         dataProbe.addUser(RECIPIENT, PASSWORD);
         dataProbe.addUser(FROM, PASSWORD);
     }
+
+    private void initJamesServer(File temporaryFolder, Module... 
overrideGuiceModules) throws Exception {
+        MailetContainer.Builder mailetContainer = 
TemporaryJamesServer.simpleMailetContainerConfiguration()
+            .putProcessor(ProcessorConfiguration.transport()
+                .addMailet(DKIMSIGN_MAILET)
+                .addMailet(DKIMVERIFY_MAILET)
+                .addMailet(STUB_MAILET)
+                .addMailetsFrom(CommonProcessors.transport()));
+        initJamesServer(mailetContainer, temporaryFolder, 
overrideGuiceModules);
+    }
 }


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

Reply via email to