[notmuch] [PATCH] Rework saving of attachments.

camalot at picnicpark.org camalot at picnicpark.org
Mon Dec 14 10:13:58 PST 2009


From: Keith Amidon <keith at nicira.com>

With this commit notmuch-show-mode supports saving a single attachment
from a message (bound to 'w') and saving all attachments to the
message (bound to 'W').  The new variable notmuch-default-save-dir
allows the user to specify a directory within which attachments should
be saved by default.  The user can modify this default path, even
specifying a non-existent directory path, in which case he or she will
be prompted to create the path.  Reporting of the actions taken is
also improved.
---
 notmuch.el |   93 ++++++++++++++++++++++++++++++++++++++++++++++-------------
 1 files changed, 72 insertions(+), 21 deletions(-)

diff --git a/notmuch.el b/notmuch.el
index 97914f2..b72548d 100644
--- a/notmuch.el
+++ b/notmuch.el
@@ -64,7 +64,8 @@
     (define-key map "f" 'notmuch-show-forward-current)
     (define-key map "r" 'notmuch-show-reply)
     (define-key map "|" 'notmuch-show-pipe-message)
-    (define-key map "w" 'notmuch-show-save-attachments)
+    (define-key map "w" 'notmuch-show-save-attachment)
+    (define-key map "W" 'notmuch-show-save-all-attachments)
     (define-key map "V" 'notmuch-show-view-raw-message)
     (define-key map "v" 'notmuch-show-view-all-mime-parts)
     (define-key map "-" 'notmuch-show-remove-tag)
@@ -98,6 +99,9 @@ pattern can still test against the entire line).")
 (defvar notmuch-command "notmuch"
   "Command to run the notmuch binary.")
 
+(defvar notmuch-default-save-dir (file-name-as-directory (getenv "HOME" ))
+  "Default directory in which attachments are saved.")
+
 (defvar notmuch-show-message-begin-regexp    "\fmessage{")
 (defvar notmuch-show-message-end-regexp      "\fmessage}")
 (defvar notmuch-show-header-begin-regexp     "\fheader{")
@@ -329,28 +333,75 @@ buffer."
      mm-handle)
     count))
 
-(defun notmuch-save-attachments (mm-handle &optional queryp)
-  (notmuch-foreach-mime-part
-   (lambda (p)
-     (let ((disposition (mm-handle-disposition p)))
-       (and (listp disposition)
-            (or (equal (car disposition) "attachment")
-                (and (equal (car disposition) "inline")
-                     (assq 'filename disposition)))
-            (or (not queryp)
-                (y-or-n-p
-                 (concat "Save '" (cdr (assq 'filename disposition)) "' ")))
-            (mm-save-part p))))
-   mm-handle))
-
-(defun notmuch-show-save-attachments ()
-  "Save all attachments from the current message."
-  (interactive)
+(defun notmuch-attachment-q (mm-handle)
+  (let ((disposition (mm-handle-disposition p)))
+    (and (listp disposition)
+         (assq 'filename disposition))))
+
+(defun notmuch-get-save-path (filename default-dir)
+  (let ((savepath nil))
+    (while (not savepath)
+      (let* ((ddir (file-name-as-directory default-dir))
+             (fn (read-file-name "Save to: " ddir nil nil filename))
+             (efn (expand-file-name fn))
+             (dir (file-name-directory efn)))
+        (when (not (file-accessible-directory-p dir))
+          (when (y-or-n-p (concat "Create directory " dir " "))
+            (make-directory dir t)))
+        (if (file-accessible-directory-p dir)
+            (setq savepath fn)
+          (setq default-dir (file-name-directory fn)))))
+    savepath))
+
+(defun notmuch-save-attachment (mm-handle default-dir)
+  "Save the current attachment part to a file."
+  (cond ((not (notmuch-attachment-q mm-handle))
+         (message "Current part is not an attachment.")
+         nil)
+        (t
+         (let* ((fn (cdr (assq 'filename (mm-handle-disposition mm-handle))))
+                (savepath (notmuch-get-save-path fn default-dir)))
+           (mm-save-part-to-file mm-handle savepath)
+           savepath))))
+
+(defun notmuch-save-attachment-num (mm-handle part-num)
+  "Save the nth part number"
+  (let ((nfound 0)
+        (nsaved 0))
+    (notmuch-foreach-mime-part
+     (lambda (p)
+       (when (notmuch-attachment-q p)
+         (cond ((equal (+ 1 nfound) part-num)
+                (when (notmuch-save-attachment p notmuch-default-save-dir)
+                  (incf nsaved))))
+         (incf nfound))) mm-handle)
+    (equal nsaved 1)))
+
+(defun notmuch-show-save-attachment (num)
+  "Save a single attachment."
+  (interactive "p")
   (with-current-notmuch-show-message
    (let ((mm-handle (mm-dissect-buffer)))
-     (notmuch-save-attachments
-      mm-handle (> (notmuch-count-attachments mm-handle) 1))))
-  (message "Done"))
+     (if (notmuch-save-attachment-num mm-handle num)
+         (message "Attachment %d saved." num)
+       (message "Failed to save attachment.")))))
+
+(defun notmuch-show-save-all-attachments ()
+  "Save all attachments of a message to a directory."
+  (interactive)
+  (with-current-notmuch-show-message
+   (let ((nfound 0)
+         (nsaved 0)
+         (default-dir notmuch-default-save-dir)
+         (mm-handle (mm-dissect-buffer)))
+     (notmuch-foreach-mime-part
+      (lambda (p)
+        (when (notmuch-attachment-q p)
+          (incf nfound)
+          (let ((savepath (notmuch-save-attachment p default-dir)))
+            (when savepath
+              (setq default-dir (file-name-directory savepath)))))) mm-handle)
+     (message "Saved %d attachments" nfound))))
 
 (defun notmuch-reply (query-string)
   (switch-to-buffer (generate-new-buffer "notmuch-draft"))
-- 
1.6.5.6



More information about the notmuch mailing list