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 <koni.marti@gmail.com>
Acked-by: Robin Jarry <robin@jarry.cc>
This commit is contained in:
Koni Marti 2022-09-21 00:27:58 +02:00 committed by Robin Jarry
parent 41822a6123
commit e5b0725824
6 changed files with 25 additions and 12 deletions

View file

@ -5,7 +5,6 @@ import (
"io" "io"
"github.com/ProtonMail/go-crypto/openpgp" "github.com/ProtonMail/go-crypto/openpgp"
"github.com/emersion/go-message"
_ "github.com/emersion/go-message/charset" _ "github.com/emersion/go-message/charset"
"git.sr.ht/~rjarry/aerc/lib/crypto" "git.sr.ht/~rjarry/aerc/lib/crypto"
@ -81,7 +80,7 @@ func NewMessageStoreView(messageInfo *models.MessageInfo,
cb(nil, err) cb(nil, err)
return return
} }
decrypted, err := message.Read(bytes.NewBuffer(msv.message)) decrypted, err := lib.ReadMessage(bytes.NewBuffer(msv.message))
if err != nil { if err != nil {
cb(nil, err) cb(nil, err)
return return
@ -124,7 +123,7 @@ func (msv *MessageStoreView) FetchBodyPart(part []int, cb func(io.Reader)) {
} }
buf := bytes.NewBuffer(msv.message) buf := bytes.NewBuffer(msv.message)
msg, err := message.Read(buf) msg, err := lib.ReadMessage(buf)
if err != nil { if err != nil {
panic(err) panic(err)
} }

View file

@ -123,7 +123,10 @@ func (imapw *IMAPWorker) handleFetchMessageBodyPart(
part, err := message.New(message.Header{Header: h}, part, err := message.New(message.Header{Header: h},
_msg.GetBody(&partBodySection)) _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) return fmt.Errorf("failed to create message reader: %w", err)
} }

View file

@ -10,6 +10,7 @@ import (
"strings" "strings"
"time" "time"
"git.sr.ht/~rjarry/aerc/logging"
"git.sr.ht/~rjarry/aerc/models" "git.sr.ht/~rjarry/aerc/models"
"github.com/emersion/go-message" "github.com/emersion/go-message"
_ "github.com/emersion/go-message/charset" _ "github.com/emersion/go-message/charset"
@ -252,7 +253,7 @@ func MessageInfo(raw RawMessage) (*models.MessageInfo, error) {
return nil, err return nil, err
} }
defer r.Close() defer r.Close()
msg, err := message.Read(r) msg, err := ReadMessage(r)
if err != nil { if err != nil {
return nil, fmt.Errorf("could not read message: %w", err) return nil, fmt.Errorf("could not read message: %w", err)
} }
@ -307,3 +308,17 @@ func NewCRLFReader(r io.Reader) io.Reader {
} }
return &buf 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
}

View file

@ -5,7 +5,6 @@ import (
"io" "io"
"github.com/emersion/go-maildir" "github.com/emersion/go-maildir"
"github.com/emersion/go-message"
"git.sr.ht/~rjarry/aerc/models" "git.sr.ht/~rjarry/aerc/models"
"git.sr.ht/~rjarry/aerc/worker/lib" "git.sr.ht/~rjarry/aerc/worker/lib"
@ -85,7 +84,7 @@ func (m Message) NewBodyPartReader(requestedParts []int) (io.Reader, error) {
return nil, err return nil, err
} }
defer f.Close() defer f.Close()
msg, err := message.Read(f) msg, err := lib.ReadMessage(f)
if err != nil { if err != nil {
return nil, fmt.Errorf("could not read message: %w", err) return nil, fmt.Errorf("could not read message: %w", err)
} }

View file

@ -15,7 +15,6 @@ import (
"git.sr.ht/~rjarry/aerc/worker/handlers" "git.sr.ht/~rjarry/aerc/worker/handlers"
"git.sr.ht/~rjarry/aerc/worker/lib" "git.sr.ht/~rjarry/aerc/worker/lib"
"git.sr.ht/~rjarry/aerc/worker/types" "git.sr.ht/~rjarry/aerc/worker/types"
gomessage "github.com/emersion/go-message"
) )
func init() { func init() {
@ -179,7 +178,7 @@ func (w *mboxWorker) handleMessage(msg types.WorkerMessage) error {
break break
} }
fullMsg, err := gomessage.Read(contentReader) fullMsg, err := lib.ReadMessage(contentReader)
if err != nil { if err != nil {
reterr = fmt.Errorf("could not read message: %w", err) reterr = fmt.Errorf("could not read message: %w", err)
break break

View file

@ -11,8 +11,6 @@ import (
"git.sr.ht/~rjarry/aerc/models" "git.sr.ht/~rjarry/aerc/models"
"git.sr.ht/~rjarry/aerc/worker/lib" "git.sr.ht/~rjarry/aerc/worker/lib"
notmuch "git.sr.ht/~rjarry/aerc/worker/notmuch/lib" notmuch "git.sr.ht/~rjarry/aerc/worker/notmuch/lib"
"github.com/emersion/go-message"
_ "github.com/emersion/go-message/charset"
) )
type Message struct { type Message struct {
@ -47,7 +45,7 @@ func (m *Message) NewBodyPartReader(requestedParts []int) (io.Reader, error) {
return nil, err return nil, err
} }
defer f.Close() defer f.Close()
msg, err := message.Read(f) msg, err := lib.ReadMessage(f)
if err != nil { if err != nil {
return nil, fmt.Errorf("could not read message: %w", err) return nil, fmt.Errorf("could not read message: %w", err)
} }