From a3aa4c4860566fc5352f01b6be82dda0f31d6a23 Mon Sep 17 00:00:00 2001 From: gonejack Date: Wed, 28 Apr 2021 11:15:56 +0800 Subject: [PATCH 1/2] Support cjk encoding --- email.go | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/email.go b/email.go index 57d1b53..a1ba840 100644 --- a/email.go +++ b/email.go @@ -24,6 +24,9 @@ import ( "strings" "time" "unicode" + + "golang.org/x/text/encoding/htmlindex" + "golang.org/x/text/transform" ) const ( @@ -90,7 +93,7 @@ func handleAddressList(v []string) []string { for _, a := range v { w := strings.Split(a, ",") for _, addr := range w { - decodedAddr, err := (&mime.WordDecoder{}).DecodeHeader(strings.TrimSpace(addr)) + decodedAddr, err := wordDecoder.DecodeHeader(strings.TrimSpace(addr)) if err == nil { res = append(res, decodedAddr) } else { @@ -118,7 +121,7 @@ func NewEmailFromReader(r io.Reader) (*Email, error) { switch h { case "Subject": e.Subject = v[0] - subj, err := (&mime.WordDecoder{}).DecodeHeader(e.Subject) + subj, err := wordDecoder.DecodeHeader(e.Subject) if err == nil && len(subj) > 0 { e.Subject = subj } @@ -137,7 +140,7 @@ func NewEmailFromReader(r io.Reader) (*Email, error) { delete(hdrs, h) case "From": e.From = v[0] - fr, err := (&mime.WordDecoder{}).DecodeHeader(e.From) + fr, err := wordDecoder.DecodeHeader(e.From) if err == nil && len(fr) > 0 { e.From = fr } @@ -216,7 +219,7 @@ func parseMIMEParts(hs textproto.MIMEHeader, b io.Reader) ([]*part, error) { if _, ok := p.Header["Content-Type"]; !ok { p.Header.Set("Content-Type", defaultContentType) } - subct, _, err := mime.ParseMediaType(p.Header.Get("Content-Type")) + subct, subps, err := mime.ParseMediaType(p.Header.Get("Content-Type")) if err != nil { return ps, err } @@ -232,6 +235,13 @@ func parseMIMEParts(hs textproto.MIMEHeader, b io.Reader) ([]*part, error) { const cte = "Content-Transfer-Encoding" if p.Header.Get(cte) == "base64" { reader = base64.NewDecoder(base64.StdEncoding, reader) + + if strings.HasPrefix(subct, "text") && subps["charset"] != "" { + transReader, err := wordDecoder.CharsetReader(subps["charset"], reader) + if err == nil { + reader = transReader + } + } } // Otherwise, just append the part to the list // Copy the part data into the buffer @@ -807,3 +817,13 @@ func generateMessageID() (string, error) { msgid := fmt.Sprintf("<%d.%d.%d@%s>", t, pid, rint, h) return msgid, nil } + +var wordDecoder = &mime.WordDecoder{ + CharsetReader: func(charset string, input io.Reader) (io.Reader, error) { + encoding, err := htmlindex.Get(charset) + if err != nil { + return nil, err + } + return transform.NewReader(input, encoding.NewDecoder()), nil + }, +} From be7ee76202de5e938804ff87131f56c5aeda85f3 Mon Sep 17 00:00:00 2001 From: gonejack Date: Wed, 28 Apr 2021 11:51:16 +0800 Subject: [PATCH 2/2] Fix html decoding within multipart --- email.go | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/email.go b/email.go index a1ba840..5343fee 100644 --- a/email.go +++ b/email.go @@ -230,19 +230,23 @@ func parseMIMEParts(hs textproto.MIMEHeader, b io.Reader) ([]*part, error) { } ps = append(ps, sps...) } else { - var reader io.Reader - reader = p + var reader io.Reader = p + const cte = "Content-Transfer-Encoding" - if p.Header.Get(cte) == "base64" { + switch p.Header.Get(cte) { + case "quoted-printable": + reader = quotedprintable.NewReader(reader) + case "base64": reader = base64.NewDecoder(base64.StdEncoding, reader) + } - if strings.HasPrefix(subct, "text") && subps["charset"] != "" { - transReader, err := wordDecoder.CharsetReader(subps["charset"], reader) - if err == nil { - reader = transReader - } + if strings.HasPrefix(subct, "text") && subps["charset"] != "" { + transReader, err := wordDecoder.CharsetReader(subps["charset"], reader) + if err == nil { + reader = transReader } } + // Otherwise, just append the part to the list // Copy the part data into the buffer if _, err := io.Copy(&buf, reader); err != nil {