aboutsummaryrefslogtreecommitdiffstats
path: root/worker/maildir
diff options
context:
space:
mode:
Diffstat (limited to 'worker/maildir')
-rw-r--r--worker/maildir/container.go40
-rw-r--r--worker/maildir/worker.go46
2 files changed, 55 insertions, 31 deletions
diff --git a/worker/maildir/container.go b/worker/maildir/container.go
index 14815c98..1bdc4e74 100644
--- a/worker/maildir/container.go
+++ b/worker/maildir/container.go
@@ -15,9 +15,10 @@ import (
// 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
+ dir string
+ log *log.Logger
+ uids *uidstore.Store
+ recentUIDS map[uint32]struct{} // used to set the recent flag
}
// NewContainer creates a new container at the specified directory
@@ -34,7 +35,8 @@ func NewContainer(dir string, l *log.Logger) (*Container, error) {
if !s.IsDir() {
return nil, fmt.Errorf("Given maildir '%s' not a directory", dir)
}
- return &Container{dir: dir, uids: uidstore.NewStore(), log: l}, nil
+ return &Container{dir: dir, uids: uidstore.NewStore(), log: l,
+ recentUIDS: make(map[uint32]struct{})}, nil
}
// ListFolders returns a list of maildir folders in the container
@@ -72,17 +74,26 @@ func (c *Container) ListFolders() ([]string, error) {
return folders, err
}
+// SyncNewMail adds emails from new to cur, tracking them
+func (c *Container) SyncNewMail(dir maildir.Dir) error {
+ keys, err := dir.Unseen()
+ if err != nil {
+ return err
+ }
+ for _, key := range keys {
+ uid := c.uids.GetOrInsert(key)
+ c.recentUIDS[uid] = struct{}{}
+ }
+ return 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 {
+ if err := c.SyncNewMail(dir); err != nil {
return dir, err
}
- for _, key := range keys {
- c.uids.GetOrInsert(key)
- }
return dir, nil
}
@@ -91,6 +102,17 @@ func (c *Container) Dir(name string) maildir.Dir {
return maildir.Dir(filepath.Join(c.dir, name))
}
+// IsRecent returns if a uid has the Recent flag set
+func (c *Container) IsRecent(uid uint32) bool {
+ _, ok := c.recentUIDS[uid]
+ return ok
+}
+
+// ClearRecentFlag removes the Recent flag from the message with the given uid
+func (c *Container) ClearRecentFlag(uid uint32) {
+ delete(c.recentUIDS, uid)
+}
+
// UIDs fetches the unique message identifiers for the maildir
func (c *Container) UIDs(d maildir.Dir) ([]uint32, error) {
keys, err := d.Keys()
diff --git a/worker/maildir/worker.go b/worker/maildir/worker.go
index 87ebc978..3f84e01d 100644
--- a/worker/maildir/worker.go
+++ b/worker/maildir/worker.go
@@ -79,11 +79,12 @@ func (w *Worker) handleFSEvent(ev fsnotify.Event) {
if w.selected == nil {
return
}
- newUnseen, err := w.selected.Unseen()
+ err := w.c.SyncNewMail(*w.selected)
if err != nil {
w.worker.Logger.Printf("could not move new to cur : %v", err)
return
}
+
uids, err := w.c.UIDs(*w.selected)
if err != nil {
w.worker.Logger.Printf("could not scan UIDs: %v", err)
@@ -98,7 +99,6 @@ func (w *Worker) handleFSEvent(ev fsnotify.Event) {
Uids: sortedUids,
}, nil)
dirInfo := w.getDirectoryInfo(w.selectedName)
- dirInfo.Recent = len(newUnseen)
w.worker.PostMessage(&types.DirectoryInfo{
Info: dirInfo,
}, nil)
@@ -138,12 +138,6 @@ func (w *Worker) getDirectoryInfo(name string) *models.DirectoryInfo {
return dirInfo
}
- recent, err := dir.UnseenCount()
- if err != nil {
- w.worker.Logger.Printf("could not get unseen count: %v", err)
- }
- dirInfo.Recent = recent
-
for _, uid := range uids {
message, err := w.c.Message(dir, uid)
if err != nil {
@@ -164,9 +158,12 @@ func (w *Worker) getDirectoryInfo(name string) *models.DirectoryInfo {
if !seen {
dirInfo.Unseen++
}
+ if w.c.IsRecent(uid) {
+ dirInfo.Recent++
+ }
}
dirInfo.Unseen += dirInfo.Recent
- dirInfo.Exists = len(uids) + recent
+ dirInfo.Exists = len(uids) + dirInfo.Recent
return dirInfo
}
@@ -332,12 +329,7 @@ func (w *Worker) sort(uids []uint32, criteria []*types.SortCriterion) ([]uint32,
}
var msgInfos []*models.MessageInfo
for _, uid := range uids {
- m, err := w.c.Message(*w.selected, uid)
- if err != nil {
- w.worker.Logger.Printf("could not get message: %v", err)
- continue
- }
- info, err := m.MessageInfo()
+ info, err := w.msgInfoFromUid(uid)
if err != nil {
w.worker.Logger.Printf("could not get message info: %v", err)
continue
@@ -375,13 +367,7 @@ func (w *Worker) handleRemoveDirectory(msg *types.RemoveDirectory) error {
func (w *Worker) handleFetchMessageHeaders(
msg *types.FetchMessageHeaders) error {
for _, uid := range msg.Uids {
- m, err := w.c.Message(*w.selected, uid)
- if err != nil {
- w.worker.Logger.Printf("could not get message: %v", err)
- w.err(msg, err)
- continue
- }
- info, err := m.MessageInfo()
+ info, err := w.msgInfoFromUid(uid)
if err != nil {
w.worker.Logger.Printf("could not get message info: %v", err)
w.err(msg, err)
@@ -391,6 +377,7 @@ func (w *Worker) handleFetchMessageHeaders(
Message: types.RespondTo(msg),
Info: info,
}, nil)
+ w.c.ClearRecentFlag(uid)
}
return nil
}
@@ -588,3 +575,18 @@ func (w *Worker) handleSearchDirectory(msg *types.SearchDirectory) error {
}, nil)
return nil
}
+
+func (w *Worker) msgInfoFromUid(uid uint32) (*models.MessageInfo, error) {
+ m, err := w.c.Message(*w.selected, uid)
+ if err != nil {
+ return nil, err
+ }
+ info, err := m.MessageInfo()
+ if err != nil {
+ return nil, err
+ }
+ if w.c.IsRecent(uid) {
+ info.Flags = append(info.Flags, models.RecentFlag)
+ }
+ return info, nil
+}