From 405c18d21388f1cc6f8b7349186efb3fa44eef87 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Thu, 19 Nov 2020 10:50:52 -0500 Subject: [PATCH] Convert HTML to plaintext for forwarding & replies --- go.mod | 3 +++ go.sum | 8 ++++++++ plugins/base/routes.go | 46 ++++++++++++++++++++++++++++++---------------- 3 files changed, 41 insertions(+), 16 deletions(-) diff --git a/go.mod b/go.mod index d784a48..e628789 100644 --- a/go.mod +++ b/go.mod @@ -23,9 +23,12 @@ require ( github.com/labstack/echo/v4 v4.1.16 github.com/labstack/gommon v0.3.0 github.com/microcosm-cc/bluemonday v1.0.2 + github.com/olekukonko/tablewriter v0.0.4 // indirect + github.com/ssor/bom v0.0.0-20170718123548-6386211fdfcf // indirect github.com/yuin/gopher-lua v0.0.0-20191220021717-ab39c6098bdb gitlab.com/golang-commonmark/linkify v0.0.0-20200225224916-64bca66f6ad3 golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37 // indirect golang.org/x/net v0.0.0-20200506145744-7e3656a0809f + jaytaylor.com/html2text v0.0.0-20200412013138-3577fbdbcff7 layeh.com/gopher-luar v1.0.7 ) diff --git a/go.sum b/go.sum index 12880bc..bb29840 100644 --- a/go.sum +++ b/go.sum @@ -103,6 +103,8 @@ github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hd github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ= github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/mattn/go-runewidth v0.0.7 h1:Ei8KR0497xHyKJPAv59M1dkC+rOZCMBJ+t3fZ+twI54= +github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/microcosm-cc/bluemonday v1.0.2 h1:5lPfLTTAvAbtS0VqT+94yOtFnGfUWYyx0+iToC3Os3s= @@ -112,6 +114,8 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJ github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/olekukonko/tablewriter v0.0.4 h1:vHD/YYe1Wolo78koG299f7V/VAS08c6IpCLn+Ejf/w8= +github.com/olekukonko/tablewriter v0.0.4/go.mod h1:zq6QwlOf5SlnkVbMSr5EoBv3636FWnp+qbPhuoO21uA= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= @@ -133,6 +137,8 @@ github.com/prometheus/procfs v0.1.3 h1:F0+tqvhOksq22sc6iCHF5WGlWjdwj92p0udFh1VFB github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +github.com/ssor/bom v0.0.0-20170718123548-6386211fdfcf h1:pvbZ0lM0XWPBqUKqFU8cmavspvIl9nulOYwdy6IFRRo= +github.com/ssor/bom v0.0.0-20170718123548-6386211fdfcf/go.mod h1:RJID2RhlZKId02nZ62WenDCkgHFerpIOmW0iT7GKmXM= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= @@ -205,5 +211,7 @@ gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +jaytaylor.com/html2text v0.0.0-20200412013138-3577fbdbcff7 h1:mub0MmFLOn8XLikZOAhgLD1kXJq8jgftSrrv7m00xFo= +jaytaylor.com/html2text v0.0.0-20200412013138-3577fbdbcff7/go.mod h1:OxvTsCwKosqQ1q7B+8FwXqg4rKZ/UG9dUW+g/VL2xH4= layeh.com/gopher-luar v1.0.7 h1:53iv6CCkRs5wyofZ+qVXcyAYQOIG52s6pt4xkqZdq7k= layeh.com/gopher-luar v1.0.7/go.mod h1:TPnIVCZ2RJBndm7ohXyaqfhzjlZ+OA2SZR/YwL8tECk= diff --git a/plugins/base/routes.go b/plugins/base/routes.go index 2107abb..0345189 100644 --- a/plugins/base/routes.go +++ b/plugins/base/routes.go @@ -14,12 +14,13 @@ import ( "git.sr.ht/~emersion/alps" "github.com/emersion/go-imap" - imapmove "github.com/emersion/go-imap-move" - imapclient "github.com/emersion/go-imap/client" "github.com/emersion/go-message" "github.com/emersion/go-message/mail" "github.com/emersion/go-smtp" "github.com/labstack/echo/v4" + "jaytaylor.com/html2text" + imapclient "github.com/emersion/go-imap/client" + imapmove "github.com/emersion/go-imap-move" ) func registerRoutes(p *alps.GoPlugin) { @@ -759,17 +760,25 @@ func handleReply(ctx *alps.Context) error { return fmt.Errorf("failed to parse part Content-Type: %v", err) } - if !strings.EqualFold(mimeType, "text/plain") { - err := fmt.Errorf("cannot reply to %q part", mimeType) + if mimeType == "text/plain" { + msg.Text, err = quote(part.Body) + if err != nil { + return err + } + } else if mimeType == "text/html" { + text, err := html2text.FromReader(part.Body, html2text.Options{}) + if err != nil { + return err + } + msg.Text, err = quote(strings.NewReader(text)) + if err != nil { + return nil + } + } else { + err := fmt.Errorf("cannot forward %q part", mimeType) return echo.NewHTTPError(http.StatusBadRequest, err) } - // TODO: strip HTML tags if text/html - msg.Text, err = quote(part.Body) - if err != nil { - return err - } - msg.MessageID = mail.GenerateMessageID() msg.InReplyTo = inReplyTo.Envelope.MessageId // TODO: populate From from known user addresses and inReplyTo.Envelope.To @@ -819,16 +828,21 @@ func handleForward(ctx *alps.Context) error { return fmt.Errorf("failed to parse part Content-Type: %v", err) } - if !strings.EqualFold(mimeType, "text/plain") { + if mimeType == "text/plain" { + msg.Text, err = quote(part.Body) + if err != nil { + return err + } + } else if mimeType == "text/html" { + msg.Text, err = html2text.FromReader(part.Body, html2text.Options{}) + if err != nil { + return err + } + } else { err := fmt.Errorf("cannot forward %q part", mimeType) return echo.NewHTTPError(http.StatusBadRequest, err) } - msg.Text, err = quote(part.Body) - if err != nil { - return err - } - msg.MessageID = mail.GenerateMessageID() msg.Subject = source.Envelope.Subject if !strings.HasPrefix(strings.ToLower(msg.Subject), "fwd:") &&