From 6ff3c7a1ba680506d77fc1fe8dfbf5b804a3fea7 Mon Sep 17 00:00:00 2001 From: Galen Abell Date: Tue, 3 Mar 2020 08:45:06 -0500 Subject: [PATCH] Mark sent messages as "seen" in maildir - Add maildir flags to complement a messages imap flags - Set the "seen" flag on sent messages when using the maildir backend - Cleanup AppendMessage interface to use models.Flag for both IMAP and maildir --- commands/compose/send.go | 4 ++-- go.mod | 2 +- go.sum | 6 ++++++ worker/imap/fetch.go | 6 +++--- worker/imap/imap.go | 24 +++++++++++++++++++++--- worker/imap/movecopy.go | 2 +- worker/imap/worker.go | 2 +- worker/maildir/message.go | 27 +++++++++++++++++++++++---- worker/maildir/worker.go | 11 ++++++----- worker/types/messages.go | 2 +- 10 files changed, 65 insertions(+), 21 deletions(-) diff --git a/commands/compose/send.go b/commands/compose/send.go index 2d994bf..9136ce8 100644 --- a/commands/compose/send.go +++ b/commands/compose/send.go @@ -10,7 +10,6 @@ import ( "strings" "time" - "github.com/emersion/go-imap" "github.com/emersion/go-sasl" "github.com/emersion/go-smtp" "github.com/gdamore/tcell" @@ -18,6 +17,7 @@ import ( "github.com/miolini/datacounter" "github.com/pkg/errors" + "git.sr.ht/~sircmpwn/aerc/models" "git.sr.ht/~sircmpwn/aerc/widgets" "git.sr.ht/~sircmpwn/aerc/worker/types" ) @@ -235,7 +235,7 @@ func (Send) Execute(aerc *widgets.Aerc, args []string) error { r, w := io.Pipe() worker.PostAction(&types.AppendMessage{ Destination: config.CopyTo, - Flags: []string{imap.SeenFlag}, + Flags: []models.Flag{models.SeenFlag}, Date: time.Now(), Reader: r, Length: nbytes, diff --git a/go.mod b/go.mod index c7839fd..2a2ff38 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,7 @@ require ( github.com/ddevault/go-libvterm v0.0.0-20190526194226-b7d861da3810 github.com/emersion/go-imap v1.0.0 github.com/emersion/go-imap-idle v0.0.0-20190519112320-2704abd7050e - github.com/emersion/go-maildir v0.0.0-20191218233049-14e25d3ea720 + github.com/emersion/go-maildir v0.2.0 github.com/emersion/go-message v0.10.7 github.com/emersion/go-sasl v0.0.0-20190817083125-240c8404624e github.com/emersion/go-smtp v0.11.2 diff --git a/go.sum b/go.sum index 01024b4..f5c2ad4 100644 --- a/go.sum +++ b/go.sum @@ -23,6 +23,12 @@ github.com/emersion/go-maildir v0.0.0-20190727102040-941194b0ac70 h1:aUiPu6/iCjc github.com/emersion/go-maildir v0.0.0-20190727102040-941194b0ac70/go.mod h1:I2j27lND/SRLgxROe50Vam81MSaqPFvJ0OHNnDZ7n84= github.com/emersion/go-maildir v0.0.0-20191218233049-14e25d3ea720 h1:0Hj2cVnV1NunzYK6Y9fjTdpeqHClF+QNTyiCyhIJ/0E= github.com/emersion/go-maildir v0.0.0-20191218233049-14e25d3ea720/go.mod h1:I2j27lND/SRLgxROe50Vam81MSaqPFvJ0OHNnDZ7n84= +github.com/emersion/go-maildir v0.1.0 h1:GwaZOjulI/6XJInH+ChOeAgXv3BuVFIBg5RtMTFwURA= +github.com/emersion/go-maildir v0.1.0/go.mod h1:I2j27lND/SRLgxROe50Vam81MSaqPFvJ0OHNnDZ7n84= +github.com/emersion/go-maildir v0.1.1-0.20200301104031-a05813beeb4a h1:3XddcpC7A4HR6iZ+xXZj3wgIk0WhrHGwZGVqffWN7Js= +github.com/emersion/go-maildir v0.1.1-0.20200301104031-a05813beeb4a/go.mod h1:I2j27lND/SRLgxROe50Vam81MSaqPFvJ0OHNnDZ7n84= +github.com/emersion/go-maildir v0.2.0 h1:fC4+UVGl8GcQGbFF7AWab2JMf4VbKz+bMNv07xxhzs8= +github.com/emersion/go-maildir v0.2.0/go.mod h1:I2j27lND/SRLgxROe50Vam81MSaqPFvJ0OHNnDZ7n84= github.com/emersion/go-message v0.10.4-0.20190609165112-592ace5bc1ca/go.mod h1:3h+HsGTCFHmk4ngJ2IV/YPhdlaOcR6hcgqM3yca9v7c= github.com/emersion/go-message v0.10.7 h1:wVC8P985qmmL9PGV/VlkBikVqFirxTeYv9xi+YyCprU= github.com/emersion/go-message v0.10.7/go.mod h1:C4jnca5HOTo4bGN9YdqNQM9sITuT3Y0K6bSUw9RklvY= diff --git a/worker/imap/fetch.go b/worker/imap/fetch.go index bf60aa9..f131117 100644 --- a/worker/imap/fetch.go +++ b/worker/imap/fetch.go @@ -91,7 +91,7 @@ func (imapw *IMAPWorker) handleFetchMessages( Info: &models.MessageInfo{ BodyStructure: translateBodyStructure(_msg.BodyStructure), Envelope: translateEnvelope(_msg.Envelope), - Flags: translateFlags(_msg.Flags), + Flags: translateImapFlags(_msg.Flags), InternalDate: _msg.InternalDate, RFC822Headers: header, Uid: _msg.Uid, @@ -115,7 +115,7 @@ func (imapw *IMAPWorker) handleFetchMessages( imapw.worker.PostMessage(&types.MessageInfo{ Message: types.RespondTo(msg), Info: &models.MessageInfo{ - Flags: translateFlags(_msg.Flags), + Flags: translateImapFlags(_msg.Flags), Uid: _msg.Uid, }, }, nil) @@ -136,7 +136,7 @@ func (imapw *IMAPWorker) handleFetchMessages( imapw.worker.PostMessage(&types.MessageInfo{ Message: types.RespondTo(msg), Info: &models.MessageInfo{ - Flags: translateFlags(_msg.Flags), + Flags: translateImapFlags(_msg.Flags), Uid: _msg.Uid, }, }, nil) diff --git a/worker/imap/imap.go b/worker/imap/imap.go index b0aacf6..fdcbc38 100644 --- a/worker/imap/imap.go +++ b/worker/imap/imap.go @@ -89,7 +89,7 @@ func translateAddresses(addrs []*imap.Address) []*models.Address { return converted } -var flagMap = map[string]models.Flag{ +var imapToFlag = map[string]models.Flag{ imap.SeenFlag: models.SeenFlag, imap.RecentFlag: models.RecentFlag, imap.AnsweredFlag: models.AnsweredFlag, @@ -97,12 +97,30 @@ var flagMap = map[string]models.Flag{ imap.FlaggedFlag: models.FlaggedFlag, } -func translateFlags(imapFlags []string) []models.Flag { +var flagToImap = map[models.Flag]string{ + models.SeenFlag: imap.SeenFlag, + models.RecentFlag: imap.RecentFlag, + models.AnsweredFlag: imap.AnsweredFlag, + models.DeletedFlag: imap.DeletedFlag, + models.FlaggedFlag: imap.FlaggedFlag, +} + +func translateImapFlags(imapFlags []string) []models.Flag { var flags []models.Flag for _, imapFlag := range imapFlags { - if flag, ok := flagMap[imapFlag]; ok { + if flag, ok := imapToFlag[imapFlag]; ok { flags = append(flags, flag) } } return flags } + +func translateFlags(flags []models.Flag) []string { + var imapFlags []string + for _, flag := range flags { + if imapFlag, ok := flagToImap[flag]; ok { + imapFlags = append(imapFlags, imapFlag) + } + } + return imapFlags +} diff --git a/worker/imap/movecopy.go b/worker/imap/movecopy.go index b01dab7..a53c7d4 100644 --- a/worker/imap/movecopy.go +++ b/worker/imap/movecopy.go @@ -28,7 +28,7 @@ func (m appendLiteral) Len() int { } func (imapw *IMAPWorker) handleAppendMessage(msg *types.AppendMessage) { - if err := imapw.client.Append(msg.Destination, msg.Flags, msg.Date, + if err := imapw.client.Append(msg.Destination, translateFlags(msg.Flags), msg.Date, &appendLiteral{ Reader: msg.Reader, Length: msg.Length, diff --git a/worker/imap/worker.go b/worker/imap/worker.go index ddd95b6..45a2269 100644 --- a/worker/imap/worker.go +++ b/worker/imap/worker.go @@ -222,7 +222,7 @@ func (w *IMAPWorker) handleImapUpdate(update client.Update) { Info: &models.MessageInfo{ BodyStructure: translateBodyStructure(msg.BodyStructure), Envelope: translateEnvelope(msg.Envelope), - Flags: translateFlags(msg.Flags), + Flags: translateImapFlags(msg.Flags), InternalDate: msg.InternalDate, Uid: msg.Uid, }, diff --git a/worker/maildir/message.go b/worker/maildir/message.go index 45b1ca6..9d622b4 100644 --- a/worker/maildir/message.go +++ b/worker/maildir/message.go @@ -45,7 +45,7 @@ func (m Message) ModelFlags() ([]models.Flag, error) { if err != nil { return nil, err } - return translateFlags(flags), nil + return translateMaildirFlags(flags), nil } // SetFlags replaces the message's flags with a new set. @@ -97,7 +97,7 @@ func (m Message) NewBodyPartReader(requestedParts []int) (io.Reader, error) { return lib.FetchEntityPartReader(msg, requestedParts) } -var flagMap = map[maildir.Flag]models.Flag{ +var maildirToFlag = map[maildir.Flag]models.Flag{ maildir.FlagReplied: models.AnsweredFlag, maildir.FlagSeen: models.SeenFlag, maildir.FlagTrashed: models.DeletedFlag, @@ -106,16 +106,35 @@ var flagMap = map[maildir.Flag]models.Flag{ // maildir.FlagPassed Flag = 'P' } -func translateFlags(maildirFlags []maildir.Flag) []models.Flag { +var flagToMaildir = map[models.Flag]maildir.Flag{ + models.AnsweredFlag: maildir.FlagReplied, + models.SeenFlag: maildir.FlagSeen, + models.DeletedFlag: maildir.FlagTrashed, + models.FlaggedFlag: maildir.FlagFlagged, + // maildir.FlagDraft Flag = 'D' + // maildir.FlagPassed Flag = 'P' +} + +func translateMaildirFlags(maildirFlags []maildir.Flag) []models.Flag { var flags []models.Flag for _, maildirFlag := range maildirFlags { - if flag, ok := flagMap[maildirFlag]; ok { + if flag, ok := maildirToFlag[maildirFlag]; ok { flags = append(flags, flag) } } return flags } +func translateFlags(flags []models.Flag) []maildir.Flag { + var maildirFlags []maildir.Flag + for _, flag := range flags { + if maildirFlag, ok := flagToMaildir[flag]; ok { + maildirFlags = append(maildirFlags, maildirFlag) + } + } + return maildirFlags +} + func (m Message) UID() uint32 { return m.uid } diff --git a/worker/maildir/worker.go b/worker/maildir/worker.go index 17123c6..2f96e6f 100644 --- a/worker/maildir/worker.go +++ b/worker/maildir/worker.go @@ -337,7 +337,7 @@ func (w *Worker) sort(uids []uint32, criteria []*types.SortCriterion) ([]uint32, func (w *Worker) handleCreateDirectory(msg *types.CreateDirectory) error { dir := w.c.Dir(msg.Directory) - if err := dir.Create(); err != nil { + if err := dir.Init(); err != nil { w.worker.Logger.Printf("could not create directory %s: %v", msg.Directory, err) return err @@ -510,15 +510,16 @@ func (w *Worker) handleCopyMessages(msg *types.CopyMessages) error { } func (w *Worker) handleAppendMessage(msg *types.AppendMessage) error { + // since we are the "master" maildir process, we can modify the maildir directly dest := w.c.Dir(msg.Destination) - delivery, err := dest.NewDelivery() + _, writer, err := dest.Create(translateFlags(msg.Flags)) if err != nil { - w.worker.Logger.Printf("could not deliver message to %s: %v", + w.worker.Logger.Printf("could not create message at %s: %v", msg.Destination, err) return err } - defer delivery.Close() - if _, err := io.Copy(delivery, msg.Reader); err != nil { + defer writer.Close() + if _, err := io.Copy(writer, msg.Reader); err != nil { w.worker.Logger.Printf("could not write message to destination: %v", err) return err } diff --git a/worker/types/messages.go b/worker/types/messages.go index c7d5077..e820585 100644 --- a/worker/types/messages.go +++ b/worker/types/messages.go @@ -131,7 +131,7 @@ type CopyMessages struct { type AppendMessage struct { Message Destination string - Flags []string + Flags []models.Flag Date time.Time Reader io.Reader Length int