fix(GODT-2966): Allow permissive parsing of MediaType parameters for import.

This commit is contained in:
Romain Le Jeune
2023-10-09 15:14:51 +00:00
parent d7dadd7578
commit 5c7e4e04f9
7 changed files with 110 additions and 61 deletions

View File

@ -547,8 +547,8 @@ func parseAttachment(h message.Header, body []byte) (Attachment, error) {
return Attachment{}, err
}
att.Header = mimeHeader
mimeType, mimeTypeParams, err := pmmime.ParseMediaType(h.Get("Content-Type"))
mimeType, mimeTypeParams, err := h.ContentType()
if err != nil {
return Attachment{}, err
}
@ -558,7 +558,8 @@ func parseAttachment(h message.Header, body []byte) (Attachment, error) {
// 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.
if disp, dispParams, err := h.ContentDisposition(); err == nil {
disp, dispParams, err := pmmime.ParseMediaType(h.Get("Content-Disposition"))
if err == nil {
att.Disposition = proton.Disposition(disp)
if filename, ok := dispParams["filename"]; ok {
@ -585,7 +586,7 @@ func parseAttachment(h message.Header, body []byte) (Attachment, error) {
// (This is necessary because some clients don't set Content-Disposition at all,
// so we need to rely on other information to deduce if it's inline or attachment.)
if h.Has("Content-Disposition") {
disp, _, err := h.ContentDisposition()
disp, _, err := pmmime.ParseMediaType(h.Get("Content-Disposition"))
if err != nil {
return Attachment{}, err
}

View File

@ -539,6 +539,18 @@ func TestParseMultipartAlternativeLatin1(t *testing.T) {
assert.Equal(t, "*aoeuaoeu*\n\n", string(m.PlainBody))
}
func TestParseMultipartAttachmentEncodedButUnquoted(t *testing.T) {
f := getFileReader("multipart_attachment_encoded_no_quote.eml")
p, err := parser.New(f)
require.NoError(t, err)
m, err := ParseWithParser(p, false)
require.NoError(t, err)
assert.Equal(t, `"Bridge Test" <bridgetest@pm.test>`, m.Sender.String())
assert.Equal(t, `"Internal Bridge" <bridgetest@protonmail.com>`, m.ToList[0].String())
}
func TestParseWithTrailingEndOfMailIndicator(t *testing.T) {
f := getFileReader("text_html_trailing_end_of_mail.eml")

View File

@ -0,0 +1,27 @@
From: Bridge Test <bridgetest@pm.test>
Date: 01 Jan 1980 00:00:00 +0000
To: Internal Bridge <bridgetest@protonmail.com>
Subject: Message with attachment name
Content-type: multipart/mixed; boundary="boundary"
Received: by 2002:0:0:0:0:0:0:0 with SMTP id 0123456789abcdef; Wed, 30 Dec 2020 01:23:45 0000
This is a multi-part message in MIME format.
--boundary
Content-Type: text/plain
Hello
--boundary
Content-Type: text/html; charset=utf-8
Content-Transfer-Encoding: 7bit
<h1> HELLO </h1>
--boundary
Content-Type: application/pdf; name==?US-ASCII?Q?filename?=
Content-Disposition: attachment; filename==?US-ASCII?Q?filename?=
somebytes
--boundary--

View File

@ -256,6 +256,10 @@ func DecodeCharset(original []byte, contentType string) ([]byte, error) {
// ParseMediaType from MIME doesn't support RFC2231 for non asci / utf8 encodings so we have to pre-parse it.
func ParseMediaType(v string) (mediatype string, params map[string]string, err error) {
v, _ = changeEncodingAndKeepLastParamDefinition(v)
decoded, err := DecodeHeader(v)
if err != nil {
return "", nil, err
}
v, _ = changeEncodingAndKeepLastParamDefinition(decoded)
return mime.ParseMediaType(v)
}