Skip to content

Commit d1e6ec1

Browse files
committed
Merge remote-tracking branch 'remotes/origin/#219-duplicate-attachment-names'
2 parents df377c5 + df0df01 commit d1e6ec1

File tree

4 files changed

+42
-19
lines changed

4 files changed

+42
-19
lines changed

src/main/java/org/simplejavamail/converter/EmailConverter.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -283,7 +283,7 @@ private static void buildEmailFromMimeMessage(@Nonnull final EmailPopulatingBuil
283283
final String cidName = checkNonEmptyArgument(cid.getKey(), "cid.key");
284284
builder.withEmbeddedImage(extractCID(cidName), cid.getValue());
285285
}
286-
for (final Map.Entry<String, DataSource> attachment : parsed.getAttachmentList().entrySet()) {
286+
for (final Map.Entry<String, DataSource> attachment : parsed.getAttachmentList()) {
287287
builder.withAttachment(extractCID(attachment.getKey()), attachment.getValue());
288288
}
289289
}

src/main/java/org/simplejavamail/converter/internal/mimemessage/MimeMessageParser.java

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package org.simplejavamail.converter.internal.mimemessage;
22

3+
import org.simplejavamail.internal.util.NaturalEntryKeyComparator;
4+
35
import javax.activation.DataHandler;
46
import javax.activation.DataSource;
57
import javax.annotation.Nonnull;
@@ -25,14 +27,8 @@
2527
import java.io.IOException;
2628
import java.io.InputStream;
2729
import java.io.UnsupportedEncodingException;
28-
import java.util.ArrayList;
29-
import java.util.Arrays;
30-
import java.util.Collections;
31-
import java.util.HashMap;
32-
import java.util.Iterator;
33-
import java.util.List;
34-
import java.util.Map;
35-
import java.util.TreeMap;
30+
import java.util.*;
31+
import java.util.AbstractMap.SimpleEntry;
3632

3733
import static java.lang.String.format;
3834
import static org.simplejavamail.internal.util.MiscUtil.extractCID;
@@ -133,13 +129,13 @@ private static void parseMimePartTree(@Nonnull final MimePart currentPart, @Nonn
133129
final DataSource ds = createDataSource(currentPart);
134130
// if the diposition is not provided, for now the part should be treated as inline (later non-embedded inline attachments are moved)
135131
if (Part.ATTACHMENT.equalsIgnoreCase(disposition)) {
136-
parsedComponents.attachmentList.put(parseResourceName(parseContentID(currentPart), parseFileName(currentPart)), ds);
132+
parsedComponents.attachmentList.add(new SimpleEntry<>(parseResourceNameOrUnnamed(parseContentID(currentPart), parseFileName(currentPart)), ds));
137133
} else if (disposition == null || Part.INLINE.equalsIgnoreCase(disposition)) {
138134
if (parseContentID(currentPart) != null) {
139135
parsedComponents.cidMap.put(parseContentID(currentPart), ds);
140136
} else {
141137
// contentID missing -> treat as standard attachment
142-
parsedComponents.attachmentList.put(parseResourceName(null, parseFileName(currentPart)), ds);
138+
parsedComponents.attachmentList.add(new SimpleEntry<>(parseResourceNameOrUnnamed(null, parseFileName(currentPart)), ds));
143139
}
144140
} else {
145141
throw new IllegalStateException("invalid attachment type");
@@ -219,7 +215,13 @@ public static String parseDisposition(@Nonnull final MimePart currentPart) {
219215
}
220216

221217
@Nonnull
222-
private static String parseResourceName(@Nullable final String possibleWrappedContentID, @Nonnull final String fileName) {
218+
private static String parseResourceNameOrUnnamed(@Nullable final String possibleWrappedContentID, @Nonnull final String fileName) {
219+
String resourceName = parseResourceName(possibleWrappedContentID, fileName);
220+
return valueNullOrEmpty(resourceName) ? "unnamed" : resourceName;
221+
}
222+
223+
@Nonnull
224+
private static String parseResourceName(@Nullable String possibleWrappedContentID, @Nonnull String fileName) {
223225
if (!valueNullOrEmpty(possibleWrappedContentID)) {
224226
// https://regex101.com/r/46ulb2/1
225227
String unwrappedContentID = possibleWrappedContentID.replaceAll("^<?(.*?)>?$", "$1");
@@ -231,7 +233,7 @@ private static String parseResourceName(@Nullable final String possibleWrappedCo
231233
return fileName;
232234
}
233235
}
234-
236+
235237
@SuppressWarnings("WeakerAccess")
236238
@Nonnull
237239
public static List<Header> retrieveAllHeaders(@Nonnull final MimePart part) {
@@ -454,14 +456,15 @@ static void moveInvalidEmbeddedResourcesToAttachments(ParsedMimeMessageComponent
454456
Map.Entry<String, DataSource> cidEntry = it.next();
455457
String cid = extractCID(cidEntry.getKey());
456458
if (htmlContent == null || !htmlContent.contains("cid:" + cid)) {
457-
parsedComponents.attachmentList.put(cid, cidEntry.getValue());
459+
parsedComponents.attachmentList.add(new SimpleEntry<>(cid, cidEntry.getValue()));
458460
it.remove();
459461
}
460462
}
461463
}
462464

463465
public static class ParsedMimeMessageComponents {
464-
final Map<String, DataSource> attachmentList = new TreeMap<>();
466+
@SuppressWarnings("unchecked")
467+
final Set<Map.Entry<String, DataSource>> attachmentList = new TreeSet<>(NaturalEntryKeyComparator.INSTANCE);
465468
final Map<String, DataSource> cidMap = new TreeMap<>();
466469
private final Map<String, Object> headers = new HashMap<>();
467470
private final List<InternetAddress> toAddresses = new ArrayList<>();
@@ -481,7 +484,7 @@ public String getMessageId() {
481484
return messageId;
482485
}
483486

484-
public Map<String, DataSource> getAttachmentList() {
487+
public Set<Map.Entry<String, DataSource>> getAttachmentList() {
485488
return attachmentList;
486489
}
487490

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package org.simplejavamail.internal.util;
2+
3+
import java.util.Comparator;
4+
import java.util.Map;
5+
6+
public class NaturalEntryKeyComparator<T extends Comparable<T>> implements Comparator<Map.Entry<T, Object>> {
7+
8+
public static final NaturalEntryKeyComparator INSTANCE = new NaturalEntryKeyComparator();
9+
10+
// TODO Lombok
11+
private NaturalEntryKeyComparator(){
12+
}
13+
14+
15+
@Override
16+
public int compare(Map.Entry<T, Object> o1, Map.Entry<T, Object> o2) {
17+
return o1.getKey().compareTo(o2.getKey());
18+
}
19+
}

src/test/java/org/simplejavamail/converter/internal/mimemessage/MimeMessageParserTest.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,9 @@ public void testMoveInvalidEmbeddedResourcesToAttachments_NoHtmlNoInvalid() thro
1818
moveInvalidEmbeddedResourcesToAttachments(parsedComponents);
1919

2020
assertThat(parsedComponents.cidMap).isEmpty();
21-
assertThat(parsedComponents.attachmentList).containsOnlyKeys("moo1","moo2");
21+
assertThat(parsedComponents.attachmentList).extracting("key").containsOnly("moo1", "moo2");
2222
}
23+
2324
@Test
2425
public void testMoveInvalidEmbeddedResourcesToAttachments_HtmlButNoInvalid() throws IOException {
2526
ParsedMimeMessageComponents parsedComponents = new ParsedMimeMessageComponents();
@@ -29,7 +30,7 @@ public void testMoveInvalidEmbeddedResourcesToAttachments_HtmlButNoInvalid() thr
2930
moveInvalidEmbeddedResourcesToAttachments(parsedComponents);
3031

3132
assertThat(parsedComponents.cidMap).isEmpty();
32-
assertThat(parsedComponents.attachmentList).containsOnlyKeys("moo1","moo2");
33+
assertThat(parsedComponents.attachmentList).extracting("key").containsOnly("moo1", "moo2");
3334
}
3435

3536
@Test
@@ -41,6 +42,6 @@ public void testMoveInvalidEmbeddedResourcesToAttachments_Invalid() throws IOExc
4142
moveInvalidEmbeddedResourcesToAttachments(parsedComponents);
4243

4344
assertThat(parsedComponents.cidMap).containsOnlyKeys("moo1");
44-
assertThat(parsedComponents.attachmentList).containsOnlyKeys("moo2");
45+
assertThat(parsedComponents.attachmentList).extracting("key").containsOnly("moo2");
4546
}
4647
}

0 commit comments

Comments
 (0)