]> Cypherpunks repositories - gostls13.git/commitdiff
net/textproto: accept multi-line error messages
authorDaniel Speichert <daniel@speichert.pl>
Tue, 29 Dec 2015 15:46:40 +0000 (16:46 +0100)
committerRuss Cox <rsc@golang.org>
Fri, 8 Jan 2016 16:32:42 +0000 (16:32 +0000)
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/18172
Reviewed-by: Russ Cox <rsc@golang.org>
src/net/textproto/reader.go
src/net/textproto/reader_test.go

index 17edfadad2d5f54e771f801594895fcdd918450e..91bbb573043c77e262e0de5908a22bd363b969fd 100644 (file)
@@ -237,7 +237,12 @@ func (r *Reader) ReadCodeLine(expectCode int) (code int, message string, err err
 // separated by a newline (\n).
 //
 // 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,
 // 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
 //
 func (r *Reader) ReadResponse(expectCode int) (code int, message string, err error) {
        code, continued, message, err := r.readCodeLine(expectCode)
-       for err == nil && continued {
+       multi := continued
+       for continued {
                line, err := r.ReadLine()
                if err != nil {
                        return 0, "", err
@@ -256,7 +262,7 @@ func (r *Reader) ReadResponse(expectCode int) (code int, message string, err err
 
                var code2 int
                var moreMessage string
-               code2, continued, moreMessage, err = parseCodeLine(line, expectCode)
+               code2, continued, moreMessage, err = parseCodeLine(line, 0)
                if err != nil || code2 != code {
                        message += "\n" + strings.TrimRight(line, "\r\n")
                        continued = true
@@ -264,6 +270,10 @@ func (r *Reader) ReadResponse(expectCode int) (code int, message string, err err
                }
                message += "\n" + moreMessage
        }
+       if err != nil && multi && message != "" {
+               // replace one line error message with all lines (full message)
+               err = &Error{code, message}
+       }
        return
 }
 
index db7d8ab41cb3bd1d8736e3ab45f0280b33517f8f..9c71594362ebb4be39cfd4e6be1c90203ef43a75 100644 (file)
@@ -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) {
        for h := range commonHeader {
                if h != CanonicalMIMEHeaderKey(h) {