Commit 7a00167687
Unsigned
Layout: unified · split
content/blog/2024-04-18-mu4e.org added +300
| @@ -0,0 +1,300 @@ | ||
| 1 | #+title: Email in Doom Emacs with Mu4e on macOS | |
| 2 | #+date: <2024-04-18 Thu 10:49:00> | |
| 3 | #+description: A short tutorial on configuring the Mu4e email client for Doom Emacs. | |
| 4 | #+filetags: emacs, org-mode, productivity | |
| 5 | #+slug: mu4e | |
| 6 | ||
| 7 | This post was heavily inspired by [[https://macowners.club/posts/email-emacs-mu4e-macos/][Email setup in Emacs with Mu4e on macOS]], but | |
| 8 | with my own tweaks for a single-account configuration and some Doom-specific | |
| 9 | configurations. | |
| 10 | ||
| 11 | * Overview | |
| 12 | ||
| 13 | [[https://github.com/emacsmirror/mu4e][Mu4e]] is an Emacs-based email client based on [[https://www.djcbsoftware.nl/code/mu/][mu]], an indexer that stores email in | |
| 14 | the Maildir format. | |
| 15 | ||
| 16 | This blog post covers the installation of Mu4e in Doom Emacs on macOS. This | |
| 17 | guide should be very similar to GNU Emacs and Linux-based systems, with a few | |
| 18 | tweaks required in the various configuration files. | |
| 19 | ||
| 20 | * Installation | |
| 21 | ** Prerequisites | |
| 22 | *** Create the Folder Structure | |
| 23 | Start by creating the base folder structure: | |
| 24 | ||
| 25 | #+begin_src sh | |
| 26 | mkdir ~/.maildir | |
| 27 | mkdir ~/.maildir/example # use whatever name you want to call your email account | |
| 28 | mkdir ~/.maildir/certificates # used to store system root certificates | |
| 29 | #+end_src | |
| 30 | ||
| 31 | *** Store Email Account Passwords in macOS Keychain | |
| 32 | Next, I will be using the macOS Keychain to store my email account passwords | |
| 33 | using the command below. | |
| 34 | ||
| 35 | #+begin_src sh | |
| 36 | security add-generic-password -s mu4e-example -a you@example.com -w | |
| 37 | #+end_src | |
| 38 | ||
| 39 | This will prompt you to input your password twice to confirm. Keep the | |
| 40 | =mu4e-example= name in mind, as you will need to reference it later in the IMAP | |
| 41 | and SMTP configuration files. | |
| 42 | ||
| 43 | *** Store Root Certificates | |
| 44 | ||
| 45 | In order to use IMAP and SMTP, we need to provide certificates to the local | |
| 46 | services. We will use the macOS defaults for this. | |
| 47 | ||
| 48 | 1. Open =Keychain Access.app=. | |
| 49 | 2. Select =System Roots= in the sidebar. | |
| 50 | 3. Select all items with =CMD + a=. | |
| 51 | 4. Export selected items with =SHIFT + CMD + a= to the file | |
| 52 | =~/.maildir/certificates/root-certificates.pem=. | |
| 53 | ||
| 54 | *** Install Dependencies | |
| 55 | ||
| 56 | Install =mbsync= (via =isync=) to fetch emails via IMAP, =mu= to index emails, | |
| 57 | and =msmtp= to send emails via SMTP. | |
| 58 | ||
| 59 | #+begin_src sh | |
| 60 | brew install mu isync msmtp | |
| 61 | #+end_src | |
| 62 | ||
| 63 | ** Installing Mu4e | |
| 64 | ||
| 65 | Within Doom Emacs, we can install Mu4e by enabling the package. | |
| 66 | ||
| 67 | #+begin_src sh | |
| 68 | nano ~/.doom.d/init.el | |
| 69 | #+end_src | |
| 70 | ||
| 71 | In this file, uncomment the =mu4e= line within the =:email= section. You can | |
| 72 | also enable the =+org= and =+gmail= options if you prefer. | |
| 73 | ||
| 74 | #+begin_src elisp | |
| 75 | (doom! :input | |
| 76 | ... | |
| 77 | ||
| 78 | mu4e | |
| 79 | ;;(mu4e +org +gmail) | |
| 80 | ... | |
| 81 | (default +bindings +smartparens)) | |
| 82 | #+end_src | |
| 83 | ||
| 84 | * Configuration | |
| 85 | As an overall suggestion, I create the following configuration files in the | |
| 86 | =~/.maildir= directory and using symlinks to their proper locations so that I | |
| 87 | can backup and restore these files easily. | |
| 88 | ||
| 89 | #+begin_src sh | |
| 90 | touch ~/.maildir/.mbsyncrc && \ | |
| 91 | touch ~/.maildir/.msmtprc && \ | |
| 92 | ln -s /Users/username/.maildir/.mbsyncrc /Users/username/.mbsyncrc && \ | |
| 93 | ln -s /Users/username/.maildir/.msmtprc /Users/username/.msmtprc | |
| 94 | #+end_src | |
| 95 | ||
| 96 | You can also create these files in your home directory and skip the symlinking | |
| 97 | process above. | |
| 98 | ||
| 99 | ** IMAP | |
| 100 | Next, let's configure =mbsync= in the file created above. Paste the following | |
| 101 | information and customize it to match your mail provider's information. | |
| 102 | ||
| 103 | #+begin_src sh | |
| 104 | nano ~/.maildir/.mbsyncrc | |
| 105 | #+end_src | |
| 106 | ||
| 107 | #+begin_src conf | |
| 108 | IMAPAccount example | |
| 109 | Host imap.example.com | |
| 110 | User dummy@example.com | |
| 111 | PassCmd "security find-generic-password -s mu4e-example -a dummy@example.com -w" | |
| 112 | Port 993 | |
| 113 | SSLType IMAPS | |
| 114 | AuthMechs Login | |
| 115 | CertificateFile ~/.maildir/certificates/root-certificates.pem | |
| 116 | ||
| 117 | IMAPStore example-remote | |
| 118 | Account example | |
| 119 | ||
| 120 | MaildirStore example-local | |
| 121 | SubFolders Verbatim | |
| 122 | Path ~/.maildir/example/ | |
| 123 | Inbox ~/.maildir/example/INBOX | |
| 124 | ||
| 125 | Channel example | |
| 126 | Far :example-remote: | |
| 127 | Near :example-local: | |
| 128 | Patterns * | |
| 129 | Create Near | |
| 130 | Sync All | |
| 131 | Expunge Both | |
| 132 | SyncState * | |
| 133 | #+end_src | |
| 134 | ||
| 135 | ** SMTP | |
| 136 | Next, let's configured =msmtprc= in the file created above. Paste the following | |
| 137 | information and customize it to match your mail provider's information. | |
| 138 | ||
| 139 | #+begin_src sh | |
| 140 | nano ~/.maildir/.msmtprc | |
| 141 | #+end_src | |
| 142 | ||
| 143 | ,#+begin_src conf | |
| 144 | defaults | |
| 145 | logfile ~/.maildir/msmtp.log | |
| 146 | tls_trust_file ~/.maildir/certificates/root-certificates.pem | |
| 147 | ||
| 148 | account example | |
| 149 | auth on | |
| 150 | host smtp.example.com | |
| 151 | port 465 | |
| 152 | protocol smtp | |
| 153 | from you@example.com | |
| 154 | user you@example.com | |
| 155 | passwordeval security find-generic-password -s mu4e-example -a you@example.com -w | |
| 156 | tls on | |
| 157 | tls_starttls off | |
| 158 | ||
| 159 | account default : example | |
| 160 | #+end_src | |
| 161 | ||
| 162 | ** Doom Emacs | |
| 163 | Finally, we need to configure Doom Emacs to use the proper packages and set some | |
| 164 | variables and functions. | |
| 165 | ||
| 166 | #+begin_src sh | |
| 167 | nano ~/.doom.d/config.el | |
| 168 | #+end_src | |
| 169 | ||
| 170 | #+begin_src elisp | |
| 171 | ;; load packages and programs | |
| 172 | (use-package mu4e | |
| 173 | :load-path "/Users/username/.emacs.d/modules/email/mu4e/") | |
| 174 | (require 'smtpmail) | |
| 175 | (setq mu4e-mu-binary (executable-find "mu")) | |
| 176 | ||
| 177 | ;; set base directory | |
| 178 | (setq mu4e-maildir "~/.maildir") | |
| 179 | ||
| 180 | ;; sync imap servers | |
| 181 | (setq mu4e-get-mail-command (concat (executable-find "mbsync") " -a")) | |
| 182 | ||
| 183 | ;; how often to sync in seconds | |
| 184 | (setq mu4e-update-interval 300) | |
| 185 | ||
| 186 | ;; save attachments to defined directory | |
| 187 | (setq mu4e-attachment-dir "~/Downloads") | |
| 188 | ||
| 189 | ;; rename files when moving - needed for mbsync: | |
| 190 | (setq mu4e-change-filenames-when-moving t) | |
| 191 | ||
| 192 | ;; list of your email adresses: | |
| 193 | (setq mu4e-user-mail-address-list '("you@example.com")) | |
| 194 | ||
| 195 | ;; check your ~/.maildir to see naming of subdirectories | |
| 196 | (setq mu4e-maildir-shortcuts | |
| 197 | '(("/example/INBOX" . ?e) | |
| 198 | ("/example/Sent" . ?E))) | |
| 199 | ||
| 200 | (setq mu4e-contexts | |
| 201 | `(,(make-mu4e-context | |
| 202 | :name "example" | |
| 203 | :enter-func | |
| 204 | (lambda () (mu4e-message "Enter you@example.com context")) | |
| 205 | :leave-func | |
| 206 | (lambda () (mu4e-message "Leave you@example.com context")) | |
| 207 | :match-func | |
| 208 | (lambda (msg) | |
| 209 | (when msg | |
| 210 | (mu4e-message-contact-field-matches msg | |
| 211 | :to "you@example.com"))) | |
| 212 | :vars '((user-mail-address . "you@example.com") | |
| 213 | (user-full-name . "Christian Cleberg") | |
| 214 | ;; check your ~/.maildir to see how the subdirectories are called | |
| 215 | ;; e.g `ls ~/.maildir/example' | |
| 216 | (mu4e-drafts-folder . "/example/Drafts") | |
| 217 | (mu4e-refile-folder . "/example/Archive") | |
| 218 | (mu4e-sent-folder . "/example/Sent") | |
| 219 | (mu4e-trash-folder . "/example/Trash"))))) | |
| 220 | ||
| 221 | (setq mu4e-context-policy 'pick-first) ;; start with the first (default) context; | |
| 222 | (setq mu4e-compose-context-policy 'ask) ;; ask for context if no context matches; | |
| 223 | ||
| 224 | ;; gpg encryptiom & decryption: | |
| 225 | ;; this can be left alone | |
| 226 | (require 'epa-file) | |
| 227 | (epa-file-enable) | |
| 228 | (setq epa-pinentry-mode 'loopback) | |
| 229 | (auth-source-forget-all-cached) | |
| 230 | ||
| 231 | ;; don't keep message compose buffers around after sending: | |
| 232 | (setq message-kill-buffer-on-exit t) | |
| 233 | ||
| 234 | ;; send function: | |
| 235 | (setq send-mail-function 'sendmail-send-it | |
| 236 | message-send-mail-function 'sendmail-send-it) | |
| 237 | ||
| 238 | ;; send program: | |
| 239 | (setq sendmail-program (executable-find "msmtp")) | |
| 240 | ||
| 241 | ;; select the right sender email from the context. | |
| 242 | (setq message-sendmail-envelope-from 'header) | |
| 243 | ||
| 244 | ;; mu4e cc & bcc | |
| 245 | (add-hook 'mu4e-compose-mode-hook | |
| 246 | (defun timu/add-cc-and-bcc () | |
| 247 | "My Function to automatically add Cc & Bcc: headers. | |
| 248 | This is in the mu4e compose mode." | |
| 249 | (save-excursion (message-add-header "Cc:\n")) | |
| 250 | (save-excursion (message-add-header "Bcc:\n")))) | |
| 251 | ||
| 252 | ;; mu4e address completion | |
| 253 | (add-hook 'mu4e-compose-mode-hook 'company-mode) | |
| 254 | #+end_src | |
| 255 | ||
| 256 | Be sure to sync Doom to update the current configurations. | |
| 257 | ||
| 258 | #+begin_src sh | |
| 259 | doom sync | |
| 260 | #+end_src | |
| 261 | ||
| 262 | If you have Doom open, execute =SPC h r r= to reload the new configurations. | |
| 263 | ||
| 264 | * Initial Sync | |
| 265 | Once you have configured all of the relevant files, you can perform an initial | |
| 266 | sync. Note that you can perform syncing within Mu4e itself afer this. | |
| 267 | ||
| 268 | #+begin_src sh | |
| 269 | mbsync -aV | |
| 270 | #+end_src | |
| 271 | ||
| 272 | Once you sync the data, you can index the emails. | |
| 273 | ||
| 274 | #+begin_src sh | |
| 275 | mu init -m ~/.maildir --my-address you@example.com && \ | |
| 276 | mu index | |
| 277 | #+end_src | |
| 278 | ||
| 279 | The emails will now to be ready to use! | |
| 280 | ||
| 281 | * Screenshots | |
| 282 | ||
| 283 | You can now launch Doom and open Mu4e with =SPC o m=. You can also explore the | |
| 284 | Mu4e options with =SPC : mu4e=. | |
| 285 | ||
| 286 | The home page shows various options and metdata about the account you've opened. | |
| 287 | ||
| 288 | #+caption: Mu4e Home Page | |
| 289 | [[https://img.cleberg.net/blog/20240418-mu4e/mu4e.png]] | |
| 290 | ||
| 291 | When composing an email, you can see the metadata fields at the top and compose | |
| 292 | the message below the indicator line. | |
| 293 | ||
| 294 | #+caption: Composition Screen | |
| 295 | [[https://img.cleberg.net/blog/20240418-mu4e/draft.png]] | |
| 296 | ||
| 297 | When in a folder, you can view emails in a pane and perform actions as needed. | |
| 298 | ||
| 299 | #+caption: Inbox | |
| 300 | [[https://img.cleberg.net/blog/20240418-mu4e/inbox.png]] | |