Skip to content

Commit

Permalink
Return public net/textproto error types
Browse files Browse the repository at this point in the history
To allow for checking returned error types, types from the standard library's `net/textproto` must be used instead of types from the private `textproto` fork.
  • Loading branch information
dcormier committed Dec 27, 2023
1 parent ed0394e commit 60b0e78
Show file tree
Hide file tree
Showing 5 changed files with 18 additions and 34 deletions.
2 changes: 1 addition & 1 deletion inspect_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@ import (
"bytes"
"io"
"net/mail"
"net/textproto"
"strings"
"testing"

"github.com/jhillyerd/enmime"
"github.com/jhillyerd/enmime/internal/test"
"github.com/jhillyerd/enmime/internal/textproto"
)

func TestDecodeRFC2047(t *testing.T) {
Expand Down
21 changes: 11 additions & 10 deletions internal/textproto/reader.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"fmt"
"io"
"math"
"net/textproto"
"strconv"
"strings"
"sync"
Expand Down Expand Up @@ -198,20 +199,20 @@ func (r *Reader) readCodeLine(expectCode int) (code int, continued bool, message

func parseCodeLine(line string, expectCode int) (code int, continued bool, message string, err error) {
if len(line) < 4 || line[3] != ' ' && line[3] != '-' {
err = ProtocolError("short response: " + line)
err = textproto.ProtocolError("short response: " + line)
return
}
continued = line[3] == '-'
code, err = strconv.Atoi(line[0:3])
if err != nil || code < 100 {
err = ProtocolError("invalid response code: " + line)
err = textproto.ProtocolError("invalid response code: " + line)
return
}
message = line[4:]
if 1 <= expectCode && expectCode < 10 && code/100 != expectCode ||
10 <= expectCode && expectCode < 100 && code/10 != expectCode ||
100 <= expectCode && expectCode < 1000 && code != expectCode {
err = &Error{code, message}
err = &textproto.Error{code, message}

Check failure on line 215 in internal/textproto/reader.go

View workflow job for this annotation

GitHub Actions / golangci

composites: net/textproto.Error struct literal uses unkeyed fields (govet)
}
return
}
Expand All @@ -236,7 +237,7 @@ func parseCodeLine(line string, expectCode int) (code int, continued bool, messa
func (r *Reader) ReadCodeLine(expectCode int) (code int, message string, err error) {
code, continued, message, err := r.readCodeLine(expectCode)
if err == nil && continued {
err = ProtocolError("unexpected multi-line response: " + message)
err = textproto.ProtocolError("unexpected multi-line response: " + message)
}
return
}
Expand Down Expand Up @@ -288,7 +289,7 @@ func (r *Reader) ReadResponse(expectCode int) (code int, message string, err err
}
if err != nil && multi && message != "" {
// replace one line error message with all lines (full message)
err = &Error{code, message}
err = &textproto.Error{code, message}

Check failure on line 292 in internal/textproto/reader.go

View workflow job for this annotation

GitHub Actions / golangci

composites: net/textproto.Error struct literal uses unkeyed fields (govet)
}
return
}
Expand Down Expand Up @@ -506,7 +507,7 @@ func readMIMEHeader(r *Reader, lim int64) (MIMEHeader, error) {
if err != nil {
return m, err
}
return m, ProtocolError("malformed MIME header initial line: " + string(line))
return m, textproto.ProtocolError("malformed MIME header initial line: " + string(line))
}

for {
Expand All @@ -518,15 +519,15 @@ func readMIMEHeader(r *Reader, lim int64) (MIMEHeader, error) {
// Key ends at first colon.
k, v, ok := bytes.Cut(kv, colon)
if !ok {
return m, ProtocolError("malformed MIME header line: " + string(kv))
return m, textproto.ProtocolError("malformed MIME header line: " + string(kv))
}
key, ok := canonicalMIMEHeaderKey(k)
if !ok {
return m, ProtocolError("malformed MIME header line: " + string(kv))
return m, textproto.ProtocolError("malformed MIME header line: " + string(kv))
}
for _, c := range v {
if !validHeaderValueByte(c) {
return m, ProtocolError("malformed MIME header line: " + string(kv))
return m, textproto.ProtocolError("malformed MIME header line: " + string(kv))
}
}

Expand Down Expand Up @@ -578,7 +579,7 @@ func noValidation(_ []byte) error { return nil }
// contain a colon.
func mustHaveFieldNameColon(line []byte) error {
if bytes.IndexByte(line, ':') < 0 {
return ProtocolError(fmt.Sprintf("malformed MIME header: missing colon: %q", line))
return textproto.ProtocolError(fmt.Sprintf("malformed MIME header: missing colon: %q", line))
}
return nil
}
Expand Down
7 changes: 4 additions & 3 deletions internal/textproto/reader_email.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"bytes"
"errors"
"math"
"net/textproto"
)

// ReadEmailMIMEHeader reads a MIME-style header from r.
Expand Down Expand Up @@ -32,7 +33,7 @@ func readEmailMIMEHeader(r *Reader, lim int64) (MIMEHeader, error) {
if err != nil {
return m, err
}
return m, ProtocolError("malformed MIME header initial line: " + string(line))
return m, textproto.ProtocolError("malformed MIME header initial line: " + string(line))
}

for {
Expand All @@ -44,11 +45,11 @@ func readEmailMIMEHeader(r *Reader, lim int64) (MIMEHeader, error) {
// Key ends at first colon.
k, v, ok := bytes.Cut(kv, colon)
if !ok {
return m, ProtocolError("malformed MIME header line: " + string(kv))
return m, textproto.ProtocolError("malformed MIME header line: " + string(kv))
}
key, ok := canonicalEmailMIMEHeaderKey(k)
if !ok {
return m, ProtocolError("malformed MIME header line: " + string(kv))
return m, textproto.ProtocolError("malformed MIME header line: " + string(kv))
}
// for _, c := range v {
// if !validHeaderValueByte(c) {
Expand Down
3 changes: 2 additions & 1 deletion internal/textproto/reader_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"bytes"
"io"
"net"
"net/textproto"
"reflect"
"strings"
"sync"
Expand Down Expand Up @@ -69,7 +70,7 @@ func TestReadCodeLine(t *testing.T) {
if code != 345 || msg != "no way" || err == nil {
t.Fatalf("Line 3: %d, %s, %v", code, msg, err)
}
if e, ok := err.(*Error); !ok || e.Code != code || e.Msg != msg {
if e, ok := err.(*textproto.Error); !ok || e.Code != code || e.Msg != msg {
t.Fatalf("Line 3: wrong error %v\n", err)
}
code, msg, err = r.ReadCodeLine(1)
Expand Down
19 changes: 0 additions & 19 deletions internal/textproto/textproto.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,29 +26,10 @@ package textproto

import (
"bufio"
"fmt"
"io"
"net"
)

// An Error represents a numeric error response from a server.
type Error struct {
Code int
Msg string
}

func (e *Error) Error() string {
return fmt.Sprintf("%03d %s", e.Code, e.Msg)
}

// A ProtocolError describes a protocol violation such
// as an invalid response or a hung-up connection.
type ProtocolError string

func (p ProtocolError) Error() string {
return string(p)
}

// A Conn represents a textual network protocol connection.
// It consists of a Reader and Writer to manage I/O
// and a Pipeline to sequence concurrent requests on the connection.
Expand Down

0 comments on commit 60b0e78

Please sign in to comment.