From e2c362457be4bd9dcb8d89f0f79efda92a91592f Mon Sep 17 00:00:00 2001 From: Vincent Batts Date: Fri, 12 Dec 2014 21:22:05 -0500 Subject: [PATCH] mailnotify: basic libnotify on Maildir new messages --- cmd/mailnotify/main.go | 150 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 150 insertions(+) create mode 100644 cmd/mailnotify/main.go diff --git a/cmd/mailnotify/main.go b/cmd/mailnotify/main.go new file mode 100644 index 0000000..72443c4 --- /dev/null +++ b/cmd/mailnotify/main.go @@ -0,0 +1,150 @@ +package main + +import ( + "flag" + "fmt" + "log" + "net/mail" + "os" + "path/filepath" + "time" + + "github.com/luksen/maildir" + notify "github.com/mqu/go-notify" + fsnotify "gopkg.in/fsnotify.v1" +) + +var ( + AppName = os.Args[0] + Linger = 2 +) + +func init() { + notify.Init(AppName) +} + +func main() { + flag.Parse() + watcher, err := fsnotify.NewWatcher() + if err != nil { + log.Fatal(err) + } + done := make(chan bool) + go func() { + for { + select { + case event := <-watcher.Events: + // 2014/12/12 21:18:08 event: "/home/vbatts/Maildir/INBOX/new/1418437088_0.3432.valse.usersys.redhat.com,U=478874,FMD5=7e33429f656f1e6e9d79b29c3f82c57e:2,": CREATE + log.Println("event:", event) + if event.Op == fsnotify.Create { + func() { + //Notify("new msg", filepath.Dir(filepath.Dir(event.Name))) + fh, err := os.Open(event.Name) + if err != nil { + log.Println(err) + return + } + msg, err := mail.ReadMessage(fh) + if err != nil { + log.Println(err) + return + } + //fmt.Printf("%#v\n", msg.Header) + Notify(filepath.Base(filepath.Dir(filepath.Dir(event.Name))), fmt.Sprintf("%s; From %s", msg.Header["Subject"][0], msg.Header["From"][0])) + }() + } + if event.Op&fsnotify.Write == fsnotify.Write { + log.Println("modified file:", event.Name) + } + case err := <-watcher.Errors: + log.Println("error:", err) + } + } + }() + + go func() { + if err := Notify(AppName, "running ..."); err != nil { + log.Println(err) + } + }() + + for _, arg := range flag.Args() { + dirs, err := GetMailDirs(arg) + if err != nil { + log.Fatal(err) + } + for _, dirPath := range dirs { + if err = watcher.Add(filepath.Join(dirPath, "new")); err != nil { + log.Fatal(err) + } + + dir := maildir.Dir(dirPath) + keys, err := dir.Keys() + if err != nil { + log.Fatal(err) + } + u, err := dir.UnreadKeys() + if err != nil { + log.Fatal(err) + } + fmt.Println(dir, len(keys), len(u)) + } + } + + if flag.NArg() == 0 { + close(done) + } + <-done +} + +func Notify(title, message string) error { + hello := notify.NotificationNew(title, message, "mail-message-new") + notify.NotificationSetTimeout(hello, 0) + + if err := notify.NotificationShow(hello); err != nil && len(err.Message()) > 0 { + return fmt.Errorf("%s", err.Message()) + } + time.Sleep(time.Duration(Linger) * time.Second) + if err := notify.NotificationClose(hello); err != nil && len(err.Message()) > 0 { + return fmt.Errorf("%s", err.Message()) + } + return nil +} + +func GetMailDirs(root string) ([]string, error) { + dirs := []string{} + err := filepath.Walk(root, func(path string, info os.FileInfo, err error) error { + if err != nil { + return err + } + base := filepath.Base(path) + if !info.IsDir() || base == "cur" || base == "new" || base == "tmp" { + return filepath.SkipDir + } + if b, err := IsMaildir(path); err == nil && b { + dirs = append(dirs, path) + } + return nil + }) + if err != nil { + return nil, err + } + return dirs, nil + //return []string{root}, nil +} + +func IsMaildir(path string) (bool, error) { + curInfo, err := os.Stat(filepath.Join(path, "cur")) + if err != nil { + return false, err + } + tmpInfo, err := os.Stat(filepath.Join(path, "tmp")) + if err != nil { + return false, err + } + newInfo, err := os.Stat(filepath.Join(path, "new")) + if err != nil { + return false, err + } + return (curInfo != nil && tmpInfo != nil && newInfo != nil), nil +}