From e5b0725824ac9ccf218732238e4b3b525fa6ad46 Mon Sep 17 00:00:00 2001 From: Koni Marti Date: Wed, 21 Sep 2022 00:27:58 +0200 Subject: [PATCH] charset: handle unknown charsets more user-friendly Do not throw an error when the charset is unknown; the message entity can still be read, but log the error instead. Reported-by: falsifian Signed-off-by: Koni Marti Acked-by: Robin Jarry --- lib/messageview.go | 5 ++--- worker/imap/fetch.go | 5 ++++- worker/lib/parse.go | 17 ++++++++++++++++- worker/maildir/message.go | 3 +-- worker/mbox/worker.go | 3 +-- worker/notmuch/message.go | 4 +--- 6 files changed, 25 insertions(+), 12 deletions(-) diff --git a/lib/messageview.go b/lib/messageview.go index 6ad86c9..ff754a4 100644 --- a/lib/messageview.go +++ b/lib/messageview.go @@ -5,7 +5,6 @@ import ( "io" "github.com/ProtonMail/go-crypto/openpgp" - "github.com/emersion/go-message" _ "github.com/emersion/go-message/charset" "git.sr.ht/~rjarry/aerc/lib/crypto" @@ -81,7 +80,7 @@ func NewMessageStoreView(messageInfo *models.MessageInfo, cb(nil, err) return } - decrypted, err := message.Read(bytes.NewBuffer(msv.message)) + decrypted, err := lib.ReadMessage(bytes.NewBuffer(msv.message)) if err != nil { cb(nil, err) return @@ -124,7 +123,7 @@ func (msv *MessageStoreView) FetchBodyPart(part []int, cb func(io.Reader)) { } buf := bytes.NewBuffer(msv.message) - msg, err := message.Read(buf) + msg, err := lib.ReadMessage(buf) if err != nil { panic(err) } diff --git a/worker/imap/fetch.go b/worker/imap/fetch.go index f21c6e9..d675ed1 100644 --- a/worker/imap/fetch.go +++ b/worker/imap/fetch.go @@ -123,7 +123,10 @@ func (imapw *IMAPWorker) handleFetchMessageBodyPart( part, err := message.New(message.Header{Header: h}, _msg.GetBody(&partBodySection)) - if err != nil { + if message.IsUnknownCharset(err) { + logging.Warnf("unknown charset encountered "+ + "for uid %d", _msg.Uid) + } else if err != nil { return fmt.Errorf("failed to create message reader: %w", err) } diff --git a/worker/lib/parse.go b/worker/lib/parse.go index 30d06a9..3eaa2ae 100644 --- a/worker/lib/parse.go +++ b/worker/lib/parse.go @@ -10,6 +10,7 @@ import ( "strings" "time" + "git.sr.ht/~rjarry/aerc/logging" "git.sr.ht/~rjarry/aerc/models" "github.com/emersion/go-message" _ "github.com/emersion/go-message/charset" @@ -252,7 +253,7 @@ func MessageInfo(raw RawMessage) (*models.MessageInfo, error) { return nil, err } defer r.Close() - msg, err := message.Read(r) + msg, err := ReadMessage(r) if err != nil { return nil, fmt.Errorf("could not read message: %w", err) } @@ -307,3 +308,17 @@ func NewCRLFReader(r io.Reader) io.Reader { } return &buf } + +// ReadMessage is a wrapper for the message.Read function to read a message +// from r. The message's encoding and charset are automatically decoded to +// UTF-8. If an unknown charset is encountered, the error is logged but a nil +// error is returned since the entity object can still be read. +func ReadMessage(r io.Reader) (*message.Entity, error) { + entity, err := message.Read(r) + if message.IsUnknownCharset(err) { + logging.Warnf("unknown charset encountered") + } else if err != nil { + return nil, fmt.Errorf("could not read message: %w", err) + } + return entity, nil +} diff --git a/worker/maildir/message.go b/worker/maildir/message.go index 81573c5..9cd1331 100644 --- a/worker/maildir/message.go +++ b/worker/maildir/message.go @@ -5,7 +5,6 @@ import ( "io" "github.com/emersion/go-maildir" - "github.com/emersion/go-message" "git.sr.ht/~rjarry/aerc/models" "git.sr.ht/~rjarry/aerc/worker/lib" @@ -85,7 +84,7 @@ func (m Message) NewBodyPartReader(requestedParts []int) (io.Reader, error) { return nil, err } defer f.Close() - msg, err := message.Read(f) + msg, err := lib.ReadMessage(f) if err != nil { return nil, fmt.Errorf("could not read message: %w", err) } diff --git a/worker/mbox/worker.go b/worker/mbox/worker.go index 067147e..c5c7082 100644 --- a/worker/mbox/worker.go +++ b/worker/mbox/worker.go @@ -15,7 +15,6 @@ import ( "git.sr.ht/~rjarry/aerc/worker/handlers" "git.sr.ht/~rjarry/aerc/worker/lib" "git.sr.ht/~rjarry/aerc/worker/types" - gomessage "github.com/emersion/go-message" ) func init() { @@ -179,7 +178,7 @@ func (w *mboxWorker) handleMessage(msg types.WorkerMessage) error { break } - fullMsg, err := gomessage.Read(contentReader) + fullMsg, err := lib.ReadMessage(contentReader) if err != nil { reterr = fmt.Errorf("could not read message: %w", err) break diff --git a/worker/notmuch/message.go b/worker/notmuch/message.go index a51f78b..59367fd 100644 --- a/worker/notmuch/message.go +++ b/worker/notmuch/message.go @@ -11,8 +11,6 @@ import ( "git.sr.ht/~rjarry/aerc/models" "git.sr.ht/~rjarry/aerc/worker/lib" notmuch "git.sr.ht/~rjarry/aerc/worker/notmuch/lib" - "github.com/emersion/go-message" - _ "github.com/emersion/go-message/charset" ) type Message struct { @@ -47,7 +45,7 @@ func (m *Message) NewBodyPartReader(requestedParts []int) (io.Reader, error) { return nil, err } defer f.Close() - msg, err := message.Read(f) + msg, err := lib.ReadMessage(f) if err != nil { return nil, fmt.Errorf("could not read message: %w", err) }