Email, hate it or love it, we all have to deal with it. Thankfully, thanks to Emacs & mu4e you can have a productive and, dare I say, fun time working with emails.
About
In this guide I will guide you through setting up mu4e with multiple accounts, using isync & mu, as well as the basics of how to incorporate mu4e into your workflow, plus tips & tricks like using mu4e actions to apply git patches.
To follow this guide, make sure to enable IMAP/SMTP access for your email account. The steps to enable this may vary depending on your specific email provider, so I won’t cover that in this guide.
Why mu4e?
There are multiple options available in GNU Emacs for managing emails, such as rmail, gnus, notmuch, and mu4e.
Each of these options has its own complexities, depending on your specific use case.
In my personal experience, I find mu4e to be preferable due to its ease of setup, particularly when dealing with multiple accounts.
Installing MU & isync
To get started, install mu & isync
- Arch Linux
$ sudo pacman -S mu isync
- Gentoo
$ sudo emerge -av mu isync
NOTE
: Make sure you to use emacs
USEFLAG for mu
If mu
is not packaged for your distro, I recommend changing to a new
one. But if you insist, you might have success installing mu from
source, using
straight.el:
(straight-use-package 'mu4e)
Setting up mbsync
Edit your configuration: ~/.mbsyncrc
Example setup for Fastmail:
IMAPAccount fastmail
Host imap.fastmail.com
Port 993
User [email protected]
PassCmd "emacsclient -e '(password-store-get-field \"fastmail.com/[email protected]\" \"smtp\)'"
SSLType IMAPS
SSLVersions TLSv1.2
CertificateFile /etc/ssl/certs/ca-certificates.crt
IMAPStore fastmail-remote
Account fastmail
MaildirStore fastmail-local
Path ~/Mail/Fastmail/
Inbox ~/Mail/Fastmail/Inbox
Trash ~/Mail/Fastmail/Trash/
SubFolders Verbatim
Channel fastmail
Far :fastmail-remote:
Near :fastmail-local:
Patterns *
Expunge None
CopyArrivalDate yes
Sync All
Create Both
SyncState *
Example setup for Gmail:
IMAPAccount gmail
Host imap.gmail.com
Port 993
User [email protected]
PassCmd "pass google/mygmail.com"
SSLType IMAPS
SSLVersions TLSv1.2
CertificateFile /etc/ssl/certs/ca-certificates.crt
IMAPStore gmail-remote
Account gmail
MaildirStore gmail-local
Path ~/Mail/Account-GMAIL/
SubFolders Verbatim
Channel gmail
Far :gmail-remote:
Near :gmail-local:
Patterns * ![Gmail]* "[Gmail]/Sent Mail" "[Gmail]/Starred" "[Gmail]/All Mail" "[Gmail]/Trash"
Expunge None
CopyArrivalDate yes
Sync All
Create Both
SyncState *
Settings you should adjust:
PassCmd
this should output your account password. I personally use pass as my password manager.
In the fastmail example above I get my password with this emacs function:
(password-store-get-field \"fastmail.com/[email protected]\" \"smtp\)
password-store
is a pass front-end for Emacs.
NOTE
: You can instead of PassCmd, use Pass that just has your
password in plain text, but I do not recommend this for security
reasons.
CertificateFile
- This location can vary based on your Linux distribution.Patterns
- Defines which folders will be synced, I personally just define my folders manually, similarly to the fastmail example.
Feel free to define multiple accounts this way.
After configuring isync, start the initial sync by running this command:
$ mbsync -a
Setting up mu & mu4e
First, you have to run the initial index.
mu init --maildir=~/Mail --my-address [email protected]
mu index
NOTE
: You may add as many --my-address
arguments you want.
Now, it’s time to create your mu4e configuration for Emacs.
You may create this as a module, or just as part of your :config using use-package. I personally define variables in my init.el like this:
(defvar is-desktop (equal (system-name) "desktop-hostname")) ;; your $HOSTNAME
(defvar is-laptop (equal (system-name) "laptop-hostname"))
Create ~/.emacs.d/modules/thanos-mu4e.el
for the mu4e module
configuration. And add this to my init.el
(add-to-list 'load-path "~/.emacs.d/modules")
(when (or is-desktop is-laptop)
(require 'thanos-mu4e))
This way I only load my mu4e configuration only when I’m using my laptop or desktop.
Loading Mu4e
Make sure mu4e
is on load-path:
(add-to-list 'load-path "/usr/share/emacs/site-lisp/mu4e/") ;; path to mu4e
(require 'mu4e)
The essentials
This is an example configuration to get started with mu4e using multiple accounts:
(setf mu4e-get-mail-command "mbsync -a")
(when (and is-desktop (server-running-p))
(setf mu4e-update-interval (* 10 60)))
;; Snippet from EmacsWiki
(defun set-mu4e-context (context-name full-name mail-address signature)
"Return a mu4e context named CONTEXT-NAME with :match-func matching
folder name CONTEXT-NAME in Maildir. The context's `user-mail-address',
`user-full-name' and `mu4e-compose-signature'`smtpmail-smpt-server' is set to MAIL-ADDRESS
FULL-NAME SIGNATURE and SERVER respectively.
Special folders are set to context specific folders."
(let ((dir-name (concat "/" context-name)))
(make-mu4e-context
:name context-name
;; we match based on the maildir of the message
:match-func
`(lambda (msg)
(when msg
(string-match-p
,(concat "^" dir-name)
(mu4e-message-field msg :maildir))))
:vars
`((user-mail-address . ,mail-address)
(user-full-name . ,full-name)
(mu4e-sent-folder . ,(concat dir-name "/Sent"))
(mu4e-drafts-folder . ,(concat dir-name "/Drafts"))
(mu4e-trash-folder . ,(concat dir-name "/Trash"))
(mu4e-trash-folder . ,(concat dir-name "/Starred"))
(mu4e-refile-folder . ,(concat dir-name "/Archive"))
(mu4e-compose-signature . ,signature)))))
;;Fixing duplicate UID errors when using mbsync and mu4e
(setf mu4e-change-filenames-when-moving t)
(setf mu4e-maildir-shortcuts
'(("/Fastmail/Inbox" . ?f)
("/Drafts" . ?d)
("/Sent" . ?s)
("/Gmail-Account/[Gmail]/All Mail" . ?g)
(setf mu4e-contexts
(list
(make-mu4e-context
:name "fastmail"
:match-func
(lambda (msg)
(when msg
(string-prefix-p "/Fastmail" (mu4e-message-field msg :maildir))))
:vars '((user-mail-address . "[email protected]")
(user-full-name . "User Name")
(smtpmail-smtp-server . "smtp.fastmail.com")
(smtpmail-smtp-service . 465)
(smtpmail-stream-type . ssl)
(mu4e-drafts-folder . "/Drafts")
(mu4e-sent-folder . "/Sent")
(mu4e-refile-folder . "/Archive")
(mu4e-trash-folder . "/Trash")))
;; You can comment out the second account.
(make-mu4e-context
:name "gmail"
:match-func
(lambda (msg)
(when msg
(string-prefix-p "/Gmail-Account" (mu4e-message-field msg :maildir))))
:vars '((user-mail-address . "[email protected]")
(user-full-name . "User Name")
(smtpmail-smtp-server . "smtp.gmail.com")
(smtpmail-smtp-service . 465)
(smtpmail-stream-type . ssl)))))
(setf message-send-mail-function 'smtpmail-send-it
mu4e-compose-signature "My Signature"
mu4e-compose-context-policy 'ask)
Extras
Mu4e actions
Mu4e actions makes it really simple to work with git patches, this is an example configuration you may like to use:
(setf mu4e-view-actions
(delete-dups
(append
'(("gapply git patches" . mu4e-action-git-apply-patch)
("mgit am patch" . mu4e-action-git-apply-mbox)))))
Sign your emails using pgp
If you have setup your own pgp key, you may sign automatically all your emails using this hook:
(add-hook 'message-send-hook 'mml-secure-message-sign-pgpmime)
Take a look at the functions defined for mml-mode-map
for more.