diff --git a/cmd/process/main.go b/cmd/process/main.go index 71f81ae..aab34e3 100644 --- a/cmd/process/main.go +++ b/cmd/process/main.go @@ -8,7 +8,6 @@ import ( "strings" "git.sr.ht/~ewintr/gte/pkg/mstore" - "github.com/emersion/go-imap" ) type Body struct { @@ -32,7 +31,7 @@ func (b *Body) Len() int { } func main() { - config := &mstore.EMailStoreConfiguration{ + config := &mstore.EmailConfiguration{ IMAPURL: os.Getenv("IMAP_URL"), IMAPUsername: os.Getenv("IMAP_USERNAME"), IMAPPassword: os.Getenv("IMAP_PASSWORD"), @@ -43,36 +42,50 @@ func main() { } //fmt.Printf("conf: %+v\n", config) - mailStore, err := mstore.EMailConnect(config) + mailStore, err := mstore.EmailConnect(config) if err != nil { log.Fatal(err) } defer mailStore.Disconnect() - folders, err := mailStore.Folders() - if err != nil { - log.Fatal(err) - } - for _, f := range folders { - fmt.Println(f.Name) - } - /* - messages, err := mailStore.Inbox() + folders, err := mailStore.FolderNames() if err != nil { log.Fatal(err) } - for _, m := range messages { - fmt.Println(m.Subject) + for _, f := range folders { + fmt.Println(f) } */ - body := NewBody(`From: todo -Subject: the subject - -And here comes the body`) - - if err := mailStore.Append("INBOX", imap.Literal(body)); err != nil { + if err := mailStore.Select("Today"); err != nil { log.Fatal(err) } + + messages, err := mailStore.Messages() + if err != nil { + log.Fatal(err) + } + for _, m := range messages { + fmt.Printf("%d: %s\n", m.ID, m.Subject) + } + if len(messages) == 0 { + log.Fatal("no messages") + return + } + + if err := mailStore.Remove(messages[0].ID); err != nil { + log.Fatal(err) + } + + /* + body := NewBody(`From: todo + Subject: the subject + + And here comes the body`) + + if err := mailStore.Append("INBOX", imap.Literal(body)); err != nil { + log.Fatal(err) + } + */ } diff --git a/pkg/mstore/email.go b/pkg/mstore/email.go index 5fd0845..a0c7a72 100644 --- a/pkg/mstore/email.go +++ b/pkg/mstore/email.go @@ -8,13 +8,13 @@ import ( "github.com/emersion/go-imap/client" ) -type EMailStoreConfiguration struct { +type EmailConfiguration struct { IMAPURL string IMAPUsername string IMAPPassword string } -func (esc *EMailStoreConfiguration) Valid() bool { +func (esc *EmailConfiguration) Valid() bool { if esc.IMAPURL == "" { return false } @@ -25,73 +25,77 @@ func (esc *EMailStoreConfiguration) Valid() bool { return true } -type smtpConf struct { - url string - to string +type Email struct { + imap *client.Client + mboxStatus *imap.MailboxStatus } -type EMailStore struct { - imap *client.Client -} - -func EMailConnect(conf *EMailStoreConfiguration) (*EMailStore, error) { +func EmailConnect(conf *EmailConfiguration) (*Email, error) { imap, err := client.DialTLS(conf.IMAPURL, nil) if err != nil { - return &EMailStore{}, err + return &Email{}, err } if err := imap.Login(conf.IMAPUsername, conf.IMAPPassword); err != nil { - return &EMailStore{}, err + return &Email{}, err } - return &EMailStore{ + return &Email{ imap: imap, }, nil } -func (es *EMailStore) Disconnect() { +func (es *Email) Disconnect() { es.imap.Logout() } -func (es *EMailStore) Folders() ([]*Folder, error) { +func (es *Email) FolderNames() ([]string, error) { boxes, done := make(chan *imap.MailboxInfo), make(chan error) go func() { done <- es.imap.List("", "*", boxes) }() - folders := []*Folder{} + folders := []string{} for b := range boxes { - folders = append(folders, &Folder{ - Name: b.Name, - }) + folders = append(folders, b.Name) } if err := <-done; err != nil { - return []*Folder{}, err + return []string{}, err } return folders, nil } -func (es *EMailStore) Inbox() ([]*Message, error) { - mbox, err := es.imap.Select("INBOX", false) +func (es *Email) Select(folder string) error { + status, err := es.imap.Select(folder, false) if err != nil { - return []*Message{}, err + return err } - fmt.Println("Flags for INBOX:", mbox.Flags) + fmt.Printf("status: %+v\n", status) - fmt.Println("Messages: ", mbox.Messages) + es.mboxStatus = status + + return nil +} + +func (es *Email) Messages() ([]*Message, error) { + if es.mboxStatus == nil { + return []*Message{}, fmt.Errorf("no mailbox selected") + } seqset := new(imap.SeqSet) - seqset.AddRange(uint32(1), mbox.Messages) + seqset.AddRange(uint32(1), es.mboxStatus.Messages) imsg, done := make(chan *imap.Message), make(chan error) go func() { - done <- es.imap.Fetch(seqset, []imap.FetchItem{imap.FetchEnvelope}, imsg) + done <- es.imap.Fetch(seqset, []imap.FetchItem{imap.FetchEnvelope, imap.FetchUid}, imsg) }() messages := []*Message{} for m := range imsg { + //fmt.Printf("%+v\n", m) messages = append(messages, &Message{ + ID: m.Uid, Subject: m.Envelope.Subject, }) } @@ -103,6 +107,28 @@ func (es *EMailStore) Inbox() ([]*Message, error) { return messages, nil } -func (es *EMailStore) Append(mbox string, msg imap.Literal) error { +func (es *Email) Append(mbox string, msg imap.Literal) error { return es.imap.Append(mbox, nil, time.Time{}, msg) } + +func (es *Email) Remove(id uint32) error { + if es.mboxStatus == nil { + return fmt.Errorf("no mailbox selected") + } + + // set deleted flag + seqset := new(imap.SeqSet) + seqset.AddRange(id, id) + storeItem := imap.FormatFlagsOp(imap.SetFlags, true) + err := es.imap.UidStore(seqset, storeItem, imap.FormatStringList([]string{imap.DeletedFlag}), nil) + if err != nil { + return err + } + + // expunge box + if err := es.imap.Expunge(nil); err != nil { + return err + } + + return nil +} diff --git a/pkg/mstore/memory.go b/pkg/mstore/memory.go new file mode 100644 index 0000000..e4d1025 --- /dev/null +++ b/pkg/mstore/memory.go @@ -0,0 +1,5 @@ +package mstore + +type Memory struct { + messages map[*Folder][]*Message +} diff --git a/pkg/mstore/mstore.go b/pkg/mstore/mstore.go index 49ffe6c..e7d42a2 100644 --- a/pkg/mstore/mstore.go +++ b/pkg/mstore/mstore.go @@ -1,18 +1,20 @@ package mstore type Folder struct { - Name string + Name string + Version uint32 } type Message struct { + ID uint32 Subject string Body string } type MStorer interface { - Folders() ([]*Folder, error) - Messages(folder Folder) ([]Message, error) - Move(message Message, folder Folder) error - Update(message Message) error - Add(message Message) error + Folders() ([]string, error) + Select(folder string) error + Messages() ([]*Message, error) + Add(message *Message) error + Remove(id string) error }