Skip to content

Commit df0df01

Browse files
committed
Streamlining code, fixed regression bug where the attachment names are not ordered anymore, breaking unit tests
1 parent a675673 commit df0df01

File tree

3 files changed

+40
-23
lines changed

3 files changed

+40
-23
lines changed

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

Lines changed: 17 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;
@@ -26,6 +28,7 @@
2628
import java.io.InputStream;
2729
import java.io.UnsupportedEncodingException;
2830
import java.util.*;
31+
import java.util.AbstractMap.SimpleEntry;
2932

3033
import static java.lang.String.format;
3134
import static org.simplejavamail.internal.util.MiscUtil.extractCID;
@@ -126,21 +129,13 @@ private static void parseMimePartTree(@Nonnull final MimePart currentPart, @Nonn
126129
final DataSource ds = createDataSource(currentPart);
127130
// if the diposition is not provided, for now the part should be treated as inline (later non-embedded inline attachments are moved)
128131
if (Part.ATTACHMENT.equalsIgnoreCase(disposition)) {
129-
String resourceName = parseResourceName(parseContentID(currentPart), parseFileName(currentPart));
130-
if (valueNullOrEmpty(resourceName)) {
131-
resourceName = "unnamed";
132-
}
133-
parsedComponents.attachmentList.add(new AbstractMap.SimpleEntry(resourceName, ds));
132+
parsedComponents.attachmentList.add(new SimpleEntry<>(parseResourceNameOrUnnamed(parseContentID(currentPart), parseFileName(currentPart)), ds));
134133
} else if (disposition == null || Part.INLINE.equalsIgnoreCase(disposition)) {
135134
if (parseContentID(currentPart) != null) {
136135
parsedComponents.cidMap.put(parseContentID(currentPart), ds);
137136
} else {
138137
// contentID missing -> treat as standard attachment
139-
String resourceName = parseResourceName(null, parseFileName(currentPart));
140-
if (valueNullOrEmpty(resourceName)) {
141-
resourceName = "unnamed";
142-
}
143-
parsedComponents.attachmentList.add(new AbstractMap.SimpleEntry(resourceName, ds));
138+
parsedComponents.attachmentList.add(new SimpleEntry<>(parseResourceNameOrUnnamed(null, parseFileName(currentPart)), ds));
144139
}
145140
} else {
146141
throw new IllegalStateException("invalid attachment type");
@@ -220,7 +215,13 @@ public static String parseDisposition(@Nonnull final MimePart currentPart) {
220215
}
221216

222217
@Nonnull
223-
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) {
224225
if (!valueNullOrEmpty(possibleWrappedContentID)) {
225226
// https://regex101.com/r/46ulb2/1
226227
String unwrappedContentID = possibleWrappedContentID.replaceAll("^<?(.*?)>?$", "$1");
@@ -232,7 +233,7 @@ private static String parseResourceName(@Nullable final String possibleWrappedCo
232233
return fileName;
233234
}
234235
}
235-
236+
236237
@SuppressWarnings("WeakerAccess")
237238
@Nonnull
238239
public static List<Header> retrieveAllHeaders(@Nonnull final MimePart part) {
@@ -455,14 +456,15 @@ static void moveInvalidEmbeddedResourcesToAttachments(ParsedMimeMessageComponent
455456
Map.Entry<String, DataSource> cidEntry = it.next();
456457
String cid = extractCID(cidEntry.getKey());
457458
if (htmlContent == null || !htmlContent.contains("cid:" + cid)) {
458-
parsedComponents.attachmentList.add(new AbstractMap.SimpleEntry(cid, cidEntry.getValue()));
459+
parsedComponents.attachmentList.add(new SimpleEntry<>(cid, cidEntry.getValue()));
459460
it.remove();
460461
}
461462
}
462463
}
463464

464465
public static class ParsedMimeMessageComponents {
465-
final List<Map.Entry<String, DataSource>> attachmentList = new ArrayList<>();
466+
@SuppressWarnings("unchecked")
467+
final Set<Map.Entry<String, DataSource>> attachmentList = new TreeSet<>(NaturalEntryKeyComparator.INSTANCE);
466468
final Map<String, DataSource> cidMap = new TreeMap<>();
467469
private final Map<String, Object> headers = new HashMap<>();
468470
private final List<InternetAddress> toAddresses = new ArrayList<>();
@@ -482,7 +484,7 @@ public String getMessageId() {
482484
return messageId;
483485
}
484486

485-
public List<Map.Entry<String, DataSource>> getAttachmentList() {
487+
public Set<Map.Entry<String, DataSource>> getAttachmentList() {
486488
return attachmentList;
487489
}
488490

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 & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,9 @@ public void testMoveInvalidEmbeddedResourcesToAttachments_NoHtmlNoInvalid() thro
1818
moveInvalidEmbeddedResourcesToAttachments(parsedComponents);
1919

2020
assertThat(parsedComponents.cidMap).isEmpty();
21-
assertThat(parsedComponents.attachmentList.size()).isEqualTo(2);
22-
assertThat(parsedComponents.attachmentList.get(0).getKey()).isEqualTo("moo1");
23-
assertThat(parsedComponents.attachmentList.get(1).getKey()).isEqualTo("moo2");
21+
assertThat(parsedComponents.attachmentList).extracting("key").containsOnly("moo1", "moo2");
2422
}
23+
2524
@Test
2625
public void testMoveInvalidEmbeddedResourcesToAttachments_HtmlButNoInvalid() throws IOException {
2726
ParsedMimeMessageComponents parsedComponents = new ParsedMimeMessageComponents();
@@ -31,9 +30,7 @@ public void testMoveInvalidEmbeddedResourcesToAttachments_HtmlButNoInvalid() thr
3130
moveInvalidEmbeddedResourcesToAttachments(parsedComponents);
3231

3332
assertThat(parsedComponents.cidMap).isEmpty();
34-
assertThat(parsedComponents.attachmentList.size()).isEqualTo(2);
35-
assertThat(parsedComponents.attachmentList.get(0).getKey()).isEqualTo("moo1");
36-
assertThat(parsedComponents.attachmentList.get(1).getKey()).isEqualTo("moo2");
33+
assertThat(parsedComponents.attachmentList).extracting("key").containsOnly("moo1", "moo2");
3734
}
3835

3936
@Test
@@ -45,7 +42,6 @@ public void testMoveInvalidEmbeddedResourcesToAttachments_Invalid() throws IOExc
4542
moveInvalidEmbeddedResourcesToAttachments(parsedComponents);
4643

4744
assertThat(parsedComponents.cidMap).containsOnlyKeys("moo1");
48-
assertThat(parsedComponents.attachmentList.size()).isEqualTo(1);
49-
assertThat(parsedComponents.attachmentList.get(0).getKey()).isEqualTo("moo2");
45+
assertThat(parsedComponents.attachmentList).extracting("key").containsOnly("moo2");
5046
}
5147
}

0 commit comments

Comments
 (0)