Mu4e Configuration

This post is the latest in my series on installing and configuring mu4e on a Mac and using Apple as a mail provider. As I wrote in my post on mbsync configuration, setting up mu4e is simple by comparison. On my MacBook Pro, I compiled the mu package from source. On my iMac I installed it with homebrew. Either way works fine. The advantage of homebrew is that it will load all the libraries that you need but aren’t included in the base macOS install.

My configuration is an adaption of Charl Botha’s, which uses some of the features in the latest release, with the addition of some ideas from Ben Maughan and a few bits of my own:

  1: (require 'mu4e)
  2: 
  3: ;; Call EWW to display HTML messages
  4: (defun jcs-view-in-eww (msg)
  5:   (eww-browse-url (concat "file://" (mu4e~write-body-to-html msg))))
  6: 
  7: ;; Arrange to view messages in either the default browser or EWW
  8: (add-to-list 'mu4e-view-actions '("ViewInBrowser" . mu4e-action-view-in-browser) t)
  9: (add-to-list 'mu4e-view-actions '("Eww view" . jcs-view-in-eww) t)
 10: 
 11: ;; From Ben Maughan: Get some Org functionality in compose buffer
 12: (add-hook 'message-mode-hook 'turn-on-orgtbl)
 13: (add-hook 'message-mode-hook 'turn-on-orgstruct++)
 14: 
 15: ;; Call mu every 5 minutes to update and index Maildir
 16: (setq mu4e-update-interval 300)
 17: 
 18: ;; Set format=flowed
 19: ;; mu4e sets up visual-line-mode and also fill (M-q) to do the right thing
 20: ;; each paragraph is a single long line; at sending, emacs will add the
 21: ;; special line continuation characters.
 22: (setq mu4e-compose-format-flowed t)
 23: 
 24: ;; every new email composition gets its own frame! (window)
 25: ;;(setq mu4e-compose-in-new-frame t)
 26: 
 27: ;; give me ISO(ish) format date-time stamps in the header list
 28: (setq mu4e-headers-date-format "%Y-%m-%d %H:%M")
 29: 
 30: ;; show full addresses in view message (instead of just names)
 31: ;; toggle per name with M-RET
 32: (setq mu4e-view-show-addresses 't)
 33: 
 34: ;;store org-mode links to messages
 35: (require 'org-mu4e)
 36: ;;store link to message if in header view, not to header query
 37: (setq org-mu4e-link-query-in-headers-mode nil)
 38: 
 39: ;;rename files when moving
 40: ;;NEEDED FOR MBSYNC
 41: (setq mu4e-change-filenames-when-moving t)
 42: 
 43: ;; Try to show images
 44: (setq mu4e-view-show-images t
 45:       mu4e-show-images t
 46:       mu4e-view-image-max-width 800)
 47: 
 48: ;; path to our Maildir directory
 49: (setq mu4e-maildir "~/Maildir")
 50: 
 51: ;; the next are relative to `mu4e-maildir'
 52: ;; instead of strings, they can be functions too, see
 53: ;; their docstring or the chapter 'Dynamic folders'
 54: (setq mu4e-sent-folder   "/icloud/Sent Messages"
 55:       mu4e-drafts-folder "/icloud/Drafts"
 56:       mu4e-trash-folder  "/icloud/Trash")
 57: 
 58: ;; the maildirs you use frequently; access them with 'j' ('jump')
 59: (setq   mu4e-maildir-shortcuts
 60:         '(("/icloud/Archive"             . ?a)
 61:           ("/icloud/inbox"               . ?i)
 62:           ("/icloud/Saved"               . ?v)
 63:           ("/icloud/Sent Messages"       . ?s)))
 64: 
 65: ;; the list of all of my e-mail addresses
 66: (setq mu4e-user-mail-address-list '("XXX@mac.com"
 67:                                     "YYY@irreal.org"))
 68: 
 69: ;; the headers to show in the headers list -- a pair of a field
 70: ;; and its width, with `nil' meaning 'unlimited'
 71: ;; (better only use that for the last field.
 72: ;; These are the defaults:
 73: (setq mu4e-headers-fields
 74:     '( (:date          .  25)    ;; alternatively, use :human-date
 75:        (:flags         .   6)
 76:        (:from          .  22)
 77:        (:subject       .  nil))) ;; alternatively, use :thread-subject
 78: 
 79: ;; Program to get mail.
 80: ;; Called when 'U' is pressed in main view.
 81: 
 82: ;; If you get your mail without an explicit command,
 83: ;; use "true" for the command (this is the default)
 84: ;; when I press U in the main view, or C-c C-u elsewhere,
 85: ;; this command is called, followed by the mu indexer
 86: (setq mu4e-get-mail-command "mbsync icloud")
 87: 
 88: ;; not using smtp-async yet
 89: ;; some of these variables will get overridden by the contexts
 90: (setq
 91:  send-mail-function 'smtpmail-send-it
 92:  message-send-mail-function 'smtpmail-send-it)
 93: 
 94: ;; don't keep message buffers around
 95: (setq message-kill-buffer-on-exit t)
 96: 
 97: ;; Contexts: One for each mail personality.
 98: (setq mu4e-contexts
 99:       `( ,(make-mu4e-context
100:            :name "a XXX@mac.com"
101:            :enter-func (lambda () (mu4e-message "Enter XXX@mac.com context"))
102:            :leave-func (lambda () (mu4e-message "Leave XXX@mac.com context"))
103:            ;; Match based on the contact-fields of the message (that we are replying to)
104:            :match-func (lambda (msg)
105:                          (when msg 
106:                            (mu4e-message-contact-field-matches msg 
107:                                                                :to "XXX@mac.com")))
108:            :vars '( ( user-mail-address      . "XXX@mac.com"  )
109:                     ( user-full-name         . "Jon Snader" )
110:                     ( smtpmail-smtp-server   . "smtp.mail.me.com" )
111:                     ( smtpmail-smtp-service  . 587)
112:                     ( smtpmail-stream-type   . starttls)))
113: 
114:          ,(make-mu4e-context
115:            :name "i YYY@irreal.org"
116:            :enter-func (lambda () (mu4e-message "Enter YYY@irreal.org context"))
117:            :leave-func (lambda () (mu4e-message "Leave YYY@irreal.org context"))
118:            ;; we match based on the contact-fields of the message
119:            :match-func (lambda (msg)
120:                          (when msg 
121:                            (mu4e-message-contact-field-matches msg 
122:                                                                :to "YYY@irreal.org")))
123:            :vars '( ( user-mail-address       . "YYY@irreal.org" )
124:                     ( user-full-name          . "Jon Snader" )
125:                     ( smtpmail-smtp-server    . "smtp-server.tampabay.rr.com" )
126:                     ( smtpmail-stream-type    . plain)
127:                     ( smtpmail-smtp-service   . 25)))))
128: 
129: 
130: ;; start with the first (default) context; 
131: (setq mu4e-context-policy 'pick-first)
132: 
133: ;; compose with the current context if no context matches;
134: (setq mu4e-compose-context-policy nil)
135: 
136: (global-set-key (kbd "C-<f6>") 'mu4e)

As you can see, it’s very similar to Botha’s. Some emails, especially commercial ones (like those from Amazon) and those from professional groups like ACM, don’t render very well so I prefer to view them in a browser environment. Usually, EWW is sufficient but sometimes I need the full Safari treatment. Lines 39 show how to do that. If I press a while viewing a message, it will bring up a menu with various viewing options. If I choose E the message is displayed in EWW. V displays it in the default browser, Safari in my case.

The other noteworthy thing about the configuration are the contexts, which are configured on lines 97134. All my emails are filtered through the Apple server so the contexts allow me to send mail either from my Apple account or my Irreal account. When I respond to an email, the correct “From:” address is chosen from the “To:” line of the original message.

Finally, there’s the matter of sending messages. Many writers recommend third party packages to handle multiple accounts but I’ve found the contexts in mu4e handles that nicely. Unless you have special needs, like Ben Maughan, using the built-in smtpmail functionality is fine. You’ll want to set up an .authinfo file to list the servers, accounts, and passwords. The line for the apple server looks like

machine smtp.mail.me.com login XXX@mac.com password same-password-as-for-mbsync

You’ll want to encrypt the file for security, but Emacs only asks for the password one time per (Emacs) session so that’s not burdensome.

This entry was posted in General and tagged , . Bookmark the permalink.