feat: strip comments from addresses
This commit is contained in:
@ -19,7 +19,9 @@ package message
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"mime"
|
"mime"
|
||||||
|
"net/mail"
|
||||||
"net/textproto"
|
"net/textproto"
|
||||||
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@ -139,3 +141,42 @@ func GetAttachmentHeader(att *pmapi.Attachment) textproto.MIMEHeader {
|
|||||||
|
|
||||||
return h
|
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
|
m.Subject = val
|
||||||
|
|
||||||
case "from":
|
case "from":
|
||||||
sender, err := mail.ParseAddress(val)
|
sender, err := parseAddressList(val)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
m.Sender = sender
|
if len(sender) > 0 {
|
||||||
|
m.Sender = sender[0]
|
||||||
|
}
|
||||||
|
|
||||||
case "to":
|
case "to":
|
||||||
toList, err := mail.ParseAddressList(val)
|
toList, err := parseAddressList(val)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
m.ToList = toList
|
m.ToList = toList
|
||||||
|
|
||||||
case "reply-to":
|
case "reply-to":
|
||||||
replyTos, err := mail.ParseAddressList(val)
|
replyTos, err := parseAddressList(val)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
m.ReplyTos = replyTos
|
m.ReplyTos = replyTos
|
||||||
|
|
||||||
case "cc":
|
case "cc":
|
||||||
ccList, err := mail.ParseAddressList(val)
|
ccList, err := parseAddressList(val)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
m.CCList = ccList
|
m.CCList = ccList
|
||||||
|
|
||||||
case "bcc":
|
case "bcc":
|
||||||
bccList, err := mail.ParseAddressList(val)
|
bccList, err := parseAddressList(val)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@ -434,3 +434,80 @@ func readerToString(r io.Reader) string {
|
|||||||
|
|
||||||
return string(b)
|
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