ENH make email config modular
This commit is contained in:
parent
810f759d1c
commit
6df300b58a
366
etc/conf.org
366
etc/conf.org
|
@ -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)))))
|
||||||
|
|
||||||
|
;; display mu4e in same window
|
||||||
|
(add-to-list 'display-buffer-alist
|
||||||
|
`(,(regexp-quote mu4e-main-buffer-name)
|
||||||
|
display-buffer-same-window))
|
||||||
|
|
||||||
(setq mail-user-agent 'mu4e-user-agent
|
;; special mark for junk (which is different from trash)
|
||||||
message-kill-buffer-on-exit t
|
;; trash = delete later
|
||||||
|
;; junk = spam, which I don't want to delete so I can train spam filters
|
||||||
|
;;
|
||||||
|
;; NOTE weird cross symbol picked because it looks like a certain digit
|
||||||
|
(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"))))
|
||||||
|
|
||||||
;; misc
|
;; buttload of common settings I like
|
||||||
mu4e-change-filenames-when-moving t
|
(setq mail-user-agent 'mu4e-user-agent
|
||||||
mu4e-confirm-quit nil
|
message-kill-buffer-on-exit t
|
||||||
mu4e-compose-dont-reply-to-self t
|
|
||||||
mu4e-get-mail-command "mbsync -a && mu-index-emacs-maybe"
|
|
||||||
mu4e-use-fancy-chars t
|
|
||||||
|
|
||||||
;; sub some fancy chars that don't have valid codes
|
;; misc
|
||||||
mu4e-headers-trashed-mark '("T" . "Ω")
|
mu4e-change-filenames-when-moving t
|
||||||
mu4e-headers-unread-mark '("U" . "✉")
|
mu4e-confirm-quit nil
|
||||||
mu4e-headers-personal-mark '("P" . "Ρ")
|
mu4e-compose-dont-reply-to-self t
|
||||||
mu4e-headers-list-mark '("L" . "Λ")
|
mu4e-get-mail-command "mbsync -a && mu-index-emacs-maybe"
|
||||||
mu4e-headers-attach-mark '("a" . "ɑ")
|
mu4e-use-fancy-chars t
|
||||||
mu4e-headers-thread-root-prefix '("* " . "● ")
|
|
||||||
mu4e-headers-threaded-label '("T" . "Ψ")
|
|
||||||
mu4e-headers-related-label '("R" . "↔")
|
|
||||||
|
|
||||||
;; directories
|
;; sub some fancy chars that don't have valid codes
|
||||||
mu4e-attachment-dir "~/Downloads"
|
mu4e-headers-trashed-mark '("T" . "Ω")
|
||||||
|
mu4e-headers-unread-mark '("U" . "✉")
|
||||||
|
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" . "↔")
|
||||||
|
|
||||||
;; headers
|
;; directories
|
||||||
mu4e-headers-show-target nil
|
mu4e-attachment-dir "~/Downloads"
|
||||||
mu4e-headers-fields '((:human-date . 11)
|
|
||||||
(:flags . 5)
|
|
||||||
(:from . 22)
|
|
||||||
(:thread-subject))
|
|
||||||
mu4e-headers-date-format "%F"
|
|
||||||
mu4e-headers-time-format "%R"
|
|
||||||
|
|
||||||
;; view
|
;; headers
|
||||||
mu4e-view-show-images t
|
mu4e-headers-show-target nil
|
||||||
mu4e-view-show-addresses t
|
mu4e-headers-fields '((:human-date . 11)
|
||||||
mu4e-view-prefer-html t
|
(:flags . 5)
|
||||||
|
(:from . 22)
|
||||||
|
(:thread-subject))
|
||||||
|
mu4e-headers-date-format "%F"
|
||||||
|
mu4e-headers-time-format "%R"
|
||||||
|
|
||||||
;; compose
|
;; view
|
||||||
mu4e-compose-signature-auto-include nil ;; sigs are annoying by default
|
mu4e-view-show-images t
|
||||||
mu4e-compose-signature "Thank you,\nNathan Dwarshuis"
|
mu4e-view-show-addresses t
|
||||||
|
mu4e-view-prefer-html t
|
||||||
|
|
||||||
;; aliases
|
;; compose
|
||||||
mail-personal-alias-file (no-littering-expand-etc-file-name
|
message-signature nil
|
||||||
"mailrc")
|
|
||||||
|
|
||||||
;; yanking (aka citing)
|
;; aliases
|
||||||
message-yank-prefix "" ;; the ">" characters are annoying
|
mail-personal-alias-file (no-littering-expand-etc-file-name
|
||||||
message-yank-cited-prefix ""
|
"mailrc")
|
||||||
message-yank-empty-prefix ""
|
|
||||||
|
|
||||||
;; contexts (multiple inboxes)
|
;; yanking (aka citing)
|
||||||
mu4e-context-policy 'pick-first
|
message-yank-prefix "" ;; the ">" characters are annoying
|
||||||
mu4e-compose-context-policy 'ask-if-none
|
message-yank-cited-prefix ""
|
||||||
mu4e-contexts
|
message-yank-empty-prefix ""
|
||||||
(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
|
;; contexts (multiple inboxes)
|
||||||
(add-hook 'mu4e-compose-mode-hook 'turn-off-auto-fill)
|
mu4e-context-policy 'pick-first
|
||||||
(add-hook 'mu4e-compose-mode-hook 'visual-line-mode)
|
mu4e-compose-context-policy 'ask-if-none)
|
||||||
(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
|
;; enable visual line mode and spell checking
|
||||||
;; This is enabled by using 32 underscores followed by the addressing
|
(add-hook 'mu4e-compose-mode-hook 'turn-off-auto-fill)
|
||||||
;; info of the previou message(s).
|
(add-hook 'mu4e-compose-mode-hook 'visual-line-mode)
|
||||||
(require 'nnheader) ; necessary for the header macros below
|
(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)))
|
||||||
|
|
||||||
(defun nd/message-insert-citation-header ()
|
;; Outlook doesn't know how to fold mu4e messages by default
|
||||||
"Insert the header of the reply message."
|
;; This is enabled by using 32 underscores followed by the addressing
|
||||||
(let* ((h message-reply-headers)
|
;; info of the previou message(s).
|
||||||
(sep "________________________________")
|
(require 'nnheader) ; necessary for the header macros below
|
||||||
(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)
|
(defun nd/message-insert-citation-header ()
|
||||||
|
"Insert the header of the reply message."
|
||||||
|
(let* ((h message-reply-headers)
|
||||||
|
(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"))))
|
||||||
|
|
||||||
;; prevent html to text conversion from destroying links
|
(setq message-citation-line-function 'nd/message-insert-citation-header)
|
||||||
(setq
|
|
||||||
mu4e-compose-pre-hook
|
|
||||||
(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)
|
;; prevent html to text conversion from destroying links
|
||||||
;; (require 'smtpmail-async)
|
(setq
|
||||||
(setq send-mail-function 'smtpmail-send-it
|
mu4e-compose-pre-hook
|
||||||
smtpmail-debug-info nil
|
(lambda ()
|
||||||
auth-source-debug nil
|
(let* ((msg mu4e-compose-parent-message)
|
||||||
message-send-mail-function 'smtpmail-send-it)
|
(html (and msg (plist-get msg :body-html)))
|
||||||
(setq auth-sources '(password-store))
|
;; 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)))))
|
||||||
|
|
||||||
(defun nd/mu-init ()
|
(setq send-mail-function 'smtpmail-send-it
|
||||||
"Initialize the mu database"
|
smtpmail-debug-info nil
|
||||||
(->> mu4e-contexts
|
auth-source-debug nil
|
||||||
(--map (->> (mu4e-context-vars it)
|
message-send-mail-function 'smtpmail-send-it)
|
||||||
(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)
|
;; load instance-specific accounts
|
||||||
(->> (format "pass email/%s/%s" user type)
|
(load-file acnts-path))))
|
||||||
(shell-command-to-string)
|
|
||||||
(s-trim)))
|
|
||||||
|
|
||||||
(defun nd/xoauth2-get-secrets (host user port)
|
|
||||||
(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
|
|
||||||
:straight t
|
|
||||||
:after smtpmail
|
|
||||||
:config
|
|
||||||
(setq auth-source-xoauth2-creds #'nd/xoauth2-get-secrets)
|
|
||||||
(add-to-list 'smtpmail-auth-supported 'xoauth2)
|
|
||||||
(auth-source-xoauth2-enable)))
|
|
||||||
#+END_SRC
|
#+END_SRC
|
||||||
** shell
|
** shell
|
||||||
#+begin_src emacs-lisp
|
#+begin_src emacs-lisp
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
!mu4e
|
Loading…
Reference in New Issue