diff --git a/go.mod b/go.mod index e321d83d..061f13c9 100644 --- a/go.mod +++ b/go.mod @@ -122,7 +122,7 @@ require ( ) replace ( - github.com/emersion/go-message => github.com/ProtonMail/go-message v0.13.1-0.20230526094639-b62c999c85b7 + github.com/emersion/go-message => github.com/ProtonMail/go-message v0.13.1-0.20240919135104-3bc88e6a9423 github.com/emersion/go-smtp => github.com/ProtonMail/go-smtp v0.0.0-20231109081432-2b3d50599865 github.com/go-resty/resty/v2 => github.com/LBeernaertProton/resty/v2 v2.0.0-20231129100320-dddf8030d93a github.com/keybase/go-keychain => github.com/cuthix/go-keychain v0.0.0-20240103134243-0b6a41580b77 diff --git a/go.sum b/go.sum index 3a6c6f83..698371ba 100644 --- a/go.sum +++ b/go.sum @@ -36,6 +36,14 @@ github.com/ProtonMail/go-crypto v0.0.0-20230717121622-edf196117233 h1:bdoKdh0f66 github.com/ProtonMail/go-crypto v0.0.0-20230717121622-edf196117233/go.mod h1:EjAoLdwvbIOoOQr3ihjnSoLZRtE8azugULFRteWMNc0= github.com/ProtonMail/go-message v0.13.1-0.20230526094639-b62c999c85b7 h1:+j+Kd/DyZ/qGfMT9htAT7HxqIEbZHsatsx+m8AoV6fc= github.com/ProtonMail/go-message v0.13.1-0.20230526094639-b62c999c85b7/go.mod h1:NBAn21zgCJ/52WLDyed18YvYFm5tEoeDauubFqLokM4= +github.com/ProtonMail/go-message v0.13.1-0.20240906141354-38c596f2f5a8 h1:+eE7FGX+4Hu8RZaRmSebrDVXyLuowKSaO7ZhQ6ca4+E= +github.com/ProtonMail/go-message v0.13.1-0.20240906141354-38c596f2f5a8/go.mod h1:NBAn21zgCJ/52WLDyed18YvYFm5tEoeDauubFqLokM4= +github.com/ProtonMail/go-message v0.13.1-0.20240906144417-4083506a9542 h1:5DqSycYnKfUdHiu0yOdiYW5R2hVxoE0Mk4PLSYwqGyg= +github.com/ProtonMail/go-message v0.13.1-0.20240906144417-4083506a9542/go.mod h1:NBAn21zgCJ/52WLDyed18YvYFm5tEoeDauubFqLokM4= +github.com/ProtonMail/go-message v0.13.1-0.20240910093530-2ada52e7dffb h1:uOKp93u6JFYlBoJJvOhzmHZURcvWmXiqhihGWtT3HtY= +github.com/ProtonMail/go-message v0.13.1-0.20240910093530-2ada52e7dffb/go.mod h1:NBAn21zgCJ/52WLDyed18YvYFm5tEoeDauubFqLokM4= +github.com/ProtonMail/go-message v0.13.1-0.20240919135104-3bc88e6a9423 h1:p8nBDxvRnvDOyrcePKkPpErWGhDoTqpX8a1c54CcSu0= +github.com/ProtonMail/go-message v0.13.1-0.20240919135104-3bc88e6a9423/go.mod h1:NBAn21zgCJ/52WLDyed18YvYFm5tEoeDauubFqLokM4= github.com/ProtonMail/go-mime v0.0.0-20230322103455-7d82a3887f2f h1:tCbYj7/299ekTTXpdwKYF8eBlsYsDVoggDAuAjoK66k= github.com/ProtonMail/go-mime v0.0.0-20230322103455-7d82a3887f2f/go.mod h1:gcr0kNtGBqin9zDW9GOHcVntrwnjrK+qdJ06mWYBybw= github.com/ProtonMail/go-proton-api v0.4.1-0.20240612082117-0f92424eed80 h1:cP4+6RFn9vVgYnoDwxBU4EtIAZA+eM4rzOaSZNqZ1xg= diff --git a/pkg/message/parser_test.go b/pkg/message/parser_test.go index 7aa9e704..d8d1da40 100644 --- a/pkg/message/parser_test.go +++ b/pkg/message/parser_test.go @@ -857,6 +857,23 @@ func getFileReader(filename string) io.Reader { return f } +func TestParseInvalidOriginalBoundary(t *testing.T) { + f := getFileReader("incorrect_boundary_w_invalid_character_tuta.eml") + + p, err := parser.New(f) + require.NoError(t, err) + + require.Equal(t, true, p.Root().Header.Get("Content-Type") == `multipart/related; boundary="------------1234567890@tutanota"`) + + m, err := ParseWithParser(p, false) + require.NoError(t, err) + + require.Equal(t, true, strings.HasPrefix(string(m.MIMEBody), "Content-Type: multipart/related;\r\n boundary=")) + require.Equal(t, false, strings.HasPrefix(string(m.MIMEBody), `Content-Type: multipart/related;\n boundary="------------1234567890@tutanota"`)) + require.Equal(t, false, strings.HasPrefix(string(m.MIMEBody), `Content-Type: multipart/related;\n boundary=------------1234567890@tutanota`)) + require.Equal(t, false, strings.HasPrefix(string(m.MIMEBody), `Content-Type: multipart/related;\n boundary=1234567890@tutanota`)) +} + type panicReader struct{} func (panicReader) Read(_ []byte) (int, error) { diff --git a/pkg/message/testdata/incorrect_boundary_w_invalid_character_tuta.eml b/pkg/message/testdata/incorrect_boundary_w_invalid_character_tuta.eml new file mode 100644 index 00000000..908643eb --- /dev/null +++ b/pkg/message/testdata/incorrect_boundary_w_invalid_character_tuta.eml @@ -0,0 +1,13 @@ +Date: Mon, 01 Jan 2000 00:00:00 +0000 (UTC) +From: Daniel at Test +Mime-Version: 1.0 +Subject: Test incorrect original boundary w. invalid character +To: david@test.com +Content-Type: multipart/related; boundary="------------1234567890@tutanota" + +--------------1234567890@tutanota +Content-Type: text/html; charset=UTF-8 +Content-transfer-encoding: base64 + +PGh0bWw+PGgxPkhlbGxvIFdvcmxkITwvaDE+PC9odG1sPg== +--------------1234567890@tutanota-- diff --git a/tests/features/imap/message/import.feature b/tests/features/imap/message/import.feature index 2da987bc..da5602cc 100644 --- a/tests/features/imap/message/import.feature +++ b/tests/features/imap/message/import.feature @@ -651,3 +651,83 @@ Feature: IMAP import messages } } """ + + Scenario: Message import multipart/related with invalid boundary character + When IMAP client "1" appends the following message to "INBOX": + """ + From: Bridge Test + Date: 01 Jan 1980 00:00:00 +0000 + To: Internal Bridge + Received: by 2002:0:0:0:0:0:0:0 with SMTP id 0123456789abcdef; Wed, 30 Dec 2020 01:23:45 0000 + Subject: Message with invalid boundary + Content-Type: multipart/related; boundary="------------123456789@tutanota" + + --------------123456789@tutanota + Content-Type: text/html; charset=UTF-8 + Content-transfer-encoding: base64 + + PGRpdiBjbGFzcz0iIj4KPHAgY2xhc3M9IiI+PGEgbmFtZT0iX0hsazE5MDA1NjM2IiByZWw9Im5vb3 + BlbmVyIG5vcmVmZXJyZXIiIHRhcmdldD0iX2JsYW5rIj48c3BhbiBzdHlsZT0ibXNvLWZhcmVhc3Qt + + --------------123456789@tutanota + Content-Type: image/png; + name==?UTF-8?B?MC5wbmc=?= + Content-Transfer-Encoding: base64 + Content-Disposition: attachment; + filename=image1.png + + iVBORw0KGgoAAAANSUhEUgAAACsAAAArCAYAAADhXXHAAAAPq3pUWHRSYXcgcHJvZmlsZSB0eXBlIG + V4aWYAAHjarZlrliOpkoT/s4pZAuCAw3J4njM7mOXP54SUlZmV1bd7plNVEVIoAhx/mJsht//nv4/7 + + --------------123456789@tutanota + Content-Type: image/png; + name==?UTF-8?B?Mi5wbmc=?= + Content-Transfer-Encoding: base64 + Content-Disposition: attachment; + filename=img2.png + + iVBORw0KGgoAAAANSUhEUgAAACsAAAArCAYAAADhXXHAAAAR+HpUWHRSYXcgcHJvZmlsZSB0eXBlIG + V4aWYAAHjarZprdhs5DoX/cxWzBD4Bcjl8njM7mOXPB5bsOI49SU+3nViKLFWxgIv7YMXt//z7uH/x + + --------------123456789@tutanota-- + + """ + Then it succeeds + And IMAP client "1" eventually sees the following message in "INBOX" with this structure: + """ + { + "from": "Bridge Test ", + "date": "01 Jan 80 00:00 +0000", + "to": "Internal Bridge ", + "subject": "Message with invalid boundary", + "content": { + "content-type": "multipart/mixed", + "sections":[ + { + "content-type": "multipart/related", + "sections": [ + { + "content-type": "text/html", + "transfer-encoding": "base64", + "body-is": "PGRpdiBjbGFzcz0iIj4KPHAgY2xhc3M9IiI+PGEgbmFtZT0iX0hsazE5MDA1NjM2IiByZWw9Im5v\r\nb3BlbmVyIG5vcmVmZXJyZXIiIHRhcmdldD0iX2JsYW5rIj48c3BhbiBzdHlsZT0ibXNvLWZhcmVh\r\nc3Qt" + }, + { + "content-type": "image/png", + "transfer-encoding": "base64", + "content-disposition": "attachment", + "content-disposition-filename": "image1.png", + "body-is": "iVBORw0KGgoAAAANSUhEUgAAACsAAAArCAYAAADhXXHAAAAPq3pUWHRSYXcgcHJvZmlsZSB0eXBl\r\nIGV4aWYAAHjarZlrliOpkoT/s4pZAuCAw3J4njM7mOXP54SUlZmV1bd7plNVEVIoAhx/mJsht//n\r\nv4/7" + }, + { + "content-type": "image/png", + "transfer-encoding": "base64", + "content-disposition": "attachment", + "content-disposition-filename": "img2.png", + "body-is": "iVBORw0KGgoAAAANSUhEUgAAACsAAAArCAYAAADhXXHAAAAR+HpUWHRSYXcgcHJvZmlsZSB0eXBl\r\nIGV4aWYAAHjarZprdhs5DoX/cxWzBD4Bcjl8njM7mOXPB5bsOI49SU+3nViKLFWxgIv7YMXt//z7\r\nuH/x" + } + ] + } + ] + } + } + """