summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--TODO.org145
-rw-r--r--modules/mail-config.el121
2 files changed, 159 insertions, 107 deletions
diff --git a/TODO.org b/TODO.org
index 449ec7ea..5e1b1027 100644
--- a/TODO.org
+++ b/TODO.org
@@ -786,76 +786,7 @@ This is the result of overriding that function in cj/invincible-buffers in syste
*** DONE [#C] Bookmark-save-flag Replaces Bookmark-set-and-save
CLOSED: [2024-04-03 Wed 15:00]
remove cj/bookmark-set-and-save if setting bookmark-save-flat to 1 saves when adding/modifying a bookmark
-** DOING Open v0.7 Fit and Finish (ends 2024.04.20) [0/2]
-*** DOING [#B] Save All Attachments Working in Mu4e
-**** 2024-04-18 Thu @ 05:55:32 -0500 The Documentation Suggests A Path Forward
-This suggests that if I'm writing another function, I should
-- first query the user to select/create the directory
-- make sure mu4e-view-completion-minor-mode is on
-- call mu4e-view-complete-all to get all the files
-- within the context of mu4e-view-save-attachments
-
-#+BEGIN_QUOTE
-E-mail messages can be though as a series of “MIME-parts”, which are sections of the message. The most prominent is the ’body’, that is the main message your are reading. Many e-mail messages also contains attachments, which MIME-parts that contain files10.
-
-To save such attachments as files on your file systems, the mu4e message-view offers the command mu4e-view-save-attachments; default keybinding is e (think extract). After invoking the command, you can enter the file names to save, comma-separated, and using the completion support. Press RET to save the chosen files to your file-system.
-
-With a prefix argument, you get to choose the target-directory, otherwise, mu4e determines it following the variable mu4e-attachment-dir (which can be file-system path or a function; see its docstring for details.
-
-While completing, mu4e-view-completion-minor-mode is active, which offers mu4e-view-complete-all (bound to C-c C-a to complete all files11.
-#+END_QUOTE
-[[https://www.djcbsoftware.nl/code/mu/mu4e/MSGV-Attachments-and-MIME_002dparts.html][MSGV Attachments and MIME-parts (Mu4e 1.12.3 user manual)]]
-
-**** 2024-04-18 Thu @ 05:05:03 -0500 Etienne's config failed
-It relies on this line to find all the mime-parts:
-
-(let ((parts (mu4e--view-gather-mime-parts))
-
-and that doesn't exist any longer.
-**** Test Etienne's Configuration
-https://etienne.depar.is/emacs.d/mu4e.html
-(defun ed/mu4e-view-save-all-attachments (&optional arg)
- "Save all attachments of a given message.
-
-If ARG is nil, all attachments will be saved in
-`mu4e-attachment-dir'. When non-nil, user will be prompted to
-choose a specific directory where to save all the files."
- (interactive "P")
- (when (and (eq major-mode 'mu4e-view-mode)
- (derived-mode-p 'gnus-article-mode))
- (let ((parts (mu4e--view-gather-mime-parts))
- (handles '())
- (files '())
- (directory (if arg
- (read-directory-name "Save to directory: ")
- mu4e-attachment-dir)))
- (dolist (part parts)
- (let ((fname (or (cdr (assoc 'filename (assoc "attachment" (cdr part))))
- (cl-loop for item in part
- for name = (and (listp item) (assoc-default 'name item))
- thereis (and (stringp name) name)))))
- (when fname
- (push `(,fname . ,(cdr part)) handles)
- (push fname files))))
- (if files
- (cl-loop for (f . h) in handles
- when (member f files)
- do (mm-save-part-to-file
- h (let ((file (expand-file-name f directory)))
- (if (file-exists-p file)
- (let (newname (count 1))
- (while (and
- (setq newname
- (format "%s-%s%s"
- (file-name-sans-extension file)
- count
- (file-name-extension file t)))
- (file-exists-p newname))
- (cl-incf count))
- newname)
- file))))
- (mu4e-message "No attached files found")))))
-(define-key mu4e-view-mode-map "X" #'ed/mu4e-view-save-all-attachments)
+** DOING Open v0.7 Fit and Finish (ends 2024.04.20) [0/1]
*** TODO [#B] Get queued email working for both mail accounts
**** using sendmail for gmail
#+BEGIN_QUOTE
@@ -1269,6 +1200,80 @@ This involves changing webclipper. Webclipper as it is now doesn't return the co
What I want is something to return the content in the way that a template would expect it. This way, I can create templates that would work with org-roam as well, such as creating a separate org-roam node just by clicking an org-protocol bookmarklet.
This might be too large to fit as a bug fix for v0.7. I began doing some research (below) yesterday to help me size the work.
+**** DONE [#B] Save All Attachments Working in Mu4e
+CLOSED: [2024-04-26 Fri 17:04]
+:LOGBOOK:
+- State "DONE" from "DOING" [2024-04-26 Fri 17:04]
+:END:
+
+***** 2024-04-18 Thu @ 05:55:32 -0500 The Documentation Suggests A Path Forward
+This suggests that if I'm writing another function, I should
+- first query the user to select/create the directory
+- make sure mu4e-view-completion-minor-mode is on
+- call mu4e-view-complete-all to get all the files
+- within the context of mu4e-view-save-attachments
+
+#+BEGIN_QUOTE
+E-mail messages can be though as a series of “MIME-parts”, which are sections of the message. The most prominent is the ’body’, that is the main message your are reading. Many e-mail messages also contains attachments, which MIME-parts that contain files10.
+
+To save such attachments as files on your file systems, the mu4e message-view offers the command mu4e-view-save-attachments; default keybinding is e (think extract). After invoking the command, you can enter the file names to save, comma-separated, and using the completion support. Press RET to save the chosen files to your file-system.
+
+With a prefix argument, you get to choose the target-directory, otherwise, mu4e determines it following the variable mu4e-attachment-dir (which can be file-system path or a function; see its docstring for details.
+
+While completing, mu4e-view-completion-minor-mode is active, which offers mu4e-view-complete-all (bound to C-c C-a to complete all files11.
+#+END_QUOTE
+[[https://www.djcbsoftware.nl/code/mu/mu4e/MSGV-Attachments-and-MIME_002dparts.html][MSGV Attachments and MIME-parts (Mu4e 1.12.3 user manual)]]
+
+***** 2024-04-18 Thu @ 05:05:03 -0500 Etienne's config failed
+It relies on this line to find all the mime-parts:
+
+(let ((parts (mu4e--view-gather-mime-parts))
+
+and that doesn't exist any longer.
+***** Test Etienne's Configuration
+https://etienne.depar.is/emacs.d/mu4e.html
+(defun ed/mu4e-view-save-all-attachments (&optional arg)
+ "Save all attachments of a given message.
+
+If ARG is nil, all attachments will be saved in
+`mu4e-attachment-dir'. When non-nil, user will be prompted to
+choose a specific directory where to save all the files."
+ (interactive "P")
+ (when (and (eq major-mode 'mu4e-view-mode)
+ (derived-mode-p 'gnus-article-mode))
+ (let ((parts (mu4e--view-gather-mime-parts))
+ (handles '())
+ (files '())
+ (directory (if arg
+ (read-directory-name "Save to directory: ")
+ mu4e-attachment-dir)))
+ (dolist (part parts)
+ (let ((fname (or (cdr (assoc 'filename (assoc "attachment" (cdr part))))
+ (cl-loop for item in part
+ for name = (and (listp item) (assoc-default 'name item))
+ thereis (and (stringp name) name)))))
+ (when fname
+ (push `(,fname . ,(cdr part)) handles)
+ (push fname files))))
+ (if files
+ (cl-loop for (f . h) in handles
+ when (member f files)
+ do (mm-save-part-to-file
+ h (let ((file (expand-file-name f directory)))
+ (if (file-exists-p file)
+ (let (newname (count 1))
+ (while (and
+ (setq newname
+ (format "%s-%s%s"
+ (file-name-sans-extension file)
+ count
+ (file-name-extension file t)))
+ (file-exists-p newname))
+ (cl-incf count))
+ newname)
+ file))))
+ (mu4e-message "No attached files found")))))
+(define-key mu4e-view-mode-map "X" #'ed/mu4e-view-save-all-attachments)
** DOING Complete v0.7 Release Checklist [8/11]
*** DOING Fit and Finish Period
*** TODO Clean Launch from Archsetup
diff --git a/modules/mail-config.el b/modules/mail-config.el
index 2d9288ac..64437155 100644
--- a/modules/mail-config.el
+++ b/modules/mail-config.el
@@ -9,6 +9,73 @@
;;; Code:
+;; ----------------------- Mu4e View Save All Attachments ----------------------
+;; replacement for the extract function which saves all attachments
+
+(defun cj/mu4e-view-save-all-attachments (&optional msg)
+ "Save all attachments from the current email.
+Prompt user for directory, creating if necessary, select all attachments in the
+email, and save them in the specified directory. The optional MSG is only
+provided when calling this function from mu4e's action context. This function is
+intended to be used as a `mu4e-view-action' and/or bound to a key in
+mu4e-view-mode-map."
+ (interactive)
+ (let ((msg (or msg (mu4e-message-at-point))))
+ (let* ((parts (mu4e-view-mime-parts))
+ ;; build cons list of candidate mime parts
+ (candidates (seq-map
+ (lambda (attachment-part)
+ (cons ;; (filename . annotation)
+ (plist-get attachment-part :filename)
+ attachment-part))
+ ;; scope to parts with a filename
+ (seq-filter
+ (lambda (part) (plist-get part :attachment-like))
+ parts)))
+ (candidates (or candidates (mu4e-warn "No attachments for this message")))
+ (files (mapcar 'car candidates)) ;; Select all attachments
+ (custom-dir (read-directory-name "Save to directory: ")))
+ (unless (file-exists-p custom-dir)
+ (make-directory custom-dir t)) ;; t creates parent dirs if needed
+ ;; iterate over each file
+ (seq-do
+ (lambda (fname)
+ (let* ((part (cdr (assoc fname candidates)))
+ ;; build unique full file path
+ (path (mu4e--uniqify-file-name
+ (mu4e-join-paths
+ custom-dir
+ (plist-get part :filename)))))
+ ;; save the file
+ (mm-save-part-to-file (plist-get part :handle) path)))
+ files))))
+
+;; ------------------------- Mark All Headers ------------------------
+;; convenience function to mark all headers for an action
+
+(defun cj/mu4e-mark-all-headers ()
+ "Mark all headers for a later action.
+Prompts user for the action when executing."
+ (interactive)
+ (mu4e-headers-mark-for-each-if
+ (cons 'something nil)
+ (lambda (_msg _param) t)))
+
+;;; ------------------ Smtpmail & Easy PG Assistant -----------------
+;; send mail to smtp host from smtpmail temp buffer.
+(use-package smtpmail
+ :ensure nil ;; built-in
+ :defer .5
+ :config
+ (setq message-kill-buffer-on-exit t) ;; don't keep compose buffers after sending
+ (setq sendmail-program (executable-find "msmtp"))
+ (setq send-mail-function 'message-send-mail-with-sendmail
+ message-send-mail-function 'message-send-mail-with-sendmail)
+ (setq message-sendmail-envelope-from 'header)
+ (setq smtpmail-debug-info t))
+
+;; --------------------------------- Mu4e Email --------------------------------
+
(use-package mu4e
:ensure nil ;; mu4e gets installed by installing 'mu' via the system package manager
:load-path "/usr/share/emacs/site-lisp/mu4e/"
@@ -18,10 +85,11 @@
(:map mu4e-headers-mode-map
("M" . cj/mu4e-mark-all-headers)
("D" . mu4e-headers-mark-for-trash)
- ("d" . mu4e-headers-mark-for-delete))
+ ("d" . mu4e-headers-mark-for-delete))
(:map mu4e-view-mode-map
- ("r" . mu4e-compose-wide-reply)
- ("R" . mu4e-compose-reply))
+ ("r" . mu4e-compose-wide-reply)
+ ("R" . mu4e-compose-reply)
+ ("e" . cj/mu4e-view-save-all-attachments))
:hook
(mu4e-view-mode . turn-on-visual-line-mode)
:config
@@ -52,7 +120,6 @@
(setq mu4e-contexts
(list
-
(make-mu4e-context
:name "gmail.com"
:match-func
@@ -115,6 +182,10 @@
"My settings for message composition."
(set-fill-column 72)))
+ ;; add save-all-attachments to view actions list
+ (add-to-list 'mu4e-view-actions
+ '("save all attachments" . cj/mu4e-view-save-all-attachments))
+
;; Always BCC myself
;; http://www.djcbsoftware.nl/code/mu/mu4e/Compose-hooks.html
(defun cj/add-header ()
@@ -133,21 +204,22 @@
;; use imagemagick to render images, if available
(when (fboundp 'imagemagick-register-types)
- (imagemagick-register-types)))
+ (imagemagick-register-types))
+
+ ;; xwidgets not able to be built into emacs on linux
+ ;; ;; view in xwidget html rendererer
+ ;; (add-to-list 'mu4e-headers-actions
+ ;; '("xWidget" . mu4e-action-view-with-xwidget) t)
+ ;; (add-to-list 'mu4e-view-actions
+ ;; '("xWidget" . mu4e-action-view-with-xwidget) t))
-;; xwidgets not able to be built into emacs on linux
-;; ;; view in xwidget html rendererer
-;; (add-to-list 'mu4e-headers-actions
-;; '("xWidget" . mu4e-action-view-with-xwidget) t)
-;; (add-to-list 'mu4e-view-actions
-;; '("xWidget" . mu4e-action-view-with-xwidget) t))
+ ) ;; end use-package mu4e
(defun no-auto-fill ()
"Turn off \'auto-fill-mode\'."
(auto-fill-mode -1))
(add-hook 'mu4e-compose-mode-hook #'no-auto-fill)
-
;; ----------------------------- Compose Mode Hydra ----------------------------
;; WIP: menu available in compose mode
@@ -163,30 +235,5 @@
(local-set-key (kbd "C-c ?") 'hydra-mu4e-compose/body))
(add-hook 'mu4e-compose-mode-hook 'mu4e-compose-mode-hook-hydra-setup)
-;; ------------------------- Mark All Headers ------------------------
-;; convenience function to mark all headers for an action
-
-(defun cj/mu4e-mark-all-headers ()
- "Mark all headers for a later action.
-Prompts user for the action when executing."
- (interactive)
- (mu4e-headers-mark-for-each-if
- (cons 'something nil)
- (lambda (_msg _param) t)))
-
-;;; ------------------ Smtpmail & Easy PG Assistant -----------------
-
-;; send mail to smtp host from smtpmail temp buffer.
-(use-package smtpmail
- :ensure nil ;; built-in
- :defer .5
- :config
- (setq message-kill-buffer-on-exit t) ;; don't keep compose buffers after sending
- (setq sendmail-program (executable-find "msmtp"))
- (setq send-mail-function 'message-send-mail-with-sendmail
- message-send-mail-function 'message-send-mail-with-sendmail)
- (setq message-sendmail-envelope-from 'header)
- (setq smtpmail-debug-info t))
-
(provide 'mail-config)
;;; mail-config.el ends here