Add a new flag --message-headers to notmuch show, in order to let the
user specify displayed headers using `notmuch-message-headers' in the
emacs mua.

The flag will impact which headers are output in
format_headers_sprinter.

By default only the following headers are output by notmuch show with
--format=sexp :

- From
- To
- Subject
- Cc
- Bcc
- Reply-To
- In-reply-to
- References
- Date

`From' is always output regardless of what is specified in
--message-headers.

See this bug report:

  https://notmuchmail.org/pipermail/notmuch/2017/026069.html

This commit does not include documentation updates.
---
 emacs/notmuch-query.el |   4 +-
 emacs/notmuch-tree.el  |   2 +
 notmuch-show.c         | 138 +++++++++++++++++++++++++++++------------
 3 files changed, 104 insertions(+), 40 deletions(-)

diff --git a/emacs/notmuch-query.el b/emacs/notmuch-query.el
index 563e4acf..61c921a4 100644
--- a/emacs/notmuch-query.el
+++ b/emacs/notmuch-query.el
@@ -30,7 +30,9 @@ A thread is a forest or list of trees. A tree is a two element
 list where the first element is a message, and the second element
 is a possibly empty forest of replies.
 "
-  (let ((args '("show" "--format=sexp" "--format-version=4")))
+  (let ((args `("show" "--format=sexp" "--format-version=4"
+               ,(concat "--message-headers="
+                         (mapconcat #'identity notmuch-message-headers ",")))))
     (if notmuch-show-process-crypto
        (setq args (append args '("--decrypt=true"))))
     (setq args (append args search-terms))
diff --git a/emacs/notmuch-tree.el b/emacs/notmuch-tree.el
index c00315e8..1d793ec3 100644
--- a/emacs/notmuch-tree.el
+++ b/emacs/notmuch-tree.el
@@ -922,6 +922,8 @@ the same as for the function notmuch-tree."
     (let ((proc (notmuch-start-notmuch
                 "notmuch-tree" (current-buffer) #'notmuch-tree-process-sentinel
                 "show" "--body=false" "--format=sexp" "--format-version=4"
+                 (concat "--message-headers="
+                         (mapconcat #'identity notmuch-message-headers ","))
                 message-arg search-args))
          ;; Use a scratch buffer to accumulate partial output.
          ;; This buffer will be killed by the sentinel, which
diff --git a/notmuch-show.c b/notmuch-show.c
index 21792a57..1658b66e 100644
--- a/notmuch-show.c
+++ b/notmuch-show.c
@@ -18,11 +18,31 @@
  * Author: Carl Worth <cwo...@cworth.org>
  */
 
+#include <string.h>
+#include <stdlib.h>
+
 #include "notmuch-client.h"
 #include "gmime-filter-reply.h"
 #include "sprinter.h"
 #include "zlib-extra.h"
 
+/* Max number of headers that can be output from
+ * format_headers_sprinter */
+#define MAX_PRINTABLE_MESSAGE_HEADERS 25
+
+/* Default list of header names to be printed by
+ * format_headers_sprinter */
+static const char *default_message_header_list[] = {
+    "To", "Subject", "Cc", "Bcc", "Reply-To", "In-reply-to",
+    "References", "Date"};
+
+/* List of header names to be printed by format_headers_sprinter */
+static char **message_header_list_p = (char **) default_message_header_list;
+
+static int message_header_list_len =
+    sizeof(default_message_header_list) / sizeof(char *);
+
+
 static const char *
 _get_tags_as_string (const void *ctx, notmuch_message_t *message)
 {
@@ -48,6 +68,26 @@ _get_tags_as_string (const void *ctx, notmuch_message_t 
*message)
     return result;
 }
 
+/* Extract requested header names from the message-headers command
+ * line argument.
+ */
+static void
+extract_requested_headers (const char *opt_str)
+{
+    int count = 0;
+    char *tofree = strdup (opt_str);
+    char *string = tofree;
+    char *header_name;
+
+    message_header_list_p = malloc(MAX_PRINTABLE_MESSAGE_HEADERS * sizeof(char 
*));
+    while ((header_name = strsep(&string, ",")) != NULL &&
+          count < MAX_PRINTABLE_MESSAGE_HEADERS)
+       message_header_list_p[count++] = strdup(header_name);
+
+    message_header_list_len = count;
+    free(tofree);
+}
+
 /* Get a nice, single-line summary of message. */
 static const char *
 _get_one_line_summary (const void *ctx, notmuch_message_t *message)
@@ -202,57 +242,72 @@ format_headers_sprinter (sprinter_t *sp, GMimeMessage 
*message,
     /* Any changes to the JSON or S-Expression format should be
      * reflected in the file devel/schemata. */
 
-    char *recipients_string;
-    const char *reply_to_string;
     void *local = talloc_new (sp);
+    GMimeHeaderList *header_list;
 
-    sp->begin_map (sp);
+    /* Not currently used */
+    (void) reply;
 
-    sp->map_key (sp, "Subject");
-    if (msg_crypto && msg_crypto->payload_subject) {
-       sp->string (sp, msg_crypto->payload_subject);
-    } else
-       sp->string (sp, g_mime_message_get_subject (message));
+    sp->begin_map (sp);
 
     sp->map_key (sp, "From");
     sp->string (sp, g_mime_message_get_from_string (message));
 
-    recipients_string = g_mime_message_get_address_string (message, 
GMIME_ADDRESS_TYPE_TO);
-    if (recipients_string) {
-       sp->map_key (sp, "To");
-       sp->string (sp, recipients_string);
-       g_free (recipients_string);
-    }
+    header_list  = g_mime_object_get_header_list (GMIME_OBJECT(message));
 
-    recipients_string = g_mime_message_get_address_string (message, 
GMIME_ADDRESS_TYPE_CC);
-    if (recipients_string) {
-       sp->map_key (sp, "Cc");
-       sp->string (sp, recipients_string);
-       g_free (recipients_string);
-    }
+    for (int i = 0; i < message_header_list_len; i++) {
+       const char *name = message_header_list_p[i];
 
-    recipients_string = g_mime_message_get_address_string (message, 
GMIME_ADDRESS_TYPE_BCC);
-    if (recipients_string) {
-       sp->map_key (sp, "Bcc");
-       sp->string (sp, recipients_string);
-       g_free (recipients_string);
-    }
+       if (!STRNCMP_LITERAL (name, "Subject")) {
+           sp->map_key (sp, "Subject");
+           if (msg_crypto && msg_crypto->payload_subject) {
+               sp->string (sp, msg_crypto->payload_subject);
+           } else
+               sp->string (sp, g_mime_message_get_subject (message));
+       }
 
-    reply_to_string = g_mime_message_get_reply_to_string (local, message);
-    if (reply_to_string) {
-       sp->map_key (sp, "Reply-To");
-       sp->string (sp, reply_to_string);
-    }
+       else if (!STRNCMP_LITERAL (name, "To") ||
+                !STRNCMP_LITERAL (name, "Cc") ||
+                !STRNCMP_LITERAL (name, "Bcc")) {
+           GMimeAddressType addr_type;
+           char *recipients_string;
+
+           if (!STRNCMP_LITERAL (name, "To"))
+               addr_type = GMIME_ADDRESS_TYPE_TO;
+           else if (!STRNCMP_LITERAL (name, "Cc"))
+               addr_type = GMIME_ADDRESS_TYPE_CC;
+           else
+               addr_type = GMIME_ADDRESS_TYPE_BCC;
+
+           recipients_string = g_mime_message_get_address_string (
+               message, addr_type);
+           if (recipients_string) {
+               sp->map_key (sp, name);
+               sp->string (sp, recipients_string);
+               g_free (recipients_string);
+           }
+       }
 
-    if (reply) {
-       sp->map_key (sp, "In-reply-to");
-       sp->string (sp, g_mime_object_get_header (GMIME_OBJECT (message), 
"In-reply-to"));
+       else if (!STRNCMP_LITERAL (name, "Reply-To")) {
+           const char *reply_to_string;
 
-       sp->map_key (sp, "References");
-       sp->string (sp, g_mime_object_get_header (GMIME_OBJECT (message), 
"References"));
-    } else {
-       sp->map_key (sp, "Date");
-       sp->string (sp, g_mime_message_get_date_string (sp, message));
+           reply_to_string = g_mime_message_get_reply_to_string (local, 
message);
+           if (reply_to_string) {
+               sp->map_key (sp, "Reply-To");
+               sp->string (sp, reply_to_string);
+           }
+       }
+
+       else {
+           GMimeHeader *header = g_mime_header_list_get_header(
+               header_list, name);
+
+           if (header == NULL)
+               continue;
+
+           sp->map_key (sp, g_mime_header_get_name(header));
+           sp->string (sp, g_mime_header_get_value(header));
+       }
     }
 
     sp->end (sp);
@@ -1168,6 +1223,7 @@ notmuch_show_command (notmuch_config_t *config, int argc, 
char *argv[])
     bool exclude = true;
     bool entire_thread_set = false;
     bool single_message;
+    const char *message_header_str = NULL;
 
     notmuch_opt_desc_t options[] = {
        { .opt_keyword = &format, .name = "format", .keywords =
@@ -1193,6 +1249,7 @@ notmuch_show_command (notmuch_config_t *config, int argc, 
char *argv[])
        { .opt_bool = &params.output_body, .name = "body" },
        { .opt_bool = &params.include_html, .name = "include-html" },
        { .opt_inherit = notmuch_shared_options },
+       { .opt_string = &message_header_str, .name = "message-headers" },
        { }
     };
 
@@ -1202,6 +1259,9 @@ notmuch_show_command (notmuch_config_t *config, int argc, 
char *argv[])
 
     notmuch_process_shared_options (argv[0]);
 
+    if (message_header_str)
+       extract_requested_headers(message_header_str);
+
     /* explicit decryption implies verification */
     if (params.crypto.decrypt == NOTMUCH_DECRYPT_NOSTASH ||
        params.crypto.decrypt == NOTMUCH_DECRYPT_TRUE)
-- 
2.21.0 (Apple Git-122)

_______________________________________________
notmuch mailing list
notmuch@notmuchmail.org
https://notmuchmail.org/mailman/listinfo/notmuch

Reply via email to