;;; email.el -*- lexical-binding: t; -*- ;; Start mu4e in the background ;; https://github.com/djcb/mu/issues/2282 (require 'mu4e) (mu4e 'background) ;; Recommended msmtp config from doom module documentation (setq sendmail-program (executable-find "msmtp") send-mail-function #'smtpmail-send-it message-sendmail-f-is-evil t message-sendmail-extra-arguments '("--read-envelope-from") message-send-mail-function #'message-send-mail-with-sendmail) ;; `set-email-account!' doesn't accept a custom match-func (setq mu4e-contexts (list ;; (make-mu4e-context ;; :name "upcycling" ;; :enter-func ;; (lambda () (mu4e-message "Switched to upcycling")) ;; :leave-func ;; (lambda () (progn (setq +mu4e-personal-addresses nil) ;; (mu4e-clear-caches))) ;; :match-func ;; (lambda (msg) ;; (when msg ;; (mu4e-message-contact-field-matches msg ;; :to "upcycling@fsfe.org"))) ;; :vars '((user-mail-address . "upcycling@fsfe.org") ;; (user-full-name . "FSFE Team Upcycling Android"))) (make-mu4e-context :name "mailbox" :enter-func (lambda () (mu4e-message "Switched to mailbox")) :leave-func (lambda () (progn (setq +mu4e-personal-addresses nil) (mu4e-clear-caches))) :match-func (lambda (msg) (when msg (string-prefix-p "/mailbox" (mu4e-message-field msg :maildir) t))) :vars '((user-mail-address . "me@maxschlueter.com") (user-full-name . "Max Schlueter") (+mu4e-personal-addresses ("me@maxschlueter.com") ("maxsc@fsfe.org")) )))) (setq mu4e-attachment-dir "~/Downloads" mu4e-sent-folder "/mailbox/Sent" mu4e-drafts-folder "/mailbox/Drafts" mu4e-trash-folder "/mailbox/Trash" mu4e-refile-folder "/mailbox/Archive" ;; TODO create context-aware variable mu4e-spam-folder "/mailbox/Junk" mu4e-compose-signature nil mu4e-maildir-shortcuts (list (list :maildir "/mailbox/Inbox" :key ?i) (list :maildir "/mailbox/Sent" :key ?s) (list :maildir "/mailbox/Drafts" :key ?d) (list :maildir "/mailbox/Trash" :key ?t) (list :maildir "/mailbox/Archive" :key ?a)) mu4e-bookmarks (list (list :name "All Inboxes" :query "maildir:/mailbox/Inbox" :key ?i) (list :name "Unread messages" :query "flag:unread AND NOT flag:trashed" :key ?u) (list :name "Today's messages" :query "date:today..now" :key ?t) (list :name "Last 7 days" :query "date:7d..now" :hide-unread t :key ?t))) ;; Render buttons to verify&decrypt messages (setq mm-decrypt-option 'always mm-verify-option 'always gnus-buttonized-mime-types '("multipart/encrypted" "multipart/signed") mml-secure-openpgp-encrypt-to-self t) ;; Move message to the trash folder but do not set the trash flag ;; https://github.com/djcb/mu/issues/1136#issuecomment-1066303788 (setf (alist-get 'trash mu4e-marks) (list :char '("d" . "▼") :prompt "dtrash" :dyn-target (lambda (target msg) (mu4e-get-trash-folder msg)) :action (lambda (docid msg target) ;; Here's the main difference to the regular trash mark, ;; no +T before -N so the message is not marked as ;; IMAP-deleted: (mu4e--server-move docid (mu4e--mark-check-target target) "+S-u-N")))) (add-to-list 'mu4e-marks '(spam :char "S" :prompt "Spam" :shot-target (lambda (target) mu4e-spam-folder) :action (lambda (docid msg target) (mu4e--server-move docid mu4e-spam-folder "+S-u-N")))) (defun my:mu4e-mark-for-spam() "Mark as read and move to spam." (interactive) (mu4e-headers-mark-and-next 'spam)) (map! :map mu4e-headers-mode-map :n "S" #'my:mu4e-mark-for-spam) (add-to-list 'mu4e-view-mime-part-actions '(:name "calendar" :handler (lambda (file) (shell-command (format "khal import --batch %s" file)) (khalel-import-events)) :receives temp)) ;; Sign sent email automatically ;; (add-hook 'message-send-hook 'mml-secure-message-sign-smime) (require 'khalel-icalendar) ;; (defun max/mu4e-view-import-attachment-calendar (msg attnum) ;; (let* ((att (mu4e~view-get-attach msg attnum)) ;; (index (plist-get att :index)) ;; (docid (mu4e-message-field msg :docid)) ;; (mtype (plist-get att :mime-type)) ;; (fname (plist-get att :name)) ;; (fpath (concat (mu4e~get-attachment-dir fname mtype) "/" fname))) ;; (if (string= "text/calendar" mtype) ;; (progn (mu4e~proc-extract 'save docid index mu4e-decryption-policy fpath) ;; (let ((org-caldav-inbox (max/org-caldav-get-inbox))) ;; (org-caldav-import-ics-to-org fpath))) ;; (mu4e-error "Invalid mime-type for a calendar event: `%s'" mtype)))) ;; ;; XXX ;; (add-to-list 'mu4e-view-attachment-actions ;; '("cImport in calendar" . max/mu4e-view-import-attachment-calendar) t) (defun max/=mu4e () "Start email client and view all inboxes." (interactive) (require 'mu4e) (+workspace-switch +mu4e-workspace-name t) (mu4e--start (lambda () (mu4e-headers-search (mu4e-get-bookmark-query ?i))))) (map! "" #'max/=mu4e) (after! epa (setq epa-keyserver "keys.openpgp.org") (map! :map epa-ks-search-mode-map :n "f" #'epa-ks-mark-key-to-fetch :n "i" #'epa-ks-inspect-key-to-fetch :n "u" #'epa-ks-unmark-key-to-fetch :n "x" #'epa-ks-do-key-to-fetch)) (use-package! jl-encrypt :config (setq mml-secure-insert-signature 'encrypted)) (after! mu4e-alert (when IS-MAC (mu4e-alert-set-default-style 'notifier))) ;; Fix opening attachments with mu 1.10 ;; https://github.com/doomemacs/doomemacs/issues/7196 (after! mu4e (defalias 'mu4e~view-gather-mime-parts 'mu4e--view-gather-mime-parts)) ;; Taken from http://pragmaticemacs.com/emacs/email-templates-in-mu4e-with-yasnippet/ (defun bjm/mu4e-get-names-for-yasnippet () "Return comma separated string of names for an email" (interactive) (let ((email-name "") str email-string email-list email-name2 tmpname) (save-excursion (goto-char (point-min)) ;; first line in email could be some hidden line containing NO to field (setq str (buffer-substring-no-properties (point-min) (point-max)))) ;; take name from TO field - match series of names (when (string-match "^To: \"?\\(.+\\)" str) (setq email-string (match-string 1 str))) ;;split to list by comma (setq email-list (split-string email-string " *, *")) ;;loop over emails (dolist (tmpstr email-list) ;;get first word of email string (setq tmpname (car (split-string tmpstr " "))) ;;remove whitespace or "" (setq tmpname (replace-regexp-in-string "[ \"]" "" tmpname)) ;;join to string (setq email-name (concat email-name ", " tmpname))) ;;remove initial comma (setq email-name (replace-regexp-in-string "^, " "" email-name)) ;;see if we want to use the name in the FROM field ;;get name in FROM field if available, but only if there is only ;;one name in TO field (if (< (length email-list) 2) (when (string-match "^\\([^ ,\n]+\\).+writes:$" str) (progn (setq email-name2 (match-string 1 str)) ;;prefer name in FROM field if TO field has "@" (when (string-match "@" email-name) (setq email-name email-name2)) ))) email-name))