Skip to content

mime: cannot round-trip Word{En,De}coder #14608

@nigeltao

Description

@nigeltao

WordEncoder sometimes passes text straight through, sometimes it does not. From the example_test.go:

fmt.Println(mime.QEncoding.Encode("utf-8", "¡Hola, señor!"))
fmt.Println(mime.QEncoding.Encode("utf-8", "Hello!"))

prints

// Output:
// =?utf-8?q?=C2=A1Hola,_se=C3=B1or!?=
// Hello!

The problem is that, given an arbitrary output of a WordEncoder, how should a user tell whether or not to pass it to a WordDecoder to recover the original? A WD returns an error if the input isn't actually escaped:

func main() {
    testCases := []string{
        "=?utf-8?q?=C2=A1Hola,_se=C3=B1or!?=",
        "Hello!",
    }
    for _, tc := range testCases {
        d := new(mime.WordDecoder)
        fmt.Println(d.Decode(tc))
    }
}

prints

¡Hola, señor! <nil>
 mime: invalid RFC 2047 encoded-word

RFC 2047 actually says that Generally, an "encoded-word" is a sequence of printable ASCII characters that begins with "=?", ends with "?=", and has two "?"s in between and, as a workaround, users of the mime package can check that before calling Decode.

Still, this should probably be provided by the library, instead of users of that library. I can think of two possible solutions:

  1. Add a WordDecoder.CanDecode(string) bool method. The caller should call that before calling Decode.
  2. Export the existing errInvalidWord as ErrInvalidWord (or as a better name). The caller should check err == mime.ErrInvalidWord after calling Decode.

@bradfitz, WDYT?

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions