aboutsummaryrefslogtreecommitdiffstats
path: root/worker/notmuch/message.go
diff options
context:
space:
mode:
Diffstat (limited to 'worker/notmuch/message.go')
-rw-r--r--worker/notmuch/message.go109
1 files changed, 109 insertions, 0 deletions
diff --git a/worker/notmuch/message.go b/worker/notmuch/message.go
index 59367fd1..8f8deffd 100644
--- a/worker/notmuch/message.go
+++ b/worker/notmuch/message.go
@@ -7,6 +7,10 @@ import (
"fmt"
"io"
"os"
+ "path/filepath"
+ "strings"
+
+ "github.com/emersion/go-maildir"
"git.sr.ht/~rjarry/aerc/models"
"git.sr.ht/~rjarry/aerc/worker/lib"
@@ -175,3 +179,108 @@ func (m *Message) RemoveTag(tag string) error {
func (m *Message) ModifyTags(add, remove []string) error {
return m.db.MsgModifyTags(m.key, add, remove)
}
+
+func (m *Message) Remove(dir maildir.Dir) error {
+ filenames, err := m.db.MsgFilenames(m.key)
+ if err != nil {
+ return err
+ }
+ for _, filename := range filenames {
+ if dirContains(dir, filename) {
+ err := m.db.DeleteMessage(filename)
+ if err != nil {
+ return err
+ }
+
+ if err := os.Remove(filename); err != nil {
+ return err
+ }
+
+ return nil
+ }
+ }
+
+ return fmt.Errorf("no matching message file found in %s", string(dir))
+}
+
+func (m *Message) Copy(target maildir.Dir) error {
+ filename, err := m.Filename()
+ if err != nil {
+ return err
+ }
+
+ source, key := parseFilename(filename)
+ if key == "" {
+ return fmt.Errorf("failed to parse message filename: %s", filename)
+ }
+
+ newKey, err := source.Copy(target, key)
+ if err != nil {
+ return err
+ }
+ newFilename, err := target.Filename(newKey)
+ if err != nil {
+ return err
+ }
+ _, err = m.db.IndexFile(newFilename)
+ return err
+}
+
+func (m *Message) Move(srcDir, destDir maildir.Dir) error {
+ var src string
+
+ filenames, err := m.db.MsgFilenames(m.key)
+ if err != nil {
+ return err
+ }
+ for _, filename := range filenames {
+ if dirContains(srcDir, filename) {
+ src = filename
+ break
+ }
+ }
+
+ if src == "" {
+ return fmt.Errorf("no matching message file found in %s", string(srcDir))
+ }
+
+ // Remove encoded UID information from the key to prevent sync issues
+ name := lib.StripUIDFromMessageFilename(filepath.Base(src))
+ dest := filepath.Join(string(destDir), "cur", name)
+
+ if err := m.db.DeleteMessage(src); err != nil {
+ return err
+ }
+
+ if err := os.Rename(src, dest); err != nil {
+ return err
+ }
+
+ _, err = m.db.IndexFile(dest)
+ return err
+}
+
+func parseFilename(filename string) (maildir.Dir, string) {
+ base := filepath.Base(filename)
+ dir := filepath.Dir(filename)
+ dir, curdir := filepath.Split(dir)
+ if curdir != "cur" {
+ return "", ""
+ }
+ split := strings.Split(base, ":")
+ if len(split) < 2 {
+ return maildir.Dir(dir), ""
+ }
+ key := split[0]
+ return maildir.Dir(dir), key
+}
+
+func dirContains(dir maildir.Dir, filename string) bool {
+ for _, sub := range []string{"cur", "new"} {
+ match, _ := filepath.Match(filepath.Join(string(dir), sub, "*"), filename)
+ if match {
+ return true
+ }
+ }
+ return false
+}