From 56474a5ef5dc2fccea74d14ec2a4f44b70578bbb Mon Sep 17 00:00:00 2001 From: Artem Bilan Date: Wed, 5 May 2021 16:56:01 -0400 Subject: [PATCH] GH-3560 Parse mail FROM as comma-delimited header (#3562) Fixes https://github.com/spring-projects/spring-integration/issues/3560 According RFC 5322 `FROM` and `REPLY-TO` received mail message can be as an array of addresses. * Fix `MailUtils` to present those arrays as comma-delimited strings for Spring message headers * Fix tests to deal already with several addresses for `FROM` mime header. In the future we may change the logic to map those mime headers to arrays as it states according the mentioned RFC **Cherry-pick to `5.4.x` & `5.3.x`** --- .../integration/mail/support/MailUtils.java | 24 +++++++------------ .../mail/ImapMailReceiverTests.java | 4 +--- .../integration/mail/config/Pop3Tests.java | 2 +- .../integration/mail/dsl/MailTests.java | 2 +- .../integration/test/mail/TestMailServer.java | 2 +- 5 files changed, 13 insertions(+), 21 deletions(-) diff --git a/spring-integration-mail/src/main/java/org/springframework/integration/mail/support/MailUtils.java b/spring-integration-mail/src/main/java/org/springframework/integration/mail/support/MailUtils.java index 44909442a5..91999a11b7 100644 --- a/spring-integration-mail/src/main/java/org/springframework/integration/mail/support/MailUtils.java +++ b/spring-integration-mail/src/main/java/org/springframework/integration/mail/support/MailUtils.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019 the original author or authors. + * Copyright 2016-2021 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -25,12 +25,14 @@ import javax.mail.Message.RecipientType; import org.springframework.integration.mail.MailHeaders; import org.springframework.messaging.MessagingException; -import org.springframework.util.Assert; +import org.springframework.util.StringUtils; /** * Utilities for handling mail messages. * * @author Gary Russell + * @author Artem Bilan + * * @since 4.3 * */ @@ -47,29 +49,21 @@ public final class MailUtils { * @return the map. */ public static Map extractStandardHeaders(Message source) { - Map headers = new HashMap(); + Map headers = new HashMap<>(); try { - headers.put(MailHeaders.FROM, convertToString(source.getFrom())); + headers.put(MailHeaders.FROM, StringUtils.arrayToCommaDelimitedString(source.getFrom())); headers.put(MailHeaders.BCC, convertToStringArray(source.getRecipients(RecipientType.BCC))); headers.put(MailHeaders.CC, convertToStringArray(source.getRecipients(RecipientType.CC))); headers.put(MailHeaders.TO, convertToStringArray(source.getRecipients(RecipientType.TO))); - headers.put(MailHeaders.REPLY_TO, convertToString(source.getReplyTo())); + headers.put(MailHeaders.REPLY_TO, StringUtils.arrayToCommaDelimitedString(source.getReplyTo())); headers.put(MailHeaders.SUBJECT, source.getSubject()); return headers; } - catch (Exception e) { - throw new MessagingException("conversion of MailMessage headers failed", e); + catch (Exception ex) { + throw new MessagingException("conversion of MailMessage headers failed", ex); } } - private static String convertToString(Address[] addresses) { - if (addresses == null || addresses.length == 0) { - return null; - } - Assert.state(addresses.length == 1, "expected a single value but received an Array"); - return addresses[0].toString(); - } - private static String[] convertToStringArray(Address[] addresses) { if (addresses != null) { String[] addressStrings = new String[addresses.length]; diff --git a/spring-integration-mail/src/test/java/org/springframework/integration/mail/ImapMailReceiverTests.java b/spring-integration-mail/src/test/java/org/springframework/integration/mail/ImapMailReceiverTests.java index 1a496d9836..bbcd7435ad 100644 --- a/spring-integration-mail/src/test/java/org/springframework/integration/mail/ImapMailReceiverTests.java +++ b/spring-integration-mail/src/test/java/org/springframework/integration/mail/ImapMailReceiverTests.java @@ -72,7 +72,6 @@ import org.springframework.integration.channel.QueueChannel; import org.springframework.integration.handler.AbstractReplyProducingMessageHandler; import org.springframework.integration.history.MessageHistory; import org.springframework.integration.mail.support.DefaultMailHeaderMapper; -import org.springframework.integration.test.condition.LongRunningTest; import org.springframework.integration.test.mail.TestMailServer; import org.springframework.integration.test.mail.TestMailServer.ImapServer; import org.springframework.integration.test.util.TestUtils; @@ -97,7 +96,6 @@ import com.sun.mail.imap.IMAPFolder; @ContextConfiguration( "classpath:org/springframework/integration/mail/config/ImapIdleChannelAdapterParserTests-context.xml") @DirtiesContext -@LongRunningTest public class ImapMailReceiverTests { private AtomicInteger failed; @@ -707,7 +705,7 @@ public class ImapMailReceiverTests { @Test // see INT-1801 public void testImapLifecycleForRaceCondition() throws Exception { - for (int i = 0; i < 1000; i++) { + for (int i = 0; i < 100; i++) { final ImapMailReceiver receiver = new ImapMailReceiver("imap://foo"); Store store = mock(Store.class); Folder folder = mock(Folder.class); diff --git a/spring-integration-mail/src/test/java/org/springframework/integration/mail/config/Pop3Tests.java b/spring-integration-mail/src/test/java/org/springframework/integration/mail/config/Pop3Tests.java index 9b3fb2ad87..bb02493539 100644 --- a/spring-integration-mail/src/test/java/org/springframework/integration/mail/config/Pop3Tests.java +++ b/spring-integration-mail/src/test/java/org/springframework/integration/mail/config/Pop3Tests.java @@ -67,7 +67,7 @@ public class Pop3Tests { assertThat(headers.get(MailHeaders.TO, String[].class)[0]).isEqualTo("Foo "); assertThat(Arrays.toString(headers.get(MailHeaders.CC, String[].class))).isEqualTo("[a@b, c@d]"); assertThat(Arrays.toString(headers.get(MailHeaders.BCC, String[].class))).isEqualTo("[e@f, g@h]"); - assertThat(headers.get(MailHeaders.FROM)).isEqualTo("Bar "); + assertThat(headers.get(MailHeaders.FROM)).isEqualTo("Bar ,Bar2 "); assertThat(headers.get(MailHeaders.SUBJECT)).isEqualTo("Test Email"); assertThat(message.getPayload()).isEqualTo("foo\r\n\r\n"); } diff --git a/spring-integration-mail/src/test/java/org/springframework/integration/mail/dsl/MailTests.java b/spring-integration-mail/src/test/java/org/springframework/integration/mail/dsl/MailTests.java index 151c81f35f..9771dabd90 100644 --- a/spring-integration-mail/src/test/java/org/springframework/integration/mail/dsl/MailTests.java +++ b/spring-integration-mail/src/test/java/org/springframework/integration/mail/dsl/MailTests.java @@ -141,7 +141,7 @@ public class MailTests { assertThat(message).isNotNull(); MessageHeaders headers = message.getHeaders(); assertThat(headers.get(MailHeaders.TO, String[].class)).containsExactly("Foo "); - assertThat(headers.get(MailHeaders.FROM)).isEqualTo("Bar "); + assertThat(headers.get(MailHeaders.FROM)).isEqualTo("Bar ,Bar2 "); assertThat(headers.get(MailHeaders.SUBJECT)).isEqualTo("Test Email"); assertThat(message.getPayload()).isEqualTo("foo\r\n\r\n"); assertThat(message.getHeaders().containsKey(IntegrationMessageHeaderAccessor.CLOSEABLE_RESOURCE)).isTrue(); diff --git a/spring-integration-test-support/src/main/java/org/springframework/integration/test/mail/TestMailServer.java b/spring-integration-test-support/src/main/java/org/springframework/integration/test/mail/TestMailServer.java index d9ad5e45f3..b707692a96 100644 --- a/spring-integration-test-support/src/main/java/org/springframework/integration/test/mail/TestMailServer.java +++ b/spring-integration-test-support/src/main/java/org/springframework/integration/test/mail/TestMailServer.java @@ -489,7 +489,7 @@ public final class TestMailServer { "To: Foo \r\n" + "cc: a@b, c@d\r\n" + "bcc: e@f, g@h\r\n" - + "From: Bar \r\n" + + "From: Bar , Bar2 \r\n" + "Subject: Test Email\r\n" + "\r\n" + BODY;