show: Unify JSON header output for messages and message parts

This has three ramifications:
- Blank To and Cc headers are no longer output for messages.
- Dates are now canonicalized for messages, which means they always
  have a day of the week and GMT is printed +0000 (never -0000)
- Invalid From message headers are handled slightly differently, since
  they get parsed by GMime now instead of notmuch.
This commit is contained in:
Austin Clements 2012-02-19 19:26:26 -05:00 committed by David Bremner
parent 2209d7b952
commit 86f89385c3
6 changed files with 23 additions and 61 deletions

View file

@ -291,36 +291,7 @@ format_headers_message_part_text (GMimeMessage *message)
} }
static void static void
format_headers_json (const void *ctx, notmuch_message_t *message) format_headers_json (GMimeMessage *message)
{
const char *headers[] = {
"Subject", "From", "To", "Cc", "Bcc", "Date"
};
const char *name, *value;
unsigned int i;
int first_header = 1;
void *ctx_quote = talloc_new (ctx);
for (i = 0; i < ARRAY_SIZE (headers); i++) {
name = headers[i];
value = notmuch_message_get_header (message, name);
if (value)
{
if (!first_header)
fputs (", ", stdout);
first_header = 0;
printf ("%s: %s",
json_quote_str (ctx_quote, name),
json_quote_str (ctx_quote, value));
}
}
talloc_free (ctx_quote);
}
static void
format_headers_message_part_json (GMimeMessage *message)
{ {
void *ctx = talloc_new (NULL); void *ctx = talloc_new (NULL);
void *ctx_quote = talloc_new (ctx); void *ctx_quote = talloc_new (ctx);
@ -690,7 +661,7 @@ format_part_json (const void *ctx, mime_node_t *node, notmuch_bool_t first)
format_message_json (ctx, node->envelope_file); format_message_json (ctx, node->envelope_file);
printf ("\"headers\": {"); printf ("\"headers\": {");
format_headers_json (ctx, node->envelope_file); format_headers_json (GMIME_MESSAGE (node->part));
printf ("}"); printf ("}");
printf (", \"body\": ["); printf (", \"body\": [");
@ -778,7 +749,7 @@ format_part_json (const void *ctx, mime_node_t *node, notmuch_bool_t first)
if (GMIME_IS_MESSAGE (node->part)) { if (GMIME_IS_MESSAGE (node->part)) {
printf ("\"headers\": {"); printf ("\"headers\": {");
format_headers_message_part_json (GMIME_MESSAGE (node->part)); format_headers_json (GMIME_MESSAGE (node->part));
printf ("}"); printf ("}");
printf (", \"body\": ["); printf (", \"body\": [");

View file

@ -50,9 +50,8 @@ expected='[[[{"id": "XXXXX",
"headers": {"Subject": "test signed message 001", "headers": {"Subject": "test signed message 001",
"From": "Notmuch Test Suite <test_suite@notmuchmail.org>", "From": "Notmuch Test Suite <test_suite@notmuchmail.org>",
"To": "test_suite@notmuchmail.org", "To": "test_suite@notmuchmail.org",
"Cc": "", "Date": "Sat,
"Bcc": "", 01 Jan 2000 12:00:00 +0000"},
"Date": "01 Jan 2000 12:00:00 -0000"},
"body": [{"id": 1, "body": [{"id": 1,
"sigstatus": [{"status": "good", "sigstatus": [{"status": "good",
"fingerprint": "'$FINGERPRINT'", "fingerprint": "'$FINGERPRINT'",
@ -84,9 +83,8 @@ expected='[[[{"id": "XXXXX",
"headers": {"Subject": "test signed message 001", "headers": {"Subject": "test signed message 001",
"From": "Notmuch Test Suite <test_suite@notmuchmail.org>", "From": "Notmuch Test Suite <test_suite@notmuchmail.org>",
"To": "test_suite@notmuchmail.org", "To": "test_suite@notmuchmail.org",
"Cc": "", "Date": "Sat,
"Bcc": "", 01 Jan 2000 12:00:00 +0000"},
"Date": "01 Jan 2000 12:00:00 -0000"},
"body": [{"id": 1, "body": [{"id": 1,
"sigstatus": [{"status": "good", "sigstatus": [{"status": "good",
"fingerprint": "'$FINGERPRINT'", "fingerprint": "'$FINGERPRINT'",
@ -120,9 +118,8 @@ expected='[[[{"id": "XXXXX",
"headers": {"Subject": "test signed message 001", "headers": {"Subject": "test signed message 001",
"From": "Notmuch Test Suite <test_suite@notmuchmail.org>", "From": "Notmuch Test Suite <test_suite@notmuchmail.org>",
"To": "test_suite@notmuchmail.org", "To": "test_suite@notmuchmail.org",
"Cc": "", "Date": "Sat,
"Bcc": "", 01 Jan 2000 12:00:00 +0000"},
"Date": "01 Jan 2000 12:00:00 -0000"},
"body": [{"id": 1, "body": [{"id": 1,
"sigstatus": [{"status": "error", "sigstatus": [{"status": "error",
"keyid": "'$(echo $FINGERPRINT | cut -c 25-)'", "keyid": "'$(echo $FINGERPRINT | cut -c 25-)'",
@ -194,9 +191,8 @@ expected='[[[{"id": "XXXXX",
"headers": {"Subject": "test encrypted message 001", "headers": {"Subject": "test encrypted message 001",
"From": "Notmuch Test Suite <test_suite@notmuchmail.org>", "From": "Notmuch Test Suite <test_suite@notmuchmail.org>",
"To": "test_suite@notmuchmail.org", "To": "test_suite@notmuchmail.org",
"Cc": "", "Date": "Sat,
"Bcc": "", 01 Jan 2000 12:00:00 +0000"},
"Date": "01 Jan 2000 12:00:00 -0000"},
"body": [{"id": 1, "body": [{"id": 1,
"encstatus": [{"status": "good"}], "encstatus": [{"status": "good"}],
"sigstatus": [], "sigstatus": [],
@ -249,9 +245,8 @@ expected='[[[{"id": "XXXXX",
"headers": {"Subject": "test encrypted message 001", "headers": {"Subject": "test encrypted message 001",
"From": "Notmuch Test Suite <test_suite@notmuchmail.org>", "From": "Notmuch Test Suite <test_suite@notmuchmail.org>",
"To": "test_suite@notmuchmail.org", "To": "test_suite@notmuchmail.org",
"Cc": "", "Date": "Sat,
"Bcc": "", 01 Jan 2000 12:00:00 +0000"},
"Date": "01 Jan 2000 12:00:00 -0000"},
"body": [{"id": 1, "body": [{"id": 1,
"encstatus": [{"status": "bad"}], "encstatus": [{"status": "bad"}],
"content-type": "multipart/encrypted", "content-type": "multipart/encrypted",
@ -284,9 +279,8 @@ expected='[[[{"id": "XXXXX",
"headers": {"Subject": "test encrypted message 002", "headers": {"Subject": "test encrypted message 002",
"From": "Notmuch Test Suite <test_suite@notmuchmail.org>", "From": "Notmuch Test Suite <test_suite@notmuchmail.org>",
"To": "test_suite@notmuchmail.org", "To": "test_suite@notmuchmail.org",
"Cc": "", "Date": "Sat,
"Bcc": "", 01 Jan 2000 12:00:00 +0000"},
"Date": "01 Jan 2000 12:00:00 -0000"},
"body": [{"id": 1, "body": [{"id": 1,
"encstatus": [{"status": "good"}], "encstatus": [{"status": "good"}],
"sigstatus": [{"status": "good", "sigstatus": [{"status": "good",
@ -339,9 +333,8 @@ expected='[[[{"id": "XXXXX",
"headers": {"Subject": "test signed message 001", "headers": {"Subject": "test signed message 001",
"From": "Notmuch Test Suite <test_suite@notmuchmail.org>", "From": "Notmuch Test Suite <test_suite@notmuchmail.org>",
"To": "test_suite@notmuchmail.org", "To": "test_suite@notmuchmail.org",
"Cc": "", "Date": "Sat,
"Bcc": "", 01 Jan 2000 12:00:00 +0000"},
"Date": "01 Jan 2000 12:00:00 -0000"},
"body": [{"id": 1, "body": [{"id": 1,
"sigstatus": [{"status": "error", "sigstatus": [{"status": "error",
"keyid": "6D92612D94E46381", "keyid": "6D92612D94E46381",

View file

@ -78,7 +78,7 @@ thread=$(notmuch search --output=threads subject:message-with-invalid-from)
test_emacs "(notmuch-show \"$thread\") test_emacs "(notmuch-show \"$thread\")
(test-output)" (test-output)"
cat <<EOF >EXPECTED cat <<EOF >EXPECTED
Invalid " From <test_suite@notmuchmail.org> (2001-01-05) (inbox) "Invalid " (2001-01-05) (inbox)
Subject: message-with-invalid-from Subject: message-with-invalid-from
To: Notmuch Test Suite <test_suite@notmuchmail.org> To: Notmuch Test Suite <test_suite@notmuchmail.org>
Date: Fri, 05 Jan 2001 15:43:57 +0000 Date: Fri, 05 Jan 2001 15:43:57 +0000
@ -414,7 +414,7 @@ test_emacs '(notmuch-show "id:\"bought\"")
(reverse-region (point-min) (point-max)) (reverse-region (point-min) (point-max))
(test-output)' (test-output)'
cat <<EOF >EXPECTED cat <<EOF >EXPECTED
Sat, 01 Jan 2000 12:00:00 -0000 Sat, 01 Jan 2000 12:00:00 +0000
Some One <someone@somewhere.org> Some One <someone@somewhere.org>
Some One Else <notsomeone@somewhere.org> Some One Else <notsomeone@somewhere.org>
Notmuch <notmuch@notmuchmail.org> Notmuch <notmuch@notmuchmail.org>

View file

@ -5,7 +5,7 @@ test_description="--format=json output"
test_begin_subtest "Show message: json" test_begin_subtest "Show message: json"
add_message "[subject]=\"json-show-subject\"" "[date]=\"Sat, 01 Jan 2000 12:00:00 -0000\"" "[body]=\"json-show-message\"" add_message "[subject]=\"json-show-subject\"" "[date]=\"Sat, 01 Jan 2000 12:00:00 -0000\"" "[body]=\"json-show-message\""
output=$(notmuch show --format=json "json-show-message") output=$(notmuch show --format=json "json-show-message")
test_expect_equal "$output" "[[[{\"id\": \"${gen_msg_id}\", \"match\": true, \"filename\": \"${gen_msg_filename}\", \"timestamp\": 946728000, \"date_relative\": \"2000-01-01\", \"tags\": [\"inbox\",\"unread\"], \"headers\": {\"Subject\": \"json-show-subject\", \"From\": \"Notmuch Test Suite <test_suite@notmuchmail.org>\", \"To\": \"Notmuch Test Suite <test_suite@notmuchmail.org>\", \"Cc\": \"\", \"Bcc\": \"\", \"Date\": \"Sat, 01 Jan 2000 12:00:00 -0000\"}, \"body\": [{\"id\": 1, \"content-type\": \"text/plain\", \"content\": \"json-show-message\n\"}]}, []]]]" test_expect_equal "$output" "[[[{\"id\": \"${gen_msg_id}\", \"match\": true, \"filename\": \"${gen_msg_filename}\", \"timestamp\": 946728000, \"date_relative\": \"2000-01-01\", \"tags\": [\"inbox\",\"unread\"], \"headers\": {\"Subject\": \"json-show-subject\", \"From\": \"Notmuch Test Suite <test_suite@notmuchmail.org>\", \"To\": \"Notmuch Test Suite <test_suite@notmuchmail.org>\", \"Date\": \"Sat, 01 Jan 2000 12:00:00 +0000\"}, \"body\": [{\"id\": 1, \"content-type\": \"text/plain\", \"content\": \"json-show-message\n\"}]}, []]]]"
test_begin_subtest "Search message: json" test_begin_subtest "Search message: json"
add_message "[subject]=\"json-search-subject\"" "[date]=\"Sat, 01 Jan 2000 12:00:00 -0000\"" "[body]=\"json-search-message\"" add_message "[subject]=\"json-search-subject\"" "[date]=\"Sat, 01 Jan 2000 12:00:00 -0000\"" "[body]=\"json-search-message\""
@ -22,7 +22,7 @@ test_expect_equal "$output" "[{\"thread\": \"XXX\",
test_begin_subtest "Show message: json, utf-8" test_begin_subtest "Show message: json, utf-8"
add_message "[subject]=\"json-show-utf8-body-sübjéct\"" "[date]=\"Sat, 01 Jan 2000 12:00:00 -0000\"" "[body]=\"jsön-show-méssage\"" add_message "[subject]=\"json-show-utf8-body-sübjéct\"" "[date]=\"Sat, 01 Jan 2000 12:00:00 -0000\"" "[body]=\"jsön-show-méssage\""
output=$(notmuch show --format=json "jsön-show-méssage") output=$(notmuch show --format=json "jsön-show-méssage")
test_expect_equal "$output" "[[[{\"id\": \"${gen_msg_id}\", \"match\": true, \"filename\": \"${gen_msg_filename}\", \"timestamp\": 946728000, \"date_relative\": \"2000-01-01\", \"tags\": [\"inbox\",\"unread\"], \"headers\": {\"Subject\": \"json-show-utf8-body-sübjéct\", \"From\": \"Notmuch Test Suite <test_suite@notmuchmail.org>\", \"To\": \"Notmuch Test Suite <test_suite@notmuchmail.org>\", \"Cc\": \"\", \"Bcc\": \"\", \"Date\": \"Sat, 01 Jan 2000 12:00:00 -0000\"}, \"body\": [{\"id\": 1, \"content-type\": \"text/plain\", \"content\": \"jsön-show-méssage\n\"}]}, []]]]" test_expect_equal "$output" "[[[{\"id\": \"${gen_msg_id}\", \"match\": true, \"filename\": \"${gen_msg_filename}\", \"timestamp\": 946728000, \"date_relative\": \"2000-01-01\", \"tags\": [\"inbox\",\"unread\"], \"headers\": {\"Subject\": \"json-show-utf8-body-sübjéct\", \"From\": \"Notmuch Test Suite <test_suite@notmuchmail.org>\", \"To\": \"Notmuch Test Suite <test_suite@notmuchmail.org>\", \"Date\": \"Sat, 01 Jan 2000 12:00:00 +0000\"}, \"body\": [{\"id\": 1, \"content-type\": \"text/plain\", \"content\": \"jsön-show-méssage\n\"}]}, []]]]"
test_begin_subtest "Show message: json, inline attachment filename" test_begin_subtest "Show message: json, inline attachment filename"
subject='json-show-inline-attachment-filename' subject='json-show-inline-attachment-filename'
@ -35,7 +35,7 @@ emacs_deliver_message \
(insert \"Message-ID: <$id>\n\")" (insert \"Message-ID: <$id>\n\")"
output=$(notmuch show --format=json "id:$id") output=$(notmuch show --format=json "id:$id")
filename=$(notmuch search --output=files "id:$id") filename=$(notmuch search --output=files "id:$id")
test_expect_equal "$output" "[[[{\"id\": \"$id\", \"match\": true, \"filename\": \"$filename\", \"timestamp\": 946728000, \"date_relative\": \"2000-01-01\", \"tags\": [\"inbox\"], \"headers\": {\"Subject\": \"$subject\", \"From\": \"Notmuch Test Suite <test_suite@notmuchmail.org>\", \"To\": \"test_suite@notmuchmail.org\", \"Cc\": \"\", \"Bcc\": \"\", \"Date\": \"01 Jan 2000 12:00:00 -0000\"}, \"body\": [{\"id\": 1, \"content-type\": \"multipart/mixed\", \"content\": [{\"id\": 2, \"content-type\": \"text/plain\", \"content\": \"This is a test message with inline attachment with a filename\"}, {\"id\": 3, \"content-type\": \"application/octet-stream\", \"filename\": \"README\"}]}]}, []]]]" test_expect_equal "$output" "[[[{\"id\": \"$id\", \"match\": true, \"filename\": \"$filename\", \"timestamp\": 946728000, \"date_relative\": \"2000-01-01\", \"tags\": [\"inbox\"], \"headers\": {\"Subject\": \"$subject\", \"From\": \"Notmuch Test Suite <test_suite@notmuchmail.org>\", \"To\": \"test_suite@notmuchmail.org\", \"Date\": \"Sat, 01 Jan 2000 12:00:00 +0000\"}, \"body\": [{\"id\": 1, \"content-type\": \"multipart/mixed\", \"content\": [{\"id\": 2, \"content-type\": \"text/plain\", \"content\": \"This is a test message with inline attachment with a filename\"}, {\"id\": 3, \"content-type\": \"application/octet-stream\", \"filename\": \"README\"}]}]}, []]]]"
test_begin_subtest "Search message: json, utf-8" test_begin_subtest "Search message: json, utf-8"
add_message "[subject]=\"json-search-utf8-body-sübjéct\"" "[date]=\"Sat, 01 Jan 2000 12:00:00 -0000\"" "[body]=\"jsön-search-méssage\"" add_message "[subject]=\"json-search-utf8-body-sübjéct\"" "[date]=\"Sat, 01 Jan 2000 12:00:00 -0000\"" "[body]=\"jsön-search-méssage\""

View file

@ -53,8 +53,6 @@ test_expect_equal "$output" '[[[{"id": "adding-replied-tag@notmuch-test-suite",
"headers": {"Subject": "Adding replied tag", "headers": {"Subject": "Adding replied tag",
"From": "Notmuch Test Suite <test_suite@notmuchmail.org>", "From": "Notmuch Test Suite <test_suite@notmuchmail.org>",
"To": "Notmuch Test Suite <test_suite@notmuchmail.org>", "To": "Notmuch Test Suite <test_suite@notmuchmail.org>",
"Cc": "",
"Bcc": "",
"Date": "Fri, "Date": "Fri,
05 Jan 2001 15:43:57 +0000"}, 05 Jan 2001 15:43:57 +0000"},
"body": [{"id": 1, "body": [{"id": 1,

View file

@ -322,7 +322,7 @@ notmuch show --format=json --part=0 'id:87liy5ap00.fsf@yoom.home.cworth.org' | s
echo >>OUTPUT # expect *no* newline at end of output echo >>OUTPUT # expect *no* newline at end of output
cat <<EOF >EXPECTED cat <<EOF >EXPECTED
{"id": "87liy5ap00.fsf@yoom.home.cworth.org", "match": true, "filename": "${MAIL_DIR}/multipart", "timestamp": 978709437, "date_relative": "2001-01-05", "tags": ["attachment","inbox","signed","unread"], "headers": {"Subject": "Multipart message", "From": "Carl Worth <cworth@cworth.org>", "To": "cworth@cworth.org", "Cc": "", "Bcc": "", "Date": "Fri, 05 Jan 2001 15:43:57 +0000"}, "body": [ {"id": "87liy5ap00.fsf@yoom.home.cworth.org", "match": true, "filename": "${MAIL_DIR}/multipart", "timestamp": 978709437, "date_relative": "2001-01-05", "tags": ["attachment","inbox","signed","unread"], "headers": {"Subject": "Multipart message", "From": "Carl Worth <cworth@cworth.org>", "To": "cworth@cworth.org", "Date": "Fri, 05 Jan 2001 15:43:57 +0000"}, "body": [
{"id": 1, "content-type": "multipart/signed", "content": [ {"id": 1, "content-type": "multipart/signed", "content": [
{"id": 2, "content-type": "multipart/mixed", "content": [ {"id": 2, "content-type": "multipart/mixed", "content": [
{"id": 3, "content-type": "message/rfc822", "content": [{"headers": {"Subject": "html message", "From": "Carl Worth <cworth@cworth.org>", "To": "cworth@cworth.org", "Date": "Fri, 05 Jan 2001 15:42:57 +0000"}, "body": [ {"id": 3, "content-type": "message/rfc822", "content": [{"headers": {"Subject": "html message", "From": "Carl Worth <cworth@cworth.org>", "To": "cworth@cworth.org", "Date": "Fri, 05 Jan 2001 15:42:57 +0000"}, "body": [