This is an automated email from the ASF dual-hosted git repository. rcordier 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 bbe9ffd979 JAMES-5431 add SanitizeMimeMessageId mailet (#2718) bbe9ffd979 is described below commit bbe9ffd97980193b69b243c63c31697e1c09b044 Author: AlaeMghirbi <alae.mghirbi6...@gmail.com> AuthorDate: Fri May 16 03:53:06 2025 +0200 JAMES-5431 add SanitizeMimeMessageId mailet (#2718) --- .../servers/partials/SanitizeMimeMessageId.adoc | 28 +++++++++ .../servers/partials/configure/mailets.adoc | 4 +- .../transport/mailets/SanitizeMimeMessageId.java | 52 ++++++++++++++++ .../mailets/SanitizeMimeMessageIdTest.java | 72 ++++++++++++++++++++++ 4 files changed, 155 insertions(+), 1 deletion(-) diff --git a/docs/modules/servers/partials/SanitizeMimeMessageId.adoc b/docs/modules/servers/partials/SanitizeMimeMessageId.adoc new file mode 100644 index 0000000000..6a45c354b3 --- /dev/null +++ b/docs/modules/servers/partials/SanitizeMimeMessageId.adoc @@ -0,0 +1,28 @@ +=== SanitizeMimeMessageId Mailet + +Some email clients, such as Outlook for Android, may send emails **without a `Message-ID` header**. + +== Why is this needed? + The absence of the `Message-ID` header can cause emails to be rejected by downstream mail servers, + as required by RFC 5322 specifications. For example, Gmail rejects messages without this header with + an error like the following: + 550-5.7.1 [IP] Messages missing a valid Message-ID header are not + 550-5.7.1 accepted. For more information, go to + 550-5.7.1 https://support.google.com/mail/?p=RfcMessageNonCompliant and review + 550 5.7.1 RFC 5322 specifications. + +To mitigate this, the `SanitizeMimeMessageId` mailet will automatically add a `Message-ID` to emails **that lack one**. + +== Configuration + +You can configure it simply by adding the following in your `mailetcontainer.xml` file: + +.... +<mailet match="All" class="SanitizeMimeMessageId"/> +.... + +== Behavior + +- If a `Message-ID` header already exists: nothing is done. +- If the header is missing: a new one is generated and added. + diff --git a/docs/modules/servers/partials/configure/mailets.adoc b/docs/modules/servers/partials/configure/mailets.adoc index adcdff20d6..d89df01b5c 100644 --- a/docs/modules/servers/partials/configure/mailets.adoc +++ b/docs/modules/servers/partials/configure/mailets.adoc @@ -147,4 +147,6 @@ include::partial$UseHeaderRecipients.adoc[] include::partial$WrapText.adoc[] -include::partial$SubAddressing.adoc[] \ No newline at end of file +include::partial$SubAddressing.adoc[] + +include::partial$SanitizeMimeMessageId.adoc[] \ No newline at end of file diff --git a/mailet/standard/src/main/java/org/apache/james/transport/mailets/SanitizeMimeMessageId.java b/mailet/standard/src/main/java/org/apache/james/transport/mailets/SanitizeMimeMessageId.java new file mode 100644 index 0000000000..4f43ad2be0 --- /dev/null +++ b/mailet/standard/src/main/java/org/apache/james/transport/mailets/SanitizeMimeMessageId.java @@ -0,0 +1,52 @@ +/**************************************************************** + * 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 jakarta.mail.MessagingException; + +import org.apache.mailet.Mail; +import org.apache.mailet.base.GenericMailet; + +/** +* The `SanitizeMimeMessageId` mailet is designed to address a specific issue where some email clients, such as Outlook for Android, do not add the MIME `Message-ID` header to the emails they send. +* The absence of the `Message-ID` header can cause emails to be rejected by downstream mail servers, +* as required by RFC 5322 specifications. +* +* Sample configuration: +* +* <pre><code> +* <mailet match="All" class="SanitizeMimeMessageId"> +* </mailet> +* </code></pre> +*/ +public class SanitizeMimeMessageId extends GenericMailet { + + @Override + public void service(Mail mail) throws MessagingException { + if (mail.getMessage().getMessageID() == null) { + mail.getMessage().saveChanges(); + } + } + + @Override + public String getMailetInfo() { + return "SanitizeMimeMessageId Mailet"; + } +} diff --git a/mailet/standard/src/test/java/org/apache/james/transport/mailets/SanitizeMimeMessageIdTest.java b/mailet/standard/src/test/java/org/apache/james/transport/mailets/SanitizeMimeMessageIdTest.java new file mode 100644 index 0000000000..9ca4c10c88 --- /dev/null +++ b/mailet/standard/src/test/java/org/apache/james/transport/mailets/SanitizeMimeMessageIdTest.java @@ -0,0 +1,72 @@ +/**************************************************************** + * 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.assertj.core.api.Assertions.assertThat; + +import java.util.Properties; + +import jakarta.mail.Session; +import jakarta.mail.internet.MimeMessage; + +import org.apache.mailet.base.test.FakeMail; +import org.apache.mailet.base.test.FakeMailetConfig; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +public class SanitizeMimeMessageIdTest { + + private SanitizeMimeMessageId testee; + + @BeforeEach + public void setUp() throws Exception { + testee = new SanitizeMimeMessageId(); + testee.init(FakeMailetConfig.builder() + .mailetName("SanitizeMimeMessageId") + .build()); + } + + @Test + public void shouldAddMessageIdWhenMissing() throws Exception { + MimeMessage mimeMessage = new MimeMessage(Session.getDefaultInstance(new Properties())); + FakeMail mail = FakeMail.builder() + .name("mail") + .mimeMessage(mimeMessage) + .build(); + + testee.service(mail); + + assertThat(mail.getMessage().getHeader("Message-ID")).isNotNull(); + } + + @Test + public void shouldNotModifyExistingMessageId() throws Exception { + MimeMessage mimeMessage = new MimeMessage(Session.getDefaultInstance(new Properties())); + mimeMessage.setHeader("Message-ID", "<existing...@domain.com>"); + FakeMail mail = FakeMail.builder() + .name("mail") + .mimeMessage(mimeMessage) + .build(); + + testee.service(mail); + + assertThat(mail.getMessage().getHeader("Message-ID")).containsExactly("<existing...@domain.com>"); + } +} + --------------------------------------------------------------------- To unsubscribe, e-mail: notifications-unsubscr...@james.apache.org For additional commands, e-mail: notifications-h...@james.apache.org