1
0
mirror of https://github.com/golang/go synced 2024-11-20 02:24:43 -07:00

net/mail: parse cases when phrase has special chars without quotes

Updates #21018

Change-Id: I00b6667fb5fee78559a391815f58760a2baea90e
Reviewed-on: https://go-review.googlesource.com/50911
Reviewed-by: Ian Lance Taylor <iant@golang.org>
Reviewed-by: Avelino <t@avelino.xxx>
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
This commit is contained in:
Guilherme Rezende 2017-07-24 17:04:02 -03:00 committed by Ian Lance Taylor
parent b0392159f6
commit 738acbc2f0
2 changed files with 52 additions and 7 deletions

View File

@ -14,6 +14,7 @@ Notable divergences:
* The full range of spacing (the CFWS syntax element) is not supported,
such as breaking addresses across lines.
* No unicode normalization is performed.
* Address with some RFC 5322 3.2.3 specials without quotes are parsed.
*/
package mail
@ -190,7 +191,7 @@ func (a *Address) String() string {
// Add quotes if needed
quoteLocal := false
for i, r := range local {
if isAtext(r, false) {
if isAtext(r, false, false) {
continue
}
if r == '.' {
@ -482,20 +483,20 @@ Loop:
// consumeAtom parses an RFC 5322 atom at the start of p.
// If dot is true, consumeAtom parses an RFC 5322 dot-atom instead.
// If permissive is true, consumeAtom will not fail on
// leading/trailing/double dots in the atom (see golang.org/issue/4938).
// If permissive is true, consumeAtom will not fail on:
// - leading/trailing/double dots in the atom (see golang.org/issue/4938)
// - special characters (RFC 5322 3.2.3) except '<', '>' and '"' (see golang.org/issue/21018)
func (p *addrParser) consumeAtom(dot bool, permissive bool) (atom string, err error) {
i := 0
Loop:
for {
r, size := utf8.DecodeRuneInString(p.s[i:])
switch {
case size == 1 && r == utf8.RuneError:
return "", fmt.Errorf("mail: invalid utf-8 in address: %q", p.s)
case size == 0 || !isAtext(r, dot):
case size == 0 || !isAtext(r, dot, permissive):
break Loop
default:
@ -580,12 +581,18 @@ func (e charsetError) Error() string {
// isAtext reports whether r is an RFC 5322 atext character.
// If dot is true, period is included.
func isAtext(r rune, dot bool) bool {
// If permissive is true, RFC 5322 3.2.3 specials is included,
// except '<', '>' and '"'.
func isAtext(r rune, dot, permissive bool) bool {
switch r {
case '.':
return dot
case '(', ')', '<', '>', '[', ']', ':', ';', '@', '\\', ',', '"': // RFC 5322 3.2.3. specials
// RFC 5322 3.2.3. specials
case '(', ')', '[', ']', ':', ';', '@', '\\', ',':
return permissive
case '<', '>', '"':
return false
}
return isVchar(r)

View File

@ -137,6 +137,8 @@ func TestAddressParsingError(t *testing.T) {
5: {"\"\x00\" <null@example.net>", "bad character in quoted-string"},
6: {"\"\\\x00\" <escaped-null@example.net>", "bad character in quoted-string"},
7: {"John Doe", "no angle-addr"},
8: {`<jdoe#machine.example>`, "missing @ in addr-spec"},
9: {`John <middle> Doe <jdoe@machine.example>`, "missing @ in addr-spec"},
}
for i, tc := range mustErrTestCases {
@ -175,6 +177,34 @@ func TestAddressParsing(t *testing.T) {
Address: "john.q.public@example.com",
}},
},
{
`"John (middle) Doe" <jdoe@machine.example>`,
[]*Address{{
Name: "John (middle) Doe",
Address: "jdoe@machine.example",
}},
},
{
`John (middle) Doe <jdoe@machine.example>`,
[]*Address{{
Name: "John (middle) Doe",
Address: "jdoe@machine.example",
}},
},
{
`John !@M@! Doe <jdoe@machine.example>`,
[]*Address{{
Name: "John !@M@! Doe",
Address: "jdoe@machine.example",
}},
},
{
`"John <middle> Doe" <jdoe@machine.example>`,
[]*Address{{
Name: "John <middle> Doe",
Address: "jdoe@machine.example",
}},
},
{
`Mary Smith <mary@x.test>, jdoe@example.org, Who? <one@y.test>`,
[]*Address{
@ -203,6 +233,14 @@ func TestAddressParsing(t *testing.T) {
},
},
},
// RFC 5322, Appendix A.6.1
{
`Joe Q. Public <john.q.public@example.com>`,
[]*Address{{
Name: "Joe Q. Public",
Address: "john.q.public@example.com",
}},
},
// RFC 5322, Appendix A.1.3
// TODO(dsymonds): Group addresses.