[PATCH] Add --message-headers flag to notmuch-show
Johan Parin
johanparin at gmail.com
Sun Nov 10 04:49:29 PST 2019
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 <cworth at 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 = ¶ms.output_body, .name = "body" },
{ .opt_bool = ¶ms.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)
More information about the notmuch
mailing list