aboutsummaryrefslogtreecommitdiff
path: root/worker/maildir/container.go
diff options
context:
space:
mode:
Diffstat (limited to 'worker/maildir/container.go')
-rw-r--r--worker/maildir/container.go105
1 files changed, 105 insertions, 0 deletions
diff --git a/worker/maildir/container.go b/worker/maildir/container.go
new file mode 100644
index 0000000..351afed
--- /dev/null
+++ b/worker/maildir/container.go
@@ -0,0 +1,105 @@
+package maildir
+
+import (
+ "fmt"
+ "io/ioutil"
+ "log"
+ "path/filepath"
+ "sort"
+
+ "github.com/emersion/go-maildir"
+
+ "git.sr.ht/~sircmpwn/aerc/lib/uidstore"
+)
+
+// A Container is a directory which contains other directories which adhere to
+// the Maildir spec
+type Container struct {
+ dir string
+ log *log.Logger
+ uids *uidstore.Store
+}
+
+// NewContainer creates a new container at the specified directory
+// TODO: return an error if the provided directory is not accessible
+func NewContainer(dir string, l *log.Logger) *Container {
+ return &Container{dir: dir, uids: uidstore.NewStore(), log: l}
+}
+
+// ListFolders returns a list of maildir folders in the container
+func (c *Container) ListFolders() ([]string, error) {
+ files, err := ioutil.ReadDir(c.dir)
+ if err != nil {
+ return nil, fmt.Errorf("error reading folders: %v", err)
+ }
+ dirnames := []string{}
+ for _, f := range files {
+ if f.IsDir() {
+ dirnames = append(dirnames, f.Name())
+ }
+ }
+ return dirnames, nil
+}
+
+// OpenDirectory opens an existing maildir in the container by name, moves new
+// messages into cur, and registers the new keys in the UIDStore.
+func (c *Container) OpenDirectory(name string) (maildir.Dir, error) {
+ dir := c.Dir(name)
+ keys, err := dir.Unseen()
+ if err != nil {
+ return dir, err
+ }
+ for _, key := range keys {
+ c.uids.GetOrInsert(key)
+ }
+ return dir, nil
+}
+
+// Dir returns a maildir.Dir with the specified name inside the container
+func (c *Container) Dir(name string) maildir.Dir {
+ return maildir.Dir(filepath.Join(c.dir, name))
+}
+
+// UIDs fetches the unique message identifiers for the maildir
+func (c *Container) UIDs(d maildir.Dir) ([]uint32, error) {
+ keys, err := d.Keys()
+ if err != nil {
+ return nil, fmt.Errorf("could not get keys for %s: %v", d, err)
+ }
+ sort.Strings(keys)
+ var uids []uint32
+ for _, key := range keys {
+ uids = append(uids, c.uids.GetOrInsert(key))
+ }
+ return uids, nil
+}
+
+// Message returns a Message struct for the given UID and maildir
+func (c *Container) Message(d maildir.Dir, uid uint32) (*Message, error) {
+ if key, ok := c.uids.GetKey(uid); ok {
+ return &Message{
+ dir: d,
+ uid: uid,
+ key: key,
+ }, nil
+ }
+ return nil, fmt.Errorf("could not find message with uid %d in maildir %s",
+ uid, d)
+}
+
+// DeleteAll deletes a set of messages by UID and returns the subset of UIDs
+// which were successfully deleted, stopping upon the first error.
+func (c *Container) DeleteAll(d maildir.Dir, uids []uint32) ([]uint32, error) {
+ var success []uint32
+ for _, uid := range uids {
+ msg, err := c.Message(d, uid)
+ if err != nil {
+ return success, err
+ }
+ if err := msg.Remove(); err != nil {
+ return success, err
+ }
+ success = append(success, uid)
+ }
+ return success, nil
+}