123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168 |
- package imaputils
- import (
- "fmt"
- "git.sr.ht/~blallo/papero/config"
- "github.com/emersion/go-imap"
- )
- func ListMailboxes(conf *config.AccountData, debug bool) ([]*imap.MailboxInfo, error) {
- var mailboxes []*imap.MailboxInfo
- conn := NewConnection(conf)
- err := conn.Start(debug)
- if err != nil {
- return mailboxes, err
- }
- defer conn.Close()
- mboxChan := make(chan *imap.MailboxInfo, 10)
- done := make(chan error, 1)
- go func() {
- done <- conn.client.List("", "*", mboxChan)
- }()
- for m := range mboxChan {
- mailboxes = append(mailboxes, m)
- }
- if err := <-done; err != nil {
- return mailboxes, err
- }
- return mailboxes, nil
- }
- type ListMessagesOpts struct {
- Mailbox string
- Limit uint32
- }
- func ListMessages(conf *config.AccountData, opts *ListMessagesOpts, debug bool) ([]*imap.Message, error) {
- var messages []*imap.Message
- conn := NewConnection(conf)
- err := conn.Start(debug)
- if err != nil {
- return messages, err
- }
- defer conn.Close()
- mbox, err := conn.client.Select(opts.Mailbox, true)
- if err != nil {
- return messages, err
- }
- return getMessages(mbox, conn, opts.Limit)
- }
- func getMessages(mbox *imap.MailboxStatus, conn *IMAPConnection, limit uint32) ([]*imap.Message, error) {
- var start uint32
- var msgs []*imap.Message
- seqset := new(imap.SeqSet)
- messages := make(chan *imap.Message, 10)
- done := make(chan error, 1)
- switch {
- case limit == 0:
- start = 1
- case mbox.Messages > limit:
- start = mbox.Messages - limit + 1
- default:
- start = 1
- }
- seqset.AddRange(start, mbox.Messages)
- go func() {
- done <- conn.client.Fetch(seqset, []imap.FetchItem{imap.FetchEnvelope, imap.FetchFlags}, messages)
- }()
- for msg := range messages {
- msgs = append(msgs, msg)
- }
- if err := <-done; err != nil {
- return []*imap.Message{}, err
- }
- return msgs, nil
- }
- type FetchOpts struct {
- Mailbox string
- IdList []uint32
- WithHeaders bool
- WithBody bool
- WithFlags bool
- Peek bool
- }
- func (o *FetchOpts) String() string {
- return fmt.Sprintf(
- "FetchOpts{Mailbox: %s, IdList: %v, WithHeaders: %t, WithBody: %t, Peek: %t}",
- o.Mailbox,
- o.IdList,
- o.WithHeaders,
- o.WithBody,
- o.Peek,
- )
- }
- func FetchMessages(conf *config.AccountData, opts *FetchOpts, debug bool) ([]*imap.Message, error) {
- var messages []*imap.Message
- conn := NewConnection(conf)
- err := conn.Start(debug)
- if err != nil {
- return messages, err
- }
- defer conn.Close()
- mbox, err := conn.client.Select(opts.Mailbox, true)
- if err != nil {
- return messages, err
- }
- return fetchMessage(mbox, conn, opts)
- }
- func fetchMessage(mbox *imap.MailboxStatus, conn *IMAPConnection, opts *FetchOpts) ([]*imap.Message, error) {
- var messageAcc []*imap.Message
- messages := make(chan *imap.Message, len(opts.IdList))
- done := make(chan error, 1)
- seqset := new(imap.SeqSet)
- for _, id := range opts.IdList {
- seqset.AddNum(id)
- }
- var items []imap.FetchItem
- if opts.WithHeaders {
- section := &imap.BodySectionName{Peek: opts.Peek, BodyPartName: imap.BodyPartName{Specifier: imap.HeaderSpecifier}}
- items = append(items, section.FetchItem())
- }
- items = append(items, imap.FetchEnvelope)
- if opts.WithBody {
- section := &imap.BodySectionName{Peek: opts.Peek, BodyPartName: imap.BodyPartName{Specifier: imap.TextSpecifier}}
- items = append(items, section.FetchItem())
- }
- if opts.WithFlags {
- items = append(items, imap.FetchFlags)
- }
- go func() {
- done <- conn.client.Fetch(seqset, items, messages)
- }()
- for m := range messages {
- messageAcc = append(messageAcc, m)
- }
- if err := <-done; err != nil {
- return []*imap.Message{}, err
- }
- return messageAcc, nil
- }
|