diff --git a/pkg/message/parser.go b/pkg/message/parser.go index f93d1a85..052d7d12 100644 --- a/pkg/message/parser.go +++ b/pkg/message/parser.go @@ -503,12 +503,15 @@ func parseAttachment(h message.Header) (*pmapi.Attachment, error) { } att.Header = mimeHeader - mimeType, _, err := h.ContentType() + mimeType, mimeTypeParams, err := h.ContentType() if err != nil { return nil, err } att.MIMEType = mimeType + // Prefer attachment name from filename param in content disposition. + // If not available, try to get it from name param in content type. + // Otherwise fallback to attachment.bin. _, dispParams, dispErr := h.ContentDisposition() if dispErr != nil { ext, err := mime.ExtensionsByType(att.MIMEType) @@ -521,10 +524,12 @@ func parseAttachment(h message.Header) (*pmapi.Attachment, error) { } } else { att.Name = dispParams["filename"] - - if att.Name == "" { - att.Name = "attachment.bin" - } + } + if att.Name == "" { + att.Name = mimeTypeParams["name"] + } + if att.Name == "" { + att.Name = "attachment.bin" } // Only set ContentID if it should be inline; diff --git a/pkg/message/parser_test.go b/pkg/message/parser_test.go index bd9732a8..a5794317 100644 --- a/pkg/message/parser_test.go +++ b/pkg/message/parser_test.go @@ -239,6 +239,24 @@ func TestParseTextPlainWithOctetAttachmentBadFilename(t *testing.T) { assert.Equal(t, "attachment.bin", m.Attachments[0].Name) } +func TestParseTextPlainWithOctetAttachmentNameInContentType(t *testing.T) { + f := getFileReader("text_plain_octet_attachment_name_in_contenttype.eml") + + m, _, _, _, err := Parse(f) //nolint[dogsled] + require.NoError(t, err) + + assert.Equal(t, "attachment-contenttype.txt", m.Attachments[0].Name) +} + +func TestParseTextPlainWithOctetAttachmentNameConflict(t *testing.T) { + f := getFileReader("text_plain_octet_attachment_name_conflict.eml") + + m, _, _, _, err := Parse(f) //nolint[dogsled] + require.NoError(t, err) + + assert.Equal(t, "attachment-disposition.txt", m.Attachments[0].Name) +} + func TestParseTextPlainWithPlainAttachment(t *testing.T) { f := getFileReader("text_plain_plain_attachment.eml") diff --git a/pkg/message/testdata/text_plain_octet_attachment_name_conflict.eml b/pkg/message/testdata/text_plain_octet_attachment_name_conflict.eml new file mode 100644 index 00000000..2ac79ead --- /dev/null +++ b/pkg/message/testdata/text_plain_octet_attachment_name_conflict.eml @@ -0,0 +1,14 @@ +From: Sender +To: Receiver +Content-Type: multipart/mixed; boundary=longrandomstring + +--longrandomstring + +body +--longrandomstring +Content-Type: application/octet-stream; name="attachment-contenttype.txt" +Content-Transfer-Encoding: base64 +Content-Disposition: attachment; filename="attachment-disposition.txt" + +aWYgeW91IGFyZSByZWFkaW5nIHRoaXMsIGhpIQ== +--longrandomstring-- diff --git a/pkg/message/testdata/text_plain_octet_attachment_name_in_contenttype.eml b/pkg/message/testdata/text_plain_octet_attachment_name_in_contenttype.eml new file mode 100644 index 00000000..38feb96f --- /dev/null +++ b/pkg/message/testdata/text_plain_octet_attachment_name_in_contenttype.eml @@ -0,0 +1,14 @@ +From: Sender +To: Receiver +Content-Type: multipart/mixed; boundary=longrandomstring + +--longrandomstring + +body +--longrandomstring +Content-Type: application/octet-stream; name="attachment-contenttype.txt" +Content-Transfer-Encoding: base64 +Content-Disposition: attachment + +aWYgeW91IGFyZSByZWFkaW5nIHRoaXMsIGhpIQ== +--longrandomstring--