Repository: james-project Updated Branches: refs/heads/master 46fd66b6e -> 4c27ed7ad
JAMES-2235 Contact Extractor should accept non stritly parsable recipients Project: http://git-wip-us.apache.org/repos/asf/james-project/repo Commit: http://git-wip-us.apache.org/repos/asf/james-project/commit/bbb1a4c2 Tree: http://git-wip-us.apache.org/repos/asf/james-project/tree/bbb1a4c2 Diff: http://git-wip-us.apache.org/repos/asf/james-project/diff/bbb1a4c2 Branch: refs/heads/master Commit: bbb1a4c2d0b32d12c2a482d8491f3a63a194e759 Parents: 2249568 Author: Raphael Ouazana <[email protected]> Authored: Thu Nov 23 14:07:08 2017 +0100 Committer: Matthieu Baechler <[email protected]> Committed: Wed Nov 29 10:55:57 2017 +0100 ---------------------------------------------------------------------- .../mailet/base/test/MimeMessageBuilder.java | 4 ++ .../transport/mailets/ContactExtractor.java | 55 +++++++++++----- .../transport/mailets/ContactExtractorTest.java | 69 ++++++++++++++++++-- 3 files changed, 109 insertions(+), 19 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/james-project/blob/bbb1a4c2/mailet/base/src/test/java/org/apache/mailet/base/test/MimeMessageBuilder.java ---------------------------------------------------------------------- diff --git a/mailet/base/src/test/java/org/apache/mailet/base/test/MimeMessageBuilder.java b/mailet/base/src/test/java/org/apache/mailet/base/test/MimeMessageBuilder.java index 91dafc9..498a6ff 100644 --- a/mailet/base/src/test/java/org/apache/mailet/base/test/MimeMessageBuilder.java +++ b/mailet/base/src/test/java/org/apache/mailet/base/test/MimeMessageBuilder.java @@ -192,6 +192,10 @@ public class MimeMessageBuilder { return new MimeMessage(Session.getDefaultInstance(new Properties()), inputStream); } + public static MimeMessage mimeMessageFromBytes(byte[] bytes) throws MessagingException { + return mimeMessageFromStream(new ByteArrayInputStream(bytes)); + } + public static MimeMessageBuilder mimeMessageBuilder() { return new MimeMessageBuilder(); } http://git-wip-us.apache.org/repos/asf/james-project/blob/bbb1a4c2/mailet/standard/src/main/java/org/apache/james/transport/mailets/ContactExtractor.java ---------------------------------------------------------------------- diff --git a/mailet/standard/src/main/java/org/apache/james/transport/mailets/ContactExtractor.java b/mailet/standard/src/main/java/org/apache/james/transport/mailets/ContactExtractor.java index 6c8f23e..c363f06 100644 --- a/mailet/standard/src/main/java/org/apache/james/transport/mailets/ContactExtractor.java +++ b/mailet/standard/src/main/java/org/apache/james/transport/mailets/ContactExtractor.java @@ -21,13 +21,19 @@ package org.apache.james.transport.mailets; import java.io.IOException; import java.util.Arrays; import java.util.Optional; +import java.util.function.Function; +import java.util.stream.Stream; import javax.mail.Address; +import javax.mail.Message; +import javax.mail.Message.RecipientType; import javax.mail.MessagingException; +import javax.mail.internet.InternetAddress; import javax.mail.internet.MimeMessage; import org.apache.james.core.MailAddress; import org.apache.james.mime4j.util.MimeUtil; +import org.apache.james.util.StreamUtils; import org.apache.mailet.Mail; import org.apache.mailet.Mailet; import org.apache.mailet.MailetException; @@ -95,26 +101,45 @@ public class ContactExtractor extends GenericMailet implements Mailet { } } - private Optional<String> extractContacts(Mail mail) throws MessagingException, IOException { - MimeMessage message = mail.getMessage(); + @VisibleForTesting + Optional<String> extractContacts(Mail mail) throws MessagingException, IOException { + ImmutableList<String> allRecipients = getAllRecipients(mail.getMessage()); - return Optional.of(mail.getSender()) - .map(MailAddress::asString) - .filter(Throwing.predicate(sender -> hasRecipients(message))) - .map(Throwing.function(sender -> new ExtractedContacts(sender, recipients(message)))) - .map(Throwing.function(extractedContacts -> objectMapper.writeValueAsString(extractedContacts))); + if (hasRecipient(allRecipients)) { + return Optional.of(mail.getSender()) + .map(MailAddress::asString) + .map(sender -> new ExtractedContacts(sender, allRecipients)) + .map(Throwing.function(extractedContacts -> objectMapper.writeValueAsString(extractedContacts))); + } + + return Optional.empty(); + } + + private boolean hasRecipient(ImmutableList<String> allRecipients) { + return !allRecipients.isEmpty(); } - @VisibleForTesting boolean hasRecipients(MimeMessage mimeMessage) throws MessagingException { - return mimeMessage.getAllRecipients() != null - && mimeMessage.getAllRecipients().length > 0; + private ImmutableList<String> getAllRecipients(MimeMessage mimeMessage) throws MessagingException { + return StreamUtils + .flatten( + getRecipients(mimeMessage, Message.RecipientType.TO), + getRecipients(mimeMessage, Message.RecipientType.CC), + getRecipients(mimeMessage, Message.RecipientType.BCC)) + .collect(Guavate.toImmutableList()); } - private ImmutableList<String> recipients(MimeMessage mimeMessage) throws MessagingException { - return Arrays.stream(mimeMessage.getAllRecipients()) - .map(Address::toString) - .map(MimeUtil::unscrambleHeaderValue) - .collect(Guavate.toImmutableList()); + private Stream<String> getRecipients(MimeMessage mimeMessage, RecipientType recipientType) throws MessagingException { + boolean notStrict = false; + Function<String, InternetAddress[]> parseRecipient = + Throwing + .function((String header) -> InternetAddress.parseHeader(header, notStrict)) + .sneakyThrow(); + return Optional.ofNullable(mimeMessage.getHeader(recipientType.toString(), ",")) + .map(parseRecipient) + .map(Arrays::stream) + .orElse(Stream.empty()) + .map(Address::toString) + .map(MimeUtil::unscrambleHeaderValue); } public static class ExtractedContacts { http://git-wip-us.apache.org/repos/asf/james-project/blob/bbb1a4c2/mailet/standard/src/test/java/org/apache/james/transport/mailets/ContactExtractorTest.java ---------------------------------------------------------------------- diff --git a/mailet/standard/src/test/java/org/apache/james/transport/mailets/ContactExtractorTest.java b/mailet/standard/src/test/java/org/apache/james/transport/mailets/ContactExtractorTest.java index ccde3d6..7546025 100644 --- a/mailet/standard/src/test/java/org/apache/james/transport/mailets/ContactExtractorTest.java +++ b/mailet/standard/src/test/java/org/apache/james/transport/mailets/ContactExtractorTest.java @@ -162,6 +162,66 @@ public class ContactExtractorTest { } @Test + public void serviceShouldUnscrambleRecipientsWhenNameContainsSuperiors() throws Exception { + String rawMessage = "From: [email protected]\r\n" + + "To: =?UTF-8?Q?recip_>>_Fr=c3=a9d=c3=a9ric_RECIPIENT?= <[email protected]>\r\n" + + "Subject: extract this recipient please\r\n" + + "\r\n" + + "Please!"; + MimeMessage message = MimeMessageBuilder.mimeMessageFromBytes(rawMessage.getBytes()); + FakeMail mail = FakeMail.builder().mimeMessage(message) + .sender(new MailAddress(SENDER)) + .recipient(new MailAddress("[email protected]")) + .build(); + mailet.init(mailetConfig); + + String expectedMessage = "{\"userEmail\" : \"" + SENDER + "\", \"emails\" : [ \"\\\"recip >> Frédéric RECIPIENT\\\" <[email protected]>\" ]}"; + mailet.service(mail); + + assertThatJson(mail.getAttribute(ATTRIBUTE).toString()).isEqualTo(expectedMessage); + } + + @Test + public void serviceShouldParseMultipleRecipients() throws Exception { + String rawMessage = "From: [email protected]\r\n" + + "To: User 1 <[email protected]>, =?UTF-8?Q?recip_>>_Fr=c3=a9d=c3=a9ric_RECIPIENT?= <[email protected]>\r\n" + + "Subject: extract this recipient please\r\n" + + "\r\n" + + "Please!"; + MimeMessage message = MimeMessageBuilder.mimeMessageFromBytes(rawMessage.getBytes()); + FakeMail mail = FakeMail.builder().mimeMessage(message) + .sender(new MailAddress(SENDER)) + .recipient(new MailAddress("[email protected]")) + .build(); + mailet.init(mailetConfig); + + String expectedMessage = "{\"userEmail\" : \"" + SENDER + "\", \"emails\" : [ \"User 1 <[email protected]>\", \"\\\"recip >> Frédéric RECIPIENT\\\" <[email protected]>\" ]}"; + mailet.service(mail); + + assertThatJson(mail.getAttribute(ATTRIBUTE).toString()).isEqualTo(expectedMessage); + } + + @Test + public void serviceShouldParseRecipientWithCommaInName() throws Exception { + String rawMessage = "From: [email protected]\r\n" + + "To: \"User, the first one\" <[email protected]>\r\n" + + "Subject: extract this recipient please\r\n" + + "\r\n" + + "Please!"; + MimeMessage message = MimeMessageBuilder.mimeMessageFromBytes(rawMessage.getBytes()); + FakeMail mail = FakeMail.builder().mimeMessage(message) + .sender(new MailAddress(SENDER)) + .recipient(new MailAddress("[email protected]")) + .build(); + mailet.init(mailetConfig); + + String expectedMessage = "{\"userEmail\" : \"" + SENDER + "\", \"emails\" : [ \"\\\"User, the first one\\\" <[email protected]>\" ]}"; + mailet.service(mail); + + assertThatJson(mail.getAttribute(ATTRIBUTE).toString()).isEqualTo(expectedMessage); + } + + @Test public void serviceShouldNotOverwriteSenderWhenDifferentFromField() throws Exception { MimeMessage message = MimeMessageBuilder.mimeMessageBuilder() .addFrom("[email protected]") @@ -236,15 +296,16 @@ public class ContactExtractorTest { } @Test - public void hasRecipientsShouldNotThrowWhenNoRecipient() throws Exception { + public void extractContactsShouldNotThrowWhenNoRecipient() throws Exception { MimeMessage message = MimeMessageBuilder.mimeMessageBuilder() .setSender(SENDER) .setSubject("Contact collection Rocks") .setText("This is my email") .build(); + FakeMail mail = FakeMail.builder().mimeMessage(message) + .sender(new MailAddress(SENDER)) + .build(); - boolean hasRecipients = mailet.hasRecipients(message); - - assertThat(hasRecipients).isFalse(); + mailet.extractContacts(mail); } } \ No newline at end of file --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
