fetch_messages.go 2.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. package imaputils
  2. import (
  3. "fmt"
  4. "git.sr.ht/~blallo/papero/config"
  5. "github.com/emersion/go-imap"
  6. )
  7. type FetchOpts struct {
  8. Mailbox string
  9. IdList []uint32
  10. WithHeaders bool
  11. WithBody bool
  12. WithFlags bool
  13. Peek bool
  14. }
  15. func (o *FetchOpts) String() string {
  16. return fmt.Sprintf(
  17. "FetchOpts{Mailbox: %s, IdList: %v, WithHeaders: %t, WithBody: %t, Peek: %t}",
  18. o.Mailbox,
  19. o.IdList,
  20. o.WithHeaders,
  21. o.WithBody,
  22. o.Peek,
  23. )
  24. }
  25. func FetchMessages(conf *config.AccountData, opts *FetchOpts, debug bool) ([]*imap.Message, error) {
  26. var empty []*imap.Message
  27. conn := NewConnection(conf)
  28. err := conn.Start(debug)
  29. if err != nil {
  30. return empty, err
  31. }
  32. defer conn.Close()
  33. return FetchMessagesInSession(conn, opts)
  34. }
  35. func FetchMessagesInSession(conn *IMAPConnection, opts *FetchOpts) ([]*imap.Message, error) {
  36. var empty []*imap.Message
  37. mbox, err := conn.client.Select(opts.Mailbox, true)
  38. if err != nil {
  39. return empty, err
  40. }
  41. return fetchMessage(mbox, conn, opts)
  42. }
  43. func fetchMessage(mbox *imap.MailboxStatus, conn *IMAPConnection, opts *FetchOpts) ([]*imap.Message, error) {
  44. var messageAcc []*imap.Message
  45. messages := make(chan *imap.Message, len(opts.IdList))
  46. done := make(chan error, 1)
  47. seqset := new(imap.SeqSet)
  48. for _, id := range opts.IdList {
  49. seqset.AddNum(id)
  50. }
  51. var items []imap.FetchItem
  52. if opts.WithHeaders {
  53. section := &imap.BodySectionName{Peek: opts.Peek, BodyPartName: imap.BodyPartName{Specifier: imap.HeaderSpecifier}}
  54. items = append(items, section.FetchItem())
  55. }
  56. items = append(items, imap.FetchEnvelope)
  57. if opts.WithBody {
  58. section := &imap.BodySectionName{Peek: opts.Peek, BodyPartName: imap.BodyPartName{Specifier: imap.TextSpecifier}}
  59. items = append(items, section.FetchItem())
  60. }
  61. if opts.WithFlags {
  62. items = append(items, imap.FetchFlags)
  63. }
  64. go func() {
  65. done <- conn.client.Fetch(seqset, items, messages)
  66. }()
  67. for m := range messages {
  68. messageAcc = append(messageAcc, m)
  69. }
  70. if err := <-done; err != nil {
  71. return []*imap.Message{}, err
  72. }
  73. return messageAcc, nil
  74. }