Commit 8ae584f2 authored by Daniel Speichert's avatar Daniel Speichert Committed by Russ Cox

net/textproto: accept multi-line error messages

Ads documentation for both formats of messages accepted by
ReadResponse(). Validity of message should not be altered by
the validation process. On message with unexpected code,
a properly formatted message was not fully read.

Fixes #10230

Change-Id: Ic0b473059a68ab624ce0525e359d0f5d0b8d2117
Reviewed-on: https://go-review.googlesource.com/18172Reviewed-by: default avatarRuss Cox <rsc@golang.org>
parent bb8c2e19
...@@ -237,7 +237,12 @@ func (r *Reader) ReadCodeLine(expectCode int) (code int, message string, err err ...@@ -237,7 +237,12 @@ func (r *Reader) ReadCodeLine(expectCode int) (code int, message string, err err
// separated by a newline (\n). // separated by a newline (\n).
// //
// See page 36 of RFC 959 (http://www.ietf.org/rfc/rfc959.txt) for // See page 36 of RFC 959 (http://www.ietf.org/rfc/rfc959.txt) for
// details. // details of another form of response accepted:
//
// code-message line 1
// message line 2
// ...
// code message line n
// //
// If the prefix of the status does not match the digits in expectCode, // If the prefix of the status does not match the digits in expectCode,
// ReadResponse returns with err set to &Error{code, message}. // ReadResponse returns with err set to &Error{code, message}.
...@@ -248,7 +253,8 @@ func (r *Reader) ReadCodeLine(expectCode int) (code int, message string, err err ...@@ -248,7 +253,8 @@ func (r *Reader) ReadCodeLine(expectCode int) (code int, message string, err err
// //
func (r *Reader) ReadResponse(expectCode int) (code int, message string, err error) { func (r *Reader) ReadResponse(expectCode int) (code int, message string, err error) {
code, continued, message, err := r.readCodeLine(expectCode) code, continued, message, err := r.readCodeLine(expectCode)
for err == nil && continued { multi := continued
for continued {
line, err := r.ReadLine() line, err := r.ReadLine()
if err != nil { if err != nil {
return 0, "", err return 0, "", err
...@@ -256,7 +262,7 @@ func (r *Reader) ReadResponse(expectCode int) (code int, message string, err err ...@@ -256,7 +262,7 @@ func (r *Reader) ReadResponse(expectCode int) (code int, message string, err err
var code2 int var code2 int
var moreMessage string var moreMessage string
code2, continued, moreMessage, err = parseCodeLine(line, expectCode) code2, continued, moreMessage, err = parseCodeLine(line, 0)
if err != nil || code2 != code { if err != nil || code2 != code {
message += "\n" + strings.TrimRight(line, "\r\n") message += "\n" + strings.TrimRight(line, "\r\n")
continued = true continued = true
...@@ -264,6 +270,10 @@ func (r *Reader) ReadResponse(expectCode int) (code int, message string, err err ...@@ -264,6 +270,10 @@ func (r *Reader) ReadResponse(expectCode int) (code int, message string, err err
} }
message += "\n" + moreMessage message += "\n" + moreMessage
} }
if err != nil && multi && message != "" {
// replace one line error message with all lines (full message)
err = &Error{code, message}
}
return return
} }
......
...@@ -284,6 +284,35 @@ func TestRFC959Lines(t *testing.T) { ...@@ -284,6 +284,35 @@ func TestRFC959Lines(t *testing.T) {
} }
} }
// Test that multi-line errors are appropriately and fully read. Issue 10230.
func TestReadMultiLineError(t *testing.T) {
r := reader("550-5.1.1 The email account that you tried to reach does not exist. Please try\n" +
"550-5.1.1 double-checking the recipient's email address for typos or\n" +
"550-5.1.1 unnecessary spaces. Learn more at\n" +
"Unexpected but legal text!\n" +
"550 5.1.1 https://support.google.com/mail/answer/6596 h20si25154304pfd.166 - gsmtp\n")
wantMsg := "5.1.1 The email account that you tried to reach does not exist. Please try\n" +
"5.1.1 double-checking the recipient's email address for typos or\n" +
"5.1.1 unnecessary spaces. Learn more at\n" +
"Unexpected but legal text!\n" +
"5.1.1 https://support.google.com/mail/answer/6596 h20si25154304pfd.166 - gsmtp"
code, msg, err := r.ReadResponse(250)
if err == nil {
t.Errorf("ReadResponse: no error, want error")
}
if code != 550 {
t.Errorf("ReadResponse: code=%d, want %d", code, 550)
}
if msg != wantMsg {
t.Errorf("ReadResponse: msg=%q, want %q", msg, wantMsg)
}
if err.Error() != "550 "+wantMsg {
t.Errorf("ReadResponse: error=%q, want %q", err.Error(), "550 "+wantMsg)
}
}
func TestCommonHeaders(t *testing.T) { func TestCommonHeaders(t *testing.T) {
for h := range commonHeader { for h := range commonHeader {
if h != CanonicalMIMEHeaderKey(h) { if h != CanonicalMIMEHeaderKey(h) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment