123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241 |
- package imaputils
- import (
- "errors"
- "fmt"
- "git.sr.ht/~blallo/papero/config"
- "github.com/emersion/go-imap"
- )
- type tristate int
- const (
- undef tristate = 0
- doSet tristate = 1
- doUnset tristate = 2
- )
- func (t tristate) IsSet() bool {
- switch t {
- case undef:
- return false
- case doSet:
- return true
- case doUnset:
- return false
- default:
- panic(errors.New(fmt.Sprintf("unexpected tristate value %d", t)))
- }
- }
- func (t tristate) IsUnset() bool {
- switch t {
- case undef:
- return false
- case doSet:
- return false
- case doUnset:
- return true
- default:
- panic(errors.New(fmt.Sprintf("unexpected tristate value %d", t)))
- }
- }
- func (t tristate) String() string {
- switch t {
- case undef:
- return "undef"
- case doSet:
- return "set"
- case doUnset:
- return "unset"
- }
- panic("unexpected value for tristate")
- }
- type FlagsStatus struct {
- FlagSeen tristate
- FlagAnswered tristate
- FlagFlagged tristate
- FlagDeleted tristate
- FlagDraft tristate
- //FlagUnknown bool
- }
- func NewFlagsStatus() *FlagsStatus {
- return &FlagsStatus{
- undef,
- undef,
- undef,
- undef,
- undef,
- }
- }
- func (f *FlagsStatus) IntoSetFlagList() []interface{} {
- var result []interface{}
- switch {
- case f.FlagSeen.IsSet():
- result = append(result, imap.SeenFlag)
- case f.FlagAnswered.IsSet():
- result = append(result, imap.AnsweredFlag)
- case f.FlagFlagged.IsSet():
- result = append(result, imap.FlaggedFlag)
- case f.FlagDeleted.IsSet():
- result = append(result, imap.DeletedFlag)
- case f.FlagDraft.IsSet():
- result = append(result, imap.DraftFlag)
- }
- return result
- }
- func (f *FlagsStatus) IntoUnsetFlagList() []interface{} {
- var result []interface{}
- switch {
- case f.FlagSeen.IsUnset():
- result = append(result, imap.SeenFlag)
- case f.FlagAnswered.IsUnset():
- result = append(result, imap.AnsweredFlag)
- case f.FlagFlagged.IsUnset():
- result = append(result, imap.FlaggedFlag)
- case f.FlagDeleted.IsUnset():
- result = append(result, imap.DeletedFlag)
- case f.FlagDraft.IsUnset():
- result = append(result, imap.DraftFlag)
- }
- return result
- }
- func (f *FlagsStatus) WillSet() bool {
- switch {
- case f.FlagSeen.IsSet():
- return true
- case f.FlagAnswered.IsSet():
- return true
- case f.FlagFlagged.IsSet():
- return true
- case f.FlagDeleted.IsSet():
- return true
- case f.FlagDraft.IsSet():
- return true
- }
- return false
- }
- func (f *FlagsStatus) WillUnset() bool {
- switch {
- case f.FlagSeen.IsUnset():
- return true
- case f.FlagAnswered.IsUnset():
- return true
- case f.FlagFlagged.IsUnset():
- return true
- case f.FlagDeleted.IsUnset():
- return true
- case f.FlagDraft.IsUnset():
- return true
- }
- return false
- }
- func (f *FlagsStatus) SetSeen() {
- f.FlagSeen = doSet
- }
- func (f *FlagsStatus) UnsetSeen() {
- f.FlagSeen = doUnset
- }
- func (f *FlagsStatus) SetAnswered() {
- f.FlagAnswered = doSet
- }
- func (f *FlagsStatus) UnsetAnswered() {
- f.FlagAnswered = doUnset
- }
- func (f *FlagsStatus) SetFlagged() {
- f.FlagFlagged = doSet
- }
- func (f *FlagsStatus) UnsetFlagged() {
- f.FlagFlagged = doUnset
- }
- func (f *FlagsStatus) SetDeleted() {
- f.FlagDeleted = doSet
- }
- func (f *FlagsStatus) UnsetDeleted() {
- f.FlagDeleted = doUnset
- }
- func (f *FlagsStatus) SetDraft() {
- f.FlagDraft = doSet
- }
- func (f *FlagsStatus) UnsetDraft() {
- f.FlagDraft = doUnset
- }
- //func (f *FlagsStatus) SetUnknown() {
- // f.FlagUnknown = doSet
- //}
- //func (f *FlagsStatus) UnsetUnknown() {
- // f.FlagUnknown = doUnset
- //}
- type SetFlagsOpts struct {
- Mailbox string
- MessageSeq *imap.SeqSet
- Flags *FlagsStatus
- Debug bool
- }
- // SetFlags changes the flags on the specified message in the specified mailbox.
- // First it adds the new flags set, then in removes the flags explicitly unset.
- // Unfortunately, this operation is not atomic.
- func SetFlags(conf *config.AccountData, opts *SetFlagsOpts) error {
- conn := NewConnection(conf)
- err := conn.Start(opts.Debug)
- if err != nil {
- return err
- }
- defer conn.Close()
- return SetFlagsInSession(conn, opts)
- }
- // SetFlagsInSession does the same as SetFlags, but has to be provided
- // with a started *IMAPConnection.
- func SetFlagsInSession(conn *IMAPConnection, opts *SetFlagsOpts) error {
- var err error
- _, err = conn.client.Select(opts.Mailbox, false)
- if err != nil {
- return err
- }
- if opts.Flags.WillSet() {
- item := imap.FormatFlagsOp(imap.AddFlags, true)
- flags := opts.Flags.IntoSetFlagList()
- err = conn.client.Store(opts.MessageSeq, item, flags, nil)
- if err != nil {
- return err
- }
- }
- if opts.Flags.WillUnset() {
- item := imap.FormatFlagsOp(imap.RemoveFlags, true)
- flags := opts.Flags.IntoUnsetFlagList()
- err = conn.client.Store(opts.MessageSeq, item, flags, nil)
- if err != nil {
- return err
- }
- }
- return nil
- }
|