11package org .simplejavamail .converter .internal .mimemessage ;
22
3- import jakarta .activation .CommandMap ;
4- import jakarta .activation .MailcapCommandMap ;
5- import lombok .Getter ;
6- import org .eclipse .angus .mail .handlers .text_plain ;
7- import jakarta .activation .ActivationDataFlavor ;
8- import jakarta .activation .DataHandler ;
9- import jakarta .activation .DataSource ;
3+ import jakarta .activation .*;
104import jakarta .mail .Address ;
115import jakarta .mail .Message .RecipientType ;
126import jakarta .mail .MessagingException ;
137import jakarta .mail .Multipart ;
148import jakarta .mail .Part ;
15- import jakarta .mail .internet .AddressException ;
16- import jakarta .mail .internet .ContentType ;
17- import jakarta .mail .internet .InternetAddress ;
18- import jakarta .mail .internet .MimeBodyPart ;
19- import jakarta .mail .internet .MimeMessage ;
20- import jakarta .mail .internet .MimePart ;
21- import jakarta .mail .internet .MimeUtility ;
22- import jakarta .mail .internet .ParseException ;
9+ import jakarta .mail .internet .*;
2310import jakarta .mail .util .ByteArrayDataSource ;
11+ import lombok .Getter ;
2412import lombok .val ;
13+ import org .eclipse .angus .mail .handlers .text_plain ;
2514import org .jetbrains .annotations .NotNull ;
2615import org .jetbrains .annotations .Nullable ;
27- import org .simplejavamail .api .internal .general .HeadersToIgnoreWhenParsingExternalEmails ;
2816import org .simplejavamail .internal .util .MiscUtil ;
2917import org .simplejavamail .internal .util .NamedDataSource ;
3018import org .simplejavamail .internal .util .Preconditions ;
19+ import org .slf4j .Logger ;
3120
3221import java .io .IOException ;
3322import java .io .InputStream ;
3423import java .io .UnsupportedEncodingException ;
35- import java .util .ArrayList ;
36- import java .util .Arrays ;
37- import java .util .Collection ;
38- import java .util .Collections ;
39- import java .util .Date ;
40- import java .util .HashMap ;
41- import java .util .Iterator ;
42- import java .util .List ;
43- import java .util .Map ;
44- import java .util .Set ;
45- import java .util .TreeMap ;
46- import java .util .TreeSet ;
24+ import java .util .*;
4725import java .util .regex .Matcher ;
4826import java .util .regex .Pattern ;
4927
5432import static java .util .stream .Collectors .toList ;
5533import static org .simplejavamail .internal .util .MiscUtil .extractCID ;
5634import static org .simplejavamail .internal .util .MiscUtil .valueNullOrEmpty ;
35+ import static org .slf4j .LoggerFactory .getLogger ;
5736
5837/**
5938 * Parses a MimeMessage and stores the individual parts such a plain text, HTML text and attachments.
6241 */
6342public final class MimeMessageParser {
6443
44+ private static final Logger LOGGER = getLogger (MimeMessageParser .class );
45+
6546 static {
6647 MailcapCommandMap mc = (MailcapCommandMap ) CommandMap .getDefaultCommandMap ();
6748 mc .addMailcap ("text/calendar;; x-java-content-handler=" + text_calendar .class .getName ());
@@ -116,20 +97,26 @@ private static void parseMimePartTree(@NotNull final MimePart currentPart, @NotN
11697 parseMimePartTree (getBodyPartAtIndex (mp , i ), parsedComponents , fetchAttachmentData );
11798 }
11899 } else {
119- final DataSource ds = createDataSource (currentPart , fetchAttachmentData );
120- // if the diposition is not provided, for now the part should be treated as inline (later non-embedded inline attachments are moved)
121- if (Part .ATTACHMENT .equalsIgnoreCase (disposition )) {
122- parsedComponents .attachmentList .add (parseAttachment (parseContentID (currentPart ), currentPart , ds ));
123- } else if (disposition == null || Part .INLINE .equalsIgnoreCase (disposition )) {
124- if (parseContentID (currentPart ) != null ) {
125- parsedComponents .cidMap .put (parseContentID (currentPart ), ds );
126- } else {
127- // contentID missing -> treat as standard attachment
128- parsedComponents .attachmentList .add (parseAttachment (null , currentPart , ds ));
129- }
130- } else {
131- throw new IllegalStateException ("invalid attachment type" );
132- }
100+ parseDataSource (currentPart , parsedComponents , fetchAttachmentData , disposition );
101+ }
102+ }
103+
104+ private static void parseDataSource (@ NotNull MimePart currentPart , @ NotNull ParsedMimeMessageComponents parsedComponents , boolean fetchAttachmentData , String disposition ) {
105+ final String contentID = parseContentID (currentPart );
106+ final MimeDataSource mimeDataSource = parseAttachment (contentID , currentPart , createDataSource (currentPart , fetchAttachmentData ));
107+ final boolean isAttachment = Part .ATTACHMENT .equalsIgnoreCase (disposition );
108+ final boolean isInline = Part .INLINE .equalsIgnoreCase (disposition );
109+
110+ if (disposition != null && !isAttachment && !isInline ) {
111+ LOGGER .warn ("Content-Disposition '{}' for data source not recognized (it should be either 'attachment' or 'inline'). Skipping body part" , disposition );
112+ }
113+
114+ if (!isInline || contentID == null ) {
115+ parsedComponents .attachmentList .add (mimeDataSource );
116+ }
117+ if (contentID != null ) {
118+ parsedComponents .cidMap .put (contentID , mimeDataSource );
119+ // when parsing is done, we'll move any sources from cidMap that are not referenced in HTML, to attachments (or remove if already there)
133120 }
134121 }
135122
@@ -545,11 +532,11 @@ public static Date parseSentDate(@NotNull final MimeMessage mimeMessage) {
545532
546533 static void moveInvalidEmbeddedResourcesToAttachments (ParsedMimeMessageComponents parsedComponents ) {
547534 final String htmlContent = parsedComponents .htmlContent .toString ();
548- for (Iterator <Map .Entry <String , DataSource >> it = parsedComponents .cidMap .entrySet ().iterator (); it .hasNext (); ) {
549- Map .Entry <String , DataSource > cidEntry = it .next ();
535+ for (Iterator <Map .Entry <String , MimeDataSource >> it = parsedComponents .cidMap .entrySet ().iterator (); it .hasNext (); ) {
536+ Map .Entry <String , MimeDataSource > cidEntry = it .next ();
550537 String cid = extractCID (cidEntry .getKey ());
551538 if (!htmlContent .contains ("cid:" + cid )) {
552- parsedComponents .attachmentList .add (new MimeDataSource ( cid , cidEntry .getValue (), null , null ));
539+ parsedComponents .attachmentList .add (cidEntry .getValue ());
553540 it .remove ();
554541 }
555542 }
@@ -558,7 +545,7 @@ static void moveInvalidEmbeddedResourcesToAttachments(ParsedMimeMessageComponent
558545 @ Getter
559546 public static class ParsedMimeMessageComponents {
560547 final Set <MimeDataSource > attachmentList = new TreeSet <>();
561- final Map <String , DataSource > cidMap = new TreeMap <>();
548+ final Map <String , MimeDataSource > cidMap = new TreeMap <>();
562549 private final Map <String , Collection <Object >> headers = new HashMap <>();
563550 private final List <InternetAddress > toAddresses = new ArrayList <>();
564551 private final List <InternetAddress > ccAddresses = new ArrayList <>();
@@ -608,4 +595,4 @@ protected ActivationDataFlavor[] getDataFlavors() {
608595 return myDF ;
609596 }
610597 }
611- }
598+ }
0 commit comments