mirror of
https://github.com/ProtonMail/proton-bridge.git
synced 2025-12-10 04:36:43 +00:00
feat: strip comments from addresses
This commit is contained in:
@ -19,7 +19,9 @@ package message
|
||||
|
||||
import (
|
||||
"mime"
|
||||
"net/mail"
|
||||
"net/textproto"
|
||||
"regexp"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
@ -139,3 +141,42 @@ func GetAttachmentHeader(att *pmapi.Attachment) textproto.MIMEHeader {
|
||||
|
||||
return h
|
||||
}
|
||||
|
||||
var reEmailComment = regexp.MustCompile("[(][^)]*[)]") // nolint[gochecknoglobals]
|
||||
|
||||
// parseAddressComment removes the comments completely even though they should be allowed
|
||||
// http://tools.wordtothewise.com/rfc/822
|
||||
// NOTE: This should be supported in go>1.10 but it seems it's not ¯\_(ツ)_/¯
|
||||
func parseAddressComment(raw string) string {
|
||||
return reEmailComment.ReplaceAllString(raw, "")
|
||||
}
|
||||
|
||||
func parseAddressList(val string) (addrs []*mail.Address, err error) {
|
||||
addrs, err = mail.ParseAddressList(parseAddressComment(val))
|
||||
if err == nil {
|
||||
if addrs == nil {
|
||||
addrs = []*mail.Address{}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Probably missing encoding error -- try to at least parse addresses in brackets.
|
||||
first := strings.Index(val, "<")
|
||||
last := strings.LastIndex(val, ">")
|
||||
if first < 0 || last < 0 || first >= last {
|
||||
return
|
||||
}
|
||||
var addrList []string
|
||||
open := first
|
||||
for open < last && 0 <= open {
|
||||
val = val[open:]
|
||||
close := strings.Index(val, ">")
|
||||
addrList = append(addrList, val[:close+1])
|
||||
val = val[close:]
|
||||
open = strings.Index(val, "<")
|
||||
last = strings.LastIndex(val, ">")
|
||||
}
|
||||
val = strings.Join(addrList, ", ")
|
||||
|
||||
return mail.ParseAddressList(val)
|
||||
}
|
||||
|
||||
@ -375,35 +375,37 @@ func parseMessageHeader(m *pmapi.Message, h message.Header) error { // nolint[fu
|
||||
m.Subject = val
|
||||
|
||||
case "from":
|
||||
sender, err := mail.ParseAddress(val)
|
||||
sender, err := parseAddressList(val)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
m.Sender = sender
|
||||
if len(sender) > 0 {
|
||||
m.Sender = sender[0]
|
||||
}
|
||||
|
||||
case "to":
|
||||
toList, err := mail.ParseAddressList(val)
|
||||
toList, err := parseAddressList(val)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
m.ToList = toList
|
||||
|
||||
case "reply-to":
|
||||
replyTos, err := mail.ParseAddressList(val)
|
||||
replyTos, err := parseAddressList(val)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
m.ReplyTos = replyTos
|
||||
|
||||
case "cc":
|
||||
ccList, err := mail.ParseAddressList(val)
|
||||
ccList, err := parseAddressList(val)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
m.CCList = ccList
|
||||
|
||||
case "bcc":
|
||||
bccList, err := mail.ParseAddressList(val)
|
||||
bccList, err := parseAddressList(val)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@ -434,3 +434,80 @@ func readerToString(r io.Reader) string {
|
||||
|
||||
return string(b)
|
||||
}
|
||||
|
||||
func TestRFC822AddressFormat(t *testing.T) { //nolint[funlen]
|
||||
tests := []struct {
|
||||
address string
|
||||
expected []string
|
||||
}{
|
||||
{
|
||||
" normal name <username@server.com>",
|
||||
[]string{
|
||||
"\"normal name\" <username@server.com>",
|
||||
},
|
||||
},
|
||||
{
|
||||
" \"comma, name\" <username@server.com>",
|
||||
[]string{
|
||||
"\"comma, name\" <username@server.com>",
|
||||
},
|
||||
},
|
||||
{
|
||||
" name <username@server.com> (ignore comment)",
|
||||
[]string{
|
||||
"\"name\" <username@server.com>",
|
||||
},
|
||||
},
|
||||
{
|
||||
" name (ignore comment) <username@server.com>, (Comment as name) username2@server.com",
|
||||
[]string{
|
||||
"\"name\" <username@server.com>",
|
||||
"<username2@server.com>",
|
||||
},
|
||||
},
|
||||
{
|
||||
" normal name <username@server.com>, (comment)All.(around)address@(the)server.com",
|
||||
[]string{
|
||||
"\"normal name\" <username@server.com>",
|
||||
"<All.address@server.com>",
|
||||
},
|
||||
},
|
||||
{
|
||||
" normal name <username@server.com>, All.(\"comma, in comment\")address@(the)server.com",
|
||||
[]string{
|
||||
"\"normal name\" <username@server.com>",
|
||||
"<All.address@server.com>",
|
||||
},
|
||||
},
|
||||
{
|
||||
" \"normal name\" <username@server.com>, \"comma, name\" <address@server.com>",
|
||||
[]string{
|
||||
"\"normal name\" <username@server.com>",
|
||||
"\"comma, name\" <address@server.com>",
|
||||
},
|
||||
},
|
||||
{
|
||||
" \"comma, one\" <username@server.com>, \"comma, two\" <address@server.com>",
|
||||
[]string{
|
||||
"\"comma, one\" <username@server.com>",
|
||||
"\"comma, two\" <address@server.com>",
|
||||
},
|
||||
},
|
||||
{
|
||||
" \"comma, name\" <username@server.com>, another, name <address@server.com>",
|
||||
[]string{
|
||||
"\"comma, name\" <username@server.com>",
|
||||
"\"another, name\" <address@server.com>",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, data := range tests {
|
||||
result, err := parseAddressList(data.address)
|
||||
assert.NoError(t, err)
|
||||
assert.Len(t, result, len(data.expected))
|
||||
for i, result := range result {
|
||||
assert.Equal(t, data.expected[i], result.String())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user