From 6785c0066157b451e39a57b388b4efa090273e53 Mon Sep 17 00:00:00 2001 From: Ian Gulliver Date: Sun, 30 Oct 2022 22:23:45 +0000 Subject: [PATCH] Working IMAP fetch --- imap.go | 127 ++++++++++++++++++++++++++++++++++++++++++++++++++ imap2asana.go | 58 ++++------------------- 2 files changed, 135 insertions(+), 50 deletions(-) create mode 100644 imap.go diff --git a/imap.go b/imap.go new file mode 100644 index 0000000..2823548 --- /dev/null +++ b/imap.go @@ -0,0 +1,127 @@ +package main + +import ( + "net/mail" + + "github.com/emersion/go-imap" + "github.com/emersion/go-imap/client" +) + +type ImapClient struct { + cli *client.Client + + fromFolder string + toFolder string +} + +func NewImapClient(host, user, pass, fromFolder, toFolder string) (*ImapClient, error) { + c, err := client.DialTLS(host, nil) + if err != nil { + return nil, err + } + + err = c.Login(user, pass) + if err != nil { + c.Logout() + return nil, err + } + + return &ImapClient{ + cli: c, + fromFolder: fromFolder, + toFolder: toFolder, + }, nil +} + +func (ic *ImapClient) Close() { + ic.cli.Logout() +} + +func (ic *ImapClient) Poll() ([]*Task, error) { + mbox, err := ic.Select(ic.fromFolder, false) + if err != nil { + return nil, err + } + + if mbox.Messages < 1 { + return []*Task{}, nil + } + + seqset := &imap.SeqSet{} + seqset.AddRange(1, mbox.Messages) + + section := &imap.BodySectionName{} + + msgs, err := ic.Fetch(seqset, []imap.FetchItem{section.FetchItem()}) + if err != nil { + return nil, err + } + + ret := []*Task{} + + for _, msg := range msgs { + msg, err := mail.ReadMessage(msg.GetBody(section)) + if err != nil { + return nil, err + } + + ret = append(ret, &Task{ + Name: msg.Header.Get("Subject"), + }) + } + + err = ic.Move(seqset, ic.toFolder) + if err != nil { + return nil, err + } + + return ret, nil +} + +func (ic *ImapClient) List(ref, name string) ([]*imap.MailboxInfo, error) { + ch := make(chan *imap.MailboxInfo, 10) + done := make(chan error) + go func() { + done <- ic.cli.List(ref, name, ch) + }() + + ret := []*imap.MailboxInfo{} + for mbox := range ch { + ret = append(ret, mbox) + } + + err := <-done + if err != nil { + return nil, err + } else { + return ret, nil + } +} + +func (ic *ImapClient) Fetch(seqset *imap.SeqSet, toFetch []imap.FetchItem) ([]*imap.Message, error) { + ch := make(chan *imap.Message, 10) + done := make(chan error) + go func() { + done <- ic.cli.Fetch(seqset, toFetch, ch) + }() + + ret := []*imap.Message{} + for msg := range ch { + ret = append(ret, msg) + } + + err := <-done + if err != nil { + return nil, err + } else { + return ret, nil + } +} + +func (ic *ImapClient) Select(name string, readonly bool) (*imap.MailboxStatus, error) { + return ic.cli.Select(name, readonly) +} + +func (ic *ImapClient) Move(seqset *imap.SeqSet, dest string) error { + return ic.cli.Move(seqset, dest) +} diff --git a/imap2asana.go b/imap2asana.go index c5a15d6..8ec6ba3 100644 --- a/imap2asana.go +++ b/imap2asana.go @@ -3,9 +3,6 @@ package main import ( "fmt" "os" - - "github.com/emersion/go-imap" - "github.com/emersion/go-imap/client" ) func main() { @@ -13,6 +10,8 @@ func main() { os.Getenv("IMAP_HOST"), os.Getenv("IMAP_USERNAME"), os.Getenv("IMAP_PASSWORD"), + "Asana", + "Archive", ) if err != nil { panic(err) @@ -20,58 +19,17 @@ func main() { defer ic.Close() - mboxs, err := ic.List("", "*") + tasks, err := ic.Poll() if err != nil { panic(err) } - for _, mbox := range mboxs { - fmt.Printf("%#v\n", mbox) + for _, task := range tasks { + fmt.Printf("%#v\n", task) } } -// go-imap's API is a pile of stupid; wrap it -type ImapClient struct { - cli *client.Client -} - -func NewImapClient(host, user, pass string) (*ImapClient, error) { - c, err := client.DialTLS(host, nil) - if err != nil { - return nil, err - } - - err = c.Login(user, pass) - if err != nil { - c.Logout() - return nil, err - } - - return &ImapClient{ - cli: c, - }, nil -} - -func (ic *ImapClient) Close() { - ic.cli.Logout() -} - -func (ic *ImapClient) List(ref, name string) ([]*imap.MailboxInfo, error) { - ch := make(chan *imap.MailboxInfo, 10) - done := make(chan error) - go func() { - done <- ic.cli.List(ref, name, ch) - }() - - ret := []*imap.MailboxInfo{} - for mbox := range ch { - ret = append(ret, mbox) - } - - err := <-done - if err != nil { - return nil, err - } else { - return ret, nil - } +type Task struct { + Name string + HtmlNotes string }