Skip to content

Latest commit

 

History

History
361 lines (262 loc) · 9.81 KB

Emacs-Mail-02.org

File metadata and controls

361 lines (262 loc) · 9.81 KB

Managing Multiple Email Accounts with mu4e and mbsync

How mu4e manages e-mail accounts

  • mu4e is a frontend for me mu mail indexer
  • mu just scans mail folders and indexes them
  • You tell mu4e about your mail folders and what searches you want to use
  • You can also tell mu4e how to change its configuration for different “contexts”

Laying the ground work

Since we will have two accounts under ~/Mail now, we need to move the existing mail under a subfolder.

But first, we need to stop mu4e from syncing! Run M-x mu4e-quit to stop the background sync timer.

Now we can move the Gmail folders into ~/Mail/Gmail:

cd ~
mv Mail Gmail
mkdir Mail
mv Gmail Mail

We also need to update our .mbsyncrc to use the new folders:

Path ~/Mail/Gmail/
Inbox ~/Mail/Gmail/Inbox

Test with mbsync to make sure everything syncs correctly:

mbsync -a

Lastly, reindex with mu:

mu index --maildir=~/Mail [email protected]

Setting up our first context

We will update our configuration to configure the Gmail account using mu4e-contexts:

(use-package mu4e
  :ensure nil
  :config

  ;; This is set to 't' to avoid mail syncing issues when using mbsync
  (setq mu4e-change-filenames-when-moving t)

  ;; Refresh mail using isync every 10 minutes
  (setq mu4e-update-interval (* 10 60))
  (setq mu4e-get-mail-command "mbsync -a")
  (setq mu4e-maildir "~/Mail")

  (setq mu4e-contexts
        (list
         ;; Work account
         (make-mu4e-context
          :name "Work"
          :match-func
            (lambda (msg)
              (when msg
                (string-prefix-p "/Gmail" (mu4e-message-field msg :maildir))))
          :vars '((user-mail-address . "[email protected]")
                  (user-full-name    . "System Crafters Gmail")
                  (mu4e-drafts-folder  . "/Gmail/[Gmail]/Drafts")
                  (mu4e-sent-folder  . "/Gmail/[Gmail]/Sent Mail")
                  (mu4e-refile-folder  . "/Gmail/[Gmail]/All Mail")
                  (mu4e-trash-folder  . "/Gmail/[Gmail]/Trash")))))

  (setq mu4e-maildir-shortcuts
        '(("/Gmail/Inbox"             . ?i)
          ("/Gmail/[Gmail]/Sent Mail" . ?s)
          ("/Gmail/[Gmail]/Trash"     . ?t)
          ("/Gmail/[Gmail]/Drafts"    . ?d)
          ("/Gmail/[Gmail]/All Mail"  . ?a))))

Docs: https://www.djcbsoftware.nl/code/mu/mu4e/Contexts.html Example: https://www.djcbsoftware.nl/code/mu/mu4e/Contexts-example.html

Try out the new context by evaluating the new configuration and run M-x mu4e.

You can change how the default context is picked by setting mu4e-context-policy to one of the following values:

  • ask-if-none - Ask the first time you enter the view (default)
  • pick-first - Pick the first context in the mu4e-contexts list
  • always-ask - Always ask when entering the main view

Syncing the second account

We’ll be using a Fastmail account (https://ref.fm/u7703101) for this example. It requires an App Password to connect to the IMAP endpoint:

https://www.fastmail.com/settings/security/devicekeys/new

Now we can add the IMAP configuration for the Fastmail account to our .mbsyncrc file:

... Gmail configuration from previous video ...

IMAPAccount fastmail
Host imap.fastmail.com
Port 993
User [email protected]
PassCmd "cat ~/.oh-no-another-insecure-password"
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
Master :fastmail-remote:
Slave :fastmail-local:
Patterns *
Expunge None
CopyArrivalDate yes
Sync All
Create Both
SyncState *

Now you can sync the new account:

mkdir ~/Mail/Fastmail
mbsync -a

You’ll also need to reindex with mu to add the new address:

mu index --maildir=~/Mail \
    [email protected] \
    [email protected]

NOTE: It’s possible you will see an error like this -

mu: mu_store_new_writable: xapian error 'Unable to get write lock on /home/daviwil/.mu/xapian: already locked' (11)

Just kill the running mu process and run mu index again:

pkill mu
# run mu index again

Adding the second account to mu4e

Now we can add a new context for the account to mu4e-contexts:

(setq mu4e-contexts
      (list
       ;; Work account
       (make-mu4e-context
        :name "Work"
        :match-func
          (lambda (msg)
            (when msg
              (string-prefix-p "/Gmail" (mu4e-message-field msg :maildir))))
        :vars '((user-mail-address . "[email protected]")
                (user-full-name    . "System Crafters Gmail")
                (mu4e-drafts-folder  . "/Gmail/[Gmail]/Drafts")
                (mu4e-sent-folder  . "/Gmail/[Gmail]/Sent Mail")
                (mu4e-refile-folder  . "/Gmail/[Gmail]/All Mail")
                (mu4e-trash-folder  . "/Gmail/[Gmail]/Trash")))

       ;; Personal account
       (make-mu4e-context
        :name "Personal"
        :match-func
          (lambda (msg)
            (when msg
              (string-prefix-p "/Fastmail" (mu4e-message-field msg :maildir))))
        :vars '((user-mail-address . "[email protected]")
                (user-full-name    . "System Crafters Fastmail")
                (mu4e-drafts-folder  . "/Fastmail/Drafts")
                (mu4e-sent-folder  . "/Fastmail/Sent")
                (mu4e-refile-folder  . "/Fastmail/Archive")
                (mu4e-trash-folder  . "/Fastmail/Trash")))))

After evaluating this configuration, we can launch mu4e again and switch contexts using the ; (semicolon) character.

How to use contexts

Examples:

  • Compose new mail in a context
  • Archive a message in a context (show which folder it goes to)
  • Reply to a message in a merged search

You can create bookmarks to show merged views of folders across accounts:

(add-to-list 'mu4e-bookmarks '("m:/Fastmail/INBOX or m:/Gmail/Inbox" "All Inboxes" ?i))

This is your e-mail client to build!

What’s next?

  • Composing e-mails
  • Displaying unread mail count and notifications
  • Even more uses for contexts and search queries
  • Org Mode integration

Complete Configuration

Here’s the complete configuration for this episode:

Emacs.org

(use-package mu4e
  :ensure nil
  :config

  ;; This is set to 't' to avoid mail syncing issues when using mbsync
  (setq mu4e-change-filenames-when-moving t)

  ;; Refresh mail using isync every 10 minutes
  (setq mu4e-update-interval (* 10 60))
  (setq mu4e-get-mail-command "mbsync -a")
  (setq mu4e-maildir "~/Mail")

  (setq mu4e-contexts
        (list
         ;; Work account
         (make-mu4e-context
          :name "Work"
          :match-func
            (lambda (msg)
              (when msg
                (string-prefix-p "/Gmail" (mu4e-message-field msg :maildir))))
          :vars '((user-mail-address . "[email protected]")
                  (user-full-name    . "System Crafters Gmail")
                  (mu4e-drafts-folder  . "/Gmail/[Gmail]/Drafts")
                  (mu4e-sent-folder  . "/Gmail/[Gmail]/Sent Mail")
                  (mu4e-refile-folder  . "/Gmail/[Gmail]/All Mail")
                  (mu4e-trash-folder  . "/Gmail/[Gmail]/Trash")))

         ;; Personal account
         (make-mu4e-context
          :name "Personal"
          :match-func
            (lambda (msg)
              (when msg
                (string-prefix-p "/Fastmail" (mu4e-message-field msg :maildir))))
          :vars '((user-mail-address . "[email protected]")
                  (user-full-name    . "System Crafters Fastmail")
                  (mu4e-drafts-folder  . "/Fastmail/Drafts")
                  (mu4e-sent-folder  . "/Fastmail/Sent")
                  (mu4e-refile-folder  . "/Fastmail/Archive")
                  (mu4e-trash-folder  . "/Fastmail/Trash")))))

  (setq mu4e-maildir-shortcuts
      '(("/Inbox"             . ?i)
        ("/Gmail/[Gmail]/Sent Mail" . ?s)
        ("/Gmail/[Gmail]/Trash"     . ?t)
        ("/Gmail/[Gmail]/Drafts"    . ?d)
        ("/Gmail/[Gmail]/All Mail"  . ?a))))

~/.mbsyncrc

IMAPAccount gmail
Host imap.gmail.com
User [email protected]
PassCmd "cat ~/.oh-no-insecure-password"
SSLType IMAPS
CertificateFile /etc/ssl/certs/ca-certificates.crt

IMAPStore gmail-remote
Account gmail

MaildirStore gmail-local
Subfolders Verbatim
Path ~/Mail/Gmail/
Inbox ~/Mail/Gmail/Inbox

Channel gmail
Master :gmail-remote:
Slave :gmail-local:
Patterns * ![Gmail]* "[Gmail]/Sent Mail" "[Gmail]/Starred" "[Gmail]/All Mail" "[Gmail]/Trash"
Create Both
SyncState *

IMAPAccount fastmail
Host imap.fastmail.com
Port 993
User [email protected]
PassCmd "cat ~/.oh-no-another-insecure-password"
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
Master :fastmail-remote:
Slave :fastmail-local:
Patterns *
Expunge None
CopyArrivalDate yes
Sync All
Create Both
SyncState *