diff --git a/mailbox/elasticsearch/src/main/java/org/apache/james/mailbox/elasticsearch/json/HeaderCollection.java b/mailbox/elasticsearch/src/main/java/org/apache/james/mailbox/elasticsearch/json/HeaderCollection.java index 6125ebf64e4..eef245c567f 100644 --- a/mailbox/elasticsearch/src/main/java/org/apache/james/mailbox/elasticsearch/json/HeaderCollection.java +++ b/mailbox/elasticsearch/src/main/java/org/apache/james/mailbox/elasticsearch/json/HeaderCollection.java @@ -19,12 +19,17 @@ package org.apache.james.mailbox.elasticsearch.json; -import com.google.common.annotations.VisibleForTesting; -import com.google.common.base.Preconditions; -import com.google.common.collect.ArrayListMultimap; -import com.google.common.collect.ImmutableMultimap; -import com.google.common.collect.ImmutableSet; -import com.google.common.collect.Multimap; +import java.time.ZonedDateTime; +import java.time.format.DateTimeFormatter; +import java.util.HashSet; +import java.util.Locale; +import java.util.Optional; +import java.util.Set; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.stream.Collectors; +import java.util.stream.Stream; + import org.apache.james.mailbox.store.search.SearchUtil; import org.apache.james.mime4j.codec.DecodeMonitor; import org.apache.james.mime4j.codec.DecoderUtil; @@ -37,19 +42,21 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.time.ZonedDateTime; -import java.time.format.DateTimeFormatter; -import java.util.HashSet; -import java.util.Locale; -import java.util.Optional; -import java.util.Set; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import java.util.stream.Collectors; -import java.util.stream.Stream; +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Preconditions; +import com.google.common.collect.ArrayListMultimap; +import com.google.common.collect.ImmutableMultimap; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Multimap; public class HeaderCollection { + private static String sanitizeHeaderField(String headerName) { + return DecoderUtil.decodeEncodedWords( + MimeUtil.unfold(headerName), + DecodeMonitor.SILENT); + } + public static class Builder { // Some sent e-mail have this form : Wed, 3 Jun 2015 09:05:46 +0000 (UTC) @@ -83,9 +90,10 @@ private Builder() { public Builder add(Field field) { Preconditions.checkNotNull(field); String headerName = field.getName().toLowerCase(Locale.US); - String headerValue = field.getBody(); - headers.put(headerName, DecoderUtil.decodeEncodedWords(headerValue, DecodeMonitor.SILENT)); - handleSpecificHeader(headerName, headerValue); + String sanitizedValue = sanitizeHeaderField(field.getBody()); + + headers.put(headerName, sanitizedValue); + handleSpecificHeader(headerName, sanitizedValue); return this; } @@ -121,7 +129,7 @@ private void handleSpecificHeader(String headerName, String headerValue) { private void manageAddressField(String headerName, String headerValue) { LenientAddressParser.DEFAULT - .parseAddressList(MimeUtil.unfold(headerValue)) + .parseAddressList(headerValue) .stream() .flatMap(this::convertAddressToMailboxStream) .map((mailbox) -> new EMailer(SearchUtil.getDisplayAddress(mailbox) , mailbox.getAddress())) diff --git a/mailbox/elasticsearch/src/test/java/org/apache/james/mailbox/elasticsearch/json/HeaderCollectionTest.java b/mailbox/elasticsearch/src/test/java/org/apache/james/mailbox/elasticsearch/json/HeaderCollectionTest.java index 88efd00c83d..d12cca87537 100644 --- a/mailbox/elasticsearch/src/test/java/org/apache/james/mailbox/elasticsearch/json/HeaderCollectionTest.java +++ b/mailbox/elasticsearch/src/test/java/org/apache/james/mailbox/elasticsearch/json/HeaderCollectionTest.java @@ -85,6 +85,16 @@ public void displayNamesShouldBeRetrievedWhenEncodedWord() { .contains("Frédéric MARTIN"); } + @Test + public void getHeadersShouldDecodeValues() { + HeaderCollection headerCollection = HeaderCollection.builder() + .add(new FieldImpl("From", "=?UTF-8?B?RnLDqWTDqXJpYyBNQVJUSU4=?= , Graham CROSMARIE ")) + .build(); + + assertThat(headerCollection.getHeaders().get("from")) + .containsExactly("Frédéric MARTIN , Graham CROSMARIE "); + } + @Test public void addressWithTwoDisplayNamesOnTheSameFieldShouldBeRetrieved() { HeaderCollection headerCollection = HeaderCollection.builder() @@ -94,7 +104,29 @@ public void addressWithTwoDisplayNamesOnTheSameFieldShouldBeRetrieved() { assertThat(headerCollection.getFromAddressSet()) .containsOnly(new EMailer("Christophe Hamerling", "chri.hamerling@linagora.com"), new EMailer("Graham CROSMARIE", "grah.crosmarie@linagora.com")); + } + + @Test + public void foldedFromHeaderShouldBeSupported() { + HeaderCollection headerCollection = HeaderCollection.builder() + .add(new FieldImpl("From", "Christophe Hamerling ,\r\n" + + " Graham CROSMARIE ")) + .build(); + + assertThat(headerCollection.getFromAddressSet()) + .containsOnly(new EMailer("Christophe Hamerling", "chri.hamerling@linagora.com"), + new EMailer("Graham CROSMARIE", "grah.crosmarie@linagora.com")); + } + + @Test + public void foldedHeaderShouldBeSupported() { + HeaderCollection headerCollection = HeaderCollection.builder() + .add(new FieldImpl("From", "Christophe Hamerling ,\r\n" + + " Graham CROSMARIE ")) + .build(); + assertThat(headerCollection.getHeaders().get("from")) + .containsOnly("Christophe Hamerling , Graham CROSMARIE "); } @Test