aboutsummaryrefslogtreecommitdiffstats
path: root/commands/msg
diff options
context:
space:
mode:
authorKoni Marti <koni.marti@gmail.com>2022-10-20 23:55:28 +0200
committerRobin Jarry <robin@jarry.cc>2022-10-26 00:19:49 +0200
commit19e275025538a92bae92b152c4e39bdd22ad7e7f (patch)
tree4e4cfc06b140a1cf2f8e9c342d2203578fd7a459 /commands/msg
parentb860a64622bfd10d34d24759e24cefa0221ebc5a (diff)
downloadaerc-19e275025538a92bae92b152c4e39bdd22ad7e7f.tar.gz
envelope: display message envelope info
Display entire message envelope in a user-friendly dialog popup with the :envelope command. All header fields can be displayed with the -h flag. Fixes: https://todo.sr.ht/~rjarry/aerc/85 Signed-off-by: Koni Marti <koni.marti@gmail.com> Acked-by: Robin Jarry <robin@jarry.cc>
Diffstat (limited to 'commands/msg')
-rw-r--r--commands/msg/envelope.go152
1 files changed, 152 insertions, 0 deletions
diff --git a/commands/msg/envelope.go b/commands/msg/envelope.go
new file mode 100644
index 00000000..616798d8
--- /dev/null
+++ b/commands/msg/envelope.go
@@ -0,0 +1,152 @@
+package msg
+
+import (
+ "errors"
+ "fmt"
+ "strings"
+
+ "git.sr.ht/~rjarry/aerc/lib/format"
+ "git.sr.ht/~rjarry/aerc/logging"
+ "git.sr.ht/~rjarry/aerc/models"
+ "git.sr.ht/~rjarry/aerc/widgets"
+ "git.sr.ht/~sircmpwn/getopt"
+ "github.com/emersion/go-message/mail"
+)
+
+type Envelope struct{}
+
+func init() {
+ register(Envelope{})
+}
+
+func (Envelope) Aliases() []string {
+ return []string{"envelope"}
+}
+
+func (Envelope) Complete(aerc *widgets.Aerc, args []string) []string {
+ return nil
+}
+
+func (Envelope) Execute(aerc *widgets.Aerc, args []string) error {
+ header := false
+ fmtStr := "%-20.20s: %s"
+ opts, _, err := getopt.Getopts(args, "hs:")
+ if err != nil {
+ return err
+ }
+ for _, opt := range opts {
+ switch opt.Option {
+ case 's':
+ fmtStr = opt.Value
+ case 'h':
+ header = true
+ }
+ }
+
+ acct := aerc.SelectedAccount()
+ if acct == nil {
+ return errors.New("No account selected")
+ }
+
+ var list []string
+ if msg, err := acct.SelectedMessage(); err != nil {
+ return err
+ } else {
+ if msg != nil {
+ if header {
+ list = parseHeader(msg, fmtStr)
+ } else {
+ list = parseEnvelope(msg, fmtStr,
+ acct.UiConfig().TimestampFormat)
+ }
+ } else {
+ return fmt.Errorf("Selected message is empty.")
+ }
+ }
+
+ n := len(list)
+ aerc.AddDialog(widgets.NewDialog(
+ widgets.NewListBox(
+ "Message Envelope. Press <Esc> or <Enter> to close. "+
+ "Start typing to filter.",
+ list,
+ aerc.SelectedAccountUiConfig(),
+ func(_ string) {
+ aerc.CloseDialog()
+ },
+ ),
+ // start pos on screen
+ func(h int) int {
+ if n < h/8*6 {
+ return h/2 - n/2 - 1
+ }
+ return h / 8
+ },
+ // dialog height
+ func(h int) int {
+ if n < h/8*6 {
+ return n + 2
+ }
+ return h / 8 * 6
+ },
+ ))
+
+ return nil
+}
+
+func parseEnvelope(msg *models.MessageInfo, fmtStr, fmtTime string,
+) (result []string) {
+ if envlp := msg.Envelope; envlp != nil {
+ addStr := func(key, text string) {
+ result = append(result, fmt.Sprintf(fmtStr, key, text))
+ }
+ addAddr := func(key string, ls []*mail.Address) {
+ for _, l := range ls {
+ result = append(result,
+ fmt.Sprintf(fmtStr, key,
+ format.AddressForHumans(l)))
+ }
+ }
+
+ addStr("Date", envlp.Date.Format(fmtTime))
+ addStr("Subject", envlp.Subject)
+ addStr("Message-Id", envlp.MessageId)
+
+ addAddr("From", envlp.From)
+ addAddr("To", envlp.To)
+ addAddr("ReplyTo", envlp.ReplyTo)
+ addAddr("Cc", envlp.Cc)
+ addAddr("Bcc", envlp.Bcc)
+ }
+ return
+}
+
+func parseHeader(msg *models.MessageInfo, fmtStr string) (result []string) {
+ if h := msg.RFC822Headers; h != nil {
+ hf := h.Fields()
+ for hf.Next() {
+ text, err := hf.Text()
+ if err != nil {
+ logging.Errorf(err.Error())
+ text = hf.Value()
+ }
+ result = append(result,
+ headerExpand(fmtStr, hf.Key(), text)...)
+ }
+ }
+ return
+}
+
+func headerExpand(fmtStr, key, text string) []string {
+ var result []string
+ switch strings.ToLower(key) {
+ case "to", "from", "bcc", "cc":
+ for _, item := range strings.Split(text, ",") {
+ result = append(result, fmt.Sprintf(fmtStr, key,
+ strings.TrimSpace(item)))
+ }
+ default:
+ result = append(result, fmt.Sprintf(fmtStr, key, text))
+ }
+ return result
+}