Browse Source

Selectively print header and body of message

Blallo 3 years ago
parent
commit
75aae2c509
2 changed files with 96 additions and 39 deletions
  1. 45 17
      cli/papero/info.go
  2. 51 22
      imaputils/info.go

+ 45 - 17
cli/papero/info.go

@@ -213,7 +213,11 @@ func (c CatMsgCmd) Func(args []string) error {
 		Log.Debug("enter info display-message")
 	}
 	var idList []uint32
+	var withHeaders, withBody, 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(&markRead, "seen", false, "mark as seen if not yet seen")
 	flagset.Usage = func() { c.Help(os.Stdout, flagset) }
 	flagset.Parse(args[1:])
 
@@ -236,13 +240,24 @@ func (c CatMsgCmd) Func(args []string) error {
 		}
 	}
 
-	messages, err := imaputils.FetchMessages(Session.Config, mailbox, idList, Session.Info.Opts.Debug)
+	opts := &imaputils.FetchOpts{
+		Mailbox:     mailbox,
+		IdList:      idList,
+		WithHeaders: withHeaders,
+		WithBody:    !withBody,
+		Peek:        !markRead,
+	}
+	if Session.Info.Opts.Debug {
+		Log.Debug(opts)
+	}
+
+	messages, err := imaputils.FetchMessages(Session.Config, opts, Session.Info.Opts.Debug)
 	if err != nil {
 		return err
 	}
 
 	for _, m := range messages {
-		err = printMessage(m)
+		err = printMessage(m, opts)
 		if err != nil {
 			return err
 		}
@@ -271,24 +286,37 @@ func parseToUint32(s string) (uint32, error) {
 	return uint32(out), nil
 }
 
-func printMessage(m *imap.Message) error {
+func printMessage(m *imap.Message, opts *imaputils.FetchOpts) error {
 	var out string
 
-	out += fmt.Sprintln(formatAddresses(m.Envelope.From, "From"))
-	out += fmt.Sprintln(formatAddresses(m.Envelope.Sender, "Sender"))
-	out += fmt.Sprintln(formatAddresses(m.Envelope.Cc, "Cc"))
-	out += fmt.Sprintln(formatAddresses(m.Envelope.Bcc, "Bcc"))
-	out += fmt.Sprintln(formatAddresses(m.Envelope.ReplyTo, "ReplyTo"))
-	out += fmt.Sprintf("InReplyTo: %s\n", m.Envelope.InReplyTo)
-	out += fmt.Sprintf("Date: %v\n", m.Envelope.Date)
-	out += fmt.Sprintf("Subject: %s\n", m.Envelope.Subject)
-
-	bodyReader := m.GetBody(&imap.BodySectionName{BodyPartName: imap.BodyPartName{}, Peek: true})
-	body, err := ioutil.ReadAll(bodyReader)
-	if err != nil {
-		return err
+	if opts.WithHeaders {
+		out += fmt.Sprintln(formatAddresses(m.Envelope.From, "From"))
+		out += fmt.Sprintln(formatAddresses(m.Envelope.Sender, "Sender"))
+		out += fmt.Sprintln(formatAddresses(m.Envelope.Cc, "Cc"))
+		out += fmt.Sprintln(formatAddresses(m.Envelope.Bcc, "Bcc"))
+		out += fmt.Sprintln(formatAddresses(m.Envelope.ReplyTo, "ReplyTo"))
+		out += fmt.Sprintf("InReplyTo: %s\n", m.Envelope.InReplyTo)
+		out += fmt.Sprintf("Date: %v\n", m.Envelope.Date)
+		out += fmt.Sprintf("Subject: %s\n", m.Envelope.Subject)
+
+		headersSec := &imap.BodySectionName{Peek: opts.Peek, BodyPartName: imap.BodyPartName{Specifier: imap.HeaderSpecifier}}
+		headersReader := m.GetBody(headersSec)
+		headers, err := ioutil.ReadAll(headersReader)
+		if err != nil {
+			return err
+		}
+		out += fmt.Sprintln(string(headers))
+	}
+
+	if opts.WithBody {
+		bodySec := &imap.BodySectionName{Peek: opts.Peek, BodyPartName: imap.BodyPartName{Specifier: imap.TextSpecifier}}
+		bodyReader := m.GetBody(bodySec)
+		body, err := ioutil.ReadAll(bodyReader)
+		if err != nil {
+			return err
+		}
+		out += fmt.Sprintln(string(body))
 	}
-	out += fmt.Sprintln(string(body))
 
 	fmt.Println(out)
 	return nil

+ 51 - 22
imaputils/info.go

@@ -1,6 +1,8 @@
 package imaputils
 
 import (
+	"fmt"
+
 	"git.lattuga.net/blallo/papero/config"
 	"github.com/emersion/go-imap"
 )
@@ -81,7 +83,26 @@ func getMessages(mbox *imap.MailboxStatus, conn *IMAPConnection, limit, size uin
 	return msgs, nil
 }
 
-func FetchMessages(conf *config.AccountData, mailbox string, idList []uint32, debug bool) ([]*imap.Message, error) {
+type FetchOpts struct {
+	Mailbox     string
+	IdList      []uint32
+	WithHeaders bool
+	WithBody    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)
 
@@ -91,39 +112,47 @@ func FetchMessages(conf *config.AccountData, mailbox string, idList []uint32, de
 	}
 	defer conn.Close()
 
-	mbox, err := conn.client.Select(mailbox, true)
+	mbox, err := conn.client.Select(opts.Mailbox, true)
 	if err != nil {
 		return messages, err
 	}
 
-	for _, id := range idList {
-		m, err := fetchMessage(mbox, conn, id)
-		if err != nil {
-			return messages, err
-		}
-		messages = append(messages, m)
-	}
-
-	return messages, nil
+	return fetchMessage(mbox, conn, opts)
 }
 
-func fetchMessage(mbox *imap.MailboxStatus, conn *IMAPConnection, id uint32) (*imap.Message, error) {
-	var message *imap.Message
-	seqset := new(imap.SeqSet)
-	messages := make(chan *imap.Message, 1)
+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)
-	section := &imap.BodySectionName{}
-	section.Peek = true
-	items := []imap.FetchItem{imap.FetchEnvelope, section.FetchItem()}
 
-	seqset.AddNum(id)
+	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())
+	}
+
 	go func() {
 		done <- conn.client.Fetch(seqset, items, messages)
 	}()
 
-	msg := <-messages
+	for m := range messages {
+		messageAcc = append(messageAcc, m)
+	}
 	if err := <-done; err != nil {
-		return message, err
+		return []*imap.Message{}, err
 	}
-	return msg, nil
+	return messageAcc, nil
 }