diff --git a/cli/papero/info.go b/cli/papero/info.go index f69171f..f28f7bf 100644 --- a/cli/papero/info.go +++ b/cli/papero/info.go @@ -21,13 +21,11 @@ const maxUInt32 = int(^uint32(0)) var infoVerbs cli.CommandMap func init() { - lsMailbox := LsMailboxCmd{} - lsMessages := LsMsgCmd{} - catMessage := CatMsgCmd{} infoVerbs = cli.CommandMap{ - "list-mailboxes": lsMailbox, - "list-messages": lsMessages, - "display-message": catMessage, + "list-mailboxes": LsMailboxCmd{}, + // "list-subscribed": LsSubscribedCmd{}, + "list-messages": LsMsgCmd{}, + "display-message": CatMsgCmd{}, } } @@ -123,7 +121,7 @@ func (l LsMsgCmd) Func(args []string) error { Log.Debug("enter info list-messages") } var limit uint - var withSeq, withFrom, withDate bool + var withSeq, withFrom, withDate, withFlags bool var sep string flagset := flag.NewFlagSet(args[0], flag.ExitOnError) flagset.StringVar(&sep, "sep", "\t", "separator between fields") @@ -131,6 +129,7 @@ func (l LsMsgCmd) Func(args []string) error { flagset.BoolVar(&withSeq, "seq", false, "show sequence number") flagset.BoolVar(&withFrom, "from", false, "show From address") flagset.BoolVar(&withDate, "date", false, "show message date") + flagset.BoolVar(&withFlags, "flags", false, "show message flags") flagset.Usage = func() { l.Help(os.Stdout, flagset) } flagset.Parse(args[1:]) @@ -140,11 +139,18 @@ func (l LsMsgCmd) Func(args []string) error { os.Exit(1) } - msgs, err := imaputils.ListMessages(Session.Config, uint32(limit), Session.Info.Opts.Debug, subArgs[0]) + msgs, err := imaputils.ListMessages( + Session.Config, + &imaputils.ListMessagesOpts{ + Mailbox: subArgs[0], + Limit: uint32(limit), + }, + Session.Info.Opts.Debug, + ) if err != nil { return err } - printMsgs(msgs, withSeq, withFrom, withDate, sep) + printMsgs(msgs, withSeq, withFrom, withDate, withFlags, sep) return nil } @@ -158,9 +164,9 @@ func numberSize(n uint32) int { return int(math.Floor(math.Log10(float64(n)))) } -func printMsgs(msgs []*imap.Message, withSeq, withFrom, withDate bool, sep string) { - var maxSeq, maxDateLen, maxFromLen int - var out, seqFmtStr, dateFmtStr, fromFmtStr string +func printMsgs(msgs []*imap.Message, withSeq, withFrom, withDate, withFlags bool, sep string) { + var maxSeq, maxDateLen, maxFromLen, maxFlagsLen int + var out, seqFmtStr, dateFmtStr, fromFmtStr, flagsFmtStr string for _, msg := range msgs { if seqSize := numberSize(msg.SeqNum); withSeq && seqSize > maxSeq { maxSeq = seqSize @@ -178,6 +184,16 @@ func printMsgs(msgs []*imap.Message, withSeq, withFrom, withDate bool, sep strin } } } + if withFlags { + var flags string + for _, f := range msg.Flags { + flags += fmt.Sprintf("%s ", f) + } + flags = strings.TrimRight(flags, " ") + if flagsLen := len(flags); flagsLen > maxFlagsLen { + maxFlagsLen = flagsLen + } + } } if withSeq { @@ -189,6 +205,9 @@ func printMsgs(msgs []*imap.Message, withSeq, withFrom, withDate bool, sep strin if withFrom { fromFmtStr = fmt.Sprintf("%%-%dv%s", maxFromLen, sep) } + if withFlags { + flagsFmtStr = fmt.Sprintf("%%-%dv%s", maxFlagsLen, sep) + } for _, msg := range msgs { var line string if withSeq { @@ -200,6 +219,13 @@ func printMsgs(msgs []*imap.Message, withSeq, withFrom, withDate bool, sep strin if withFrom { line += fmt.Sprintf(fromFmtStr, msg.Envelope.From[0].Address()) } + if withFlags { + var flags string + for _, f := range msg.Flags { + flags += fmt.Sprintf("%s ", f) + } + line += fmt.Sprintf(flagsFmtStr, strings.TrimRight(flags, " ")) + } line += msg.Envelope.Subject out += fmt.Sprintln(line) } @@ -213,10 +239,11 @@ func (c CatMsgCmd) Func(args []string) error { Log.Debug("enter info display-message") } var idList []uint32 - var withHeaders, withBody, markRead bool + var withHeaders, withBody, withFlags, markRead bool flagset := flag.NewFlagSet(args[0], flag.ExitOnError) flagset.BoolVar(&withHeaders, "headers", false, "toggle headers display") flagset.BoolVar(&withBody, "no-body", false, "hide body") + flagset.BoolVar(&withFlags, "flags", false, "show flags") flagset.BoolVar(&markRead, "seen", false, "mark as seen if not yet seen") flagset.Usage = func() { c.Help(os.Stdout, flagset) } flagset.Parse(args[1:]) @@ -245,6 +272,7 @@ func (c CatMsgCmd) Func(args []string) error { IdList: idList, WithHeaders: withHeaders, WithBody: !withBody, + WithFlags: withFlags, Peek: !markRead, } if Session.Info.Opts.Debug { @@ -257,7 +285,7 @@ func (c CatMsgCmd) Func(args []string) error { } for _, m := range messages { - err = printMessage(m, opts) + err = printMessage(m, opts, withFlags) if err != nil { return err } @@ -286,9 +314,20 @@ func parseToUint32(s string) (uint32, error) { return uint32(out), nil } -func printMessage(m *imap.Message, opts *imaputils.FetchOpts) error { +func printMessage(m *imap.Message, opts *imaputils.FetchOpts, withFlags bool) error { var out string + if withFlags { + if Session.Info.Opts.Debug { + Log.Debug(m.Flags) + } + for _, f := range m.Flags { + out += fmt.Sprintf("%s ", f) + } + out = strings.TrimRight(out, " ") + out += "\n" + } + if opts.WithHeaders { out += fmt.Sprintln(formatAddresses(m.Envelope.From, "From")) out += fmt.Sprintln(formatAddresses(m.Envelope.Sender, "Sender")) diff --git a/imaputils/info.go b/imaputils/info.go index 2875548..f064955 100644 --- a/imaputils/info.go +++ b/imaputils/info.go @@ -34,7 +34,12 @@ func ListMailboxes(conf *config.AccountData, debug bool) ([]*imap.MailboxInfo, e return mailboxes, nil } -func ListMessages(conf *config.AccountData, limit uint32, debug bool, mailbox string) ([]*imap.Message, error) { +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) @@ -44,19 +49,19 @@ func ListMessages(conf *config.AccountData, limit uint32, debug bool, mailbox st } defer conn.Close() - mbox, err := conn.client.Select(mailbox, true) + mbox, err := conn.client.Select(opts.Mailbox, true) if err != nil { return messages, err } - return getMessages(mbox, conn, limit, 10) + return getMessages(mbox, conn, opts.Limit) } -func getMessages(mbox *imap.MailboxStatus, conn *IMAPConnection, limit, size uint32) ([]*imap.Message, error) { +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, size) + messages := make(chan *imap.Message, 10) done := make(chan error, 1) switch { @@ -70,7 +75,7 @@ func getMessages(mbox *imap.MailboxStatus, conn *IMAPConnection, limit, size uin seqset.AddRange(start, mbox.Messages) go func() { - done <- conn.client.Fetch(seqset, []imap.FetchItem{imap.FetchEnvelope}, messages) + done <- conn.client.Fetch(seqset, []imap.FetchItem{imap.FetchEnvelope, imap.FetchFlags}, messages) }() for msg := range messages { @@ -88,6 +93,7 @@ type FetchOpts struct { IdList []uint32 WithHeaders bool WithBody bool + WithFlags bool Peek bool } @@ -144,6 +150,10 @@ func fetchMessage(mbox *imap.MailboxStatus, conn *IMAPConnection, opts *FetchOpt items = append(items, section.FetchItem()) } + if opts.WithFlags { + items = append(items, imap.FetchFlags) + } + go func() { done <- conn.client.Fetch(seqset, items, messages) }()