fix: unhandled charset in header

This commit is contained in:
James Houlahan
2020-09-02 15:17:01 +02:00
parent da751a38e3
commit 5d0e3f36b4
7 changed files with 94 additions and 112 deletions

View File

@ -27,6 +27,7 @@ import (
"strings"
"github.com/ProtonMail/proton-bridge/pkg/message/parser"
pmmime "github.com/ProtonMail/proton-bridge/pkg/mime"
"github.com/ProtonMail/proton-bridge/pkg/pmapi"
"github.com/emersion/go-message"
"github.com/emersion/go-textwrapper"
@ -374,60 +375,57 @@ func parseMessageHeader(m *pmapi.Message, h message.Header) error { // nolint[fu
}
m.Header = mimeHeader
fields := h.Fields()
for fields.Next() {
text, err := fields.Text()
if err != nil {
return err
}
switch strings.ToLower(fields.Key()) {
if err := forEachDecodedHeaderField(h, func(key, val string) error {
switch strings.ToLower(key) {
case "subject":
m.Subject = text
m.Subject = val
case "from":
sender, err := mail.ParseAddress(text)
sender, err := mail.ParseAddress(val)
if err != nil {
return err
}
m.Sender = sender
case "to":
toList, err := mail.ParseAddressList(text)
toList, err := mail.ParseAddressList(val)
if err != nil {
return err
}
m.ToList = toList
case "reply-to":
replyTos, err := mail.ParseAddressList(text)
replyTos, err := mail.ParseAddressList(val)
if err != nil {
return err
}
m.ReplyTos = replyTos
case "cc":
ccList, err := mail.ParseAddressList(text)
ccList, err := mail.ParseAddressList(val)
if err != nil {
return err
}
m.CCList = ccList
case "bcc":
bccList, err := mail.ParseAddressList(text)
bccList, err := mail.ParseAddressList(val)
if err != nil {
return err
}
m.BCCList = bccList
case "date":
date, err := mail.ParseDate(text)
date, err := mail.ParseDate(val)
if err != nil {
return err
}
m.Time = date.Unix()
}
return nil
}); err != nil {
return err
}
return nil
@ -471,18 +469,37 @@ func parseAttachment(h message.Header) (*pmapi.Attachment, error) {
return att, nil
}
func toMailHeader(h message.Header) (mail.Header, error) {
mimeHeader := make(mail.Header)
func forEachDecodedHeaderField(h message.Header, fn func(string, string) error) error {
fields := h.Fields()
for fields.Next() {
text, err := fields.Text()
if err != nil {
return nil, err
if !message.IsUnknownCharset(err) {
return err
}
if text, err = pmmime.DecodeHeader(fields.Value()); err != nil {
return err
}
}
mimeHeader[fields.Key()] = []string{text}
if err := fn(fields.Key(), text); err != nil {
return err
}
}
return nil
}
func toMailHeader(h message.Header) (mail.Header, error) {
mimeHeader := make(mail.Header)
if err := forEachDecodedHeaderField(h, func(key, val string) error {
mimeHeader[key] = []string{val}
return nil
}); err != nil {
return nil, err
}
return mimeHeader, nil
@ -491,15 +508,11 @@ func toMailHeader(h message.Header) (mail.Header, error) {
func toMIMEHeader(h message.Header) (textproto.MIMEHeader, error) {
mimeHeader := make(textproto.MIMEHeader)
fields := h.Fields()
for fields.Next() {
text, err := fields.Text()
if err != nil {
return nil, err
}
mimeHeader[fields.Key()] = []string{text}
if err := forEachDecodedHeaderField(h, func(key, val string) error {
mimeHeader[key] = []string{val}
return nil
}); err != nil {
return nil, err
}
return mimeHeader, nil

View File

@ -1,3 +1,4 @@
Mime-Version: 1.0
From: Sender <sender@pm.me>
To: Receiver <receiver@pm.me>
Content-Type: multipart/mixed; boundary=longrandomstring

View File

@ -75,6 +75,38 @@ func TestParseTextPlainLatin1(t *testing.T) {
assert.Len(t, attReaders, 0)
}
func TestParseTextPlainUTF8Subject(t *testing.T) {
f := getFileReader("text_plain_utf8_subject.eml")
m, _, plainBody, attReaders, err := Parse(f, "", "")
require.NoError(t, err)
assert.Equal(t, `"Sender" <sender@pm.me>`, m.Sender.String())
assert.Equal(t, `"Receiver" <receiver@pm.me>`, m.ToList[0].String())
assert.Equal(t, `汉字汉字汉`, m.Subject)
assert.Equal(t, "body", m.Body)
assert.Equal(t, "body", plainBody)
assert.Len(t, attReaders, 0)
}
func TestParseTextPlainLatin2Subject(t *testing.T) {
f := getFileReader("text_plain_latin2_subject.eml")
m, _, plainBody, attReaders, err := Parse(f, "", "")
require.NoError(t, err)
assert.Equal(t, `"Sender" <sender@pm.me>`, m.Sender.String())
assert.Equal(t, `"Receiver" <receiver@pm.me>`, m.ToList[0].String())
assert.Equal(t, `If you can read this you understand the example.`, m.Subject)
assert.Equal(t, "body", m.Body)
assert.Equal(t, "body", plainBody)
assert.Len(t, attReaders, 0)
}
func TestParseTextPlainUnknownCharsetIsActuallyLatin1(t *testing.T) {
f := getFileReader("text_plain_unknown_latin1.eml")

View File

@ -0,0 +1,6 @@
From: Sender <sender@pm.me>
To: Receiver <receiver@pm.me>
Subject: =?ISO-8859-1?B?SWYgeW91IGNhbiByZWFkIHRoaXMgeW8=?=
=?ISO-8859-2?B?dSB1bmRlcnN0YW5kIHRoZSBleGFtcGxlLg==?=
body

View File

@ -0,0 +1,5 @@
From: Sender <sender@pm.me>
To: Receiver <receiver@pm.me>
Subject: =?UTF-8?B?5rGJ5a2X5rGJ5a2X5rGJ?=
body