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
|
|
|
|
|
2020-10-16 10:48:41 +08:00
|
|
|
|
(defvar +mu4e-personal-addresses 'nil
|
|
|
|
|
"Alternative to mu4e-personal-addresses that can be set for each account (mu4e context).")
|
2020-10-13 16:49:09 +02:00
|
|
|
|
|
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-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))
|
2021-04-26 12:04:16 +08:00
|
|
|
|
mu4e-attachment-dir
|
2021-09-11 22:20:34 +08:00
|
|
|
|
(concat
|
2021-09-15 02:41:02 +08:00
|
|
|
|
(if-let ((xdg-download-query (and (executable-find "xdg-user-dir")
|
|
|
|
|
(doom-call-process "xdg-user-dir" "DOWNLOAD")))
|
|
|
|
|
(xdg-download-dir (and (= 0 (car xdg-download-query)) (cdr xdg-download-query))))
|
|
|
|
|
xdg-download-dir
|
2021-09-11 22:20:34 +08:00
|
|
|
|
(expand-file-name (or (getenv "XDG_DOWNLOAD_DIR")
|
|
|
|
|
"Downloads")
|
|
|
|
|
"~"))
|
2021-09-15 02:41:02 +08:00
|
|
|
|
"/") ; a trailing / makes it easier to change directory in `read-file-name'
|
2017-04-08 01:31:20 -04:00
|
|
|
|
;; no need to ask
|
2018-10-03 09:05:36 +13:00
|
|
|
|
mu4e-confirm-quit nil
|
2020-10-01 18:23:28 +08:00
|
|
|
|
mu4e-headers-thread-single-orphan-prefix '("─>" . "─▶")
|
|
|
|
|
mu4e-headers-thread-orphan-prefix '("┬>" . "┬▶ ")
|
|
|
|
|
mu4e-headers-thread-last-child-prefix '("└>" . "╰▶")
|
|
|
|
|
mu4e-headers-thread-child-prefix '("├>" . "├▶")
|
|
|
|
|
mu4e-headers-thread-connection-prefix '("│" . "│ ")
|
2017-04-09 17:42:17 -04:00
|
|
|
|
;; remove 'lists' column
|
2017-04-14 02:36:36 -04:00
|
|
|
|
mu4e-headers-fields
|
2020-10-14 17:28:10 +08:00
|
|
|
|
'((:account-stripe . 1)
|
2020-10-01 18:23:28 +08:00
|
|
|
|
(:human-date . 8)
|
|
|
|
|
(:flags . 6) ; 3 icon flags
|
2020-10-14 17:28:10 +08:00
|
|
|
|
(:from-or-to . 25)
|
2018-01-24 15:08:43 -05:00
|
|
|
|
(:subject)))
|
|
|
|
|
|
2019-01-21 16:10:27 -08:00
|
|
|
|
;; set mail user agent
|
2020-10-01 18:23:28 +08:00
|
|
|
|
(setq mail-user-agent 'mu4e-user-agent
|
|
|
|
|
message-mail-user-agent 'mu4e-user-agent)
|
2019-01-21 16:10:27 -08:00
|
|
|
|
|
2020-09-23 00:23:01 +08:00
|
|
|
|
;; Set the icons only when a graphical frame has been created
|
|
|
|
|
(if (display-graphic-p)
|
2020-10-13 16:41:33 +08:00
|
|
|
|
(+mu4e-initialise-icons)
|
2020-09-23 00:23:01 +08:00
|
|
|
|
;; When it's the server, wait till the first graphical frame
|
2021-07-23 03:17:34 +08:00
|
|
|
|
(add-hook!
|
2020-10-15 22:30:46 +08:00
|
|
|
|
'server-after-make-frame-hook
|
|
|
|
|
(defun +mu4e-initialise-icons-hook ()
|
|
|
|
|
(when (display-graphic-p)
|
|
|
|
|
(+mu4e-initialise-icons)
|
|
|
|
|
(remove-hook 'server-after-make-frame-hook
|
|
|
|
|
#'+mu4e-initialise-icons-hook)))))
|
2017-04-18 21:04:25 -04:00
|
|
|
|
|
2020-09-25 16:37:11 +08:00
|
|
|
|
(plist-put (cdr (assoc :flags mu4e-header-info)) :shortname " Flags") ; default=Flgs
|
2020-10-01 18:23:28 +08:00
|
|
|
|
(add-to-list 'mu4e-bookmarks
|
2020-10-04 01:03:26 +08:00
|
|
|
|
'(:name "Flagged messages" :query "flag:flagged" :key ?f) t)
|
2020-09-23 01:02:40 +08:00
|
|
|
|
|
2021-07-23 03:20:22 +08:00
|
|
|
|
;; TODO avoid assuming that all-the-icons is present
|
|
|
|
|
(defvar +mu4e-header-colorized-faces
|
|
|
|
|
'(all-the-icons-green
|
|
|
|
|
all-the-icons-lblue
|
|
|
|
|
all-the-icons-purple-alt
|
|
|
|
|
all-the-icons-blue-alt
|
|
|
|
|
all-the-icons-purple
|
|
|
|
|
all-the-icons-yellow)
|
|
|
|
|
"Faces to use when coloring folders and account stripes.")
|
2020-10-04 01:00:01 +08:00
|
|
|
|
|
2021-07-29 17:58:54 +08:00
|
|
|
|
(defvar +mu4e-min-header-frame-width 120
|
|
|
|
|
"Minimum reasonable with for the header view.")
|
|
|
|
|
|
2020-10-14 17:28:10 +08:00
|
|
|
|
;; Add a column to display what email account the email belongs to,
|
|
|
|
|
;; and an account color stripe column
|
|
|
|
|
(defvar +mu4e-header--maildir-colors nil)
|
2020-09-23 01:22:29 +08:00
|
|
|
|
(setq mu4e-header-info-custom
|
|
|
|
|
'((:account .
|
2020-10-14 17:28:10 +08:00
|
|
|
|
(:name "Account"
|
|
|
|
|
:shortname "Account"
|
2020-10-22 00:23:25 +08:00
|
|
|
|
:help "which account/maildir this email belongs to"
|
2020-09-23 01:22:29 +08:00
|
|
|
|
:function
|
|
|
|
|
(lambda (msg)
|
2020-10-22 00:23:25 +08:00
|
|
|
|
(let ((maildir (replace-regexp-in-string
|
|
|
|
|
"\\`/?\\([^/]+\\)/.*\\'" "\\1"
|
2020-11-18 00:20:46 +08:00
|
|
|
|
(mu4e-message-field msg :maildir))))
|
|
|
|
|
(+mu4e-colorize-str
|
|
|
|
|
(replace-regexp-in-string
|
|
|
|
|
"^gmail"
|
|
|
|
|
(propertize "g" 'face 'bold-italic)
|
|
|
|
|
maildir)
|
|
|
|
|
'+mu4e-header--maildir-colors
|
|
|
|
|
maildir)))))
|
2020-10-14 17:28:10 +08:00
|
|
|
|
(:account-stripe .
|
|
|
|
|
(:name "Account"
|
|
|
|
|
:shortname "▐"
|
2020-10-22 00:23:25 +08:00
|
|
|
|
:help "Which account/maildir this email belongs to"
|
2020-10-14 17:28:10 +08:00
|
|
|
|
:function
|
|
|
|
|
(lambda (msg)
|
|
|
|
|
(let ((account
|
|
|
|
|
(replace-regexp-in-string
|
|
|
|
|
"\\`/?\\([^/]+\\)/.*\\'" "\\1"
|
|
|
|
|
(mu4e-message-field msg :maildir))))
|
|
|
|
|
(propertize
|
|
|
|
|
(+mu4e-colorize-str "▌" '+mu4e-header--maildir-colors account)
|
|
|
|
|
'help-echo account)))))
|
2020-09-23 01:22:29 +08:00
|
|
|
|
(: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))))
|
2020-09-25 16:37:11 +08:00
|
|
|
|
'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-10-22 00:24:26 +08:00
|
|
|
|
(when (fboundp 'make-xwidget)
|
|
|
|
|
(add-to-list 'mu4e-view-actions '("xwidgets view" . mu4e-action-view-with-xwidget)))
|
2020-05-03 18:05:31 +02:00
|
|
|
|
|
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
|
2021-07-31 01:10:54 +08:00
|
|
|
|
(defun +mu4e-widen-frame-maybe ()
|
2020-10-15 22:30:23 +08:00
|
|
|
|
"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)))
|
2021-07-31 01:10:54 +08:00
|
|
|
|
(add-hook 'mu4e-headers-mode-hook #'+mu4e-widen-frame-maybe)
|
2020-09-23 01:32:18 +08:00
|
|
|
|
|
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
|
|
|
|
|
2020-10-04 01:03:26 +08:00
|
|
|
|
(map! :map mu4e-main-mode-map
|
|
|
|
|
:ne "h" #'+workspace/other)
|
|
|
|
|
|
2020-09-23 01:52:38 +08:00
|
|
|
|
(map! :map mu4e-headers-mode-map
|
2020-10-31 19:04:29 +08:00
|
|
|
|
:vne "l" #'+mu4e/capture-msg-to-agenda)
|
2020-09-23 01:52:38 +08:00
|
|
|
|
|
2021-09-11 21:05:43 +08:00
|
|
|
|
;; Functionality otherwise obscured in mu4e 1.6
|
|
|
|
|
(when (version<= "1.6" mu4e-mu-version)
|
2021-09-11 22:18:41 +08:00
|
|
|
|
(defun +mu4e-view-select-attachment ()
|
2021-09-11 22:16:02 +08:00
|
|
|
|
"Use completing-read to select a single attachment.
|
|
|
|
|
Acts like a singular `mu4e-view-save-attachments', without the saving."
|
2021-09-11 23:27:52 +08:00
|
|
|
|
(if-let ((parts (delq nil (mapcar
|
|
|
|
|
(lambda (part)
|
|
|
|
|
(when (assoc "attachment" (cdr part))
|
|
|
|
|
part))
|
|
|
|
|
(mu4e~view-gather-mime-parts))))
|
|
|
|
|
(files (+mu4e-part-selectors parts)))
|
|
|
|
|
(cdr (assoc (completing-read "Select attachment: " (mapcar #'car files)) files))
|
|
|
|
|
(user-error (mu4e-format "No attached files found"))))
|
2021-09-11 22:16:02 +08:00
|
|
|
|
|
2021-09-11 22:18:41 +08:00
|
|
|
|
(defun +mu4e-view-open-attachment ()
|
2021-09-11 22:16:02 +08:00
|
|
|
|
"Select an attachment, and open it."
|
|
|
|
|
(interactive)
|
|
|
|
|
(mu4e~view-open-file
|
2021-09-11 22:18:41 +08:00
|
|
|
|
(mu4e~view-mime-part-to-temp-file (cdr (+mu4e-view-select-attachment)))))
|
2021-09-11 22:16:02 +08:00
|
|
|
|
|
2021-09-11 22:07:39 +08:00
|
|
|
|
(defun +mu4e-view-select-mime-part-action ()
|
|
|
|
|
"Select a MIME part, and perform an action on it."
|
|
|
|
|
(interactive)
|
2021-09-11 23:27:52 +08:00
|
|
|
|
(let ((labeledparts (+mu4e-part-selectors (mu4e~view-gather-mime-parts))))
|
|
|
|
|
(if labeledparts
|
|
|
|
|
(mu4e-view-mime-part-action
|
|
|
|
|
(cadr (assoc (completing-read "Select part: " (mapcar #'car labeledparts))
|
|
|
|
|
labeledparts)))
|
|
|
|
|
(user-error (mu4e-format "No parts found")))))
|
2021-09-11 22:07:39 +08:00
|
|
|
|
|
2021-09-11 21:05:43 +08:00
|
|
|
|
(map! :map mu4e-view-mode-map
|
2021-09-11 22:07:39 +08:00
|
|
|
|
:ne "A" #'+mu4e-view-select-mime-part-action
|
2021-09-11 22:16:02 +08:00
|
|
|
|
:ne "p" #'mu4e-view-save-attachments
|
2021-09-11 23:27:52 +08:00
|
|
|
|
:ne "o" #'+mu4e-view-open-attachment)
|
|
|
|
|
|
|
|
|
|
(defun +mu4e-part-selectors (parts)
|
|
|
|
|
"Generate selection strings for PARTS."
|
|
|
|
|
(if parts
|
|
|
|
|
(let (partinfo labeledparts maxfnamelen fnamefmt maxsizelen sizefmt)
|
|
|
|
|
(dolist (part parts)
|
|
|
|
|
(push (list :index (car part)
|
|
|
|
|
:mimetype (if (and (string= "text/plain" (caaddr part))
|
|
|
|
|
(alist-get 'charset (cdaddr part)))
|
|
|
|
|
(format "%s (%s)"
|
|
|
|
|
(caaddr part)
|
|
|
|
|
(alist-get 'charset (cdaddr part)))
|
|
|
|
|
(caaddr part))
|
|
|
|
|
:type (car (nth 5 part))
|
|
|
|
|
:filename (cdr (assoc 'filename (assoc "attachment" (cdr part))))
|
|
|
|
|
:size (file-size-human-readable (with-current-buffer (cadr part) (buffer-size)))
|
|
|
|
|
:part part)
|
|
|
|
|
partinfo))
|
|
|
|
|
(setq maxfnamelen (apply #'max 7 (mapcar (lambda (i) (length (plist-get i :filename))) partinfo))
|
|
|
|
|
fnamefmt (format " %%-%ds " maxfnamelen)
|
|
|
|
|
maxsizelen (apply #'max (mapcar (lambda (i) (length (plist-get i :size))) partinfo))
|
|
|
|
|
sizefmt (format "%%-%ds " maxsizelen))
|
|
|
|
|
(dolist (pinfo partinfo)
|
|
|
|
|
(push (cons (concat (propertize (format "%-2s " (plist-get pinfo :index)) 'face '(bold font-lock-type-face))
|
|
|
|
|
(when (featurep 'all-the-icons)
|
|
|
|
|
(all-the-icons-icon-for-file (or (plist-get pinfo :filename) "")))
|
|
|
|
|
(format fnamefmt (or (plist-get pinfo :filename)
|
|
|
|
|
(propertize (plist-get pinfo :type) 'face '(italic font-lock-doc-face))))
|
|
|
|
|
(format sizefmt (propertize (plist-get pinfo :size) 'face 'font-lock-builtin-face))
|
|
|
|
|
(propertize (plist-get pinfo :mimetype) 'face 'font-lock-constant-face))
|
|
|
|
|
(plist-get pinfo :part))
|
|
|
|
|
labeledparts))
|
|
|
|
|
labeledparts))))
|
2021-09-11 21:05:43 +08:00
|
|
|
|
|
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-10-31 19:34:42 +08:00
|
|
|
|
:desc "attach" "a" #'+mu4e/attach-files)
|
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-10-14 14:15:24 +08:00
|
|
|
|
:v "u" #'mu4e-headers-mark-for-unmark))
|
2020-09-23 01:53:19 +08:00
|
|
|
|
|
2020-10-14 15:37:15 +08:00
|
|
|
|
(add-hook 'mu4e-compose-pre-hook '+mu4e-set-from-address-h)
|
2020-09-23 01:55:37 +08:00
|
|
|
|
|
2021-07-31 01:11:11 +08:00
|
|
|
|
(defadvice! +mu4e-ensure-compose-writeable-a (&rest _)
|
|
|
|
|
"Ensure that compose buffers are writable.
|
|
|
|
|
This should already be the case yet it does not always seem to be."
|
|
|
|
|
:before #'mu4e-compose-new
|
|
|
|
|
:before #'mu4e-compose-reply
|
|
|
|
|
:before #'mu4e-compose-forward
|
|
|
|
|
:before #'mu4e-compose-resend
|
|
|
|
|
(read-only-mode -1))
|
|
|
|
|
|
2021-09-11 23:44:37 +08:00
|
|
|
|
(defvar +mu4e-main-bullet "⚫"
|
|
|
|
|
"Prefix to use instead of \" *\" in the mu4e main view.
|
|
|
|
|
This is enacted by `+mu4e~main-action-str-prettier-a' and
|
|
|
|
|
`+mu4e~main-keyval-str-prettier-a'.")
|
|
|
|
|
|
2021-06-19 03:22:53 +08:00
|
|
|
|
(advice-add #'mu4e~key-val :filter-return #'+mu4e~main-keyval-str-prettier-a)
|
2020-10-14 15:37:15 +08:00
|
|
|
|
(advice-add #'mu4e~main-action-str :override #'+mu4e~main-action-str-prettier-a)
|
2020-10-04 01:03:26 +08:00
|
|
|
|
(when (featurep! :editor evil)
|
2020-10-13 16:41:33 +08:00
|
|
|
|
;; As +mu4e~main-action-str-prettier replaces [k]ey with key q]uit should become quit
|
2020-10-13 17:21:52 +08:00
|
|
|
|
(setq evil-collection-mu4e-end-region-misc "quit"))
|
|
|
|
|
|
|
|
|
|
;; process lock control
|
|
|
|
|
(when IS-WINDOWS
|
2020-10-14 15:00:57 +08:00
|
|
|
|
(setq
|
|
|
|
|
+mu4e-lock-file (expand-file-name "~/AppData/Local/Temp/mu4e_lock")
|
|
|
|
|
+mu4e-lock-request-file (expand-file-name "~/AppData/Local/Temp/mu4e_lock_request")))
|
2020-10-13 17:21:52 +08:00
|
|
|
|
|
|
|
|
|
(add-hook 'kill-emacs-hook #'+mu4e-lock-file-delete-maybe)
|
|
|
|
|
(advice-add 'mu4e~start :around #'+mu4e-lock-start)
|
|
|
|
|
(advice-add 'mu4e-quit :after #'+mu4e-lock-file-delete-maybe))
|
2017-04-08 01:31:20 -04:00
|
|
|
|
|
2020-10-31 19:12:40 +08:00
|
|
|
|
(unless (featurep! +org)
|
|
|
|
|
(after! mu4e
|
|
|
|
|
(defun org-msg-mode (&optional _)
|
|
|
|
|
"Dummy function."
|
2020-11-05 02:16:27 +08:00
|
|
|
|
(message "Enable the +org mu4e flag to use org-msg-mode."))
|
2021-07-31 01:10:54 +08:00
|
|
|
|
(defun +mu4e-compose-org-msg-handle-toggle (&rest _)
|
2020-11-05 02:16:27 +08:00
|
|
|
|
"Placeholder to allow for the assumtion that this function is defined.
|
|
|
|
|
Ignores all arguments and returns nil."
|
|
|
|
|
nil)))
|
2020-10-31 19:12:40 +08:00
|
|
|
|
|
2020-10-01 01:56:45 +08:00
|
|
|
|
(use-package! org-msg
|
2020-10-01 16:38:55 +08:00
|
|
|
|
:after mu4e
|
2020-10-14 13:01:46 +08:00
|
|
|
|
:when (featurep! +org)
|
2020-10-01 01:56:45 +08:00
|
|
|
|
:config
|
2020-10-13 14:52:31 +08:00
|
|
|
|
(setq org-msg-options "html-postamble:nil H:5 num:nil ^:{} toc:nil author:nil email:nil tex:dvipng"
|
2020-10-01 01:56:45 +08:00
|
|
|
|
org-msg-startup "hidestars indent inlineimages"
|
|
|
|
|
org-msg-greeting-name-limit 3
|
2021-07-29 18:50:39 +08:00
|
|
|
|
org-msg-default-alternatives '((new . (utf-8 html))
|
|
|
|
|
(reply-to-text . (utf-8))
|
|
|
|
|
(reply-to-html . (utf-8 html)))
|
2021-09-20 22:58:32 +08:00
|
|
|
|
org-msg-convert-citation t
|
|
|
|
|
;; The default attachment matcher gives too many false positives,
|
|
|
|
|
;; it's better to be more conservative. See https://regex101.com/r/EtaiSP/4.
|
|
|
|
|
org-msg-attached-file-reference
|
|
|
|
|
"see[ \t\n]\\(?:the[ \t\n]\\)?\\(?:\\w+[ \t\n]\\)\\{0,3\\}\\(?:attached\\|enclosed\\)\\|\
|
|
|
|
|
(\\(?:attached\\|enclosed\\))\\|\
|
|
|
|
|
\\(?:attached\\|enclosed\\)[ \t\n]\\(?:for\\|is\\)[ \t\n]")
|
2017-04-16 21:24:18 -04:00
|
|
|
|
|
2020-10-13 16:41:33 +08:00
|
|
|
|
(defvar +org-msg-currently-exporting nil
|
2020-10-01 01:56:45 +08:00
|
|
|
|
"Helper variable to indicate whether org-msg is currently exporting the org buffer to HTML.
|
2020-09-23 13:08:57 +08:00
|
|
|
|
Usefull for affecting HTML export config.")
|
2021-07-31 01:10:54 +08:00
|
|
|
|
(defadvice! +org-msg--now-exporting-a (&rest _)
|
2020-10-01 01:56:45 +08:00
|
|
|
|
:before #'org-msg-org-to-xml
|
2020-10-13 16:41:33 +08:00
|
|
|
|
(setq +org-msg-currently-exporting t))
|
2021-07-31 01:10:54 +08:00
|
|
|
|
(defadvice! +org-msg--not-exporting-a (&rest _)
|
2020-10-01 01:56:45 +08:00
|
|
|
|
:after #'org-msg-org-to-xml
|
2020-10-13 16:41:33 +08:00
|
|
|
|
(setq +org-msg-currently-exporting nil))
|
2020-09-23 13:08:57 +08:00
|
|
|
|
|
2020-10-14 15:37:15 +08:00
|
|
|
|
(advice-add #'org-html-latex-fragment :override #'+org-html-latex-fragment-scaled-a)
|
|
|
|
|
(advice-add #'org-html-latex-environment :override #'+org-html-latex-environment-scaled-a)
|
2020-10-01 01:52:58 +08:00
|
|
|
|
|
2020-10-31 19:34:42 +08:00
|
|
|
|
(map! :map org-msg-edit-mode-map
|
|
|
|
|
:desc "attach" "C-c C-a" #'+mu4e/attach-files
|
|
|
|
|
:localleader
|
|
|
|
|
:desc "attach" "a" #'+mu4e/attach-files)
|
|
|
|
|
|
2020-10-13 16:41:33 +08:00
|
|
|
|
(defvar +mu4e-compose-org-msg-toggle-next t ; t to initialise org-msg
|
2020-10-01 01:56:45 +08:00
|
|
|
|
"Whether to toggle ")
|
2021-07-31 01:10:54 +08:00
|
|
|
|
(defun +mu4e-compose-org-msg-handle-toggle (toggle-p)
|
2020-10-13 16:41:33 +08:00
|
|
|
|
(when (xor toggle-p +mu4e-compose-org-msg-toggle-next)
|
2020-10-01 01:56:45 +08:00
|
|
|
|
(org-msg-mode (if org-msg-mode -1 1))
|
2020-10-13 16:41:33 +08:00
|
|
|
|
(setq +mu4e-compose-org-msg-toggle-next
|
|
|
|
|
(not +mu4e-compose-org-msg-toggle-next))))
|
2020-10-01 01:52:58 +08:00
|
|
|
|
|
2021-08-04 01:18:06 -04:00
|
|
|
|
(defadvice! +mu4e-maybe-toggle-org-msg-a (fn &optional toggle-p)
|
2020-10-01 01:56:45 +08:00
|
|
|
|
:around #'mu4e-compose-new
|
|
|
|
|
:around #'mu4e-compose-reply
|
2020-10-31 19:11:57 +08:00
|
|
|
|
:around #'mu4e-compose-forward
|
|
|
|
|
:around #'mu4e-compose-resend
|
2020-10-01 01:56:45 +08:00
|
|
|
|
(interactive "p")
|
2021-07-31 01:10:54 +08:00
|
|
|
|
(+mu4e-compose-org-msg-handle-toggle (/= 1 (or toggle-p 0)))
|
2021-08-04 01:18:06 -04:00
|
|
|
|
(funcall fn))
|
2020-10-01 01:52:58 +08:00
|
|
|
|
|
2021-08-04 01:18:06 -04:00
|
|
|
|
(defadvice! +mu4e-draft-open-signature-a (fn &rest args)
|
2021-04-16 13:21:55 +08:00
|
|
|
|
"Prevent `mu4e-compose-signature' from being used with `org-msg-mode'."
|
|
|
|
|
:around #'mu4e-draft-open
|
|
|
|
|
(let ((mu4e-compose-signature (unless org-msg-mode mu4e-compose-signature)))
|
2021-08-04 01:18:06 -04:00
|
|
|
|
(apply fn args)))
|
2021-04-16 13:21:55 +08:00
|
|
|
|
|
2021-02-25 18:36:08 +08:00
|
|
|
|
(map! :map org-msg-edit-mode-map
|
|
|
|
|
"TAB" #'org-msg-tab) ; only <tab> bound by default
|
|
|
|
|
|
2020-10-01 01:56:45 +08:00
|
|
|
|
(defvar +org-msg-accent-color "#c01c28"
|
|
|
|
|
"Accent color to use in org-msg's generated CSS.
|
2020-10-01 01:52:58 +08:00
|
|
|
|
Must be set before org-msg is loaded to take effect.")
|
2020-10-01 01:56:45 +08:00
|
|
|
|
(setq org-msg-enforce-css
|
|
|
|
|
(let* ((font-family '(font-family . "-apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, Oxygen, Ubuntu, Cantarell,\
|
2020-09-23 13:08:57 +08:00
|
|
|
|
\"Fira Sans\", \"Droid Sans\", \"Helvetica Neue\", Arial, sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\";"))
|
2020-10-01 01:56:45 +08:00
|
|
|
|
(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 +org-msg-accent-color)
|
|
|
|
|
(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))
|
2021-04-05 02:20:10 +08:00
|
|
|
|
inline-modes))
|
|
|
|
|
(base-quote '((padding-left . "5px") (margin-left . "10px")
|
|
|
|
|
(margin-top . "20px") (margin-bottom . "0")
|
|
|
|
|
(font-style . "italic") (background . "#f9f9f9")))
|
|
|
|
|
(quote-palette '("#6A8FBF" "#bf8f6a" "#6abf8a" "#906abf"
|
|
|
|
|
"#6aaebf" "#bf736a" "#bfb66a" "#bf6a94"
|
|
|
|
|
"#6abf9b" "#bf6a7d" "#acbf6a" "#6a74bf"))
|
|
|
|
|
(quotes
|
|
|
|
|
(mapcar (lambda (x)
|
|
|
|
|
(let ((c (nth x quote-palette)))
|
|
|
|
|
`(div ,(intern (format "quote%d" (1+ x)))
|
|
|
|
|
(,@base-quote
|
|
|
|
|
(color . ,c)
|
|
|
|
|
(border-left . ,(concat "3px solid "
|
|
|
|
|
(org-msg-lighten c)))))))
|
|
|
|
|
(number-sequence 0 (1- (length quote-palette))))))
|
2020-10-01 01:56:45 +08:00
|
|
|
|
`((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")
|
2021-04-05 02:20:10 +08:00
|
|
|
|
(margin-top . "2px")
|
|
|
|
|
(max-width . "84ch")))
|
|
|
|
|
(nil org-ul ((list-style-type . "disc")))
|
2020-10-01 01:56:45 +08:00
|
|
|
|
(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 . "2px 12px") (margin-left . "10px")
|
|
|
|
|
(margin-top . "10px") (margin-bottom . "0")
|
|
|
|
|
(border-left . "3px solid #ccc")
|
|
|
|
|
(font-style . "italic")
|
|
|
|
|
(background . "#f9f9f9")))
|
|
|
|
|
(p blockquote ((margin . "0") (padding . "4px 0")))
|
2021-04-05 02:20:10 +08:00
|
|
|
|
,@quotes
|
2020-10-01 01:56:45 +08:00
|
|
|
|
(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")
|
2021-08-04 01:52:19 -04:00
|
|
|
|
(color . ,(face-foreground 'default))
|
|
|
|
|
(background-color . ,(face-background 'default))
|
2020-10-01 01:56:45 +08:00
|
|
|
|
(margin . "4px 0px 8px 0px")
|
|
|
|
|
(padding . "8px 12px")
|
2020-10-13 14:55:02 +08:00
|
|
|
|
(width . "max-content")
|
|
|
|
|
(min-width . "80ch")
|
2020-10-01 01:56:45 +08:00
|
|
|
|
(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 ((margin . "0 0.1em")))
|
|
|
|
|
(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")))
|
2020-10-13 14:55:02 +08:00
|
|
|
|
(p nil ((text-decoration . "none") (line-height . "1.4")
|
2020-10-01 01:56:45 +08:00
|
|
|
|
(margin-top . "10px") (margin-bottom . "0px")
|
2020-10-13 14:55:02 +08:00
|
|
|
|
,font-size (max-width . "90ch")))
|
2020-10-01 01:56:45 +08:00
|
|
|
|
(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
|
2021-01-17 13:49:10 -06:00
|
|
|
|
(defvar +mu4e-gmail-accounts nil
|
|
|
|
|
"Gmail accounts that do not contain \"gmail\" in address and maildir.
|
2020-10-13 23:36:55 +08:00
|
|
|
|
|
2021-01-17 13:49:10 -06:00
|
|
|
|
An alist of Gmail addresses of the format \((\"username@domain.com\" . \"account-maildir\"))
|
|
|
|
|
to which Gmail integrations (behind the `+gmail' flag of the `mu4e' module) should be applied.
|
|
|
|
|
|
|
|
|
|
See `+mu4e-msg-gmail-p' and `mu4e-sent-messages-behavior'.")
|
2020-10-13 23:36:55 +08:00
|
|
|
|
|
2019-05-05 14:11:59 -04:00
|
|
|
|
;; don't save message to Sent Messages, Gmail/IMAP takes care of this
|
2020-10-01 19:16:33 +08:00
|
|
|
|
(setq mu4e-sent-messages-behavior
|
2020-10-13 16:41:33 +08:00
|
|
|
|
(lambda () ;; TODO make use +mu4e-msg-gmail-p
|
2020-10-13 23:36:55 +08:00
|
|
|
|
(if (or (string-match-p "@gmail.com\\'" (message-sendmail-envelope-from))
|
2021-01-17 13:49:10 -06:00
|
|
|
|
(member (message-sendmail-envelope-from)
|
|
|
|
|
(mapcar #'car +mu4e-gmail-accounts)))
|
|
|
|
|
'delete 'sent)))
|
2019-05-05 14:11:59 -04:00
|
|
|
|
|
2020-10-01 19:16:33 +08:00
|
|
|
|
(defun +mu4e-msg-gmail-p (msg)
|
2021-01-17 13:49:10 -06:00
|
|
|
|
(let ((root-maildir
|
|
|
|
|
(replace-regexp-in-string "/.*" ""
|
|
|
|
|
(substring (mu4e-message-field msg :maildir) 1))))
|
|
|
|
|
(or (string-match-p "gmail" root-maildir)
|
|
|
|
|
(member root-maildir (mapcar #'cdr +mu4e-gmail-accounts)))))
|
2020-10-01 19:16:33 +08:00
|
|
|
|
|
2019-05-05 14:11:59 -04:00
|
|
|
|
;; 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.
|
2021-01-17 13:49:10 -06:00
|
|
|
|
;; However, the real magic happens in `+mu4e-gmail-fix-flags-h'.
|
2019-05-05 14:11:59 -04:00
|
|
|
|
;;
|
|
|
|
|
;; Gmail will handle the rest.
|
|
|
|
|
(defun +mu4e--mark-seen (docid _msg target)
|
|
|
|
|
(mu4e~proc-move docid (mu4e~mark-check-target target) "+S-u-N"))
|
|
|
|
|
|
2020-10-01 19:16:33 +08:00
|
|
|
|
(defvar +mu4e--last-invalid-gmail-action 0)
|
|
|
|
|
|
2019-07-23 12:30:47 +02:00
|
|
|
|
(delq! 'delete mu4e-marks #'assq)
|
2020-10-01 19:16:33 +08:00
|
|
|
|
(setf (alist-get 'delete mu4e-marks)
|
|
|
|
|
(list
|
|
|
|
|
:char '("D" . "✘")
|
|
|
|
|
:prompt "Delete"
|
2020-10-31 19:12:24 +08:00
|
|
|
|
:show-target (lambda (_target) "delete")
|
2020-10-01 19:16:33 +08:00
|
|
|
|
:action (lambda (docid msg target)
|
|
|
|
|
(if (+mu4e-msg-gmail-p msg)
|
2020-10-02 11:53:58 +08:00
|
|
|
|
(progn (message "The delete operation is invalid for Gmail accounts. Trashing instead.")
|
|
|
|
|
(+mu4e--mark-seen docid msg target)
|
2020-10-01 19:16:33 +08:00
|
|
|
|
(when (< 2 (- (float-time) +mu4e--last-invalid-gmail-action))
|
|
|
|
|
(sit-for 1))
|
|
|
|
|
(setq +mu4e--last-invalid-gmail-action (float-time)))
|
|
|
|
|
(mu4e~proc-remove docid))))
|
|
|
|
|
(alist-get 'trash mu4e-marks)
|
2019-05-05 14:11:59 -04:00
|
|
|
|
(list :char '("d" . "▼")
|
|
|
|
|
:prompt "dtrash"
|
|
|
|
|
:dyn-target (lambda (_target msg) (mu4e-get-trash-folder msg))
|
2020-10-01 19:16:33 +08:00
|
|
|
|
:action (lambda (docid msg target)
|
|
|
|
|
(if (+mu4e-msg-gmail-p msg)
|
|
|
|
|
(+mu4e--mark-seen docid msg target)
|
|
|
|
|
(mu4e~proc-move docid (mu4e~mark-check-target target) "+T-N"))))
|
2019-05-05 14:11:59 -04:00
|
|
|
|
;; 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))
|
2020-10-01 19:16:33 +08:00
|
|
|
|
:action (lambda (docid msg target)
|
|
|
|
|
(if (+mu4e-msg-gmail-p msg)
|
|
|
|
|
(+mu4e--mark-seen docid msg target)
|
|
|
|
|
(mu4e~proc-move docid (mu4e~mark-check-target target) "-N")))
|
|
|
|
|
#'+mu4e--mark-seen))
|
2019-05-05 14:11:59 -04:00
|
|
|
|
|
|
|
|
|
;; 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)
|
2020-10-01 19:16:33 +08:00
|
|
|
|
(when (+mu4e-msg-gmail-p msg)
|
|
|
|
|
(pcase mark
|
|
|
|
|
(`trash (mu4e-action-retag-message msg "-\\Inbox,+\\Trash,-\\Draft"))
|
2020-10-02 11:53:58 +08:00
|
|
|
|
(`delete (mu4e-action-retag-message msg "-\\Inbox,+\\Trash,-\\Draft"))
|
2020-10-01 19:16:33 +08:00
|
|
|
|
(`refile (mu4e-action-retag-message msg "-\\Inbox"))
|
|
|
|
|
(`flag (mu4e-action-retag-message msg "+\\Starred"))
|
|
|
|
|
(`unflag (mu4e-action-retag-message msg "-\\Starred"))))))))
|
2020-10-10 03:28:58 +08:00
|
|
|
|
|
|
|
|
|
;;
|
|
|
|
|
;;; Alerts
|
|
|
|
|
|
|
|
|
|
(use-package! mu4e-alert
|
|
|
|
|
:after mu4e
|
|
|
|
|
:config
|
|
|
|
|
(setq doom-modeline-mu4e t)
|
|
|
|
|
|
|
|
|
|
(mu4e-alert-enable-mode-line-display)
|
|
|
|
|
(mu4e-alert-enable-notifications)
|
|
|
|
|
|
|
|
|
|
(when IS-LINUX
|
|
|
|
|
(mu4e-alert-set-default-style 'libnotify)
|
|
|
|
|
|
2021-04-15 00:41:27 +08:00
|
|
|
|
(defvar +mu4e-alert-bell-cmd '("paplay" . "/usr/share/sounds/freedesktop/stereo/message.oga")
|
|
|
|
|
"Cons list with command to play a sound, and the sound file to play.
|
|
|
|
|
Disabled when set to nil.")
|
|
|
|
|
|
2020-10-10 03:28:58 +08:00
|
|
|
|
(setq mu4e-alert-email-notification-types '(subjects))
|
2020-10-31 19:12:24 +08:00
|
|
|
|
(defun +mu4e-alert-grouped-mail-notification-formatter-with-bell (mail-group _all-mails)
|
2020-10-10 03:28:58 +08:00
|
|
|
|
"Default function to format MAIL-GROUP for notification.
|
|
|
|
|
ALL-MAILS are the all the unread emails"
|
2021-04-15 00:41:27 +08:00
|
|
|
|
(when +mu4e-alert-bell-cmd
|
|
|
|
|
(start-process (car +mu4e-alert-bell-cmd) (cdr +mu4e-alert-bell-cmd)))
|
2020-10-10 03:28:58 +08:00
|
|
|
|
(if (> (length mail-group) 1)
|
|
|
|
|
(let* ((mail-count (length mail-group))
|
|
|
|
|
(first-mail (car mail-group))
|
|
|
|
|
(title-prefix (format "You have %d unread emails"
|
|
|
|
|
mail-count))
|
|
|
|
|
(field-value (mu4e-alert--get-group first-mail))
|
|
|
|
|
(title-suffix (format (pcase mu4e-alert-group-by
|
|
|
|
|
(`:from "from %s:")
|
|
|
|
|
(`:to "to %s:")
|
|
|
|
|
(`:maildir "in %s:")
|
|
|
|
|
(`:priority "with %s priority:")
|
|
|
|
|
(`:flags "with %s flags:"))
|
|
|
|
|
field-value))
|
|
|
|
|
(title (format "%s %s" title-prefix title-suffix)))
|
|
|
|
|
(list :title title
|
|
|
|
|
:body (s-join "\n"
|
|
|
|
|
(mapcar (lambda (mail)
|
|
|
|
|
(format "%s<b>%s</b> • %s"
|
|
|
|
|
(cond
|
|
|
|
|
((plist-get mail :in-reply-to) "⮩ ")
|
|
|
|
|
((string-match-p "\\`Fwd:"
|
|
|
|
|
(plist-get mail :subject)) " ⮯ ")
|
|
|
|
|
(t " "))
|
|
|
|
|
(truncate-string-to-width (caar (plist-get mail :from))
|
|
|
|
|
20 nil nil t)
|
|
|
|
|
(truncate-string-to-width
|
|
|
|
|
(replace-regexp-in-string "\\`Re: \\|\\`Fwd: " ""
|
|
|
|
|
(plist-get mail :subject))
|
|
|
|
|
40 nil nil t)))
|
|
|
|
|
mail-group))))
|
|
|
|
|
(let* ((new-mail (car mail-group))
|
|
|
|
|
(subject (plist-get new-mail :subject))
|
|
|
|
|
(sender (caar (plist-get new-mail :from))))
|
|
|
|
|
(list :title sender :body subject))))
|
2021-05-18 00:06:46 +08:00
|
|
|
|
(setq mu4e-alert-grouped-mail-notification-formatter #'+mu4e-alert-grouped-mail-notification-formatter-with-bell)))
|