2019-05-05 14:11:59 -04:00
|
|
|
;;; email/mu4e/config.el -*- lexical-binding: t; -*-
|
2017-04-08 01:31:20 -04:00
|
|
|
|
2019-05-05 14:11:59 -04:00
|
|
|
(defvar +mu4e-backend 'mbsync
|
2018-01-24 15:08:43 -05:00
|
|
|
"Which backend to use. Can either be offlineimap, mbsync or nil (manual).")
|
2017-04-08 01:31:20 -04:00
|
|
|
|
|
|
|
|
|
|
|
;;
|
2019-05-05 14:11:59 -04:00
|
|
|
;;; Packages
|
2017-04-08 01:31:20 -04:00
|
|
|
|
2019-07-23 12:44:03 +02:00
|
|
|
(use-package! mu4e
|
2019-07-23 12:30:47 +02:00
|
|
|
:commands mu4e mu4e-compose-new
|
2018-01-24 15:08:43 -05:00
|
|
|
:init
|
2018-04-04 18:22:13 -04:00
|
|
|
(provide 'html2text) ; disable obsolete package
|
2020-04-27 14:08:36 -04:00
|
|
|
(when (or (not (require 'mu4e-meta nil t))
|
|
|
|
(version< mu4e-mu-version "1.4"))
|
2020-04-22 23:38:07 +02:00
|
|
|
(setq mu4e-maildir "~/.mail"
|
|
|
|
mu4e-user-mail-address-list nil))
|
2020-05-25 02:26:38 -04:00
|
|
|
(setq mu4e-attachment-dir
|
2020-05-26 13:23:02 -04:00
|
|
|
(lambda (&rest _)
|
|
|
|
(expand-file-name ".attachments" (mu4e-root-maildir))))
|
2017-04-08 01:31:20 -04:00
|
|
|
:config
|
2019-05-05 14:11:59 -04:00
|
|
|
(pcase +mu4e-backend
|
2018-01-24 15:08:43 -05:00
|
|
|
(`mbsync
|
|
|
|
(setq mu4e-get-mail-command "mbsync -a"
|
|
|
|
mu4e-change-filenames-when-moving t))
|
|
|
|
(`offlineimap
|
|
|
|
(setq mu4e-get-mail-command "offlineimap -o -q")))
|
|
|
|
|
|
|
|
(setq mu4e-update-interval nil
|
2017-04-08 01:31:20 -04:00
|
|
|
mu4e-compose-format-flowed t ; visual-line-mode + auto-fill upon sending
|
|
|
|
mu4e-view-show-addresses t
|
2018-01-24 15:08:43 -05:00
|
|
|
mu4e-sent-messages-behavior 'sent
|
|
|
|
mu4e-hide-index-messages t
|
2017-04-08 01:31:20 -04:00
|
|
|
;; try to show images
|
|
|
|
mu4e-view-show-images t
|
|
|
|
mu4e-view-image-max-width 800
|
2020-09-23 00:22:04 +08:00
|
|
|
mu4e-view-use-gnus t ; the way of the future: https://github.com/djcb/mu/pull/1442#issuecomment-591695814
|
2017-04-08 01:31:20 -04:00
|
|
|
;; configuration for sending mail
|
2017-04-17 02:17:10 -04:00
|
|
|
message-send-mail-function #'smtpmail-send-it
|
2017-04-08 01:31:20 -04:00
|
|
|
smtpmail-stream-type 'starttls
|
2018-01-24 15:08:43 -05:00
|
|
|
message-kill-buffer-on-exit t ; close after sending
|
2017-04-08 01:31:20 -04:00
|
|
|
;; start with the first (default) context;
|
|
|
|
mu4e-context-policy 'pick-first
|
|
|
|
;; compose with the current context, or ask
|
|
|
|
mu4e-compose-context-policy 'ask-if-none
|
2021-07-09 20:16:11 +03:00
|
|
|
;; use helm/ivy/vertico
|
2018-01-24 15:08:43 -05:00
|
|
|
mu4e-completing-read-function
|
2021-07-09 20:16:11 +03:00
|
|
|
(cond ((featurep! :completion ivy) #'ivy-completing-read)
|
|
|
|
((featurep! :completion helm) #'completing-read)
|
|
|
|
((featurep! :completion vertico) #'completing-read)
|
2018-01-24 15:08:43 -05:00
|
|
|
(t #'ido-completing-read))
|
2017-04-08 01:31:20 -04:00
|
|
|
;; no need to ask
|
2018-10-03 09:05:36 +13:00
|
|
|
mu4e-confirm-quit nil
|
2017-04-09 17:42:17 -04:00
|
|
|
;; remove 'lists' column
|
2017-04-14 02:36:36 -04:00
|
|
|
mu4e-headers-fields
|
|
|
|
'((:account . 12)
|
|
|
|
(:human-date . 12)
|
|
|
|
(:flags . 4)
|
|
|
|
(:from . 25)
|
2018-01-24 15:08:43 -05:00
|
|
|
(:subject)))
|
|
|
|
|
2019-01-21 16:10:27 -08:00
|
|
|
;; set mail user agent
|
|
|
|
(setq mail-user-agent 'mu4e-user-agent)
|
|
|
|
|
2020-09-23 00:23:01 +08:00
|
|
|
;; Set the icons only when a graphical frame has been created
|
|
|
|
(if (display-graphic-p)
|
|
|
|
(mu4e~initialise-icons)
|
|
|
|
;; When it's the server, wait till the first graphical frame
|
|
|
|
(add-hook! 'server-after-make-frame-hook
|
|
|
|
(defun mu4e~initialise-icons-hook ()
|
|
|
|
(when (display-graphic-p)
|
|
|
|
(mu4e~initialise-icons)
|
|
|
|
(remove-hook #'mu4e~initialise-icons-hook)))))
|
2017-04-18 21:04:25 -04:00
|
|
|
|
2020-09-23 01:22:29 +08:00
|
|
|
;; Header view
|
|
|
|
|
2020-09-23 01:02:40 +08:00
|
|
|
(setq mu4e-headers-fields
|
|
|
|
'((:account . 12)
|
|
|
|
(:human-date . 8)
|
|
|
|
(:flags . 6) ; 3 icon flags
|
|
|
|
(:from . 25)
|
|
|
|
(:subject))
|
|
|
|
|
|
|
|
(plist-put (cdr (assoc :flags mu4e-header-info)) :shortname " Flags") ; default=Flgs
|
|
|
|
|
2020-09-23 01:22:29 +08:00
|
|
|
(defvar mu4e~header-colourised-faces
|
|
|
|
'(all-the-icons-lblue
|
|
|
|
all-the-icons-purple
|
|
|
|
all-the-icons-blue-alt
|
|
|
|
all-the-icons-green
|
|
|
|
all-the-icons-maroon
|
|
|
|
all-the-icons-yellow
|
|
|
|
all-the-icons-orange))
|
2017-04-09 17:42:17 -04:00
|
|
|
|
2020-09-23 01:22:29 +08:00
|
|
|
;; Add a column to display what email account the email belongs to.
|
|
|
|
(setq mu4e-header-info-custom
|
|
|
|
'((:account .
|
|
|
|
(:name "account"
|
|
|
|
:shortname "account"
|
|
|
|
:help "which account this email belongs to"
|
|
|
|
:function
|
|
|
|
(lambda (msg)
|
|
|
|
(let ((maildir
|
|
|
|
(mu4e-message-field msg :maildir)))
|
|
|
|
(mu4e-header-colourise
|
|
|
|
(replace-regexp-in-string
|
|
|
|
"^gmail"
|
|
|
|
(propertize "g" 'face 'bold-italic)
|
|
|
|
(format "%s"
|
|
|
|
(substring maildir 1
|
|
|
|
(string-match-p "/" maildir 1)))))))))
|
|
|
|
(:recipnum .
|
|
|
|
(:name "Number of recipients"
|
|
|
|
:shortname " ⭷"
|
|
|
|
:help "Number of recipients for this message"
|
|
|
|
:function
|
|
|
|
(lambda (msg)
|
|
|
|
(propertize (format "%2d"
|
|
|
|
(+ (length (mu4e-message-field msg :to))
|
|
|
|
(length (mu4e-message-field msg :cc))))
|
|
|
|
'face 'mu4e-footer-face)))))))
|
2020-09-23 01:32:18 +08:00
|
|
|
|
|
|
|
;; Marks usually affect the current view
|
2019-07-23 17:24:56 +02:00
|
|
|
(defadvice! +mu4e--refresh-current-view-a (&rest _)
|
|
|
|
:after #'mu4e-mark-execute-all (mu4e-headers-rerun-search))
|
2017-04-18 21:04:25 -04:00
|
|
|
|
2017-04-09 22:10:41 -04:00
|
|
|
;; Wrap text in messages
|
2018-10-24 01:09:17 -04:00
|
|
|
(setq-hook! 'mu4e-view-mode-hook truncate-lines nil)
|
2017-04-08 01:31:20 -04:00
|
|
|
|
2020-05-03 18:05:31 +02:00
|
|
|
;; Html mails might be better rendered in a browser
|
|
|
|
(add-to-list 'mu4e-view-actions '("View in browser" . mu4e-action-view-in-browser))
|
|
|
|
|
2020-09-23 01:32:18 +08:00
|
|
|
;; The header view needs a certain amount of horizontal space to
|
|
|
|
;; actually show you all the information you want to see
|
|
|
|
;; so if the header view is entered from a narrow frame,
|
|
|
|
;; it's probably worth trying to expand it
|
|
|
|
(defvar mu4e-min-header-frame-width 120
|
|
|
|
"Minimum reasonable with for the header view.")
|
|
|
|
(defun mu4e-widen-frame-maybe ()
|
|
|
|
"Expand the frame with if it's less than `mu4e-min-header-frame-width'."
|
|
|
|
(when (< (frame-width) mu4e-min-header-frame-width)
|
|
|
|
(set-frame-width (selected-frame) mu4e-min-header-frame-width)))
|
|
|
|
(add-hook 'mu4e-headers-mode-hook #'mu4e-widen-frame-maybe)
|
|
|
|
|
2017-04-08 01:31:20 -04:00
|
|
|
(when (fboundp 'imagemagick-register-types)
|
2017-04-19 13:18:03 -04:00
|
|
|
(imagemagick-register-types))
|
2020-09-23 01:52:38 +08:00
|
|
|
|
|
|
|
(map! :map mu4e-headers-mode-map
|
|
|
|
:e "l" #'mu4e-msg-to-agenda)
|
|
|
|
|
2019-10-21 02:01:37 +02:00
|
|
|
(map! :localleader
|
|
|
|
:map mu4e-compose-mode-map
|
|
|
|
:desc "send and exit" "s" #'message-send-and-exit
|
|
|
|
:desc "kill buffer" "d" #'message-kill-buffer
|
|
|
|
:desc "save draft" "S" #'message-dont-send
|
2020-09-23 01:35:59 +08:00
|
|
|
:desc "attach" "a" #'mail-add-attachment)
|
2020-09-23 13:00:33 +08:00
|
|
|
|
2020-09-23 01:35:59 +08:00
|
|
|
;; Due to evil, none of the marking commands work when making a visual selection in
|
|
|
|
;; the headers view of mu4e. Without overriding any evil commands we may actually
|
|
|
|
;; want to use in and evil selection, this can be easily fixed.
|
|
|
|
(when (featurep! :editor evil)
|
|
|
|
(map! :map mu4e-headers-mode-map
|
|
|
|
:v "*" #'mu4e-headers-mark-for-something
|
|
|
|
:v "!" #'mu4e-headers-mark-for-read
|
|
|
|
:v "?" #'mu4e-headers-mark-for-unread
|
2020-09-23 01:53:19 +08:00
|
|
|
:v "u" #'mu4e-headers-mark-for-unmark
|
|
|
|
:vn "l" #'mu4e-msg-to-agenda))
|
|
|
|
|
2020-09-23 01:55:37 +08:00
|
|
|
(add-hook 'mu4e-compose-pre-hook 'my-mu4e-set-account)
|
|
|
|
|
2020-09-23 13:00:33 +08:00
|
|
|
(advice-add #'mu4e~main-action-str :override #'mu4e~main-action-prettier-str))
|
2017-04-08 01:31:20 -04:00
|
|
|
|
2020-09-23 00:00:39 +08:00
|
|
|
(when (featurep! :lang org)
|
|
|
|
(use-package! org-msg
|
|
|
|
:hook (org-load . org-msg-mode)
|
|
|
|
:config
|
2020-09-23 13:08:57 +08:00
|
|
|
(setq org-msg-options "html-postamble:nil H:5 num:nil ^:{} toc:nil author:nil email:nil \\n:t tex:dvipng"
|
|
|
|
org-msg-startup "hidestars indent inlineimages"
|
|
|
|
org-msg-greeting-fmt "\nHi %s,\n\n"
|
2020-09-23 00:00:39 +08:00
|
|
|
org-msg-greeting-name-limit 3
|
2020-09-23 13:08:57 +08:00
|
|
|
org-msg-text-plain-alternative t)
|
2017-04-16 21:24:18 -04:00
|
|
|
|
2020-09-23 13:08:57 +08:00
|
|
|
(defvar org-msg-currently-exporting nil
|
|
|
|
"Helper variable to indicate whether org-msg is currently exporting the org buffer to HTML.
|
|
|
|
Usefull for affecting HTML export config.")
|
|
|
|
(defadvice! org-msg--now-exporting (&rest _)
|
|
|
|
:before #'org-msg-org-to-xml
|
|
|
|
(setq org-msg-currently-exporting t))
|
|
|
|
(defadvice! org-msg--not-exporting (&rest _)
|
|
|
|
:after #'org-msg-org-to-xml
|
|
|
|
(setq org-msg-currently-exporting nil))
|
|
|
|
|
|
|
|
(setq org-msg-enforce-css
|
|
|
|
(let* ((font-family '(font-family . "-apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, Oxygen, Ubuntu, Cantarell,\
|
|
|
|
\"Fira Sans\", \"Droid Sans\", \"Helvetica Neue\", Arial, sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\";"))
|
|
|
|
(monospace-font '(font-family . "SFMono-Regular, Menlo, Monaco, Consolas, \"Liberation Mono\", \"Courier New\", monospace;"))
|
|
|
|
(font-size '(font-size . "11pt"))
|
|
|
|
(font `(,font-family ,font-size))
|
|
|
|
(line-height '(line-height . "1.2"))
|
|
|
|
(theme-color "#8a0400")
|
|
|
|
(bold '(font-weight . "bold"))
|
|
|
|
(color `(color . ,theme-color))
|
|
|
|
(table `((margin-top . "6px") (margin-bottom . "6px")
|
|
|
|
(border-left . "none") (border-right . "none")
|
|
|
|
(border-top . "2px solid #222222") (border-bottom . "2px solid #222222")
|
|
|
|
))
|
|
|
|
(ftl-number `(,color ,bold (text-align . "left")))
|
|
|
|
(inline-modes '(asl c c++ conf cpp csv diff ditaa emacs-lisp
|
|
|
|
fundamental ini json makefile man org plantuml
|
|
|
|
python sh xml))
|
|
|
|
(inline-src `((background-color . "rgba(27,31,35,.05)")
|
|
|
|
(border-radius . "3px")
|
|
|
|
(padding . ".2em .4em")
|
|
|
|
(font-size . "90%") ,monospace-font
|
|
|
|
(margin . 0)))
|
|
|
|
(code-src
|
|
|
|
(mapcar (lambda (mode)
|
|
|
|
`(code ,(intern (concat "src src-" (symbol-name mode)))
|
|
|
|
,inline-src))
|
|
|
|
inline-modes)))
|
|
|
|
`((del nil ((color . "grey") (border-left . "none")
|
|
|
|
(text-decoration . "line-through") (margin-bottom . "0px")
|
|
|
|
(margin-top . "10px") (line-height . "11pt")))
|
|
|
|
(a nil (,color))
|
|
|
|
(a reply-header ((color . "black") (text-decoration . "none")))
|
|
|
|
(div reply-header ((padding . "3.0pt 0in 0in 0in")
|
|
|
|
(border-top . "solid #e1e1e1 1.0pt")
|
|
|
|
(margin-bottom . "20px")))
|
|
|
|
(span underline ((text-decoration . "underline")))
|
|
|
|
(li nil (,line-height (margin-bottom . "0px")
|
|
|
|
(margin-top . "2px")))
|
|
|
|
(nil org-ul ((list-style-type . "square")))
|
|
|
|
(nil org-ol (,@font ,line-height (margin-bottom . "0px")
|
|
|
|
(margin-top . "0px") (margin-left . "30px")
|
|
|
|
(padding-top . "0px") (padding-left . "5px")))
|
|
|
|
(nil signature (,@font (margin-bottom . "20px")))
|
|
|
|
(blockquote nil ((padding . "0px 10px") (margin-left . "10px")
|
|
|
|
(margin-top . "20px") (margin-bottom . "0")
|
|
|
|
(border-left . "3px solid #ccc") (font-style . "italic")
|
|
|
|
(background . "#f9f9f9")))
|
|
|
|
(code nil (,font-size ,monospace-font (background . "#f9f9f9")))
|
|
|
|
,@code-src
|
|
|
|
(nil linenr ((padding-right . "1em")
|
|
|
|
(color . "black")
|
|
|
|
(background-color . "#aaaaaa")))
|
|
|
|
(pre nil ((line-height . "1.2")
|
|
|
|
(color . ,(doom-color 'fg))
|
|
|
|
(background-color . ,(doom-color 'bg))
|
|
|
|
(margin . "4px 0px 8px 0px")
|
|
|
|
(padding . "8px 12px")
|
|
|
|
(width . "95%")
|
|
|
|
(border-radius . "5px")
|
|
|
|
(font-weight . "500")
|
|
|
|
,monospace-font))
|
|
|
|
(div org-src-container ((margin-top . "10px")))
|
|
|
|
(nil figure-number ,ftl-number)
|
|
|
|
(nil table-number)
|
|
|
|
(caption nil ((text-align . "left")
|
|
|
|
(background . ,theme-color)
|
|
|
|
(color . "white")
|
|
|
|
,bold))
|
|
|
|
(nil t-above ((caption-side . "top")))
|
|
|
|
(nil t-bottom ((caption-side . "bottom")))
|
|
|
|
(nil listing-number ,ftl-number)
|
|
|
|
(nil figure ,ftl-number)
|
|
|
|
(nil org-src-name ,ftl-number)
|
|
|
|
(img nil ((vertical-align . "middle")
|
|
|
|
(max-width . "100%")))
|
|
|
|
(img latex-fragment-inline ((transform . ,(format "translateY(-1px) scale(%.3f)"
|
|
|
|
(/ 1.0 (if (boundp 'preview-scale)
|
|
|
|
preview-scale 1.4))))
|
|
|
|
(margin . "0 -0.35em")))
|
|
|
|
(table nil (,@table ,line-height (border-collapse . "collapse")))
|
|
|
|
(th nil ((border . "none") (border-bottom . "1px solid #222222")
|
|
|
|
(background-color . "#EDEDED") (font-weight . "500")
|
|
|
|
(padding . "3px 10px")))
|
|
|
|
(td nil (,@table (padding . "1px 10px")
|
|
|
|
(background-color . "#f9f9f9") (border . "none")))
|
|
|
|
(td org-left ((text-align . "left")))
|
|
|
|
(td org-right ((text-align . "right")))
|
|
|
|
(td org-center ((text-align . "center")))
|
|
|
|
(kbd nil ((border . "1px solid #d1d5da") (border-radius . "3px")
|
|
|
|
(box-shadow . "inset 0 -1px 0 #d1d5da") (background-color . "#fafbfc")
|
|
|
|
(color . "#444d56") (padding . "3px 5px") (display . "inline-block")))
|
|
|
|
(div outline-text-4 ((margin-left . "15px")))
|
|
|
|
(div outline-4 ((margin-left . "10px")))
|
|
|
|
(h4 nil ((margin-bottom . "0px") (font-size . "11pt")))
|
|
|
|
(h3 nil ((margin-bottom . "0px")
|
|
|
|
,color (font-size . "14pt")))
|
|
|
|
(h2 nil ((margin-top . "20px") (margin-bottom . "20px")
|
|
|
|
,color (font-size . "18pt")))
|
|
|
|
(h1 nil ((margin-top . "20px")
|
|
|
|
(margin-bottom . "0px") ,color (font-size . "24pt")))
|
|
|
|
(p nil ((text-decoration . "none") (margin-bottom . "0px")
|
|
|
|
(margin-top . "10px") (line-height . "11pt") ,font-size
|
|
|
|
(max-width . "100ch")))
|
|
|
|
(b nil ((font-weight . "500") (color . ,theme-color)))
|
|
|
|
(div nil (,@font (line-height . "12pt"))))))))
|
2017-04-08 01:31:20 -04:00
|
|
|
|
2018-01-24 15:08:43 -05:00
|
|
|
|
|
|
|
;;
|
2019-05-05 14:11:59 -04:00
|
|
|
;;; Gmail integration
|
|
|
|
|
|
|
|
(when (featurep! +gmail)
|
|
|
|
(after! mu4e
|
|
|
|
;; don't save message to Sent Messages, Gmail/IMAP takes care of this
|
|
|
|
(setq mu4e-sent-messages-behavior 'delete
|
|
|
|
|
|
|
|
;; don't need to run cleanup after indexing for gmail
|
|
|
|
mu4e-index-cleanup nil
|
|
|
|
|
|
|
|
;; because gmail uses labels as folders we can use lazy check since
|
|
|
|
;; messages don't really "move"
|
|
|
|
mu4e-index-lazy-check t)
|
|
|
|
|
|
|
|
;; In my workflow, emails won't be moved at all. Only their flags/labels are
|
|
|
|
;; changed. Se we redefine the trash and refile marks not to do any moving.
|
|
|
|
;; However, the real magic happens in `+mu4e|gmail-fix-flags'.
|
|
|
|
;;
|
|
|
|
;; Gmail will handle the rest.
|
|
|
|
(defun +mu4e--mark-seen (docid _msg target)
|
|
|
|
(mu4e~proc-move docid (mu4e~mark-check-target target) "+S-u-N"))
|
|
|
|
|
2019-07-23 12:30:47 +02:00
|
|
|
(delq! 'delete mu4e-marks #'assq)
|
2019-05-05 14:11:59 -04:00
|
|
|
(setf (alist-get 'trash mu4e-marks)
|
|
|
|
(list :char '("d" . "▼")
|
|
|
|
:prompt "dtrash"
|
|
|
|
:dyn-target (lambda (_target msg) (mu4e-get-trash-folder msg))
|
|
|
|
:action #'+mu4e--mark-seen)
|
|
|
|
;; Refile will be my "archive" function.
|
|
|
|
(alist-get 'refile mu4e-marks)
|
2019-11-30 22:26:27 +08:00
|
|
|
(list :char '("r" . "▼")
|
|
|
|
:prompt "rrefile"
|
|
|
|
:dyn-target (lambda (_target msg) (mu4e-get-refile-folder msg))
|
2019-05-05 14:11:59 -04:00
|
|
|
:action #'+mu4e--mark-seen))
|
|
|
|
|
|
|
|
;; This hook correctly modifies gmail flags on emails when they are marked.
|
|
|
|
;; Without it, refiling (archiving), trashing, and flagging (starring) email
|
|
|
|
;; won't properly result in the corresponding gmail action, since the marks
|
|
|
|
;; are ineffectual otherwise.
|
2019-07-26 19:57:13 +02:00
|
|
|
(add-hook! 'mu4e-mark-execute-pre-hook
|
2019-07-23 12:30:47 +02:00
|
|
|
(defun +mu4e-gmail-fix-flags-h (mark msg)
|
|
|
|
(pcase mark
|
|
|
|
(`trash (mu4e-action-retag-message msg "-\\Inbox,+\\Trash,-\\Draft"))
|
|
|
|
(`refile (mu4e-action-retag-message msg "-\\Inbox"))
|
|
|
|
(`flag (mu4e-action-retag-message msg "+\\Starred"))
|
|
|
|
(`unflag (mu4e-action-retag-message msg "-\\Starred")))))))
|