aboutsummaryrefslogtreecommitdiff
path: root/modules/mail-config.el
diff options
context:
space:
mode:
Diffstat (limited to 'modules/mail-config.el')
-rw-r--r--modules/mail-config.el92
1 files changed, 73 insertions, 19 deletions
diff --git a/modules/mail-config.el b/modules/mail-config.el
index f71d6eeb5..08f50b12f 100644
--- a/modules/mail-config.el
+++ b/modules/mail-config.el
@@ -48,6 +48,31 @@
(defvar message-send-mail-function nil)
(defvar message-sendmail-envelope-from nil)
+(declare-function mu4e-message-field "mu4e-message")
+
+;; Refile (archive) target dispatch. A per-context `mu4e-refile-folder' string
+;; is unsafe: mu4e context :vars are sticky, so a value set when one context is
+;; active leaks into a later context that doesn't set its own -- archiving one
+;; account's mail into another's folder. A single function evaluated per
+;; message at refile time avoids that. Only cmail has a real synced Archive
+;; folder; the Gmail-backed accounts (gmail, dmail) sync no archive maildir, so
+;; refiling them would move mail into an unsynced, server-invisible folder
+;; (silent loss) -- signal instead.
+(defun cj/mu4e--refile-folder-for-maildir (maildir)
+ "Return the refile (archive) folder for MAILDIR, or signal when none exists.
+MAILDIR is a mu4e :maildir string such as \"/cmail/INBOX\"."
+ (cond
+ ((not (stringp maildir))
+ (user-error "Cannot refile: message has no maildir"))
+ ((string-prefix-p "/cmail" maildir) "/cmail/Archive")
+ (t
+ (user-error "No archive folder syncs for this account; refile disabled to avoid moving mail into an unsynced folder"))))
+
+(defun cj/mu4e--refile-folder (msg)
+ "Refile-folder function for `mu4e-refile-folder'.
+Dispatch on MSG's maildir via `cj/mu4e--refile-folder-for-maildir'."
+ (cj/mu4e--refile-folder-for-maildir (and msg (mu4e-message-field msg :maildir))))
+
(defcustom cj/smtpmail-debug-enabled nil
"Non-nil means enable verbose SMTP transport debug logging.
@@ -136,6 +161,12 @@ Prompts user for the action when executing."
(display-buffer-reuse-window display-buffer-same-window)
(inhibit-same-window . nil)))
+;; Keep global font-lock out of the mu4e buffers. mu4e paints header lines, the
+;; main menu, and view headers with manual `face' text properties; global
+;; font-lock strips them (the same failure the dashboard hit), leaving the
+;; buffers unthemed. Excluding these modes keeps mu4e's faces.
+(cj/exclude-from-global-font-lock 'mu4e-headers-mode 'mu4e-main-mode 'mu4e-view-mode)
+
(use-package mu4e
:ensure nil ;; mu4e gets installed by installing 'mu' via the system package manager
:load-path "/usr/share/emacs/site-lisp/mu4e/"
@@ -217,7 +248,8 @@ Prompts user for the action when executing."
:vars '((user-mail-address . "c@cjennings.net")
(user-full-name . "Craig Jennings")
(mu4e-drafts-folder . "/cmail/Drafts")
- (mu4e-sent-folder . "/cmail/Sent")))
+ (mu4e-sent-folder . "/cmail/Sent")
+ (mu4e-trash-folder . "/cmail/Trash")))
(make-mu4e-context
:name "deepsat.com"
@@ -232,6 +264,12 @@ Prompts user for the action when executing."
(mu4e-starred-folder . "/dmail/Starred")
(mu4e-trash-folder . "/dmail/Trash")))))
+ ;; Refile target is computed per message (see `cj/mu4e--refile-folder'), not
+ ;; set per context, because mu4e context :vars are sticky and would leak one
+ ;; account's archive folder into another. cmail archives to /cmail/Archive;
+ ;; gmail/dmail signal rather than move mail into an unsynced folder.
+ (setq mu4e-refile-folder #'cj/mu4e--refile-folder)
+
(setq mu4e-maildir-shortcuts
'(("/cmail/Inbox" . ?i)
("/cmail/Sent" . ?s)
@@ -379,6 +417,34 @@ Prompts user for the action when executing."
(cj/activate-mu4e-org-contacts-integration)) ;; end use-package mu4e
+;; ----------------------- Account Navigation Keymaps --------------------------
+;; The C-; e c/d/g submaps jump to each account's inbox views. Built from one
+;; template so the maildir prefix is the only per-account difference.
+
+;; eval-and-compile so the builder is defined when org-msg's :preface (below)
+;; calls it during byte-compilation, not only at load.
+(eval-and-compile
+ (defun cj/--mail-account-search-queries (account)
+ "Return an alist of (KEY . QUERY) mu4e searches for ACCOUNT's inbox.
+ACCOUNT is the maildir account name (\"cmail\", \"dmail\", \"gmail\"). The four
+entries scope inbox / unread / flagged / large searches to that account's
+INBOX maildir."
+ (let ((base (format "maildir:/%s/INBOX" account)))
+ (list (cons "i" base)
+ (cons "u" (concat base " AND flag:unread AND NOT flag:trashed"))
+ (cons "s" (concat base " AND flag:flagged"))
+ (cons "l" (concat base " AND size:5M..999M")))))
+
+ (defun cj/--mail-make-account-map (account)
+ "Build a mu4e navigation keymap for ACCOUNT (a maildir account name).
+Keys i/u/s/l run the inbox/unread/flagged/large searches from
+`cj/--mail-account-search-queries', each scoped to ACCOUNT."
+ (let ((map (make-sparse-keymap)))
+ (dolist (entry (cj/--mail-account-search-queries account) map)
+ (let ((query (cdr entry)))
+ (keymap-set map (car entry)
+ (lambda () (interactive) (mu4e-search query))))))))
+
;; ---------------------------------- Org-Msg ----------------------------------
;; user composes org mode; recipient receives html
@@ -387,24 +453,12 @@ Prompts user for the action when executing."
:defer 1
:after (org mu4e)
:preface
- (defvar-keymap cj/mail-cmail-map
- :doc "cmail account navigation"
- "i" (lambda () (interactive) (mu4e-search "maildir:/cmail/INBOX"))
- "u" (lambda () (interactive) (mu4e-search "maildir:/cmail/INBOX AND flag:unread AND NOT flag:trashed"))
- "s" (lambda () (interactive) (mu4e-search "maildir:/cmail/INBOX AND flag:flagged"))
- "l" (lambda () (interactive) (mu4e-search "maildir:/cmail/INBOX AND size:5M..999M")))
- (defvar-keymap cj/mail-dmail-map
- :doc "deepsat account navigation"
- "i" (lambda () (interactive) (mu4e-search "maildir:/dmail/INBOX"))
- "u" (lambda () (interactive) (mu4e-search "maildir:/dmail/INBOX AND flag:unread AND NOT flag:trashed"))
- "s" (lambda () (interactive) (mu4e-search "maildir:/dmail/INBOX AND flag:flagged"))
- "l" (lambda () (interactive) (mu4e-search "maildir:/dmail/INBOX AND size:5M..999M")))
- (defvar-keymap cj/mail-gmail-map
- :doc "gmail account navigation"
- "i" (lambda () (interactive) (mu4e-search "maildir:/gmail/INBOX"))
- "u" (lambda () (interactive) (mu4e-search "maildir:/gmail/INBOX AND flag:unread AND NOT flag:trashed"))
- "s" (lambda () (interactive) (mu4e-search "maildir:/gmail/INBOX AND flag:flagged"))
- "l" (lambda () (interactive) (mu4e-search "maildir:/gmail/INBOX AND size:5M..999M")))
+ (defvar cj/mail-cmail-map (cj/--mail-make-account-map "cmail")
+ "cmail account navigation.")
+ (defvar cj/mail-dmail-map (cj/--mail-make-account-map "dmail")
+ "deepsat account navigation.")
+ (defvar cj/mail-gmail-map (cj/--mail-make-account-map "gmail")
+ "gmail account navigation.")
(defvar-keymap cj/email-map
:doc "Email operations and account navigation"
"A" #'org-msg-attach-attach