Refactor app/email
This commit is contained in:
parent
c0084b5a93
commit
b3c429d92a
3 changed files with 98 additions and 157 deletions
|
@ -127,7 +127,7 @@
|
||||||
;; toward a specific purpose. They may have additional dependencies and
|
;; toward a specific purpose. They may have additional dependencies and
|
||||||
;; should be loaded late.
|
;; should be loaded late.
|
||||||
:app
|
:app
|
||||||
;email ; emacs as an email client
|
;(email +gmail) ; emacs as an email client
|
||||||
;irc ; how neckbeards socialize
|
;irc ; how neckbeards socialize
|
||||||
;rss ; emacs as an RSS reader
|
;rss ; emacs as an RSS reader
|
||||||
;twitter ; twitter client https://twitter.com/vnought
|
;twitter ; twitter client https://twitter.com/vnought
|
||||||
|
|
36
modules/app/email/+gmail.el
Normal file
36
modules/app/email/+gmail.el
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
;;; app/email/+gmail.el -*- lexical-binding: t; -*-
|
||||||
|
|
||||||
|
(after! mu4e
|
||||||
|
;; don't save message to Sent Messages, Gmail/IMAP takes care of this
|
||||||
|
(setq mu4e-sent-messages-behavior 'delete)
|
||||||
|
|
||||||
|
;; 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 `+email|gmail-fix-flags'.
|
||||||
|
;;
|
||||||
|
;; Gmail will handle the rest.
|
||||||
|
(defun +email--mark-seen (docid msg target)
|
||||||
|
(mu4e~proc-move docid (mu4e~mark-check-target target) "+S-u-N"))
|
||||||
|
|
||||||
|
(map-delete mu4e-marks 'delete)
|
||||||
|
(map-put mu4e-marks 'trash
|
||||||
|
(list :char '("d" . "▼")
|
||||||
|
:prompt "dtrash"
|
||||||
|
:dyn-target (lambda (target msg) (mu4e-get-trash-folder msg))
|
||||||
|
:action #'+email--mark-seen))
|
||||||
|
;; Refile will be my "archive" function.
|
||||||
|
(map-put mu4e-marks 'refile
|
||||||
|
(list :char '("r" . "▶") :prompt "refile"
|
||||||
|
:show-target (lambda (target) "archive")
|
||||||
|
:action #'+email--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.
|
||||||
|
(defun +email|gmail-fix-flags (mark msg)
|
||||||
|
(cond ((eq mark 'trash) (mu4e-action-retag-message msg "-\\Inbox,+\\Trash,-\\Draft"))
|
||||||
|
((eq mark 'refile) (mu4e-action-retag-message msg "-\\Inbox"))
|
||||||
|
((eq mark 'flag) (mu4e-action-retag-message msg "+\\Starred"))
|
||||||
|
((eq mark 'unflag) (mu4e-action-retag-message msg "-\\Starred"))))
|
||||||
|
(add-hook 'mu4e-mark-execute-pre-hook #'+email|gmail-fix-flags))
|
|
@ -4,13 +4,8 @@
|
||||||
;; to give me the ability to read, search, write and send my email. It does so
|
;; to give me the ability to read, search, write and send my email. It does so
|
||||||
;; with `mu4e', and requires `offlineimap' and `mu' to be installed.
|
;; with `mu4e', and requires `offlineimap' and `mu' to be installed.
|
||||||
|
|
||||||
(defvar +email-mu4e-mail-path "~/.mail"
|
(defvar +email-backend 'mbsync
|
||||||
"The directory path of mu's maildir.")
|
"Which backend to use. Can either be offlineimap, mbsync or nil (manual).")
|
||||||
|
|
||||||
|
|
||||||
;;
|
|
||||||
;; Config
|
|
||||||
;;
|
|
||||||
|
|
||||||
(def-setting! :email (label letvars &optional default-p)
|
(def-setting! :email (label letvars &optional default-p)
|
||||||
"Registers an email address for mu4e. The LABEL is a string. LETVARS are a
|
"Registers an email address for mu4e. The LABEL is a string. LETVARS are a
|
||||||
|
@ -54,54 +49,68 @@ default/fallback account."
|
||||||
|
|
||||||
(def-package! mu4e
|
(def-package! mu4e
|
||||||
:commands (mu4e mu4e-compose-new)
|
:commands (mu4e mu4e-compose-new)
|
||||||
|
:init
|
||||||
|
(setq mu4e-maildir "~/.mail"
|
||||||
|
mu4e-attachment-dir "~/.mail/.attachments"
|
||||||
|
mu4e-user-mail-address-list nil)
|
||||||
:config
|
:config
|
||||||
(setq mu4e-maildir +email-mu4e-mail-path
|
(pcase +email-backend
|
||||||
mu4e-attachment-dir "~/Downloads"
|
(`mbsync
|
||||||
mu4e-user-mail-address-list nil
|
(setq mu4e-get-mail-command "mbsync -a"
|
||||||
mu4e-update-interval nil
|
mu4e-change-filenames-when-moving t))
|
||||||
|
(`offlineimap
|
||||||
|
(setq mu4e-get-mail-command "offlineimap -o -q")))
|
||||||
|
|
||||||
|
(setq mu4e-update-interval nil
|
||||||
mu4e-compose-format-flowed t ; visual-line-mode + auto-fill upon sending
|
mu4e-compose-format-flowed t ; visual-line-mode + auto-fill upon sending
|
||||||
mu4e-view-show-addresses t
|
mu4e-view-show-addresses t
|
||||||
|
mu4e-sent-messages-behavior 'sent
|
||||||
|
mu4e-index-cleanup nil
|
||||||
|
mu4e-index-lazy-check t
|
||||||
|
mu4e-hide-index-messages t
|
||||||
;; try to show images
|
;; try to show images
|
||||||
mu4e-view-show-images t
|
mu4e-view-show-images t
|
||||||
mu4e-view-image-max-width 800
|
mu4e-view-image-max-width 800
|
||||||
;; don't save message to Sent Messages, Gmail/IMAP takes care of this
|
|
||||||
mu4e-sent-messages-behavior 'delete
|
|
||||||
;; allow for updating mail using 'U' in the main view:
|
|
||||||
;; for mbsync
|
|
||||||
;; mu4e-headers-skip-duplicates t
|
|
||||||
;; mu4e-change-filenames-when-moving nil
|
|
||||||
;; mu4e-get-mail-command "mbsync -a"
|
|
||||||
;; for offlineimap
|
|
||||||
mu4e-get-mail-command "offlineimap -o -q"
|
|
||||||
;; configuration for sending mail
|
;; configuration for sending mail
|
||||||
message-send-mail-function #'smtpmail-send-it
|
message-send-mail-function #'smtpmail-send-it
|
||||||
smtpmail-stream-type 'starttls
|
smtpmail-stream-type 'starttls
|
||||||
|
message-kill-buffer-on-exit t ; close after sending
|
||||||
;; start with the first (default) context;
|
;; start with the first (default) context;
|
||||||
mu4e-context-policy 'pick-first
|
mu4e-context-policy 'pick-first
|
||||||
;; compose with the current context, or ask
|
;; compose with the current context, or ask
|
||||||
mu4e-compose-context-policy 'ask-if-none
|
mu4e-compose-context-policy 'ask-if-none
|
||||||
;; use helm/ivy
|
;; use helm/ivy
|
||||||
mu4e-completing-read-function (cond ((featurep! :completion ivy) #'ivy-completing-read)
|
mu4e-completing-read-function
|
||||||
((featurep! :completion helm) #'completing-read)
|
(cond ((featurep! :completion ivy) #'ivy-completing-read)
|
||||||
(t #'ido-completing-read))
|
((featurep! :completion helm) #'completing-read)
|
||||||
;; close message after sending it
|
(t #'ido-completing-read))
|
||||||
message-kill-buffer-on-exit t
|
|
||||||
;; no need to ask
|
;; no need to ask
|
||||||
mu4e-confirm-quit nil
|
mu4e-confirm-quit t
|
||||||
;; remove 'lists' column
|
;; remove 'lists' column
|
||||||
mu4e-headers-fields
|
mu4e-headers-fields
|
||||||
'((:account . 12)
|
'((:account . 12)
|
||||||
(:human-date . 12)
|
(:human-date . 12)
|
||||||
(:flags . 4)
|
(:flags . 4)
|
||||||
(:from . 25)
|
(:from . 25)
|
||||||
(:subject))
|
(:subject)))
|
||||||
mu4e-bookmarks `(("\\\\Inbox" "Inbox" ?i)
|
|
||||||
("\\\\Draft" "Drafts" ?d)
|
;; Use fancy icons
|
||||||
("flag:unread AND \\\\Inbox" "Unread messages" ?u)
|
(setq mu4e-headers-has-child-prefix '("+" . "")
|
||||||
("flag:flagged" "Starred messages" ?s)
|
mu4e-headers-empty-parent-prefix '("-" . "")
|
||||||
("date:today..now" "Today's messages" ?t)
|
mu4e-headers-first-child-prefix '("-" . "")
|
||||||
("date:7d..now" "Last 7 days" ?w)
|
mu4e-headers-duplicate-prefix '("-" . "")
|
||||||
("mime:image/*" "Messages with images" ?p)))
|
mu4e-headers-default-prefix '("-" . "")
|
||||||
|
mu4e-headers-draft-mark '("-" . "")
|
||||||
|
mu4e-headers-flagged-mark '("-" . "")
|
||||||
|
mu4e-headers-new-mark '("-" . "")
|
||||||
|
mu4e-headers-passed-mark '("-" . "")
|
||||||
|
mu4e-headers-replied-mark '("-" . "")
|
||||||
|
mu4e-headers-seen-mark '("-" . "")
|
||||||
|
mu4e-headers-trashed-mark '("-" . "")
|
||||||
|
mu4e-headers-attach-mark '("-" . "")
|
||||||
|
mu4e-headers-encrypted-mark '("-" . "")
|
||||||
|
mu4e-headers-signed-mark '("-" . "")
|
||||||
|
mu4e-headers-unread-mark '("-" . ""))
|
||||||
|
|
||||||
;; Add a column to display what email account the email belongs to.
|
;; Add a column to display what email account the email belongs to.
|
||||||
(add-to-list 'mu4e-header-info-custom
|
(add-to-list 'mu4e-header-info-custom
|
||||||
|
@ -114,37 +123,6 @@ default/fallback account."
|
||||||
(let ((maildir (mu4e-message-field msg :maildir)))
|
(let ((maildir (mu4e-message-field msg :maildir)))
|
||||||
(format "%s" (substring maildir 1 (string-match-p "/" maildir 1)))))))
|
(format "%s" (substring maildir 1 (string-match-p "/" maildir 1)))))))
|
||||||
|
|
||||||
;; 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 `+email|gmail-fix-flags'.
|
|
||||||
;;
|
|
||||||
;; Gmail will handle the rest.
|
|
||||||
(defun +email--mark-seen (docid msg target)
|
|
||||||
(mu4e~proc-move docid (mu4e~mark-check-target target) "+S-u-N"))
|
|
||||||
|
|
||||||
(map-delete mu4e-marks 'delete)
|
|
||||||
(map-put mu4e-marks 'trash
|
|
||||||
(list :char '("d" . "▼")
|
|
||||||
:prompt "dtrash"
|
|
||||||
:dyn-target (lambda (target msg) (mu4e-get-trash-folder msg))
|
|
||||||
:action #'+email--mark-seen))
|
|
||||||
;; Refile will be my "archive" function.
|
|
||||||
(map-put mu4e-marks 'refile
|
|
||||||
(list :char '("r" . "▶") :prompt "refile"
|
|
||||||
:show-target (lambda (target) "archive")
|
|
||||||
:action #'+email--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.
|
|
||||||
(defun +email|gmail-fix-flags (mark msg)
|
|
||||||
(cond ((eq mark 'trash) (mu4e-action-retag-message msg "-\\Inbox,+\\Trash,-\\Draft"))
|
|
||||||
((eq mark 'refile) (mu4e-action-retag-message msg "-\\Inbox"))
|
|
||||||
((eq mark 'flag) (mu4e-action-retag-message msg "+\\Starred"))
|
|
||||||
((eq mark 'unflag) (mu4e-action-retag-message msg "-\\Starred"))))
|
|
||||||
(add-hook 'mu4e-mark-execute-pre-hook #'+email|gmail-fix-flags)
|
|
||||||
|
|
||||||
;; Refresh the current view after marks are executed
|
;; Refresh the current view after marks are executed
|
||||||
(defun +email*refresh (&rest _) (mu4e-headers-rerun-search))
|
(defun +email*refresh (&rest _) (mu4e-headers-rerun-search))
|
||||||
(advice-add #'mu4e-mark-execute-all :after #'+email*refresh)
|
(advice-add #'mu4e-mark-execute-all :after #'+email*refresh)
|
||||||
|
@ -160,101 +138,22 @@ default/fallback account."
|
||||||
(imagemagick-register-types))
|
(imagemagick-register-types))
|
||||||
|
|
||||||
(after! evil
|
(after! evil
|
||||||
(cl-loop for str in '((mu4e-main-mode . normal)
|
(dolist (mode '(mu4e-main-mode mu4e-view-mode mu4e-headers-mode
|
||||||
(mu4e-view-mode . normal)
|
mu4e-compose-mode mu4e~update-mail-mode))
|
||||||
(mu4e-headers-mode . normal)
|
(evil-set-initial-state mode 'normal))))
|
||||||
(mu4e-compose-mode . normal)
|
|
||||||
(mu4e~update-mail-mode . normal))
|
|
||||||
do (evil-set-initial-state (car str) (cdr str)))
|
|
||||||
|
|
||||||
(setq mu4e-view-mode-map (make-sparse-keymap)
|
|
||||||
;; mu4e-compose-mode-map (make-sparse-keymap)
|
|
||||||
mu4e-headers-mode-map (make-sparse-keymap)
|
|
||||||
mu4e-main-mode-map (make-sparse-keymap))
|
|
||||||
|
|
||||||
(map! (:map (mu4e-main-mode-map mu4e-view-mode-map)
|
|
||||||
:leader
|
|
||||||
:n "," #'mu4e-context-switch
|
|
||||||
:n "." #'mu4e-headers-search-bookmark
|
|
||||||
:n ">" #'mu4e-headers-search-bookmark-edit
|
|
||||||
:n "/" #'mu4e~headers-jump-to-maildir)
|
|
||||||
|
|
||||||
(:map (mu4e-headers-mode-map mu4e-view-mode-map)
|
|
||||||
:localleader
|
|
||||||
:n "f" #'mu4e-compose-forward
|
|
||||||
:n "r" #'mu4e-compose-reply
|
|
||||||
:n "c" #'mu4e-compose-new
|
|
||||||
:n "e" #'mu4e-compose-edit)
|
|
||||||
|
|
||||||
(:map mu4e-main-mode-map
|
|
||||||
:n "q" #'mu4e-quit
|
|
||||||
:n "u" #'mu4e-update-index
|
|
||||||
:n "U" #'mu4e-update-mail-and-index
|
|
||||||
:n "J" #'mu4e~headers-jump-to-maildir
|
|
||||||
:n "c" #'+email/compose
|
|
||||||
:n "b" #'mu4e-headers-search-bookmark)
|
|
||||||
|
|
||||||
(:map mu4e-headers-mode-map
|
|
||||||
:n "q" #'mu4e~headers-quit-buffer
|
|
||||||
:n "r" #'mu4e-compose-reply
|
|
||||||
:n "c" #'mu4e-compose-edit
|
|
||||||
:n "s" #'mu4e-headers-search-edit
|
|
||||||
:n "S" #'mu4e-headers-search-narrow
|
|
||||||
:n "RET" #'mu4e-headers-view-message
|
|
||||||
:n "u" #'mu4e-headers-mark-for-unmark
|
|
||||||
:n "U" #'mu4e-mark-unmark-all
|
|
||||||
:n "v" #'evil-visual-line
|
|
||||||
:nv "d" #'+email/mark
|
|
||||||
:nv "=" #'+email/mark
|
|
||||||
:nv "-" #'+email/mark
|
|
||||||
:nv "+" #'+email/mark
|
|
||||||
:nv "!" #'+email/mark
|
|
||||||
:nv "?" #'+email/mark
|
|
||||||
:nv "r" #'+email/mark
|
|
||||||
:nv "m" #'+email/mark
|
|
||||||
:n "x" #'mu4e-mark-execute-all
|
|
||||||
|
|
||||||
:n "]]" #'mu4e-headers-next-unread
|
|
||||||
:n "[[" #'mu4e-headers-prev-unread
|
|
||||||
|
|
||||||
(:localleader
|
|
||||||
:n "s" 'mu4e-headers-change-sorting
|
|
||||||
:n "t" 'mu4e-headers-toggle-threading
|
|
||||||
:n "r" 'mu4e-headers-toggle-include-related
|
|
||||||
|
|
||||||
:n "%" #'mu4e-headers-mark-pattern
|
|
||||||
:n "t" #'mu4e-headers-mark-subthread
|
|
||||||
:n "T" #'mu4e-headers-mark-thread))
|
|
||||||
|
|
||||||
(:map mu4e-view-mode-map
|
|
||||||
:n "q" #'mu4e~view-quit-buffer
|
|
||||||
:n "r" #'mu4e-compose-reply
|
|
||||||
:n "c" #'mu4e-compose-edit
|
|
||||||
:n "o" #'ace-link-mu4e
|
|
||||||
|
|
||||||
:n "<M-Left>" #'mu4e-view-headers-prev
|
|
||||||
:n "<M-Right>" #'mu4e-view-headers-next
|
|
||||||
:n "[m" #'mu4e-view-headers-prev
|
|
||||||
:n "]m" #'mu4e-view-headers-next
|
|
||||||
:n "[u" #'mu4e-view-headers-prev-unread
|
|
||||||
:n "]u" #'mu4e-view-headers-next-unread
|
|
||||||
|
|
||||||
(:localleader
|
|
||||||
:n "%" #'mu4e-view-mark-pattern
|
|
||||||
:n "t" #'mu4e-view-mark-subthread
|
|
||||||
:n "T" #'mu4e-view-mark-thread
|
|
||||||
|
|
||||||
:n "d" #'mu4e-view-mark-for-trash
|
|
||||||
:n "r" #'mu4e-view-mark-for-refile
|
|
||||||
:n "m" #'mu4e-view-mark-for-move))
|
|
||||||
|
|
||||||
(:map mu4e~update-mail-mode-map
|
|
||||||
:n "q" #'mu4e-interrupt-update-mail))))
|
|
||||||
|
|
||||||
|
|
||||||
(def-package! mu4e-maildirs-extension
|
(def-package! mu4e-maildirs-extension
|
||||||
:after mu4e
|
:after mu4e
|
||||||
:config (mu4e-maildirs-extension-load))
|
:config
|
||||||
|
(mu4e-maildirs-extension-load)
|
||||||
|
(setq mu4e-maildirs-extension-title nil
|
||||||
|
;; mu4e-maildirs-extension-ignored-regex "^*~*"
|
||||||
|
mu4e-maildirs-extension-buffer-name "*Mail*"
|
||||||
|
mu4e-maildirs-extension-insert-before-str "\n\t[c] Compose a message"
|
||||||
|
mu4e-maildirs-extension-action-text "\t[g] Update mail and index\n"
|
||||||
|
mu4e-maildirs-extension-maildir-expanded-prefix "-"
|
||||||
|
mu4e-maildirs-extension-maildir-default-prefix "|"))
|
||||||
|
|
||||||
|
|
||||||
(def-package! org-mu4e
|
(def-package! org-mu4e
|
||||||
|
@ -268,3 +167,9 @@ default/fallback account."
|
||||||
(add-hook! 'message-send-hook
|
(add-hook! 'message-send-hook
|
||||||
(setq-local org-mu4e-convert-to-html nil)))
|
(setq-local org-mu4e-convert-to-html nil)))
|
||||||
|
|
||||||
|
|
||||||
|
;;
|
||||||
|
;; Sub-modules
|
||||||
|
;;
|
||||||
|
|
||||||
|
(if (featurep! +gmail) (load! +gmail))
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue