From 738acbc2f0c93a84ce3c4c5436456e63f18553bd Mon Sep 17 00:00:00 2001 From: Guilherme Rezende Date: Mon, 24 Jul 2017 17:04:02 -0300 Subject: [PATCH] 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 Reviewed-by: Avelino Run-TryBot: Ian Lance Taylor TryBot-Result: Gobot Gobot --- src/net/mail/message.go | 21 +++++++++++++------- src/net/mail/message_test.go | 38 ++++++++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+), 7 deletions(-) diff --git a/src/net/mail/message.go b/src/net/mail/message.go index 45a995ec72..debc77d733 100644 --- a/src/net/mail/message.go +++ b/src/net/mail/message.go @@ -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) diff --git a/src/net/mail/message_test.go b/src/net/mail/message_test.go index 2106a0b97d..9026937112 100644 --- a/src/net/mail/message_test.go +++ b/src/net/mail/message_test.go @@ -137,6 +137,8 @@ func TestAddressParsingError(t *testing.T) { 5: {"\"\x00\" ", "bad character in quoted-string"}, 6: {"\"\\\x00\" ", "bad character in quoted-string"}, 7: {"John Doe", "no angle-addr"}, + 8: {``, "missing @ in addr-spec"}, + 9: {`John Doe `, "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" `, + []*Address{{ + Name: "John (middle) Doe", + Address: "jdoe@machine.example", + }}, + }, + { + `John (middle) Doe `, + []*Address{{ + Name: "John (middle) Doe", + Address: "jdoe@machine.example", + }}, + }, + { + `John !@M@! Doe `, + []*Address{{ + Name: "John !@M@! Doe", + Address: "jdoe@machine.example", + }}, + }, + { + `"John Doe" `, + []*Address{{ + Name: "John Doe", + Address: "jdoe@machine.example", + }}, + }, { `Mary Smith , jdoe@example.org, Who? `, []*Address{ @@ -203,6 +233,14 @@ func TestAddressParsing(t *testing.T) { }, }, }, + // RFC 5322, Appendix A.6.1 + { + `Joe Q. Public `, + []*Address{{ + Name: "Joe Q. Public", + Address: "john.q.public@example.com", + }}, + }, // RFC 5322, Appendix A.1.3 // TODO(dsymonds): Group addresses. -- 2.50.0