1 Return-Path: <dmitry.kurochkin@gmail.com>
\r
2 X-Original-To: notmuch@notmuchmail.org
\r
3 Delivered-To: notmuch@notmuchmail.org
\r
4 Received: from localhost (localhost [127.0.0.1])
\r
5 by olra.theworths.org (Postfix) with ESMTP id 3D9FF429E25
\r
6 for <notmuch@notmuchmail.org>; Fri, 18 Nov 2011 15:45:28 -0800 (PST)
\r
7 X-Virus-Scanned: Debian amavisd-new at olra.theworths.org
\r
11 X-Spam-Status: No, score=-0.799 tagged_above=-999 required=5
\r
12 tests=[DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1,
\r
13 FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_LOW=-0.7] autolearn=disabled
\r
14 Received: from olra.theworths.org ([127.0.0.1])
\r
15 by localhost (olra.theworths.org [127.0.0.1]) (amavisd-new, port 10024)
\r
16 with ESMTP id 5dVuWTj9TDEK for <notmuch@notmuchmail.org>;
\r
17 Fri, 18 Nov 2011 15:45:25 -0800 (PST)
\r
18 Received: from mail-bw0-f53.google.com (mail-bw0-f53.google.com
\r
19 [209.85.214.53]) (using TLSv1 with cipher RC4-SHA (128/128 bits))
\r
20 (No client certificate requested)
\r
21 by olra.theworths.org (Postfix) with ESMTPS id A88FE431FD0
\r
22 for <notmuch@notmuchmail.org>; Fri, 18 Nov 2011 15:45:24 -0800 (PST)
\r
23 Received: by bkaq10 with SMTP id q10so4401847bka.26
\r
24 for <notmuch@notmuchmail.org>; Fri, 18 Nov 2011 15:45:23 -0800 (PST)
\r
25 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma;
\r
26 h=from:to:subject:date:message-id:x-mailer:mime-version:content-type
\r
27 :content-transfer-encoding;
\r
28 bh=iPCTQynsTs3zP2Tx9a2FU7l6GyheJeBxqxox+HandH8=;
\r
29 b=VNdWIn7gJXo9BINAwGaVivtGQ4LvLncF9FnmJQvjrKWgIcVL7+WblRN7681w/J2E9H
\r
30 LptQN5R1f/jzDDgzJe0XwWws2JgAph+UKycr2W6Kb83Ds3c7YQpjYil4Hc9klnAE2wWN
\r
31 vHKDMaAE8nnYbH4S1jq92R2jSASv86E2Urrxs=
\r
32 Received: by 10.204.141.2 with SMTP id k2mr2087713bku.81.1321659922273;
\r
33 Fri, 18 Nov 2011 15:45:22 -0800 (PST)
\r
34 Received: from localhost ([91.144.186.21])
\r
35 by mx.google.com with ESMTPS id q6sm1874625bka.6.2011.11.18.15.45.20
\r
36 (version=TLSv1/SSLv3 cipher=OTHER);
\r
37 Fri, 18 Nov 2011 15:45:21 -0800 (PST)
\r
38 From: Dmitry Kurochkin <dmitry.kurochkin@gmail.com>
\r
39 To: notmuch@notmuchmail.org
\r
40 Subject: [PATCH] Output unmodified Content-Type header value for JSON format.
\r
41 Date: Sat, 19 Nov 2011 03:45:05 +0400
\r
42 Message-Id: <1321659905-24367-1-git-send-email-dmitry.kurochkin@gmail.com>
\r
43 X-Mailer: git-send-email 1.7.7.3
\r
45 Content-Type: text/plain; charset=UTF-8
\r
46 Content-Transfer-Encoding: 8bit
\r
47 X-BeenThere: notmuch@notmuchmail.org
\r
48 X-Mailman-Version: 2.1.13
\r
50 List-Id: "Use and development of the notmuch mail system."
\r
51 <notmuch.notmuchmail.org>
\r
52 List-Unsubscribe: <http://notmuchmail.org/mailman/options/notmuch>,
\r
53 <mailto:notmuch-request@notmuchmail.org?subject=unsubscribe>
\r
54 List-Archive: <http://notmuchmail.org/pipermail/notmuch>
\r
55 List-Post: <mailto:notmuch@notmuchmail.org>
\r
56 List-Help: <mailto:notmuch-request@notmuchmail.org?subject=help>
\r
57 List-Subscribe: <http://notmuchmail.org/mailman/listinfo/notmuch>,
\r
58 <mailto:notmuch-request@notmuchmail.org?subject=subscribe>
\r
59 X-List-Received-Date: Fri, 18 Nov 2011 23:45:28 -0000
\r
61 Before the change, notmuch used g_mime_content_type_to_string(3)
\r
62 function to output Content-Type header value. Turns out it outputs
\r
63 only "type/subtype" part and ignores all parameters. Also, if there
\r
64 is no Content-Type header, default "text/plain" value is used.
\r
66 JSON is supposed to be a "low-level" structured format and should not
\r
67 add missing values or throw away information. The patch changes
\r
68 notmuch show to use unmodified Content-Type value for JSON format.
\r
69 Also, no default value is added if the header is missing.
\r
71 Corresponding changes to Emacs UI are made to handle full Content-Type
\r
72 header values. The header is parsed using MIME
\r
73 `mail-header-parse-content-type' function. All message part rendering
\r
74 functions have access to full Content-Type value. In particular, this
\r
75 is important for `notmuch-show-mm-display-part-inline' which uses
\r
76 `mm-display-part' to display parts that notmuch-show does not handle.
\r
78 Expected results for the tests are updated accordingly.
\r
80 emacs/notmuch-show.el | 28 ++++++++++++++++++----------
\r
81 notmuch-show.c | 14 ++++++++++++--
\r
82 test/crypto | 23 ++++++++---------------
\r
83 test/json | 6 +++---
\r
84 test/maildir-sync | 1 -
\r
85 test/multipart | 36 ++++++++++++++++++------------------
\r
86 6 files changed, 59 insertions(+), 49 deletions(-)
\r
88 diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el
\r
89 index d5c95d8..d2c2fa3 100644
\r
90 --- a/emacs/notmuch-show.el
\r
91 +++ b/emacs/notmuch-show.el
\r
92 @@ -261,120 +261,120 @@ message at DEPTH in the current thread."
\r
93 (if (and header-value
\r
94 (not (string-equal "" header-value)))
\r
95 (notmuch-show-insert-header header header-value))))
\r
96 notmuch-message-headers)
\r
99 (narrow-to-region start (point-max))
\r
100 (run-hooks 'notmuch-show-markup-headers-hook)))))
\r
102 (define-button-type 'notmuch-show-part-button-type
\r
103 'action 'notmuch-show-part-button-action
\r
105 'face 'message-mml)
\r
107 (defun notmuch-show-insert-part-header (nth content-type declared-type &optional name comment)
\r
112 (if name (concat name ": ") "")
\r
114 - (if (not (string-equal declared-type content-type))
\r
115 - (concat " (as " content-type ")")
\r
116 + (car declared-type)
\r
117 + (if (not (string-equal (car declared-type) (car content-type)))
\r
118 + (concat " (as " (car content-type) ")")
\r
122 :type 'notmuch-show-part-button-type
\r
124 :notmuch-filename name))
\r
129 ;; Functions handling particular MIME parts.
\r
131 (defun notmuch-show-save-part (message-id nth &optional filename)
\r
132 (let ((process-crypto notmuch-show-process-crypto))
\r
134 (setq notmuch-show-process-crypto process-crypto)
\r
135 ;; Always acquires the part via `notmuch part', even if it is
\r
136 ;; available in the JSON output.
\r
137 (insert (notmuch-show-get-bodypart-internal message-id nth))
\r
138 (let ((file (read-file-name
\r
139 "Filename to save as: "
\r
140 (or mailcap-download-directory "~/")
\r
143 ;; Don't re-compress .gz & al. Arguably we should make
\r
144 ;; `file-name-handler-alist' nil, but that would chop
\r
145 ;; ange-ftp, which is reasonable to use here.
\r
146 (mm-write-region (point-min) (point-max) file nil nil nil 'no-conversion t)))))
\r
148 (defun notmuch-show-mm-display-part-inline (msg part content-type content)
\r
149 "Use the mm-decode/mm-view functions to display a part in the
\r
150 current buffer, if possible."
\r
151 (let ((display-buffer (current-buffer)))
\r
154 - (let ((handle (mm-make-handle (current-buffer) (list content-type))))
\r
155 + (let ((handle (mm-make-handle (current-buffer) content-type)))
\r
156 (set-buffer display-buffer)
\r
157 (if (and (mm-inlinable-p handle)
\r
158 (mm-inlined-p handle))
\r
160 (mm-display-part handle)
\r
164 (defvar notmuch-show-multipart/alternative-discouraged
\r
166 ;; Avoid HTML parts.
\r
168 ;; multipart/related usually contain a text/html part and some associated graphics.
\r
169 "multipart/related"
\r
172 (defun notmuch-show-multipart/*-to-list (part)
\r
173 - (mapcar '(lambda (inner-part) (plist-get inner-part :content-type))
\r
174 + (mapcar '(lambda (inner-part) (car (notmuch-show-get-content-type inner-part)))
\r
175 (plist-get part :content)))
\r
177 (defun notmuch-show-multipart/alternative-choose (types)
\r
178 ;; Based on `mm-preferred-alternative-precedence'.
\r
180 (dolist (pref (reverse notmuch-show-multipart/alternative-discouraged))
\r
181 (dolist (elem (copy-sequence seq))
\r
182 (when (string-match pref elem)
\r
183 (setq seq (nconc (delete elem seq) (list elem))))))
\r
186 (defun notmuch-show-insert-part-multipart/alternative (msg part content-type nth depth declared-type)
\r
187 (notmuch-show-insert-part-header nth declared-type content-type nil)
\r
188 (let ((chosen-type (car (notmuch-show-multipart/alternative-choose (notmuch-show-multipart/*-to-list part))))
\r
189 (inner-parts (plist-get part :content))
\r
191 ;; This inserts all parts of the chosen type rather than just one,
\r
192 ;; but it's not clear that this is the wrong thing to do - which
\r
193 ;; should be chosen if there are more than one that match?
\r
194 (mapc (lambda (inner-part)
\r
195 - (let ((inner-type (plist-get inner-part :content-type)))
\r
196 + (let ((inner-type (notmuch-show-get-content-type inner-part)))
\r
197 (if (or notmuch-show-all-multipart/alternative-parts
\r
198 - (string= chosen-type inner-type))
\r
199 + (string= chosen-type (car inner-type)))
\r
200 (notmuch-show-insert-bodypart msg inner-part depth)
\r
201 (notmuch-show-insert-part-header (plist-get inner-part :id) inner-type inner-type nil " (not shown)"))))
\r
204 (when notmuch-show-indent-multipart
\r
205 (indent-rigidly start (point) 1)))
\r
208 (defun notmuch-show-setup-w3m ()
\r
209 "Instruct w3m how to retrieve content from a \"related\" part of a message."
\r
211 (if (boundp 'w3m-cid-retrieve-function-alist)
\r
212 (unless (assq 'notmuch-show-mode w3m-cid-retrieve-function-alist)
\r
213 (push (cons 'notmuch-show-mode 'notmuch-show-w3m-cid-retrieve)
\r
214 w3m-cid-retrieve-function-alist)))
\r
215 (setq mm-inline-text-html-with-images t))
\r
217 (defvar w3m-current-buffer) ;; From `w3m.el'.
\r
218 (defvar notmuch-show-w3m-cid-store nil)
\r
219 (make-variable-buffer-local 'notmuch-show-w3m-cid-store)
\r
220 @@ -557,41 +557,42 @@ current buffer, if possible."
\r
221 (set-buffer (get-file-buffer file))
\r
222 (setq result (buffer-substring (point-min) (point-max)))
\r
223 (set-buffer-modified-p nil)
\r
224 (kill-buffer (current-buffer))
\r
229 (defun notmuch-show-insert-part-application/octet-stream (msg part content-type nth depth declared-type)
\r
230 ;; If we can deduce a MIME type from the filename of the attachment,
\r
231 ;; do so and pass it on to the handler for that type.
\r
232 (if (plist-get part :filename)
\r
233 (let ((extension (file-name-extension (plist-get part :filename)))
\r
237 (mailcap-parse-mimetypes)
\r
238 (setq mime-type (mailcap-extension-to-mime extension))
\r
240 (not (string-equal mime-type "application/octet-stream")))
\r
241 - (notmuch-show-insert-bodypart-internal msg part mime-type nth depth content-type)
\r
242 + (notmuch-show-insert-bodypart-internal msg part (list mime-type)
\r
243 + nth depth content-type)
\r
247 (defun notmuch-show-insert-part-application/* (msg part content-type nth depth declared-type
\r
249 ;; do not render random "application" parts
\r
250 (notmuch-show-insert-part-header nth content-type declared-type (plist-get part :filename)))
\r
252 (defun notmuch-show-insert-part-*/* (msg part content-type nth depth declared-type)
\r
253 ;; This handler _must_ succeed - it is the handler of last resort.
\r
254 (notmuch-show-insert-part-header nth content-type declared-type (plist-get part :filename))
\r
255 (let ((content (notmuch-show-get-bodypart-content msg part nth)))
\r
257 (notmuch-show-mm-display-part-inline msg part content-type content)))
\r
260 ;; Functions for determining how to handle MIME parts.
\r
262 (defun notmuch-show-split-content-type (content-type)
\r
263 (split-string content-type "/"))
\r
264 @@ -618,51 +619,51 @@ current buffer, if possible."
\r
265 (defun notmuch-show-get-bodypart-internal (message-id part-number)
\r
266 (let ((args '("show" "--format=raw"))
\r
267 (part-arg (format "--part=%s" part-number)))
\r
268 (setq args (append args (list part-arg)))
\r
269 (if notmuch-show-process-crypto
\r
270 (setq args (append args '("--decrypt"))))
\r
271 (setq args (append args (list message-id)))
\r
273 (let ((coding-system-for-read 'no-conversion))
\r
275 (apply 'call-process (append (list notmuch-command nil (list t nil) nil) args))
\r
276 (buffer-string))))))
\r
278 (defun notmuch-show-get-bodypart-content (msg part nth)
\r
279 (or (plist-get part :content)
\r
280 (notmuch-show-get-bodypart-internal (concat "id:" (plist-get msg :id)) nth)))
\r
285 (defun notmuch-show-insert-bodypart-internal (msg part content-type nth depth declared-type)
\r
286 - (let ((handlers (notmuch-show-handlers-for content-type)))
\r
287 + (let ((handlers (notmuch-show-handlers-for (car content-type))))
\r
288 ;; Run the content handlers until one of them returns a non-nil
\r
290 (while (and handlers
\r
291 (not (funcall (car handlers) msg part content-type nth depth declared-type)))
\r
292 (setq handlers (cdr handlers))))
\r
295 (defun notmuch-show-insert-bodypart (msg part depth)
\r
296 "Insert the body part PART at depth DEPTH in the current thread."
\r
297 - (let ((content-type (downcase (plist-get part :content-type)))
\r
298 + (let ((content-type (notmuch-show-get-content-type part))
\r
299 (nth (plist-get part :id)))
\r
300 (notmuch-show-insert-bodypart-internal msg part content-type nth depth content-type))
\r
301 ;; Some of the body part handlers leave point somewhere up in the
\r
302 ;; part, so we make sure that we're down at the end.
\r
303 (goto-char (point-max))
\r
304 ;; Ensure that the part ends with a carriage return.
\r
308 (defun notmuch-show-insert-body (msg body depth)
\r
309 "Insert the body BODY at depth DEPTH in the current thread."
\r
310 (mapc '(lambda (part) (notmuch-show-insert-bodypart msg part depth)) body))
\r
312 (defun notmuch-show-make-symbol (type)
\r
313 (make-symbol (concat "notmuch-show-" type)))
\r
315 (defun notmuch-show-strip-re (string)
\r
316 (replace-regexp-in-string "\\([Rr]e: *\\)+" "" string))
\r
318 (defvar notmuch-show-previous-subject "")
\r
319 @@ -1054,40 +1055,47 @@ All currently available key bindings:
\r
321 (notmuch-show-move-to-message-top)
\r
322 (get-text-property (point) :notmuch-message-properties)))
\r
324 (defun notmuch-show-set-prop (prop val &optional props)
\r
325 (let ((inhibit-read-only t)
\r
327 (notmuch-show-get-message-properties))))
\r
328 (plist-put props prop val)
\r
329 (notmuch-show-set-message-properties props)))
\r
331 (defun notmuch-show-get-prop (prop &optional props)
\r
332 (let ((props (or props
\r
333 (notmuch-show-get-message-properties))))
\r
334 (plist-get props prop)))
\r
336 (defun notmuch-show-get-message-id ()
\r
337 "Return the message id of the current message."
\r
338 (concat "id:\"" (notmuch-show-get-prop :id) "\""))
\r
340 +(defun notmuch-show-get-content-type (&optional props)
\r
341 + "Return parsed Content-Type of the given message, or part, or
\r
342 +current message if no `props` is given. If there is no
\r
343 +Content-Type header, it defaults to \"text/plain\"."
\r
344 + (mail-header-parse-content-type (or (notmuch-show-get-prop :content-type props)
\r
347 ;; dme: Would it make sense to use a macro for many of these?
\r
349 (defun notmuch-show-get-filename ()
\r
350 "Return the filename of the current message."
\r
351 (notmuch-show-get-prop :filename))
\r
353 (defun notmuch-show-get-header (header)
\r
354 "Return the named header of the current message, if any."
\r
355 (plist-get (notmuch-show-get-prop :headers) header))
\r
357 (defun notmuch-show-get-cc ()
\r
358 (notmuch-show-get-header :Cc))
\r
360 (defun notmuch-show-get-date ()
\r
361 (notmuch-show-get-header :Date))
\r
363 (defun notmuch-show-get-from ()
\r
364 (notmuch-show-get-header :From))
\r
366 (defun notmuch-show-get-subject ()
\r
367 diff --git a/notmuch-show.c b/notmuch-show.c
\r
368 index 603992a..da3e87f 100644
\r
369 --- a/notmuch-show.c
\r
370 +++ b/notmuch-show.c
\r
372 * Copyright © 2009 Carl Worth
\r
374 * This program is free software: you can redistribute it and/or modify
\r
375 * it under the terms of the GNU General Public License as published by
\r
376 * the Free Software Foundation, either version 3 of the License, or
\r
377 * (at your option) any later version.
\r
379 * This program is distributed in the hope that it will be useful,
\r
380 * but WITHOUT ANY WARRANTY; without even the implied warranty of
\r
381 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
\r
382 * GNU General Public License for more details.
\r
384 * You should have received a copy of the GNU General Public License
\r
385 * along with this program. If not, see http://www.gnu.org/licenses/ .
\r
387 * Author: Carl Worth <cworth@cworth.org>
\r
390 #include "notmuch-client.h"
\r
392 +static const char HEADER_CONTENT_TYPE[] = "Content-Type";
\r
395 format_message_text (unused (const void *ctx),
\r
396 notmuch_message_t *message,
\r
399 format_headers_text (const void *ctx,
\r
400 notmuch_message_t *message);
\r
403 format_headers_message_part_text (GMimeMessage *message);
\r
406 format_part_start_text (GMimeObject *part,
\r
410 format_part_content_text (GMimeObject *part);
\r
413 format_part_end_text (GMimeObject *part);
\r
414 @@ -640,42 +642,50 @@ format_part_sigstatus_json (const GMimeSignatureValidity* validity)
\r
418 signer = signer->next;
\r
423 talloc_free (ctx_quote);
\r
427 format_part_content_json (GMimeObject *part)
\r
429 GMimeContentType *content_type = g_mime_object_get_content_type (GMIME_OBJECT (part));
\r
430 GMimeStream *stream_memory = g_mime_stream_mem_new ();
\r
431 const char *cid = g_mime_object_get_content_id (part);
\r
432 void *ctx = talloc_new (NULL);
\r
433 GByteArray *part_content;
\r
435 - printf (", \"content-type\": %s",
\r
436 - json_quote_str (ctx, g_mime_content_type_to_string (content_type)));
\r
438 + /* Output full Content-Type header value,
\r
439 + * g_mime_content_type_to_string(3) does not include
\r
440 + * parameters. Content-Type header may be missing,
\r
441 + * g_mime_object_get_content_type(3) defaults to "text/plain"
\r
442 + * in this case. */
\r
443 + const char *const h = g_mime_object_get_header (part, HEADER_CONTENT_TYPE);
\r
445 + printf (", \"content-type\": %s", json_quote_str (ctx, h));
\r
449 printf(", \"content-id\": %s", json_quote_str (ctx, cid));
\r
451 if (GMIME_IS_PART (part))
\r
453 const char *filename = g_mime_part_get_filename (GMIME_PART (part));
\r
455 printf (", \"filename\": %s", json_quote_str (ctx, filename));
\r
458 if (g_mime_content_type_is_type (content_type, "text", "*") &&
\r
459 !g_mime_content_type_is_type (content_type, "text", "html"))
\r
461 show_text_part_content (part, stream_memory);
\r
462 part_content = g_mime_stream_mem_get_byte_array (GMIME_STREAM_MEM (stream_memory));
\r
464 printf (", \"content\": %s", json_quote_chararray (ctx, (char *) part_content->data, part_content->len));
\r
466 else if (g_mime_content_type_is_type (content_type, "multipart", "*"))
\r
467 diff --git a/test/crypto b/test/crypto
\r
468 index 0af4aa8..b923d22 100755
\r
471 @@ -40,111 +40,108 @@ test_expect_success 'emacs delivery of signed message' \
\r
472 test_begin_subtest "signature verification"
\r
473 output=$(notmuch show --format=json --verify subject:"test signed message 001" \
\r
474 | notmuch_json_show_sanitize \
\r
475 | sed -e 's|"created": [1234567890]*|"created": 946728000|')
\r
476 expected='[[[{"id": "XXXXX",
\r
478 "filename": "YYYYY",
\r
479 "timestamp": 946728000,
\r
480 "date_relative": "2000-01-01",
\r
481 "tags": ["inbox","signed"],
\r
482 "headers": {"Subject": "test signed message 001",
\r
483 "From": "Notmuch Test Suite <test_suite@notmuchmail.org>",
\r
484 "To": "test_suite@notmuchmail.org",
\r
487 "Date": "01 Jan 2000 12:00:00 -0000"},
\r
489 "sigstatus": [{"status": "good",
\r
490 "fingerprint": "'$FINGERPRINT'",
\r
491 "created": 946728000}],
\r
492 - "content-type": "multipart/signed",
\r
493 + "content-type": "multipart/signed; boundary=\"=-=-=\";\tmicalg=pgp-sha1; protocol=\"application/pgp-signature\"",
\r
494 "content": [{"id": 2,
\r
495 - "content-type": "text/plain",
\r
496 "content": "This is a test signed message.\n"},
\r
498 "content-type": "application/pgp-signature"}]}]},
\r
500 test_expect_equal \
\r
504 test_begin_subtest "signature verification with full owner trust"
\r
505 # give the key full owner trust
\r
506 echo "${FINGERPRINT}:6:" | gpg --no-tty --import-ownertrust >>"$GNUPGHOME"/trust.log 2>&1
\r
507 gpg --no-tty --check-trustdb >>"$GNUPGHOME"/trust.log 2>&1
\r
508 output=$(notmuch show --format=json --verify subject:"test signed message 001" \
\r
509 | notmuch_json_show_sanitize \
\r
510 | sed -e 's|"created": [1234567890]*|"created": 946728000|')
\r
511 expected='[[[{"id": "XXXXX",
\r
513 "filename": "YYYYY",
\r
514 "timestamp": 946728000,
\r
515 "date_relative": "2000-01-01",
\r
516 "tags": ["inbox","signed"],
\r
517 "headers": {"Subject": "test signed message 001",
\r
518 "From": "Notmuch Test Suite <test_suite@notmuchmail.org>",
\r
519 "To": "test_suite@notmuchmail.org",
\r
522 "Date": "01 Jan 2000 12:00:00 -0000"},
\r
524 "sigstatus": [{"status": "good",
\r
525 "fingerprint": "'$FINGERPRINT'",
\r
526 "created": 946728000,
\r
527 "userid": " Notmuch Test Suite <test_suite@notmuchmail.org> (INSECURE!)"}],
\r
528 - "content-type": "multipart/signed",
\r
529 + "content-type": "multipart/signed; boundary=\"=-=-=\";\tmicalg=pgp-sha1; protocol=\"application/pgp-signature\"",
\r
530 "content": [{"id": 2,
\r
531 - "content-type": "text/plain",
\r
532 "content": "This is a test signed message.\n"},
\r
534 "content-type": "application/pgp-signature"}]}]},
\r
536 test_expect_equal \
\r
540 test_begin_subtest "signature verification with signer key unavailable"
\r
541 # move the gnupghome temporarily out of the way
\r
542 mv "${GNUPGHOME}"{,.bak}
\r
543 output=$(notmuch show --format=json --verify subject:"test signed message 001" \
\r
544 | notmuch_json_show_sanitize \
\r
545 | sed -e 's|"created": [1234567890]*|"created": 946728000|')
\r
546 expected='[[[{"id": "XXXXX",
\r
548 "filename": "YYYYY",
\r
549 "timestamp": 946728000,
\r
550 "date_relative": "2000-01-01",
\r
551 "tags": ["inbox","signed"],
\r
552 "headers": {"Subject": "test signed message 001",
\r
553 "From": "Notmuch Test Suite <test_suite@notmuchmail.org>",
\r
554 "To": "test_suite@notmuchmail.org",
\r
557 "Date": "01 Jan 2000 12:00:00 -0000"},
\r
559 "sigstatus": [{"status": "error",
\r
560 "keyid": "'$(echo $FINGERPRINT | cut -c 25-)'",
\r
562 - "content-type": "multipart/signed",
\r
563 + "content-type": "multipart/signed; boundary=\"=-=-=\";\tmicalg=pgp-sha1; protocol=\"application/pgp-signature\"",
\r
564 "content": [{"id": 2,
\r
565 - "content-type": "text/plain",
\r
566 "content": "This is a test signed message.\n"},
\r
568 "content-type": "application/pgp-signature"}]}]},
\r
570 test_expect_equal \
\r
573 mv "${GNUPGHOME}"{.bak,}
\r
575 # create a test encrypted message with attachment
\r
576 cat <<EOF >TESTATTACHMENT
\r
577 This is a test file.
\r
579 test_expect_success 'emacs delivery of encrypted message with attachment' \
\r
580 'emacs_deliver_message \
\r
581 "test encrypted message 001" \
\r
582 "This is a test encrypted message.\n" \
\r
583 "(mml-attach-file \"TESTATTACHMENT\") (mml-secure-message-encrypt)"'
\r
585 test_begin_subtest "decryption, --format=text"
\r
586 @@ -181,138 +178,135 @@ test_expect_equal \
\r
588 test_begin_subtest "decryption, --format=json"
\r
589 output=$(notmuch show --format=json --decrypt subject:"test encrypted message 001" \
\r
590 | notmuch_json_show_sanitize \
\r
591 | sed -e 's|"created": [1234567890]*|"created": 946728000|')
\r
592 expected='[[[{"id": "XXXXX",
\r
594 "filename": "YYYYY",
\r
595 "timestamp": 946728000,
\r
596 "date_relative": "2000-01-01",
\r
597 "tags": ["encrypted","inbox"],
\r
598 "headers": {"Subject": "test encrypted message 001",
\r
599 "From": "Notmuch Test Suite <test_suite@notmuchmail.org>",
\r
600 "To": "test_suite@notmuchmail.org",
\r
603 "Date": "01 Jan 2000 12:00:00 -0000"},
\r
605 "encstatus": [{"status": "good"}],
\r
607 - "content-type": "multipart/encrypted",
\r
608 + "content-type": "multipart/encrypted; boundary=\"==-=-=\";\tprotocol=\"application/pgp-encrypted\"",
\r
609 "content": [{"id": 2,
\r
610 "content-type": "application/pgp-encrypted"},
\r
612 - "content-type": "multipart/mixed",
\r
613 + "content-type": "multipart/mixed; boundary=\"=-=-=\"",
\r
614 "content": [{"id": 4,
\r
615 - "content-type": "text/plain",
\r
616 "content": "This is a test encrypted message.\n"},
\r
618 "content-type": "application/octet-stream",
\r
619 "filename": "TESTATTACHMENT"}]}]}]},
\r
621 test_expect_equal \
\r
625 test_begin_subtest "decryption, --format=json, --part=4"
\r
626 output=$(notmuch show --format=json --part=4 --decrypt subject:"test encrypted message 001" \
\r
627 | notmuch_json_show_sanitize \
\r
628 | sed -e 's|"created": [1234567890]*|"created": 946728000|')
\r
629 expected='{"id": 4,
\r
630 - "content-type": "text/plain",
\r
631 "content": "This is a test encrypted message.\n"}'
\r
632 test_expect_equal \
\r
636 test_begin_subtest "decrypt attachment (--part=5 --format=raw)"
\r
641 subject:"test encrypted message 001" >OUTPUT
\r
642 test_expect_equal_file OUTPUT TESTATTACHMENT
\r
644 test_begin_subtest "decryption failure with missing key"
\r
645 mv "${GNUPGHOME}"{,.bak}
\r
646 output=$(notmuch show --format=json --decrypt subject:"test encrypted message 001" \
\r
647 | notmuch_json_show_sanitize \
\r
648 | sed -e 's|"created": [1234567890]*|"created": 946728000|')
\r
649 expected='[[[{"id": "XXXXX",
\r
651 "filename": "YYYYY",
\r
652 "timestamp": 946728000,
\r
653 "date_relative": "2000-01-01",
\r
654 "tags": ["encrypted","inbox"],
\r
655 "headers": {"Subject": "test encrypted message 001",
\r
656 "From": "Notmuch Test Suite <test_suite@notmuchmail.org>",
\r
657 "To": "test_suite@notmuchmail.org",
\r
660 "Date": "01 Jan 2000 12:00:00 -0000"},
\r
662 "encstatus": [{"status": "bad"}],
\r
663 - "content-type": "multipart/encrypted",
\r
664 + "content-type": "multipart/encrypted; boundary=\"==-=-=\";\tprotocol=\"application/pgp-encrypted\"",
\r
665 "content": [{"id": 2,
\r
666 "content-type": "application/pgp-encrypted"},
\r
668 "content-type": "application/octet-stream"}]}]},
\r
670 test_expect_equal \
\r
673 mv "${GNUPGHOME}"{.bak,}
\r
675 test_expect_success 'emacs delivery of encrypted + signed message' \
\r
676 'emacs_deliver_message \
\r
677 "test encrypted message 002" \
\r
678 "This is another test encrypted message.\n" \
\r
679 "(mml-secure-message-sign-encrypt)"'
\r
681 test_begin_subtest "decryption + signature verification"
\r
682 output=$(notmuch show --format=json --decrypt subject:"test encrypted message 002" \
\r
683 | notmuch_json_show_sanitize \
\r
684 | sed -e 's|"created": [1234567890]*|"created": 946728000|')
\r
685 expected='[[[{"id": "XXXXX",
\r
687 "filename": "YYYYY",
\r
688 "timestamp": 946728000,
\r
689 "date_relative": "2000-01-01",
\r
690 "tags": ["encrypted","inbox"],
\r
691 "headers": {"Subject": "test encrypted message 002",
\r
692 "From": "Notmuch Test Suite <test_suite@notmuchmail.org>",
\r
693 "To": "test_suite@notmuchmail.org",
\r
696 "Date": "01 Jan 2000 12:00:00 -0000"},
\r
698 "encstatus": [{"status": "good"}],
\r
699 "sigstatus": [{"status": "good",
\r
700 "fingerprint": "'$FINGERPRINT'",
\r
701 "created": 946728000,
\r
702 "userid": " Notmuch Test Suite <test_suite@notmuchmail.org> (INSECURE!)"}],
\r
703 - "content-type": "multipart/encrypted",
\r
704 + "content-type": "multipart/encrypted; boundary=\"=-=-=\";\tprotocol=\"application/pgp-encrypted\"",
\r
705 "content": [{"id": 2,
\r
706 "content-type": "application/pgp-encrypted"},
\r
708 - "content-type": "text/plain",
\r
709 "content": "This is another test encrypted message.\n"}]}]},
\r
711 test_expect_equal \
\r
715 test_begin_subtest "reply to encrypted message"
\r
716 output=$(notmuch reply --decrypt subject:"test encrypted message 002" \
\r
717 | grep -v -e '^In-Reply-To:' -e '^References:')
\r
718 expected='From: Notmuch Test Suite <test_suite@notmuchmail.org>
\r
719 Subject: Re: test encrypted message 002
\r
721 On 01 Jan 2000 12:00:00 -0000, Notmuch Test Suite <test_suite@notmuchmail.org> wrote:
\r
722 > This is another test encrypted message.'
\r
723 test_expect_equal \
\r
727 test_begin_subtest "signature verification with revoked key"
\r
728 # generate revocation certificate and load it to revoke key
\r
729 @@ -327,32 +321,31 @@ y
\r
730 | gpg --no-tty --quiet --import
\r
731 output=$(notmuch show --format=json --verify subject:"test signed message 001" \
\r
732 | notmuch_json_show_sanitize \
\r
733 | sed -e 's|"created": [1234567890]*|"created": 946728000|')
\r
734 expected='[[[{"id": "XXXXX",
\r
736 "filename": "YYYYY",
\r
737 "timestamp": 946728000,
\r
738 "date_relative": "2000-01-01",
\r
739 "tags": ["inbox","signed"],
\r
740 "headers": {"Subject": "test signed message 001",
\r
741 "From": "Notmuch Test Suite <test_suite@notmuchmail.org>",
\r
742 "To": "test_suite@notmuchmail.org",
\r
745 "Date": "01 Jan 2000 12:00:00 -0000"},
\r
747 "sigstatus": [{"status": "error",
\r
748 "keyid": "6D92612D94E46381",
\r
750 - "content-type": "multipart/signed",
\r
751 + "content-type": "multipart/signed; boundary=\"=-=-=\";\tmicalg=pgp-sha1; protocol=\"application/pgp-signature\"",
\r
752 "content": [{"id": 2,
\r
753 - "content-type": "text/plain",
\r
754 "content": "This is a test signed message.\n"},
\r
756 "content-type": "application/pgp-signature"}]}]},
\r
758 test_expect_equal \
\r
763 diff --git a/test/json b/test/json
\r
764 index 592b068..64f35cf 100755
\r
768 #!/usr/bin/env bash
\r
769 test_description="--format=json output"
\r
772 test_begin_subtest "Show message: json"
\r
773 add_message "[subject]=\"json-show-subject\"" "[date]=\"Sat, 01 Jan 2000 12:00:00 -0000\"" "[body]=\"json-show-message\""
\r
774 output=$(notmuch show --format=json "json-show-message")
\r
775 -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\"}]}, []]]]"
\r
776 +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\": \"json-show-message\n\"}]}, []]]]"
\r
778 test_begin_subtest "Search message: json"
\r
779 add_message "[subject]=\"json-search-subject\"" "[date]=\"Sat, 01 Jan 2000 12:00:00 -0000\"" "[body]=\"json-search-message\""
\r
780 output=$(notmuch search --format=json "json-search-message" | notmuch_search_sanitize)
\r
781 test_expect_equal "$output" "[{\"thread\": \"XXX\",
\r
782 \"timestamp\": 946728000,
\r
785 \"authors\": \"Notmuch Test Suite\",
\r
786 \"subject\": \"json-search-subject\",
\r
787 \"tags\": [\"inbox\", \"unread\"]}]"
\r
789 test_begin_subtest "Show message: json, utf-8"
\r
790 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\""
\r
791 output=$(notmuch show --format=json "jsön-show-méssage")
\r
792 -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\"}]}, []]]]"
\r
793 +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\": \"jsön-show-méssage\n\"}]}, []]]]"
\r
795 test_begin_subtest "Show message: json, inline attachment filename"
\r
796 subject='json-show-inline-attachment-filename'
\r
797 id="json-show-inline-attachment-filename@notmuchmail.org"
\r
798 emacs_deliver_message \
\r
800 'This is a test message with inline attachment with a filename' \
\r
801 "(mml-attach-file \"$TEST_DIRECTORY/README\" nil nil \"inline\")
\r
803 (insert \"Message-ID: <$id>\n\")"
\r
804 output=$(notmuch show --format=json "id:$id")
\r
805 filename=$(notmuch search --output=files "id:$id")
\r
806 -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\"}]}]}, []]]]"
\r
807 +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; 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\"}]}]}, []]]]"
\r
809 test_begin_subtest "Search message: json, utf-8"
\r
810 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\""
\r
811 output=$(notmuch search --format=json "jsön-search-méssage" | notmuch_search_sanitize)
\r
812 test_expect_equal "$output" "[{\"thread\": \"XXX\",
\r
813 \"timestamp\": 946728000,
\r
816 \"authors\": \"Notmuch Test Suite\",
\r
817 \"subject\": \"json-search-utf8-body-sübjéct\",
\r
818 \"tags\": [\"inbox\", \"unread\"]}]"
\r
821 diff --git a/test/maildir-sync b/test/maildir-sync
\r
822 index a60854f..c7ca22f 100755
\r
823 --- a/test/maildir-sync
\r
824 +++ b/test/maildir-sync
\r
825 @@ -41,41 +41,40 @@ add_message [subject]='"Adding replied tag"' [filename]='adding-replied-tag:2,S'
\r
826 notmuch tag +replied subject:"Adding replied tag"
\r
827 output=$(cd ${MAIL_DIR}/cur; ls -1 adding-replied*)
\r
828 test_expect_equal "$output" "adding-replied-tag:2,RS"
\r
830 test_begin_subtest "notmuch show works with renamed file (without notmuch new)"
\r
831 output=$(notmuch show --format=json id:${gen_msg_id} | filter_show_json)
\r
832 test_expect_equal "$output" '[[[{"id": "adding-replied-tag@notmuch-test-suite",
\r
834 "filename": "MAIL_DIR/cur/adding-replied-tag:2,RS",
\r
835 "timestamp": 978709437,
\r
836 "date_relative": "2001-01-05",
\r
837 "tags": ["inbox","replied"],
\r
838 "headers": {"Subject": "Adding replied tag",
\r
839 "From": "Notmuch Test Suite <test_suite@notmuchmail.org>",
\r
840 "To": "Notmuch Test Suite <test_suite@notmuchmail.org>",
\r
844 05 Jan 2001 15:43:57 -0000"},
\r
846 -"content-type": "text/plain",
\r
847 "content": "This is just a test message (#3)\n"}]},
\r
850 test_expect_success 'notmuch reply works with renamed file (without notmuch new)' 'notmuch reply id:${gen_msg_id}'
\r
852 test_begin_subtest "notmuch new detects no file rename after tag->flag synchronization"
\r
853 output=$(NOTMUCH_NEW)
\r
854 test_expect_equal "$output" "No new mail."
\r
856 test_begin_subtest "When read, message moved from new to cur"
\r
857 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
\r
858 notmuch tag -unread subject:"Message to move to cur"
\r
859 output=$(cd "$MAIL_DIR/cur"; ls message-to-move*)
\r
860 test_expect_equal "$output" "message-to-move-to-cur:2,S"
\r
862 test_begin_subtest "No rename should be detected by notmuch new"
\r
863 output=$(NOTMUCH_NEW)
\r
864 test_expect_equal "$output" "No new mail."
\r
865 # (*) If notmuch new was not run we've got "Processed 1 file in almost
\r
866 # no time" here. The reason is that removing unread tag in a previous
\r
867 diff --git a/test/multipart b/test/multipart
\r
868 index f83526b..ca4db71 100755
\r
869 --- a/test/multipart
\r
870 +++ b/test/multipart
\r
871 @@ -306,140 +306,140 @@ test_expect_equal_file OUTPUT EXPECTED
\r
873 test_begin_subtest "--format=text --part=9, pgp signature (unverified)"
\r
874 notmuch show --format=text --part=9 'id:87liy5ap00.fsf@yoom.home.cworth.org' >OUTPUT
\r
875 cat <<EOF >EXPECTED
\r
877 part{ ID: 9, Content-type: application/pgp-signature
\r
878 Non-text part: application/pgp-signature
\r
882 test_expect_equal_file OUTPUT EXPECTED
\r
884 test_expect_success \
\r
885 "--format=text --part=8, no part, expect error" \
\r
886 "notmuch show --format=text --part=8 'id:87liy5ap00.fsf@yoom.home.cworth.org'"
\r
888 test_begin_subtest "--format=json --part=0, full message"
\r
889 notmuch show --format=json --part=0 'id:87liy5ap00.fsf@yoom.home.cworth.org' | sed 's|{"id":|\n{"id":|g' >OUTPUT
\r
890 echo >>OUTPUT # expect *no* newline at end of output
\r
891 cat <<EOF >EXPECTED
\r
893 {"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": [
\r
894 -{"id": 1, "content-type": "multipart/signed", "content": [
\r
895 -{"id": 2, "content-type": "multipart/mixed", "content": [
\r
896 +{"id": 1, "content-type": "multipart/signed; boundary=\"==-=-=\";\tmicalg=pgp-sha1; protocol=\"application/pgp-signature\"", "content": [
\r
897 +{"id": 2, "content-type": "multipart/mixed; boundary=\"=-=-=\"", "content": [
\r
898 {"id": 3, "content-type": "message/rfc822", "content": [{"headers": {"From": "Carl Worth <cworth@cworth.org>", "To": "cworth@cworth.org", "Subject": "html message", "Date": "Fri, 05 Jan 2001 15:42:57 +0000"}, "body": [
\r
899 -{"id": 4, "content-type": "multipart/alternative", "content": [
\r
900 +{"id": 4, "content-type": "multipart/alternative; boundary=\"==-=-==\"", "content": [
\r
901 {"id": 5, "content-type": "text/html"},
\r
902 {"id": 6, "content-type": "text/plain", "content": "This is an embedded message, with a multipart/alternative part.\n"}]}]}]},
\r
903 -{"id": 7, "content-type": "text/plain", "filename": "attachment", "content": "This is a text attachment.\n"},
\r
904 -{"id": 8, "content-type": "text/plain", "content": "And this message is signed.\n\n-Carl\n"}]},
\r
905 +{"id": 7, "filename": "attachment", "content": "This is a text attachment.\n"},
\r
906 +{"id": 8, "content": "And this message is signed.\n\n-Carl\n"}]},
\r
907 {"id": 9, "content-type": "application/pgp-signature"}]}]}
\r
909 test_expect_equal_file OUTPUT EXPECTED
\r
911 test_begin_subtest "--format=json --part=1, message body"
\r
912 notmuch show --format=json --part=1 'id:87liy5ap00.fsf@yoom.home.cworth.org' | sed 's|{"id":|\n{"id":|g' >OUTPUT
\r
913 echo >>OUTPUT # expect *no* newline at end of output
\r
914 cat <<EOF >EXPECTED
\r
916 -{"id": 1, "content-type": "multipart/signed", "content": [
\r
917 -{"id": 2, "content-type": "multipart/mixed", "content": [
\r
918 +{"id": 1, "content-type": "multipart/signed; boundary=\"==-=-=\";\tmicalg=pgp-sha1; protocol=\"application/pgp-signature\"", "content": [
\r
919 +{"id": 2, "content-type": "multipart/mixed; boundary=\"=-=-=\"", "content": [
\r
920 {"id": 3, "content-type": "message/rfc822", "content": [{"headers": {"From": "Carl Worth <cworth@cworth.org>", "To": "cworth@cworth.org", "Subject": "html message", "Date": "Fri, 05 Jan 2001 15:42:57 +0000"}, "body": [
\r
921 -{"id": 4, "content-type": "multipart/alternative", "content": [
\r
922 +{"id": 4, "content-type": "multipart/alternative; boundary=\"==-=-==\"", "content": [
\r
923 {"id": 5, "content-type": "text/html"},
\r
924 {"id": 6, "content-type": "text/plain", "content": "This is an embedded message, with a multipart/alternative part.\n"}]}]}]},
\r
925 -{"id": 7, "content-type": "text/plain", "filename": "attachment", "content": "This is a text attachment.\n"},
\r
926 -{"id": 8, "content-type": "text/plain", "content": "And this message is signed.\n\n-Carl\n"}]},
\r
927 +{"id": 7, "filename": "attachment", "content": "This is a text attachment.\n"},
\r
928 +{"id": 8, "content": "And this message is signed.\n\n-Carl\n"}]},
\r
929 {"id": 9, "content-type": "application/pgp-signature"}]}
\r
931 test_expect_equal_file OUTPUT EXPECTED
\r
933 test_begin_subtest "--format=json --part=2, multipart/mixed"
\r
934 notmuch show --format=json --part=2 'id:87liy5ap00.fsf@yoom.home.cworth.org' | sed 's|{"id":|\n{"id":|g' >OUTPUT
\r
935 echo >>OUTPUT # expect *no* newline at end of output
\r
936 cat <<EOF >EXPECTED
\r
938 -{"id": 2, "content-type": "multipart/mixed", "content": [
\r
939 +{"id": 2, "content-type": "multipart/mixed; boundary=\"=-=-=\"", "content": [
\r
940 {"id": 3, "content-type": "message/rfc822", "content": [{"headers": {"From": "Carl Worth <cworth@cworth.org>", "To": "cworth@cworth.org", "Subject": "html message", "Date": "Fri, 05 Jan 2001 15:42:57 +0000"}, "body": [
\r
941 -{"id": 4, "content-type": "multipart/alternative", "content": [
\r
942 +{"id": 4, "content-type": "multipart/alternative; boundary=\"==-=-==\"", "content": [
\r
943 {"id": 5, "content-type": "text/html"},
\r
944 {"id": 6, "content-type": "text/plain", "content": "This is an embedded message, with a multipart/alternative part.\n"}]}]}]},
\r
945 -{"id": 7, "content-type": "text/plain", "filename": "attachment", "content": "This is a text attachment.\n"},
\r
946 -{"id": 8, "content-type": "text/plain", "content": "And this message is signed.\n\n-Carl\n"}]}
\r
947 +{"id": 7, "filename": "attachment", "content": "This is a text attachment.\n"},
\r
948 +{"id": 8, "content": "And this message is signed.\n\n-Carl\n"}]}
\r
950 test_expect_equal_file OUTPUT EXPECTED
\r
952 test_begin_subtest "--format=json --part=3, rfc822 part"
\r
953 notmuch show --format=json --part=3 'id:87liy5ap00.fsf@yoom.home.cworth.org' | sed 's|{"id":|\n{"id":|g' >OUTPUT
\r
954 echo >>OUTPUT # expect *no* newline at end of output
\r
955 cat <<EOF >EXPECTED
\r
957 {"id": 3, "content-type": "message/rfc822", "content": [{"headers": {"From": "Carl Worth <cworth@cworth.org>", "To": "cworth@cworth.org", "Subject": "html message", "Date": "Fri, 05 Jan 2001 15:42:57 +0000"}, "body": [
\r
958 -{"id": 4, "content-type": "multipart/alternative", "content": [
\r
959 +{"id": 4, "content-type": "multipart/alternative; boundary=\"==-=-==\"", "content": [
\r
960 {"id": 5, "content-type": "text/html"},
\r
961 {"id": 6, "content-type": "text/plain", "content": "This is an embedded message, with a multipart/alternative part.\n"}]}]}]}
\r
963 test_expect_equal_file OUTPUT EXPECTED
\r
965 test_begin_subtest "--format=json --part=4, rfc822's multipart/alternative"
\r
966 notmuch show --format=json --part=4 'id:87liy5ap00.fsf@yoom.home.cworth.org' | sed 's|{"id":|\n{"id":|g' >OUTPUT
\r
967 echo >>OUTPUT # expect *no* newline at end of output
\r
968 cat <<EOF >EXPECTED
\r
970 -{"id": 4, "content-type": "multipart/alternative", "content": [
\r
971 +{"id": 4, "content-type": "multipart/alternative; boundary=\"==-=-==\"", "content": [
\r
972 {"id": 5, "content-type": "text/html"},
\r
973 {"id": 6, "content-type": "text/plain", "content": "This is an embedded message, with a multipart/alternative part.\n"}]}
\r
975 test_expect_equal_file OUTPUT EXPECTED
\r
977 test_begin_subtest "--format=json --part=5, rfc822's html part"
\r
978 notmuch show --format=json --part=5 'id:87liy5ap00.fsf@yoom.home.cworth.org' | sed 's|{"id":|\n{"id":|g' >OUTPUT
\r
979 echo >>OUTPUT # expect *no* newline at end of output
\r
980 cat <<EOF >EXPECTED
\r
982 {"id": 5, "content-type": "text/html"}
\r
984 test_expect_equal_file OUTPUT EXPECTED
\r
986 test_begin_subtest "--format=json --part=6, rfc822's text part"
\r
987 notmuch show --format=json --part=6 'id:87liy5ap00.fsf@yoom.home.cworth.org' | sed 's|{"id":|\n{"id":|g' >OUTPUT
\r
988 echo >>OUTPUT # expect *no* newline at end of output
\r
989 cat <<EOF >EXPECTED
\r
991 {"id": 6, "content-type": "text/plain", "content": "This is an embedded message, with a multipart/alternative part.\n"}
\r
993 test_expect_equal_file OUTPUT EXPECTED
\r
995 test_begin_subtest "--format=json --part=7, inline attachment"
\r
996 notmuch show --format=json --part=7 'id:87liy5ap00.fsf@yoom.home.cworth.org' | sed 's|{"id":|\n{"id":|g' >OUTPUT
\r
997 echo >>OUTPUT # expect *no* newline at end of output
\r
998 cat <<EOF >EXPECTED
\r
1000 -{"id": 7, "content-type": "text/plain", "filename": "attachment", "content": "This is a text attachment.\n"}
\r
1001 +{"id": 7, "filename": "attachment", "content": "This is a text attachment.\n"}
\r
1003 test_expect_equal_file OUTPUT EXPECTED
\r
1005 test_begin_subtest "--format=json --part=8, plain text part"
\r
1006 notmuch show --format=json --part=8 'id:87liy5ap00.fsf@yoom.home.cworth.org' | sed 's|{"id":|\n{"id":|g' >OUTPUT
\r
1007 echo >>OUTPUT # expect *no* newline at end of output
\r
1008 cat <<EOF >EXPECTED
\r
1010 -{"id": 8, "content-type": "text/plain", "content": "And this message is signed.\n\n-Carl\n"}
\r
1011 +{"id": 8, "content": "And this message is signed.\n\n-Carl\n"}
\r
1013 test_expect_equal_file OUTPUT EXPECTED
\r
1015 test_begin_subtest "--format=json --part=9, pgp signature (unverified)"
\r
1016 notmuch show --format=json --part=9 'id:87liy5ap00.fsf@yoom.home.cworth.org' | sed 's|{"id":|\n{"id":|g' >OUTPUT
\r
1017 echo >>OUTPUT # expect *no* newline at end of output
\r
1018 cat <<EOF >EXPECTED
\r
1020 {"id": 9, "content-type": "application/pgp-signature"}
\r
1022 test_expect_equal_file OUTPUT EXPECTED
\r
1024 test_expect_success \
\r
1025 "--format=json --part=10, no part, expect error" \
\r
1026 "notmuch show --format=json --part=10 'id:87liy5ap00.fsf@yoom.home.cworth.org'"
\r
1028 test_begin_subtest "--format=raw"
\r
1029 notmuch show --format=raw 'id:87liy5ap00.fsf@yoom.home.cworth.org' >OUTPUT
\r
1030 test_expect_equal_file OUTPUT "${MAIL_DIR}"/multipart
\r