Skip to content

Commit b59efe6

Browse files
ianlancetaylorIan Lance Taylor
authored and
Ian Lance Taylor
committed
[release-branch.go1.20] net/mail: permit more characters in mail headers
We parse mail messages using net/textproto. For #53188, we tightened up the bytes permitted by net/textproto to match RFC 7230. However, this package uses RFC 5322 which is more permissive. Restore the permisiveness we used to have, so that older code continues to work. For #58862 For #60332 Fixes #60874 Fixes #60875 Change-Id: I5437f5e18a756f6ca61c13c4d8ba727be73eff9a Reviewed-on: https://go-review.googlesource.com/c/go/+/504881 Run-TryBot: Ian Lance Taylor <[email protected]> TryBot-Result: Gopher Robot <[email protected]> Reviewed-by: Ian Lance Taylor <[email protected]> Reviewed-by: Damien Neil <[email protected]>
1 parent c32f1af commit b59efe6

File tree

2 files changed

+78
-1
lines changed

2 files changed

+78
-1
lines changed

src/net/mail/message.go

+50-1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ Notable divergences:
1414
such as breaking addresses across lines.
1515
- No unicode normalization is performed.
1616
- The special characters ()[]:;@\, are allowed to appear unquoted in names.
17+
- A leading From line is permitted, as in mbox format (RFC 4155).
1718
*/
1819
package mail
1920

@@ -53,7 +54,7 @@ type Message struct {
5354
func ReadMessage(r io.Reader) (msg *Message, err error) {
5455
tp := textproto.NewReader(bufio.NewReader(r))
5556

56-
hdr, err := tp.ReadMIMEHeader()
57+
hdr, err := readHeader(tp)
5758
if err != nil {
5859
return nil, err
5960
}
@@ -64,6 +65,54 @@ func ReadMessage(r io.Reader) (msg *Message, err error) {
6465
}, nil
6566
}
6667

68+
// readHeader reads the message headers from r.
69+
// This is like textproto.ReadMIMEHeader, but doesn't validate.
70+
// The fix for issue #53188 tightened up net/textproto to enforce
71+
// restrictions of RFC 7230.
72+
// This package implements RFC 5322, which does not have those restrictions.
73+
// This function copies the relevant code from net/textproto,
74+
// simplified for RFC 5322.
75+
func readHeader(r *textproto.Reader) (map[string][]string, error) {
76+
m := make(map[string][]string)
77+
78+
// The first line cannot start with a leading space.
79+
if buf, err := r.R.Peek(1); err == nil && (buf[0] == ' ' || buf[0] == '\t') {
80+
line, err := r.ReadLine()
81+
if err != nil {
82+
return m, err
83+
}
84+
return m, errors.New("malformed initial line: " + line)
85+
}
86+
87+
for {
88+
kv, err := r.ReadContinuedLine()
89+
if kv == "" {
90+
return m, err
91+
}
92+
93+
// Key ends at first colon.
94+
k, v, ok := strings.Cut(kv, ":")
95+
if !ok {
96+
return m, errors.New("malformed header line: " + kv)
97+
}
98+
key := textproto.CanonicalMIMEHeaderKey(k)
99+
100+
// Permit empty key, because that is what we did in the past.
101+
if key == "" {
102+
continue
103+
}
104+
105+
// Skip initial spaces in value.
106+
value := strings.TrimLeft(v, " \t")
107+
108+
m[key] = append(m[key], value)
109+
110+
if err != nil {
111+
return m, err
112+
}
113+
}
114+
}
115+
67116
// Layouts suitable for passing to time.Parse.
68117
// These are tried in order.
69118
var (

src/net/mail/message_test.go

+28
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,34 @@ So, "Hello".
3939
},
4040
body: "This is a message just to say hello.\nSo, \"Hello\".\n",
4141
},
42+
{
43+
// RFC 5322 permits any printable ASCII character,
44+
// except colon, in a header key. Issue #58862.
45+
in: `From: [email protected]
46+
Custom/Header: v
47+
48+
Body
49+
`,
50+
header: Header{
51+
"From": []string{"[email protected]"},
52+
"Custom/Header": []string{"v"},
53+
},
54+
body: "Body\n",
55+
},
56+
{
57+
// RFC 4155 mbox format. We've historically permitted this,
58+
// so we continue to permit it. Issue #60332.
59+
in: `From [email protected] Mon Jun 19 00:00:00 2023
60+
61+
62+
Hello, gophers!
63+
`,
64+
header: Header{
65+
"From": []string{"[email protected]"},
66+
"From [email protected] Mon Jun 19 00": []string{"00:00 2023"},
67+
},
68+
body: "Hello, gophers!\n",
69+
},
4270
}
4371

4472
func TestParsing(t *testing.T) {

0 commit comments

Comments
 (0)