Before the change, notmuch used g_mime_content_type_to_string(3)
function to output Content-Type header value.  Turns out it outputs
only "type/subtype" part and ignores all parameters.  Also, if there
is no Content-Type header, default "text/plain" value is used.

JSON is supposed to be a "low-level" structured format and should not
add missing values or throw away information.  The patch changes
notmuch show to use unmodified Content-Type value for JSON format.
Also, no default value is added if the header is missing.

Corresponding changes to Emacs UI are made to handle full Content-Type
header values.  The header is parsed using MIME
`mail-header-parse-content-type' function.  All message part rendering
functions have access to full Content-Type value.  In particular, this
is important for `notmuch-show-mm-display-part-inline' which uses
`mm-display-part' to display parts that notmuch-show does not handle.

Expected results for the tests are updated accordingly.
---
 emacs/notmuch-show.el |   28 ++++++++++++++++++----------
 notmuch-show.c        |   14 ++++++++++++--
 test/crypto           |   23 ++++++++---------------
 test/json             |    6 +++---
 test/maildir-sync     |    1 -
 test/multipart        |   36 ++++++++++++++++++------------------
 6 files changed, 59 insertions(+), 49 deletions(-)

diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el
index d5c95d8..d2c2fa3 100644
--- a/emacs/notmuch-show.el
+++ b/emacs/notmuch-show.el
@@ -261,120 +261,120 @@ message at DEPTH in the current thread."
               (if (and header-value
                        (not (string-equal "" header-value)))
                   (notmuch-show-insert-header header header-value))))
          notmuch-message-headers)
     (save-excursion
       (save-restriction
        (narrow-to-region start (point-max))
        (run-hooks 'notmuch-show-markup-headers-hook)))))

 (define-button-type 'notmuch-show-part-button-type
   'action 'notmuch-show-part-button-action
   'follow-link t
   'face 'message-mml)

 (defun notmuch-show-insert-part-header (nth content-type declared-type 
&optional name comment)
   (let ((button))
     (setq button
          (insert-button
           (concat "[ "
                   (if name (concat name ": ") "")
-                  declared-type
-                  (if (not (string-equal declared-type content-type))
-                      (concat " (as " content-type ")")
+                  (car declared-type)
+                  (if (not (string-equal (car declared-type) (car 
content-type)))
+                      (concat " (as " (car content-type) ")")
                     "")
                   (or comment "")
                   " ]")
           :type 'notmuch-show-part-button-type
           :notmuch-part nth
           :notmuch-filename name))
     (insert "\n")
     ;; return button
     button))

 ;; Functions handling particular MIME parts.

 (defun notmuch-show-save-part (message-id nth &optional filename)
   (let ((process-crypto notmuch-show-process-crypto))
     (with-temp-buffer
       (setq notmuch-show-process-crypto process-crypto)
       ;; Always acquires the part via `notmuch part', even if it is
       ;; available in the JSON output.
       (insert (notmuch-show-get-bodypart-internal message-id nth))
       (let ((file (read-file-name
                   "Filename to save as: "
                   (or mailcap-download-directory "~/")
                   nil nil
                   filename)))
        ;; Don't re-compress .gz & al.  Arguably we should make
        ;; `file-name-handler-alist' nil, but that would chop
        ;; ange-ftp, which is reasonable to use here.
        (mm-write-region (point-min) (point-max) file nil nil nil 
'no-conversion t)))))

 (defun notmuch-show-mm-display-part-inline (msg part content-type content)
   "Use the mm-decode/mm-view functions to display a part in the
 current buffer, if possible."
   (let ((display-buffer (current-buffer)))
     (with-temp-buffer
       (insert content)
-      (let ((handle (mm-make-handle (current-buffer) (list content-type))))
+      (let ((handle (mm-make-handle (current-buffer) content-type)))
        (set-buffer display-buffer)
        (if (and (mm-inlinable-p handle)
                 (mm-inlined-p handle))
            (progn
              (mm-display-part handle)
              t)
          nil)))))

 (defvar notmuch-show-multipart/alternative-discouraged
   '(
     ;; Avoid HTML parts.
     "text/html"
     ;; multipart/related usually contain a text/html part and some associated 
graphics.
     "multipart/related"
     ))

 (defun notmuch-show-multipart/*-to-list (part)
-  (mapcar '(lambda (inner-part) (plist-get inner-part :content-type))
+  (mapcar '(lambda (inner-part) (car (notmuch-show-get-content-type 
inner-part)))
          (plist-get part :content)))

 (defun notmuch-show-multipart/alternative-choose (types)
   ;; Based on `mm-preferred-alternative-precedence'.
   (let ((seq types))
     (dolist (pref (reverse notmuch-show-multipart/alternative-discouraged))
       (dolist (elem (copy-sequence seq))
        (when (string-match pref elem)
          (setq seq (nconc (delete elem seq) (list elem))))))
     seq))

 (defun notmuch-show-insert-part-multipart/alternative (msg part content-type 
nth depth declared-type)
   (notmuch-show-insert-part-header nth declared-type content-type nil)
   (let ((chosen-type (car (notmuch-show-multipart/alternative-choose 
(notmuch-show-multipart/*-to-list part))))
        (inner-parts (plist-get part :content))
        (start (point)))
     ;; This inserts all parts of the chosen type rather than just one,
     ;; but it's not clear that this is the wrong thing to do - which
     ;; should be chosen if there are more than one that match?
     (mapc (lambda (inner-part)
-           (let ((inner-type (plist-get inner-part :content-type)))
+           (let ((inner-type (notmuch-show-get-content-type inner-part)))
              (if (or notmuch-show-all-multipart/alternative-parts
-                     (string= chosen-type inner-type))
+                     (string= chosen-type (car inner-type)))
                  (notmuch-show-insert-bodypart msg inner-part depth)
                (notmuch-show-insert-part-header (plist-get inner-part :id) 
inner-type inner-type nil " (not shown)"))))
          inner-parts)

     (when notmuch-show-indent-multipart
       (indent-rigidly start (point) 1)))
   t)

 (defun notmuch-show-setup-w3m ()
   "Instruct w3m how to retrieve content from a \"related\" part of a message."
   (interactive)
   (if (boundp 'w3m-cid-retrieve-function-alist)
     (unless (assq 'notmuch-show-mode w3m-cid-retrieve-function-alist)
       (push (cons 'notmuch-show-mode 'notmuch-show-w3m-cid-retrieve)
            w3m-cid-retrieve-function-alist)))
   (setq mm-inline-text-html-with-images t))

 (defvar w3m-current-buffer) ;; From `w3m.el'.
 (defvar notmuch-show-w3m-cid-store nil)
 (make-variable-buffer-local 'notmuch-show-w3m-cid-store)
@@ -557,41 +557,42 @@ current buffer, if possible."
              (set-buffer (get-file-buffer file))
              (setq result (buffer-substring (point-min) (point-max)))
              (set-buffer-modified-p nil)
              (kill-buffer (current-buffer))
              (delete-file file)
              result)))
   t)

 (defun notmuch-show-insert-part-application/octet-stream (msg part 
content-type nth depth declared-type)
   ;; If we can deduce a MIME type from the filename of the attachment,
   ;; do so and pass it on to the handler for that type.
   (if (plist-get part :filename)
       (let ((extension (file-name-extension (plist-get part :filename)))
            mime-type)
        (if extension
            (progn
              (mailcap-parse-mimetypes)
              (setq mime-type (mailcap-extension-to-mime extension))
              (if (and mime-type
                       (not (string-equal mime-type 
"application/octet-stream")))
-                 (notmuch-show-insert-bodypart-internal msg part mime-type nth 
depth content-type)
+                 (notmuch-show-insert-bodypart-internal msg part (list 
mime-type)
+                                                        nth depth content-type)
                nil))
          nil))))

 (defun notmuch-show-insert-part-application/* (msg part content-type nth depth 
declared-type
 )
   ;; do not render random "application" parts
   (notmuch-show-insert-part-header nth content-type declared-type (plist-get 
part :filename)))

 (defun notmuch-show-insert-part-*/* (msg part content-type nth depth 
declared-type)
   ;; This handler _must_ succeed - it is the handler of last resort.
   (notmuch-show-insert-part-header nth content-type declared-type (plist-get 
part :filename))
   (let ((content (notmuch-show-get-bodypart-content msg part nth)))
     (if content
        (notmuch-show-mm-display-part-inline msg part content-type content)))
   t)

 ;; Functions for determining how to handle MIME parts.

 (defun notmuch-show-split-content-type (content-type)
   (split-string content-type "/"))
@@ -618,51 +619,51 @@ current buffer, if possible."
 (defun notmuch-show-get-bodypart-internal (message-id part-number)
   (let ((args '("show" "--format=raw"))
        (part-arg (format "--part=%s" part-number)))
     (setq args (append args (list part-arg)))
     (if notmuch-show-process-crypto
        (setq args (append args '("--decrypt"))))
     (setq args (append args (list message-id)))
     (with-temp-buffer
       (let ((coding-system-for-read 'no-conversion))
        (progn
          (apply 'call-process (append (list notmuch-command nil (list t nil) 
nil) args))
          (buffer-string))))))

 (defun notmuch-show-get-bodypart-content (msg part nth)
   (or (plist-get part :content)
       (notmuch-show-get-bodypart-internal (concat "id:" (plist-get msg :id)) 
nth)))

 ;; 

 (defun notmuch-show-insert-bodypart-internal (msg part content-type nth depth 
declared-type)
-  (let ((handlers (notmuch-show-handlers-for content-type)))
+  (let ((handlers (notmuch-show-handlers-for (car content-type))))
     ;; Run the content handlers until one of them returns a non-nil
     ;; value.
     (while (and handlers
                (not (funcall (car handlers) msg part content-type nth depth 
declared-type)))
       (setq handlers (cdr handlers))))
   t)

 (defun notmuch-show-insert-bodypart (msg part depth)
   "Insert the body part PART at depth DEPTH in the current thread."
-  (let ((content-type (downcase (plist-get part :content-type)))
+  (let ((content-type (notmuch-show-get-content-type part))
        (nth (plist-get part :id)))
     (notmuch-show-insert-bodypart-internal msg part content-type nth depth 
content-type))
   ;; Some of the body part handlers leave point somewhere up in the
   ;; part, so we make sure that we're down at the end.
   (goto-char (point-max))
   ;; Ensure that the part ends with a carriage return.
   (if (not (bolp))
       (insert "\n")))

 (defun notmuch-show-insert-body (msg body depth)
   "Insert the body BODY at depth DEPTH in the current thread."
   (mapc '(lambda (part) (notmuch-show-insert-bodypart msg part depth)) body))

 (defun notmuch-show-make-symbol (type)
   (make-symbol (concat "notmuch-show-" type)))

 (defun notmuch-show-strip-re (string)
   (replace-regexp-in-string "\\([Rr]e: *\\)+" "" string))

 (defvar notmuch-show-previous-subject "")
@@ -1054,40 +1055,47 @@ All currently available key bindings:
   (save-excursion
     (notmuch-show-move-to-message-top)
     (get-text-property (point) :notmuch-message-properties)))

 (defun notmuch-show-set-prop (prop val &optional props)
   (let ((inhibit-read-only t)
        (props (or props
                   (notmuch-show-get-message-properties))))
     (plist-put props prop val)
     (notmuch-show-set-message-properties props)))

 (defun notmuch-show-get-prop (prop &optional props)
   (let ((props (or props
                   (notmuch-show-get-message-properties))))
     (plist-get props prop)))

 (defun notmuch-show-get-message-id ()
   "Return the message id of the current message."
   (concat "id:\"" (notmuch-show-get-prop :id) "\""))

+(defun notmuch-show-get-content-type (&optional props)
+  "Return parsed Content-Type of the given message, or part, or
+current message if no `props` is given.  If there is no
+Content-Type header, it defaults to \"text/plain\"."
+  (mail-header-parse-content-type (or (notmuch-show-get-prop :content-type 
props)
+                                     "text/plain")))
+
 ;; dme: Would it make sense to use a macro for many of these?

 (defun notmuch-show-get-filename ()
   "Return the filename of the current message."
   (notmuch-show-get-prop :filename))

 (defun notmuch-show-get-header (header)
   "Return the named header of the current message, if any."
   (plist-get (notmuch-show-get-prop :headers) header))

 (defun notmuch-show-get-cc ()
   (notmuch-show-get-header :Cc))

 (defun notmuch-show-get-date ()
   (notmuch-show-get-header :Date))

 (defun notmuch-show-get-from ()
   (notmuch-show-get-header :From))

 (defun notmuch-show-get-subject ()
diff --git a/notmuch-show.c b/notmuch-show.c
index 603992a..da3e87f 100644
--- a/notmuch-show.c
+++ b/notmuch-show.c
@@ -3,40 +3,42 @@
  * Copyright ? 2009 Carl Worth
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation, either version 3 of the License, or
  * (at your option) any later version.
  *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
  * along with this program.  If not, see http://www.gnu.org/licenses/ .
  *
  * Author: Carl Worth <cworth at cworth.org>
  */

 #include "notmuch-client.h"

+static const char HEADER_CONTENT_TYPE[] = "Content-Type";
+
 static void
 format_message_text (unused (const void *ctx),
                     notmuch_message_t *message,
                     int indent);
 static void
 format_headers_text (const void *ctx,
                     notmuch_message_t *message);

 static void
 format_headers_message_part_text (GMimeMessage *message);

 static void
 format_part_start_text (GMimeObject *part,
                        int *part_count);

 static void
 format_part_content_text (GMimeObject *part);

 static void
 format_part_end_text (GMimeObject *part);
@@ -640,42 +642,50 @@ format_part_sigstatus_json (const GMimeSignatureValidity* 
validity)
        }

        printf ("}");
        signer = signer->next;
     }

     printf ("]");

     talloc_free (ctx_quote);
 }

 static void
 format_part_content_json (GMimeObject *part)
 {
     GMimeContentType *content_type = g_mime_object_get_content_type 
(GMIME_OBJECT (part));
     GMimeStream *stream_memory = g_mime_stream_mem_new ();
     const char *cid = g_mime_object_get_content_id (part);
     void *ctx = talloc_new (NULL);
     GByteArray *part_content;

-    printf (", \"content-type\": %s",
-           json_quote_str (ctx, g_mime_content_type_to_string (content_type)));
+    {
+       /* Output full Content-Type header value,
+        * g_mime_content_type_to_string(3) does not include
+        * parameters.  Content-Type header may be missing,
+        * g_mime_object_get_content_type(3) defaults to "text/plain"
+        * in this case. */
+       const char *const h = g_mime_object_get_header (part, 
HEADER_CONTENT_TYPE);
+       if (h)
+           printf (", \"content-type\": %s", json_quote_str (ctx, h));
+    }

     if (cid != NULL)
            printf(", \"content-id\": %s", json_quote_str (ctx, cid));

     if (GMIME_IS_PART (part))
     {
        const char *filename = g_mime_part_get_filename (GMIME_PART (part));
        if (filename)
            printf (", \"filename\": %s", json_quote_str (ctx, filename));
     }

     if (g_mime_content_type_is_type (content_type, "text", "*") &&
        !g_mime_content_type_is_type (content_type, "text", "html"))
     {
        show_text_part_content (part, stream_memory);
        part_content = g_mime_stream_mem_get_byte_array (GMIME_STREAM_MEM 
(stream_memory));

        printf (", \"content\": %s", json_quote_chararray (ctx, (char *) 
part_content->data, part_content->len));
     }
     else if (g_mime_content_type_is_type (content_type, "multipart", "*"))
diff --git a/test/crypto b/test/crypto
index 0af4aa8..b923d22 100755
--- a/test/crypto
+++ b/test/crypto
@@ -40,111 +40,108 @@ test_expect_success 'emacs delivery of signed message' \
 test_begin_subtest "signature verification"
 output=$(notmuch show --format=json --verify subject:"test signed message 001" 
\
     | notmuch_json_show_sanitize \
     | sed -e 's|"created": [1234567890]*|"created": 946728000|')
 expected='[[[{"id": "XXXXX",
  "match": true,
  "filename": "YYYYY",
  "timestamp": 946728000,
  "date_relative": "2000-01-01",
  "tags": ["inbox","signed"],
  "headers": {"Subject": "test signed message 001",
  "From": "Notmuch Test Suite <test_suite at notmuchmail.org>",
  "To": "test_suite at notmuchmail.org",
  "Cc": "",
  "Bcc": "",
  "Date": "01 Jan 2000 12:00:00 -0000"},
  "body": [{"id": 1,
  "sigstatus": [{"status": "good",
  "fingerprint": "'$FINGERPRINT'",
  "created": 946728000}],
- "content-type": "multipart/signed",
+ "content-type": "multipart/signed; boundary=\"=-=-=\";\tmicalg=pgp-sha1; 
protocol=\"application/pgp-signature\"",
  "content": [{"id": 2,
- "content-type": "text/plain",
  "content": "This is a test signed message.\n"},
  {"id": 3,
  "content-type": "application/pgp-signature"}]}]},
  []]]]'
 test_expect_equal \
     "$output" \
     "$expected"

 test_begin_subtest "signature verification with full owner trust"
 # give the key full owner trust
 echo "${FINGERPRINT}:6:" | gpg --no-tty --import-ownertrust 
>>"$GNUPGHOME"/trust.log 2>&1
 gpg --no-tty --check-trustdb >>"$GNUPGHOME"/trust.log 2>&1
 output=$(notmuch show --format=json --verify subject:"test signed message 001" 
\
     | notmuch_json_show_sanitize \
     | sed -e 's|"created": [1234567890]*|"created": 946728000|')
 expected='[[[{"id": "XXXXX",
  "match": true,
  "filename": "YYYYY",
  "timestamp": 946728000,
  "date_relative": "2000-01-01",
  "tags": ["inbox","signed"],
  "headers": {"Subject": "test signed message 001",
  "From": "Notmuch Test Suite <test_suite at notmuchmail.org>",
  "To": "test_suite at notmuchmail.org",
  "Cc": "",
  "Bcc": "",
  "Date": "01 Jan 2000 12:00:00 -0000"},
  "body": [{"id": 1,
  "sigstatus": [{"status": "good",
  "fingerprint": "'$FINGERPRINT'",
  "created": 946728000,
  "userid": " Notmuch Test Suite <test_suite at notmuchmail.org> (INSECURE!)"}],
- "content-type": "multipart/signed",
+ "content-type": "multipart/signed; boundary=\"=-=-=\";\tmicalg=pgp-sha1; 
protocol=\"application/pgp-signature\"",
  "content": [{"id": 2,
- "content-type": "text/plain",
  "content": "This is a test signed message.\n"},
  {"id": 3,
  "content-type": "application/pgp-signature"}]}]},
  []]]]'
 test_expect_equal \
     "$output" \
     "$expected"

 test_begin_subtest "signature verification with signer key unavailable"
 # move the gnupghome temporarily out of the way
 mv "${GNUPGHOME}"{,.bak}
 output=$(notmuch show --format=json --verify subject:"test signed message 001" 
\
     | notmuch_json_show_sanitize \
     | sed -e 's|"created": [1234567890]*|"created": 946728000|')
 expected='[[[{"id": "XXXXX",
  "match": true,
  "filename": "YYYYY",
  "timestamp": 946728000,
  "date_relative": "2000-01-01",
  "tags": ["inbox","signed"],
  "headers": {"Subject": "test signed message 001",
  "From": "Notmuch Test Suite <test_suite at notmuchmail.org>",
  "To": "test_suite at notmuchmail.org",
  "Cc": "",
  "Bcc": "",
  "Date": "01 Jan 2000 12:00:00 -0000"},
  "body": [{"id": 1,
  "sigstatus": [{"status": "error",
  "keyid": "'$(echo $FINGERPRINT | cut -c 25-)'",
  "errors": 2}],
- "content-type": "multipart/signed",
+ "content-type": "multipart/signed; boundary=\"=-=-=\";\tmicalg=pgp-sha1; 
protocol=\"application/pgp-signature\"",
  "content": [{"id": 2,
- "content-type": "text/plain",
  "content": "This is a test signed message.\n"},
  {"id": 3,
  "content-type": "application/pgp-signature"}]}]},
  []]]]'
 test_expect_equal \
     "$output" \
     "$expected"
 mv "${GNUPGHOME}"{.bak,}

 # create a test encrypted message with attachment
 cat <<EOF >TESTATTACHMENT
 This is a test file.
 EOF
 test_expect_success 'emacs delivery of encrypted message with attachment' \
 'emacs_deliver_message \
     "test encrypted message 001" \
     "This is a test encrypted message.\n" \
     "(mml-attach-file \"TESTATTACHMENT\") (mml-secure-message-encrypt)"'

 test_begin_subtest "decryption, --format=text"
@@ -181,138 +178,135 @@ test_expect_equal \

 test_begin_subtest "decryption, --format=json"
 output=$(notmuch show --format=json --decrypt subject:"test encrypted message 
001" \
     | notmuch_json_show_sanitize \
     | sed -e 's|"created": [1234567890]*|"created": 946728000|')
 expected='[[[{"id": "XXXXX",
  "match": true,
  "filename": "YYYYY",
  "timestamp": 946728000,
  "date_relative": "2000-01-01",
  "tags": ["encrypted","inbox"],
  "headers": {"Subject": "test encrypted message 001",
  "From": "Notmuch Test Suite <test_suite at notmuchmail.org>",
  "To": "test_suite at notmuchmail.org",
  "Cc": "",
  "Bcc": "",
  "Date": "01 Jan 2000 12:00:00 -0000"},
  "body": [{"id": 1,
  "encstatus": [{"status": "good"}],
  "sigstatus": [],
- "content-type": "multipart/encrypted",
+ "content-type": "multipart/encrypted; 
boundary=\"==-=-=\";\tprotocol=\"application/pgp-encrypted\"",
  "content": [{"id": 2,
  "content-type": "application/pgp-encrypted"},
  {"id": 3,
- "content-type": "multipart/mixed",
+ "content-type": "multipart/mixed; boundary=\"=-=-=\"",
  "content": [{"id": 4,
- "content-type": "text/plain",
  "content": "This is a test encrypted message.\n"},
  {"id": 5,
  "content-type": "application/octet-stream",
  "filename": "TESTATTACHMENT"}]}]}]},
  []]]]'
 test_expect_equal \
     "$output" \
     "$expected"

 test_begin_subtest "decryption, --format=json, --part=4"
 output=$(notmuch show --format=json --part=4 --decrypt subject:"test encrypted 
message 001" \
     | notmuch_json_show_sanitize \
     | sed -e 's|"created": [1234567890]*|"created": 946728000|')
 expected='{"id": 4,
- "content-type": "text/plain",
  "content": "This is a test encrypted message.\n"}'
 test_expect_equal \
     "$output" \
     "$expected"

 test_begin_subtest "decrypt attachment (--part=5 --format=raw)"
 notmuch show \
     --format=raw \
     --part=5 \
     --decrypt \
     subject:"test encrypted message 001" >OUTPUT
 test_expect_equal_file OUTPUT TESTATTACHMENT

 test_begin_subtest "decryption failure with missing key"
 mv "${GNUPGHOME}"{,.bak}
 output=$(notmuch show --format=json --decrypt subject:"test encrypted message 
001" \
     | notmuch_json_show_sanitize \
     | sed -e 's|"created": [1234567890]*|"created": 946728000|')
 expected='[[[{"id": "XXXXX",
  "match": true,
  "filename": "YYYYY",
  "timestamp": 946728000,
  "date_relative": "2000-01-01",
  "tags": ["encrypted","inbox"],
  "headers": {"Subject": "test encrypted message 001",
  "From": "Notmuch Test Suite <test_suite at notmuchmail.org>",
  "To": "test_suite at notmuchmail.org",
  "Cc": "",
  "Bcc": "",
  "Date": "01 Jan 2000 12:00:00 -0000"},
  "body": [{"id": 1,
  "encstatus": [{"status": "bad"}],
- "content-type": "multipart/encrypted",
+ "content-type": "multipart/encrypted; 
boundary=\"==-=-=\";\tprotocol=\"application/pgp-encrypted\"",
  "content": [{"id": 2,
  "content-type": "application/pgp-encrypted"},
  {"id": 3,
  "content-type": "application/octet-stream"}]}]},
  []]]]'
 test_expect_equal \
     "$output" \
     "$expected"
 mv "${GNUPGHOME}"{.bak,}

 test_expect_success 'emacs delivery of encrypted + signed message' \
 'emacs_deliver_message \
     "test encrypted message 002" \
     "This is another test encrypted message.\n" \
     "(mml-secure-message-sign-encrypt)"'

 test_begin_subtest "decryption + signature verification"
 output=$(notmuch show --format=json --decrypt subject:"test encrypted message 
002" \
     | notmuch_json_show_sanitize \
     | sed -e 's|"created": [1234567890]*|"created": 946728000|')
 expected='[[[{"id": "XXXXX",
  "match": true,
  "filename": "YYYYY",
  "timestamp": 946728000,
  "date_relative": "2000-01-01",
  "tags": ["encrypted","inbox"],
  "headers": {"Subject": "test encrypted message 002",
  "From": "Notmuch Test Suite <test_suite at notmuchmail.org>",
  "To": "test_suite at notmuchmail.org",
  "Cc": "",
  "Bcc": "",
  "Date": "01 Jan 2000 12:00:00 -0000"},
  "body": [{"id": 1,
  "encstatus": [{"status": "good"}],
  "sigstatus": [{"status": "good",
  "fingerprint": "'$FINGERPRINT'",
  "created": 946728000,
  "userid": " Notmuch Test Suite <test_suite at notmuchmail.org> (INSECURE!)"}],
- "content-type": "multipart/encrypted",
+ "content-type": "multipart/encrypted; 
boundary=\"=-=-=\";\tprotocol=\"application/pgp-encrypted\"",
  "content": [{"id": 2,
  "content-type": "application/pgp-encrypted"},
  {"id": 3,
- "content-type": "text/plain",
  "content": "This is another test encrypted message.\n"}]}]},
  []]]]'
 test_expect_equal \
     "$output" \
     "$expected"

 test_begin_subtest "reply to encrypted message"
 output=$(notmuch reply --decrypt subject:"test encrypted message 002" \
     | grep -v -e '^In-Reply-To:' -e '^References:')
 expected='From: Notmuch Test Suite <test_suite at notmuchmail.org>
 Subject: Re: test encrypted message 002

 On 01 Jan 2000 12:00:00 -0000, Notmuch Test Suite <test_suite at 
notmuchmail.org> wrote:
 > This is another test encrypted message.'
 test_expect_equal \
     "$output" \
     "$expected"

 test_begin_subtest "signature verification with revoked key"
 # generate revocation certificate and load it to revoke key
@@ -327,32 +321,31 @@ y
     | gpg --no-tty --quiet --import
 output=$(notmuch show --format=json --verify subject:"test signed message 001" 
\
     | notmuch_json_show_sanitize \
     | sed -e 's|"created": [1234567890]*|"created": 946728000|')
 expected='[[[{"id": "XXXXX",
  "match": true,
  "filename": "YYYYY",
  "timestamp": 946728000,
  "date_relative": "2000-01-01",
  "tags": ["inbox","signed"],
  "headers": {"Subject": "test signed message 001",
  "From": "Notmuch Test Suite <test_suite at notmuchmail.org>",
  "To": "test_suite at notmuchmail.org",
  "Cc": "",
  "Bcc": "",
  "Date": "01 Jan 2000 12:00:00 -0000"},
  "body": [{"id": 1,
  "sigstatus": [{"status": "error",
  "keyid": "6D92612D94E46381",
  "errors": 8}],
- "content-type": "multipart/signed",
+ "content-type": "multipart/signed; boundary=\"=-=-=\";\tmicalg=pgp-sha1; 
protocol=\"application/pgp-signature\"",
  "content": [{"id": 2,
- "content-type": "text/plain",
  "content": "This is a test signed message.\n"},
  {"id": 3,
  "content-type": "application/pgp-signature"}]}]},
  []]]]'
 test_expect_equal \
     "$output" \
     "$expected"

 test_done
diff --git a/test/json b/test/json
index 592b068..64f35cf 100755
--- a/test/json
+++ b/test/json
@@ -1,50 +1,50 @@
 #!/usr/bin/env bash
 test_description="--format=json output"
 . ./test-lib.sh

 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\""
 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 at notmuchmail.org>\", \"To\": \"Notmuch Test Suite 
<test_suite at 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 at notmuchmail.org>\", \"To\": \"Notmuch Test Suite 
<test_suite at notmuchmail.org>\", \"Cc\": \"\", \"Bcc\": \"\", \"Date\": 
\"Sat, 01 Jan 2000 12:00:00 -0000\"}, \"body\": [{\"id\": 1, \"content\": 
\"json-show-message\n\"}]}, []]]]"

 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\""
 output=$(notmuch search --format=json "json-search-message" | 
notmuch_search_sanitize)
 test_expect_equal "$output" "[{\"thread\": \"XXX\",
 \"timestamp\": 946728000,
 \"matched\": 1,
 \"total\": 1,
 \"authors\": \"Notmuch Test Suite\",
 \"subject\": \"json-search-subject\",
 \"tags\": [\"inbox\", \"unread\"]}]"

 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\""
 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 at notmuchmail.org>\", \"To\": \"Notmuch Test Suite 
<test_suite at 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 at notmuchmail.org>\", \"To\": \"Notmuch Test Suite 
<test_suite at notmuchmail.org>\", \"Cc\": \"\", \"Bcc\": \"\", \"Date\": 
\"Sat, 01 Jan 2000 12:00:00 -0000\"}, \"body\": [{\"id\": 1, \"content\": 
\"js?n-show-m?ssage\n\"}]}, []]]]"

 test_begin_subtest "Show message: json, inline attachment filename"
 subject='json-show-inline-attachment-filename'
 id="json-show-inline-attachment-filename at notmuchmail.org"
 emacs_deliver_message \
     "$subject" \
     'This is a test message with inline attachment with a filename' \
     "(mml-attach-file \"$TEST_DIRECTORY/README\" nil nil \"inline\")
      (message-goto-eoh)
      (insert \"Message-ID: <$id>\n\")"
 output=$(notmuch show --format=json "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 at notmuchmail.org>\", \"To\": 
\"test_suite at 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 at notmuchmail.org>\", \"To\": 
\"test_suite at notmuchmail.org\", \"Cc\": \"\", \"Bcc\": \"\", \"Date\": \"01 
Jan 2000 12:00:00 -0000\"}, \"body\": [{\"id\": 1, \"content-type\": 
\"multipart/mixed; boundary=\\\"=-=-=\\\"\", \"content\": [{\"id\": 2, 
\"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"
 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\""
 output=$(notmuch search --format=json "js?n-search-m?ssage" | 
notmuch_search_sanitize)
 test_expect_equal "$output" "[{\"thread\": \"XXX\",
 \"timestamp\": 946728000,
 \"matched\": 1,
 \"total\": 1,
 \"authors\": \"Notmuch Test Suite\",
 \"subject\": \"json-search-utf8-body-s?bj?ct\",
 \"tags\": [\"inbox\", \"unread\"]}]"

 test_done
diff --git a/test/maildir-sync b/test/maildir-sync
index a60854f..c7ca22f 100755
--- a/test/maildir-sync
+++ b/test/maildir-sync
@@ -41,41 +41,40 @@ add_message [subject]='"Adding replied tag"' 
[filename]='adding-replied-tag:2,S'
 notmuch tag +replied subject:"Adding replied tag"
 output=$(cd ${MAIL_DIR}/cur; ls -1 adding-replied*)
 test_expect_equal "$output" "adding-replied-tag:2,RS"

 test_begin_subtest "notmuch show works with renamed file (without notmuch new)"
 output=$(notmuch show --format=json id:${gen_msg_id} | filter_show_json)
 test_expect_equal "$output" '[[[{"id": "adding-replied-tag at 
notmuch-test-suite",
 "match": true,
 "filename": "MAIL_DIR/cur/adding-replied-tag:2,RS",
 "timestamp": 978709437,
 "date_relative": "2001-01-05",
 "tags": ["inbox","replied"],
 "headers": {"Subject": "Adding replied tag",
 "From": "Notmuch Test Suite <test_suite at notmuchmail.org>",
 "To": "Notmuch Test Suite <test_suite at notmuchmail.org>",
 "Cc": "",
 "Bcc": "",
 "Date": "Tue,
 05 Jan 2001 15:43:57 -0000"},
 "body": [{"id": 1,
-"content-type": "text/plain",
 "content": "This is just a test message (#3)\n"}]},
 []]]]'

 test_expect_success 'notmuch reply works with renamed file (without notmuch 
new)' 'notmuch reply id:${gen_msg_id}'

 test_begin_subtest "notmuch new detects no file rename after tag->flag 
synchronization"
 output=$(NOTMUCH_NEW)
 test_expect_equal "$output" "No new mail."

 test_begin_subtest "When read, message moved from new to cur"
 add_message [subject]='"Message to move to cur"' [date]='"Sat, 01 Jan 2000 
12:00:00 -0000"' [filename]='message-to-move-to-cur' [dir]=new
 notmuch tag -unread subject:"Message to move to cur"
 output=$(cd "$MAIL_DIR/cur"; ls message-to-move*)
 test_expect_equal "$output" "message-to-move-to-cur:2,S"

 test_begin_subtest "No rename should be detected by notmuch new"
 output=$(NOTMUCH_NEW)
 test_expect_equal "$output" "No new mail."
 # (*) If notmuch new was not run we've got "Processed 1 file in almost
 # no time" here. The reason is that removing unread tag in a previous
diff --git a/test/multipart b/test/multipart
index f83526b..ca4db71 100755
--- a/test/multipart
+++ b/test/multipart
@@ -306,140 +306,140 @@ test_expect_equal_file OUTPUT EXPECTED

 test_begin_subtest "--format=text --part=9, pgp signature (unverified)"
 notmuch show --format=text --part=9 'id:87liy5ap00.fsf at 
yoom.home.cworth.org' >OUTPUT
 cat <<EOF >EXPECTED
 part{ ID: 9, Content-type: application/pgp-signature
 Non-text part: application/pgp-signature
 part}
 EOF
 test_expect_equal_file OUTPUT EXPECTED

 test_expect_success \
     "--format=text --part=8, no part, expect error" \
     "notmuch show --format=text --part=8 'id:87liy5ap00.fsf at 
yoom.home.cworth.org'"

 test_begin_subtest "--format=json --part=0, full message"
 notmuch show --format=json --part=0 'id:87liy5ap00.fsf at 
yoom.home.cworth.org' | sed 's|{"id":|\n{"id":|g' >OUTPUT
 echo >>OUTPUT # expect *no* newline at end of output
 cat <<EOF >EXPECTED

 {"id": "87liy5ap00.fsf at 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 at cworth.org>", "To": "cworth 
at cworth.org", "Cc": "", "Bcc": "", "Date": "Fri, 05 Jan 2001 15:43:57 
+0000"}, "body": [
-{"id": 1, "content-type": "multipart/signed", "content": [
-{"id": 2, "content-type": "multipart/mixed", "content": [
+{"id": 1, "content-type": "multipart/signed; 
boundary=\"==-=-=\";\tmicalg=pgp-sha1; protocol=\"application/pgp-signature\"", 
"content": [
+{"id": 2, "content-type": "multipart/mixed; boundary=\"=-=-=\"", "content": [
 {"id": 3, "content-type": "message/rfc822", "content": [{"headers": {"From": 
"Carl Worth <cworth at cworth.org>", "To": "cworth at cworth.org", "Subject": 
"html message", "Date": "Fri, 05 Jan 2001 15:42:57 +0000"}, "body": [
-{"id": 4, "content-type": "multipart/alternative", "content": [
+{"id": 4, "content-type": "multipart/alternative; boundary=\"==-=-==\"", 
"content": [
 {"id": 5, "content-type": "text/html"}, 
 {"id": 6, "content-type": "text/plain", "content": "This is an embedded 
message, with a multipart/alternative part.\n"}]}]}]}, 
-{"id": 7, "content-type": "text/plain", "filename": "attachment", "content": 
"This is a text attachment.\n"}, 
-{"id": 8, "content-type": "text/plain", "content": "And this message is 
signed.\n\n-Carl\n"}]}, 
+{"id": 7, "filename": "attachment", "content": "This is a text 
attachment.\n"}, 
+{"id": 8, "content": "And this message is signed.\n\n-Carl\n"}]}, 
 {"id": 9, "content-type": "application/pgp-signature"}]}]}
 EOF
 test_expect_equal_file OUTPUT EXPECTED

 test_begin_subtest "--format=json --part=1, message body"
 notmuch show --format=json --part=1 'id:87liy5ap00.fsf at 
yoom.home.cworth.org' | sed 's|{"id":|\n{"id":|g' >OUTPUT
 echo >>OUTPUT # expect *no* newline at end of output
 cat <<EOF >EXPECTED

-{"id": 1, "content-type": "multipart/signed", "content": [
-{"id": 2, "content-type": "multipart/mixed", "content": [
+{"id": 1, "content-type": "multipart/signed; 
boundary=\"==-=-=\";\tmicalg=pgp-sha1; protocol=\"application/pgp-signature\"", 
"content": [
+{"id": 2, "content-type": "multipart/mixed; boundary=\"=-=-=\"", "content": [
 {"id": 3, "content-type": "message/rfc822", "content": [{"headers": {"From": 
"Carl Worth <cworth at cworth.org>", "To": "cworth at cworth.org", "Subject": 
"html message", "Date": "Fri, 05 Jan 2001 15:42:57 +0000"}, "body": [
-{"id": 4, "content-type": "multipart/alternative", "content": [
+{"id": 4, "content-type": "multipart/alternative; boundary=\"==-=-==\"", 
"content": [
 {"id": 5, "content-type": "text/html"}, 
 {"id": 6, "content-type": "text/plain", "content": "This is an embedded 
message, with a multipart/alternative part.\n"}]}]}]}, 
-{"id": 7, "content-type": "text/plain", "filename": "attachment", "content": 
"This is a text attachment.\n"}, 
-{"id": 8, "content-type": "text/plain", "content": "And this message is 
signed.\n\n-Carl\n"}]}, 
+{"id": 7, "filename": "attachment", "content": "This is a text 
attachment.\n"}, 
+{"id": 8, "content": "And this message is signed.\n\n-Carl\n"}]}, 
 {"id": 9, "content-type": "application/pgp-signature"}]}
 EOF
 test_expect_equal_file OUTPUT EXPECTED

 test_begin_subtest "--format=json --part=2, multipart/mixed"
 notmuch show --format=json --part=2 'id:87liy5ap00.fsf at 
yoom.home.cworth.org' | sed 's|{"id":|\n{"id":|g' >OUTPUT
 echo >>OUTPUT # expect *no* newline at end of output
 cat <<EOF >EXPECTED

-{"id": 2, "content-type": "multipart/mixed", "content": [
+{"id": 2, "content-type": "multipart/mixed; boundary=\"=-=-=\"", "content": [
 {"id": 3, "content-type": "message/rfc822", "content": [{"headers": {"From": 
"Carl Worth <cworth at cworth.org>", "To": "cworth at cworth.org", "Subject": 
"html message", "Date": "Fri, 05 Jan 2001 15:42:57 +0000"}, "body": [
-{"id": 4, "content-type": "multipart/alternative", "content": [
+{"id": 4, "content-type": "multipart/alternative; boundary=\"==-=-==\"", 
"content": [
 {"id": 5, "content-type": "text/html"}, 
 {"id": 6, "content-type": "text/plain", "content": "This is an embedded 
message, with a multipart/alternative part.\n"}]}]}]}, 
-{"id": 7, "content-type": "text/plain", "filename": "attachment", "content": 
"This is a text attachment.\n"}, 
-{"id": 8, "content-type": "text/plain", "content": "And this message is 
signed.\n\n-Carl\n"}]}
+{"id": 7, "filename": "attachment", "content": "This is a text 
attachment.\n"}, 
+{"id": 8, "content": "And this message is signed.\n\n-Carl\n"}]}
 EOF
 test_expect_equal_file OUTPUT EXPECTED

 test_begin_subtest "--format=json --part=3, rfc822 part"
 notmuch show --format=json --part=3 'id:87liy5ap00.fsf at 
yoom.home.cworth.org' | sed 's|{"id":|\n{"id":|g' >OUTPUT
 echo >>OUTPUT # expect *no* newline at end of output
 cat <<EOF >EXPECTED

 {"id": 3, "content-type": "message/rfc822", "content": [{"headers": {"From": 
"Carl Worth <cworth at cworth.org>", "To": "cworth at cworth.org", "Subject": 
"html message", "Date": "Fri, 05 Jan 2001 15:42:57 +0000"}, "body": [
-{"id": 4, "content-type": "multipart/alternative", "content": [
+{"id": 4, "content-type": "multipart/alternative; boundary=\"==-=-==\"", 
"content": [
 {"id": 5, "content-type": "text/html"}, 
 {"id": 6, "content-type": "text/plain", "content": "This is an embedded 
message, with a multipart/alternative part.\n"}]}]}]}
 EOF
 test_expect_equal_file OUTPUT EXPECTED

 test_begin_subtest "--format=json --part=4, rfc822's multipart/alternative"
 notmuch show --format=json --part=4 'id:87liy5ap00.fsf at 
yoom.home.cworth.org' | sed 's|{"id":|\n{"id":|g' >OUTPUT
 echo >>OUTPUT # expect *no* newline at end of output
 cat <<EOF >EXPECTED

-{"id": 4, "content-type": "multipart/alternative", "content": [
+{"id": 4, "content-type": "multipart/alternative; boundary=\"==-=-==\"", 
"content": [
 {"id": 5, "content-type": "text/html"}, 
 {"id": 6, "content-type": "text/plain", "content": "This is an embedded 
message, with a multipart/alternative part.\n"}]}
 EOF
 test_expect_equal_file OUTPUT EXPECTED

 test_begin_subtest "--format=json --part=5, rfc822's html part"
 notmuch show --format=json --part=5 'id:87liy5ap00.fsf at 
yoom.home.cworth.org' | sed 's|{"id":|\n{"id":|g' >OUTPUT
 echo >>OUTPUT # expect *no* newline at end of output
 cat <<EOF >EXPECTED

 {"id": 5, "content-type": "text/html"}
 EOF
 test_expect_equal_file OUTPUT EXPECTED

 test_begin_subtest "--format=json --part=6, rfc822's text part"
 notmuch show --format=json --part=6 'id:87liy5ap00.fsf at 
yoom.home.cworth.org' | sed 's|{"id":|\n{"id":|g' >OUTPUT
 echo >>OUTPUT # expect *no* newline at end of output
 cat <<EOF >EXPECTED

 {"id": 6, "content-type": "text/plain", "content": "This is an embedded 
message, with a multipart/alternative part.\n"}
 EOF
 test_expect_equal_file OUTPUT EXPECTED

 test_begin_subtest "--format=json --part=7, inline attachment"
 notmuch show --format=json --part=7 'id:87liy5ap00.fsf at 
yoom.home.cworth.org' | sed 's|{"id":|\n{"id":|g' >OUTPUT
 echo >>OUTPUT # expect *no* newline at end of output
 cat <<EOF >EXPECTED

-{"id": 7, "content-type": "text/plain", "filename": "attachment", "content": 
"This is a text attachment.\n"}
+{"id": 7, "filename": "attachment", "content": "This is a text attachment.\n"}
 EOF
 test_expect_equal_file OUTPUT EXPECTED

 test_begin_subtest "--format=json --part=8, plain text part"
 notmuch show --format=json --part=8 'id:87liy5ap00.fsf at 
yoom.home.cworth.org' | sed 's|{"id":|\n{"id":|g' >OUTPUT
 echo >>OUTPUT # expect *no* newline at end of output
 cat <<EOF >EXPECTED

-{"id": 8, "content-type": "text/plain", "content": "And this message is 
signed.\n\n-Carl\n"}
+{"id": 8, "content": "And this message is signed.\n\n-Carl\n"}
 EOF
 test_expect_equal_file OUTPUT EXPECTED

 test_begin_subtest "--format=json --part=9, pgp signature (unverified)"
 notmuch show --format=json --part=9 'id:87liy5ap00.fsf at 
yoom.home.cworth.org' | sed 's|{"id":|\n{"id":|g' >OUTPUT
 echo >>OUTPUT # expect *no* newline at end of output
 cat <<EOF >EXPECTED

 {"id": 9, "content-type": "application/pgp-signature"}
 EOF
 test_expect_equal_file OUTPUT EXPECTED

 test_expect_success \
     "--format=json --part=10, no part, expect error" \
     "notmuch show --format=json --part=10 'id:87liy5ap00.fsf at 
yoom.home.cworth.org'"

 test_begin_subtest "--format=raw"
 notmuch show --format=raw 'id:87liy5ap00.fsf at yoom.home.cworth.org' >OUTPUT
 test_expect_equal_file OUTPUT "${MAIL_DIR}"/multipart

-- 
1.7.7.3

Reply via email to