diff options
Diffstat (limited to 'src/pkg/net/mail')
-rw-r--r-- | src/pkg/net/mail/message.go | 20 | ||||
-rw-r--r-- | src/pkg/net/mail/message_test.go | 17 |
2 files changed, 31 insertions, 6 deletions
diff --git a/src/pkg/net/mail/message.go b/src/pkg/net/mail/message.go index dc2ab44da..ba0778caa 100644 --- a/src/pkg/net/mail/message.go +++ b/src/pkg/net/mail/message.go @@ -159,7 +159,9 @@ func (a *Address) String() string { // If every character is printable ASCII, quoting is simple. allPrintable := true for i := 0; i < len(a.Name); i++ { - if !isVchar(a.Name[i]) { + // isWSP here should actually be isFWS, + // but we don't support folding yet. + if !isVchar(a.Name[i]) && !isWSP(a.Name[i]) { allPrintable = false break } @@ -167,7 +169,7 @@ func (a *Address) String() string { if allPrintable { b := bytes.NewBufferString(`"`) for i := 0; i < len(a.Name); i++ { - if !isQtext(a.Name[i]) { + if !isQtext(a.Name[i]) && !isWSP(a.Name[i]) { b.WriteByte('\\') } b.WriteByte(a.Name[i]) @@ -361,7 +363,7 @@ func (p *addrParser) consumePhrase() (phrase string, err error) { // Ignore any error if we got at least one word. if err != nil && len(words) == 0 { debug.Printf("consumePhrase: hit err: %v", err) - return "", errors.New("mail: missing word in phrase") + return "", fmt.Errorf("mail: missing word in phrase: %v", err) } phrase = strings.Join(words, " ") return phrase, nil @@ -440,11 +442,11 @@ func (p *addrParser) len() int { func decodeRFC2047Word(s string) (string, error) { fields := strings.Split(s, "?") if len(fields) != 5 || fields[0] != "=" || fields[4] != "=" { - return "", errors.New("mail: address not RFC 2047 encoded") + return "", errors.New("address not RFC 2047 encoded") } charset, enc := strings.ToLower(fields[1]), strings.ToLower(fields[2]) if charset != "iso-8859-1" && charset != "utf-8" { - return "", fmt.Errorf("mail: charset not supported: %q", charset) + return "", fmt.Errorf("charset not supported: %q", charset) } in := bytes.NewBufferString(fields[3]) @@ -455,7 +457,7 @@ func decodeRFC2047Word(s string) (string, error) { case "q": r = qDecoder{r: in} default: - return "", fmt.Errorf("mail: RFC 2047 encoding not supported: %q", enc) + return "", fmt.Errorf("RFC 2047 encoding not supported: %q", enc) } dec, err := ioutil.ReadAll(r) @@ -535,3 +537,9 @@ func isVchar(c byte) bool { // Visible (printing) characters. return '!' <= c && c <= '~' } + +// isWSP returns true if c is a WSP (white space). +// WSP is a space or horizontal tab (RFC5234 Appendix B). +func isWSP(c byte) bool { + return c == ' ' || c == '\t' +} diff --git a/src/pkg/net/mail/message_test.go b/src/pkg/net/mail/message_test.go index 3c037f383..eb9c8cbdc 100644 --- a/src/pkg/net/mail/message_test.go +++ b/src/pkg/net/mail/message_test.go @@ -8,6 +8,7 @@ import ( "bytes" "io/ioutil" "reflect" + "strings" "testing" "time" ) @@ -116,6 +117,14 @@ func TestDateParsing(t *testing.T) { } } +func TestAddressParsingError(t *testing.T) { + const txt = "=?iso-8859-2?Q?Bogl=E1rka_Tak=E1cs?= <unknown@gmail.com>" + _, err := ParseAddress(txt) + if err == nil || !strings.Contains(err.Error(), "charset not supported") { + t.Errorf(`mail.ParseAddress(%q) err: %q, want ".*charset not supported.*"`, txt, err) + } +} + func TestAddressParsing(t *testing.T) { tests := []struct { addrsStr string @@ -277,6 +286,14 @@ func TestAddressFormatting(t *testing.T) { &Address{Name: "Böb", Address: "bob@example.com"}, `=?utf-8?q?B=C3=B6b?= <bob@example.com>`, }, + { + &Address{Name: "Bob Jane", Address: "bob@example.com"}, + `"Bob Jane" <bob@example.com>`, + }, + { + &Address{Name: "Böb Jacöb", Address: "bob@example.com"}, + `=?utf-8?q?B=C3=B6b_Jac=C3=B6b?= <bob@example.com>`, + }, } for _, test := range tests { s := test.addr.String() |