ENH make email config modular

This commit is contained in:
Nathan Dwarshuis 2024-03-14 10:19:08 -04:00
parent 810f759d1c
commit 6df300b58a
2 changed files with 179 additions and 194 deletions

View File

@ -3402,223 +3402,207 @@ Initialize by running =nd/mu-init=.
#+BEGIN_SRC emacs-lisp #+BEGIN_SRC emacs-lisp
(nd/require-bin "pandoc" :aur "pandoc-bin") (nd/require-bin "pandoc" :aur "pandoc-bin")
(nd/when-bin "mu"
(require 'mu4e)
(use-package password-store (let ((acnts-path (f-join (nd/expand-lib-directory "mu4e") "accounts.el")))
:straight t) (when (f-exists-p acnts-path)
(nd/when-bin "mu"
;; load mu itself
(require 'mu4e)
(require 'smtpmail)
;; (require 'smtpmail-async)
(defun nd/mu4e-junk-folder (msg) ;;
(->> (mu4e-context-determine msg nil) ;; apply common config shared b/t all accounts I use
(mu4e-context-vars) ;;
(alist-get 'nd/mu4e-junk-folder)))
(defun nd/mu4e-headers-mark-for-junk () (defun nd/mu-init (maildir)
(interactive) "Initialize the mu database using available contexts."
(mu4e-headers-mark-and-next 'junk)) (->> mu4e-contexts
(--map (->> (mu4e-context-vars it)
(alist-get 'user-mail-address)
(format "--my-address=%s")))
(s-join " ")
(format "mu init --maildir %s %s" maildir)
(shell-command-to-string)))
(defun nd/make-mu4e-context (name dir addr smtp-srv sent-behavior) (defun nd/mu4e-junk-folder (msg)
(let* ((trash (format "/%s/trash" dir)) "Hacky function to return junk folder from context.
(drafts (format "/%s/drafts" dir))
(sent (format "/%s/sent" dir))
(archive (format "/%s/archive" dir))
(inbox (format "/%s/inbox" dir))
(junk (format "/%s/junk" dir))
(shortcuts (--map (list :maildir (car it) :key (cdr it))
`((,trash . ?t)
(,drafts . ?d)
(,sent . ?s)
(,archive . ?a)
(,inbox . ?i)
(,junk . ?j))))
(mf (lambda (d msg) Must be bound to symbol `nd/mu4e-junk-folder`."
(-some--> msg (->> (mu4e-context-determine msg nil)
(mu4e-message-field it :maildir) (mu4e-context-vars)
(string-prefix-p (concat "/" d) it))))) (alist-get 'nd/mu4e-junk-folder)))
(make-mu4e-context
:name name
:match-func (-partial mf dir) ; use lexical scope here
:vars `((mu4e-trash-folder . ,trash)
(mu4e-drafts-folder . ,drafts)
(mu4e-sent-folder . ,sent)
(mu4e-refile-folder . ,archive)
(nd/mu4e-junk-folder . ,junk)
(mu4e-sent-messages-behavior . ,sent-behavior)
(smtpmail-stream-type . starttls)
(smtpmail-smtp-server . ,smtp-srv)
(smtpmail-smtp-service . 587)
(smtpmail-smtp-user . ,addr)
(user-mail-address . ,addr)
(mu4e-maildir-shortcuts . ,shortcuts)))))
;; display mu4e in same window (defun nd/mu4e-headers-mark-for-junk ()
(add-to-list 'display-buffer-alist "Function to mark messages as junk."
`(,(regexp-quote mu4e-main-buffer-name) (interactive)
display-buffer-same-window)) (mu4e-headers-mark-and-next 'junk))
(add-to-list (defun nd/make-mu4e-context (name dir addr smtp-srv smtp-tls sent-behavior)
'mu4e-marks (-let* ((trash (format "/%s/trash" dir))
'(junk :char ("j" . "┻") (drafts (format "/%s/drafts" dir))
:prompt "junk" (sent (format "/%s/sent" dir))
:dyn-target (archive (format "/%s/archive" dir))
(lambda (target msg) (nd/mu4e-junk-folder msg)) (inbox (format "/%s/inbox" dir))
:action (junk (format "/%s/junk" dir))
(lambda (shortcuts (--map (list :maildir (car it) :key (cdr it))
(docid msg target) `((,trash . ?t)
(mu4e--server-move docid (,drafts . ?d)
(mu4e--mark-check-target target) (,sent . ?s)
"-N")))) (,archive . ?a)
(,inbox . ?i)
(,junk . ?j))))
;; either use TLS or no authentication for outgoing
((smtp-proto smtp-port) (if smtp-tls
'(starttls 587)
'(nil 25)))
(mf (lambda (d msg)
(-some--> msg
(mu4e-message-field it :maildir)
(string-prefix-p (concat "/" d) it)))))
(make-mu4e-context
:name name
:match-func (-partial mf dir) ; use lexical scope here
:vars `((mu4e-trash-folder . ,trash)
(mu4e-drafts-folder . ,drafts)
(mu4e-sent-folder . ,sent)
(mu4e-refile-folder . ,archive)
(nd/mu4e-junk-folder . ,junk)
(mu4e-sent-messages-behavior . ,sent-behavior)
(smtpmail-stream-type . ,smtp-proto)
(smtpmail-smtp-server . ,smtp-srv)
(smtpmail-smtp-service . ,smtp-port)
(smtpmail-smtp-user . ,addr)
(user-mail-address . ,addr)
(mu4e-maildir-shortcuts . ,shortcuts)))))
(setq mail-user-agent 'mu4e-user-agent ;; display mu4e in same window
message-kill-buffer-on-exit t (add-to-list 'display-buffer-alist
`(,(regexp-quote mu4e-main-buffer-name)
display-buffer-same-window))
;; misc ;; special mark for junk (which is different from trash)
mu4e-change-filenames-when-moving t ;; trash = delete later
mu4e-confirm-quit nil ;; junk = spam, which I don't want to delete so I can train spam filters
mu4e-compose-dont-reply-to-self t ;;
mu4e-get-mail-command "mbsync -a && mu-index-emacs-maybe" ;; NOTE weird cross symbol picked because it looks like a certain digit
mu4e-use-fancy-chars t (add-to-list
'mu4e-marks
'(junk :char ("j" . "┻")
:prompt "junk"
:dyn-target
(lambda (target msg) (nd/mu4e-junk-folder msg))
:action
(lambda
(docid msg target)
(mu4e--server-move docid
(mu4e--mark-check-target target)
"-N"))))
;; sub some fancy chars that don't have valid codes ;; buttload of common settings I like
mu4e-headers-trashed-mark '("T" . "Ω") (setq mail-user-agent 'mu4e-user-agent
mu4e-headers-unread-mark '("U" . "✉") message-kill-buffer-on-exit t
mu4e-headers-personal-mark '("P" . "Ρ")
mu4e-headers-list-mark '("L" . "Λ")
mu4e-headers-attach-mark '("a" . "ɑ")
mu4e-headers-thread-root-prefix '("* " . "● ")
mu4e-headers-threaded-label '("T" . "Ψ")
mu4e-headers-related-label '("R" . "↔")
;; directories ;; misc
mu4e-attachment-dir "~/Downloads" mu4e-change-filenames-when-moving t
mu4e-confirm-quit nil
;; headers mu4e-compose-dont-reply-to-self t
mu4e-headers-show-target nil mu4e-get-mail-command "mbsync -a && mu-index-emacs-maybe"
mu4e-headers-fields '((:human-date . 11) mu4e-use-fancy-chars t
(:flags . 5)
(:from . 22)
(:thread-subject))
mu4e-headers-date-format "%F"
mu4e-headers-time-format "%R"
;; view ;; sub some fancy chars that don't have valid codes
mu4e-view-show-images t mu4e-headers-trashed-mark '("T" . "Ω")
mu4e-view-show-addresses t mu4e-headers-unread-mark '("U" . "✉")
mu4e-view-prefer-html t mu4e-headers-personal-mark '("P" . "Ρ")
mu4e-headers-list-mark '("L" . "Λ")
mu4e-headers-attach-mark '("a" . "ɑ")
mu4e-headers-thread-root-prefix '("* " . "● ")
mu4e-headers-threaded-label '("T" . "Ψ")
mu4e-headers-related-label '("R" . "↔")
;; compose ;; directories
mu4e-compose-signature-auto-include nil ;; sigs are annoying by default mu4e-attachment-dir "~/Downloads"
mu4e-compose-signature "Thank you,\nNathan Dwarshuis"
;; headers
mu4e-headers-show-target nil
mu4e-headers-fields '((:human-date . 11)
(:flags . 5)
(:from . 22)
(:thread-subject))
mu4e-headers-date-format "%F"
mu4e-headers-time-format "%R"
;; aliases ;; view
mail-personal-alias-file (no-littering-expand-etc-file-name mu4e-view-show-images t
"mailrc") mu4e-view-show-addresses t
mu4e-view-prefer-html t
;; yanking (aka citing) ;; compose
message-yank-prefix "" ;; the ">" characters are annoying message-signature nil
message-yank-cited-prefix ""
message-yank-empty-prefix ""
;; contexts (multiple inboxes) ;; aliases
mu4e-context-policy 'pick-first mail-personal-alias-file (no-littering-expand-etc-file-name
mu4e-compose-context-policy 'ask-if-none "mailrc")
mu4e-contexts
(list
(nd/make-mu4e-context "personal"
"yavin4"
"ndwar@yavin4.ch"
"peart4prez.yavin4.ch"
'sent)
(nd/make-mu4e-context "alpha"
"gmail"
"natedwarshuis@gmail.com"
"smtp.gmail.com"
'delete)))
;; enable visual line mode and spell checking
(add-hook 'mu4e-compose-mode-hook 'turn-off-auto-fill)
(add-hook 'mu4e-compose-mode-hook 'visual-line-mode)
(add-hook 'mu4e-view-mode-hook 'turn-off-auto-fill)
(add-hook 'mu4e-view-mode-hook 'visual-line-mode)
(add-hook 'mu4e-compose-mode-hook (lambda () (flyspell-mode 1)))
;; Outlook doesn't know how to fold mu4e messages by default
;; This is enabled by using 32 underscores followed by the addressing
;; info of the previou message(s).
(require 'nnheader) ; necessary for the header macros below
(defun nd/message-insert-citation-header () ;; yanking (aka citing)
"Insert the header of the reply message." message-yank-prefix "" ;; the ">" characters are annoying
(let* ((h message-reply-headers) message-yank-cited-prefix ""
(sep "________________________________") message-yank-empty-prefix ""
(from (concat "From: " (mail-header-from h)))
(date (concat "Sent: " (mail-header-date h)))
(to (concat "To: " user-full-name))
(subj (concat "Subject: " (message-strip-subject-re (mail-header-subject h)))))
(insert (string-join `("" ,sep ,from ,date ,to ,subj "") "\n"))))
(setq message-citation-line-function 'nd/message-insert-citation-header)
;; prevent html to text conversion from destroying links ;; contexts (multiple inboxes)
(setq mu4e-context-policy 'pick-first
mu4e-compose-pre-hook mu4e-compose-context-policy 'ask-if-none)
(lambda ()
(let* ((msg mu4e-compose-parent-message)
(html (and msg (plist-get msg :body-html)))
;; oops, mu4e screwed up
(mu4e-html2text-command
(nd/if-bin "pandoc"
"pandoc -f html -t plain --reference-links"
'mu4e-shr2text)))
(when (and html mu4e-view-prefer-html (member mu4e-compose-type '(reply forward)))
;; hackity hack, since the normal mu4e-message-body-text function
;; does not render the desired html, do it here and force the
;; aforementioned function to only look at text by removing
;; the html
(plist-put msg :body-txt (mu4e~html2text-shell msg mu4e-html2text-command))
(plist-put msg :body-html nil)))))
(require 'smtpmail) ;; enable visual line mode and spell checking
;; (require 'smtpmail-async) (add-hook 'mu4e-compose-mode-hook 'turn-off-auto-fill)
(setq send-mail-function 'smtpmail-send-it (add-hook 'mu4e-compose-mode-hook 'visual-line-mode)
smtpmail-debug-info nil (add-hook 'mu4e-view-mode-hook 'turn-off-auto-fill)
auth-source-debug nil (add-hook 'mu4e-view-mode-hook 'visual-line-mode)
message-send-mail-function 'smtpmail-send-it) (add-hook 'mu4e-compose-mode-hook (lambda () (flyspell-mode 1)))
(setq auth-sources '(password-store))
(defun nd/mu-init () ;; Outlook doesn't know how to fold mu4e messages by default
"Initialize the mu database" ;; This is enabled by using 32 underscores followed by the addressing
(->> mu4e-contexts ;; info of the previou message(s).
(--map (->> (mu4e-context-vars it) (require 'nnheader) ; necessary for the header macros below
(alist-get 'user-mail-address)
(format "--my-address=%s")))
(s-join " ")
(format "mu init --maildir /mnt/data/Mail %s")
(shell-command-to-string)))
(defun nd/lookup-oauth-secret (type user) (defun nd/message-insert-citation-header ()
(->> (format "pass email/%s/%s" user type) "Insert the header of the reply message."
(shell-command-to-string) (let* ((h message-reply-headers)
(s-trim))) (sep "________________________________")
(from (concat "From: " (mail-header-from h)))
(date (concat "Sent: " (mail-header-date h)))
(to (concat "To: " user-full-name))
(subj (concat "Subject: " (message-strip-subject-re (mail-header-subject h)))))
(insert (string-join `("" ,sep ,from ,date ,to ,subj "") "\n"))))
(defun nd/xoauth2-get-secrets (host user port) (setq message-citation-line-function 'nd/message-insert-citation-header)
(when (and (string= host "smtp.gmail.com")
(string= user "natedwarshuis@gmail.com")
(string= port "587"))
(list :token-url (nd/lookup-oauth-secret "token_url" user)
:client-id (nd/lookup-oauth-secret "client_id" user)
:client-secret (nd/lookup-oauth-secret "client_secret" user)
:refresh-token (nd/lookup-oauth-secret "refresh_token" user))))
(use-package auth-source-xoauth2 ;; prevent html to text conversion from destroying links
:straight t (setq
:after smtpmail mu4e-compose-pre-hook
:config (lambda ()
(setq auth-source-xoauth2-creds #'nd/xoauth2-get-secrets) (let* ((msg mu4e-compose-parent-message)
(add-to-list 'smtpmail-auth-supported 'xoauth2) (html (and msg (plist-get msg :body-html)))
(auth-source-xoauth2-enable))) ;; oops, mu4e screwed up
(mu4e-html2text-command
(nd/if-bin "pandoc"
"pandoc -f html -t plain --reference-links"
'mu4e-shr2text)))
(when (and html mu4e-view-prefer-html (member mu4e-compose-type '(reply forward)))
;; hackity hack, since the normal mu4e-message-body-text function
;; does not render the desired html, do it here and force the
;; aforementioned function to only look at text by removing
;; the html
(plist-put msg :body-txt (mu4e~html2text-shell msg mu4e-html2text-command))
(plist-put msg :body-html nil)))))
(setq send-mail-function 'smtpmail-send-it
smtpmail-debug-info nil
auth-source-debug nil
message-send-mail-function 'smtpmail-send-it)
;; load instance-specific accounts
(load-file acnts-path))))
#+END_SRC #+END_SRC
** shell ** shell
#+begin_src emacs-lisp #+begin_src emacs-lisp

1
local/lib/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
!mu4e