diff --git a/src/net/mail/message.go b/src/net/mail/message.go index 01290bc65b..571c95ddc9 100644 --- a/src/net/mail/message.go +++ b/src/net/mail/message.go @@ -234,6 +234,12 @@ func (a *Address) String() string { return b.String() } + // Text in an encoded-word in a display-name must not contain certain + // characters like quotes or parentheses (see RFC 2047 section 5.3). + // When this is the case encode the name using base64 encoding. + if strings.ContainsAny(a.Name, "\"#$%&'(),.:;<>@[]^`{|}~") { + return mime.BEncoding.Encode("utf-8", a.Name) + " " + s + } return mime.QEncoding.Encode("utf-8", a.Name) + " " + s } diff --git a/src/net/mail/message_test.go b/src/net/mail/message_test.go index e05af6c6ba..9fd7923c34 100644 --- a/src/net/mail/message_test.go +++ b/src/net/mail/message_test.go @@ -499,6 +499,10 @@ func TestAddressFormatting(t *testing.T) { &Address{Name: "Rob", Address: "@"}, `"Rob" <@>`, }, + { + &Address{Name: "Böb, Jacöb", Address: "bob@example.com"}, + `=?utf-8?b?QsO2YiwgSmFjw7Zi?= `, + }, } for _, test := range tests { s := test.addr.String() @@ -594,3 +598,32 @@ func TestAddressParsingAndFormatting(t *testing.T) { } } + +func TestAddressFormattingAndParsing(t *testing.T) { + tests := []*Address{ + &Address{Name: "@lïce", Address: "alice@example.com"}, + &Address{Name: "Böb O'Connor", Address: "bob@example.com"}, + &Address{Name: "???", Address: "bob@example.com"}, + &Address{Name: "Böb ???", Address: "bob@example.com"}, + &Address{Name: "Böb (Jacöb)", Address: "bob@example.com"}, + &Address{Name: "à#$%&'(),.:;<>@[]^`{|}~'", Address: "bob@example.com"}, + // https://golang.org/issue/11292 + &Address{Name: "\"\\\x1f,\"", Address: "0@0"}, + // https://golang.org/issue/12782 + &Address{Name: "naé, mée", Address: "test.mail@gmail.com"}, + } + + for _, test := range tests { + parsed, err := ParseAddress(test.String()) + if err != nil { + t.Errorf("ParseAddr(%q) error: %v", test.String(), err) + continue + } + if parsed.Name != test.Name { + t.Errorf("Parsed name = %q; want %q", parsed.Name, test.Name) + } + if parsed.Address != test.Address { + t.Errorf("Parsed address = %q; want %q", parsed.Address, test.Address) + } + } +}