2

I'm struggling to get mu4e to work with different (private and work) email accounts. The behaviour is different from what I expected, and I am not sure whether this is due to an issue in my configuration or in my expectation :-)

Learning how to install, configure and use offlineimap, mu and mu4e took an hour or two for my Private account, and since then I've been struggling for about a whole day to get it to work with a second, Work, account. Syncing and indexing the Work email is no problem, but presenting and in particular separating emails from the two accounts. I think I've read every post on SO mentioning mu4e and context, the mu4e manual, FAQ, and GitHub issues, many blogs, and seen many example inits, but no combination of any of them seems to work. I may still have missed something obvious though.

Current settings

My directories are set up as follows:

~/.emacs_mail
├── PrivateEmail
│   ├── Drafts
│   ├── Sent
│   ├── Trash
│   └── INBOX
└── WorkEmail
    ├── Drafts
    ├── INBOX
    ├── Sent
    └── Trash

offlineimap is asked to sync email from my private server and account to the PrivateEmail subfolder, and from my work server and account to WorkEmail. mu4e is instructed that the mu4e-maildir is ~/.emacs_mail/ and I'm trying to use contexts to separate the two. The mu4e part of my emacs init is shown here (the two context blocks are nearly identical in structure, and have some identical overlap, because I want to add more email accounts later on):

(require 'mu4e)
(setq mail-user-agent 'mu4e-user-agent)
(setq message-kill-buffer-on-exit t)
(require 'smtpmail)
(setq mu4e-headers-skip-duplicates t)
(setq mu4e-compose-format-flowed t)
(setq mu4e-headers-date-format "%Y-%m-%d %H:%M")
(setq mu4e-headers-fields
    '( (:date    .  25)    ;; use :date  / :human-date
       (:flags   .   6)
       (:from    .  22)
       (:subject .  nil)   ;; use :subject / :thread-subject
       )
    )
(setq mu4e-user-mail-address-list '("private@email.org"
                                    "me@work.com")
      )
(setq mu4e-maildir "~/.emacs_mail")
(setq mu4e-contexts
      `(
        ;; Private context:
        ,(make-mu4e-context
          :name "Private"
          :enter-func (lambda () (mu4e-message "Entering Private context"))
          :leave-func (lambda () (mu4e-message "Leaving Private context"))
          :match-func (lambda (msg)
                        (when msg
                          (mu4e-message-contact-field-matches msg
                                                              :to "private@email.com")
                          )
                        )
          :vars '(
                  ( mu4e-drafts-folder . "/PrivateEmail/Drafts" )
                  ( mu4e-sent-folder   . "/PrivateEmail/Sent" )
                  ( mu4e-trash-folder  . "/PrivateEmail/Trash" )
                  ( mu4e-maildir-shortcuts .
                                           (
                                            ("/INBOX"  . ?i)
                                            ("/Sent"   . ?s)
                                            ("/Trash"  . ?t)
                                            )
                                           )
                  ( user-mail-address      . "private@email.com" )
                  ( user-full-name         . "My Name" )
                  ( mu4e-compose-signature .
                                           (concat
                                            "My Name\n"
                                            "http://private.org\n"
                                            )
                                           )
                  ( mu4e-sent-messages-behavior  . 'delete )
                  ( mu4e-get-mail-command        . "offlineimap" )  ;; Alternatives: fetchmail, getmail, isync, ...
                  ( message-send-mail-function   . 'smtpmail-send-it )
                  ( smtpmail-stream-type         . 'starttls )
                  ( smtpmail-default-smtp-server . "smtp.email.com" )
                  ( smtpmail-smtp-server         . "smtp.email.com" )
                  ( smtpmail-smtp-service        .  587)
                  )  ;; vars
          )  ;; Private
        ;; Work context:
        ,(make-mu4e-context
          :name "Work"
          :enter-func (lambda () (mu4e-message "Entering Work context"))
          :leave-func (lambda () (mu4e-message "Leaving Work context"))
          :match-func (lambda (msg)
                        (when msg
                          (mu4e-message-contact-field-matches msg
                                                              :to "me@work.com")
                          )
                        )
          :vars '(
                  ( mu4e-drafts-folder . "/WorkEmail/Drafts" )
                  ( mu4e-sent-folder   . "/WorkEmail/Sent" )
                  ( mu4e-trash-folder  . "/WorkEmail/Trash" )
                  ( mu4e-maildir-shortcuts .
                                           (
                                            ("/INBOX"   . ?i)
                                            ("/Sent"    . ?s)
                                            ("/Trash"   . ?t)
                                            ("/Drafts"  . ?d)
                                            )
                                           )
                  ( user-mail-address      . "me@work.com" )
                  ( user-full-name         . "My Full Name" )
                  ( mu4e-compose-signature .
                                           (concat
                                            "Visiting address:\n"
                                            "Room B2.70\n"
                                            )
                                           )
                  ( mu4e-sent-messages-behavior  . 'delete )
                  ( mu4e-get-mail-command        . "offlineimap" )
                  ( message-send-mail-function   . 'smtpmail-send-it )
                  ( smtpmail-stream-type         . 'starttls )
                  ( smtpmail-default-smtp-server . "smtp.work.com" )
                  ( smtpmail-smtp-server         . "smtp.work.com" )
                  ( smtpmail-smtp-service        .  587)
                  )  ;; vars
          )  ;; Work
        )
      )
(add-to-list 'mu4e-bookmarks
             (make-mu4e-bookmark
              :name  "PrivateEmail unread inbox"
              :query "flag:unread AND maildir:/PrivateEmail/INBOX AND NOT flag:trashed"
              :key ?p)
             )

(I used sed to anonimise this file and to remove blank lines (many, for readability) and lines starting with ;;).

Current behaviour

When I (re)start emacs (with or without using -q and manually loading my mu4e.el) and start mu4e, I have to choose between the Private and Work contexts as expected. However, when I then press ji, I get a list of email headers from both my Private and Work contexts, where I would expect only headers from the current context. Hence, I get identical results, independent of the current context.

Or, perhaps, I would expect to see nothing at all, since according to my init the ji shortcut refers to /INBOX w.r.t. the mu4e-maildir, i.e. to the directory ~/.emacs_mail/INBOX/, which does not exist. In fact, I originally set up the maildir-shortcuts to "/PrivateEmail/INBOX", etc., but that doesn't work at all — I get an empty header list — I suppose mu4e thinks that the directory ~/.emacs_mail/PrivateEmail/INBOX/ doesn't exist. Also, pressing s to search for maildir:/INBOX 'works' (though I still get headers from both accounts, contrary to my desire) while maildir:/PrivateEmail/INBOX doesn't (empty list).

Probably for the same reason, the bookmark I defined at the bottom of the file also produces an empty list. When I remove the /PrivateEmail part, the header list is full of emails from both accounts...

Understanding contexts

What doesn't help is the fact that from the mu4e manual, I don't understand what exactly the contexts, and central in that I think, the :match-func, are supposed to achieve. Is the :match-func supposed to filter emails for me, so that when listing my Inbox headers, I only see those from the current context? Or should the :match-func only (help to) determine which account to use when e.g. replying to an email? The obvious variable I wanted to set differently in my different contexts was mu4e-maildir, but according to the docs I'm not supposed to do that (and I'd have to restart mu4e or even emacs, which I'd like to avoid (in that case, I could write a script to rename email dirs before starting mu4e)).

Desired behaviour

Ideally, I would like to achieve that when I'm at work, I'd switch to the Work context and only deal with Work email (incoming, outgoing, other boxes I sedded out here, whatever). When I would press ji, I'd see my Work inbox, and when I'd press bu, I'd get only unread Work emails. When I'd go home, I'd press ;p and I'd never see a work email again. And I'd be able to add another ~3-5 email accounts which wouldn't get mixed up. Are these realistic wishes? How would I achieve them, or get as close as possible? Have I just missed one vital setting in my init?

Curiouser and curiouser

With my shortcut ("/Private/Sent" . ?s), when I try to move an email to that box using ms and x, I get an error that the mail could not be moved to ~/.emacs_mail/Private/Private/Sent/.... Hence, I changed the shortcut to ("/Sent" . ?s) which throws the error that the mail could not be moved to ~/.emacs_mail/Sent/.... I'm not sure how to get a single /Private in there, rather than zero or two. Leading slashes don't make a difference...

Environment

Gentoo Linux, GNU emacs 26.1, mu(4e) 1.3.1.

1

I just got it working with 2 contexts this week-end, so I looked at your config but can't find the specific error for your problem This is my setup:

(add-to-list 'load-path "~/mu/mu4e")
(require 'mu4e)
(require 'smtpmail)

(setq mu4e-get-mail-command "mbsync -c ~/.emacs.d/.mbsyncrc -a"
      mu4e-maildir (expand-file-name "~/.email")
      mu4e-update-interval 180
      message-kill-buffer-on-exit t
      mu4e-headers-skip-duplicates t
      mu4e-compose-signature-auto-include nil
      mu4e-view-show-images t
      mu4e-view-show-addresses t
      mu4e-attachment-dir "~/Downloads"
      mu4e-use-fancy-chars t
      mu4e-headers-auto-update t
      message-signature-file "~/.emacs.d/.signature"
      mu4e-compose-signature-auto-include nil
      mu4e-view-prefer-html t
      mu4e-compose-in-new-frame t
      mu4e-change-filenames-when-moving t
      message-send-mail-function 'smtpmail-send-it
      starttls-use-gnutls t
      smtpmail-stream-type 'starttls
      ;;mu4e-html2text-command "w3m -T text/html"
      )

(setq mu4e-context-policy 'pick-first)
(setq mu4e-compose-context-policy 'always-ask)
(setq mu4e-contexts
      (list
       (make-mu4e-context
    :name "personnel"
    :enter-func (lambda () (mu4e-message "Entering personal context"))
    :leave-func (lambda () (mu4e-message "Leaving personal context"))
    :match-func (lambda (msg)
              (when msg
            (mu4e-message-contact-field-matches
             msg '(:from :to :cc :bcc) "mail@xxx.com")))
    :vars '((user-mail-address . "mail@xxx.com")
        (user-full-name . "Mr Plouc")
        (mu4e-sent-folder . "/work/Sent")
        (mu4e-drafts-folder . "/work/Drafts")
        (mu4e-trash-folder . "/work/Trash")
        (mu4e-refile-folder . "/work/Archives")
        (smtpmail-queue-dir . "~/.email/gmail/queue/cur")
        (smtpmail-smtp-user . "mail@xxx.com")
        (smtpmail-starttls-credentials . (("mail.xxx.com" 587 nil nil)))
        (smtpmail-auth-credentials . (expand-file-name "~/.authinfo.gpg"))
        (smtpmail-default-smtp-server . "mail.xxx.com")
        (smtpmail-smtp-server . "mail.xxx.com")
        (smtpmail-smtp-service . 587)
        (mu4e-sent-messages-behavior . sent)
        (mu4e-maildir-shortcuts . ( ("/work/INBOX"    . ?i)
                        ("/work/Sent"     . ?s)
                        ("/work/Trash"    . ?t)
                        ("/work/Archives" . ?a)
                        ("/work/Drafts"   . ?d)
                        ))))

       (make-mu4e-context
    :name "gmail"
    :enter-func (lambda () (mu4e-message "Entering gmail context"))
    :leave-func (lambda () (mu4e-message "Leaving gmail context"))
    :match-func (lambda (msg)
              (when msg
            (mu4e-message-contact-field-matches
             msg '(:from :to :cc :bcc) "xxx@gmail.com")))
    :vars '((user-mail-address . "xxx@gmail.com")
        (user-full-name . "Mr Plouc")
        (mu4e-sent-folder . "/gmail/[Gmail]/Messages envoy&AOk-s")
        (mu4e-drafts-folder . "/gmail/[Gmail]/Brouillons")
        (mu4e-trash-folder . "/gmail/[Gmail]/Corbeille")
        (mu4e-refile-folder . "/gmail/[Gmail]/Tous les messages")
        (smtpmail-queue-dir . "~/.email/gmail/queue/cur")
        (smtpmail-smtp-user . "xxx@gmail.com")
        (smtpmail-starttls-credentials . (("smtp.gmail.com" 587 nil nil)))
        (smtpmail-auth-credentials . (expand-file-name "~/.authinfo.gpg"))
        (smtpmail-default-smtp-server . "smtp.gmail.com")
        (smtpmail-smtp-server . "smtp.gmail.com")
        (smtpmail-smtp-service . 587)
        (mu4e-sent-messages-behavior . delete)
        (mu4e-maildir-shortcuts . ( ("/gmail/INBOX"                        . ?i)
                        ("/gmail/[Gmail]/Messages envoy&AOk-s" . ?s)
                        ("/gmail/[Gmail]/Corbeille"            . ?t)
                        ("/gmail/[Gmail]/Tous les messages"    . ?a)
                        ("/gmail/[Gmail]/Brouillons"           . ?d)
                        ))))))

;; don't save messages to Sent Messages, Gmail/IMAP takes care of this

;;; Bookmarks
(setq mu4e-bookmarks
      `(
    ("flag:unread AND NOT flag:trashed" "Unread messages" ?u)
    ("flag:unread" "new messages" ?n)
        ("date:today..now" "Today's messages" ?t)
        ("date:7d..now" "Last 7 days" ?w)
        ("mime:image/*" "Messages with images" ?p)
        ))

(require 'org-mu4e)
(setq org-mu4e-convert-to-html t)

(use-package org-mime
  :ensure t)

With this config I can switch contexts and show only my particular Inbox or waht ever folder.

For bookmarks, if you want them contexts-based then I think they have to be added right inside the make-mu4e-context block, didn't try it yet though

  • Thanks for sharing, it's often useful to have working examples - I'll have a good look later this week and see whether I can find anything that I did differently. I have two questions: 1) I take it that your syncs the email from your two accounts (independently) into ~/.email/work/ and ~/.email/gmail, correct? And 2), do/can you then switch from one Inbox to the other pressing ; <select context> and then ji for the Inbox? – AstroFloyd May 7 at 19:19
  • That's it, two different accounts. A personal one and a general one (gmail). And you're welcome! Yep you can switch context and show only the appropriate mails exactely as you said. The gmail has a bit of a strange structure though with the [Gmail] thing, I know it's possible to tweak. ps: my Sent folder is in french and is called "messages envoyés" and made a strange folder name...but that still works xD – JC0nde May 8 at 8:08
0

There were a number of issues (mostly my ignorance) that causes at least some of my problems. Since this could happen to others, I'll post the solutions here. Things seem to be working fine currently using three different accounts.

Mixing emails from different accounts

The mixing of emails happened because I started with one account and added another later. I had already indexed ~/.emacs_mail/PrivateEmail and I indexed ~/.emacs_mail after I added the second account/subdirectory. That messed up the mu database. rm -rf ~/.mu/ and indexing only ~/.emacs_mail fixed that.

Mixing emails from different maildirs in one account

However, after the fix above, my strict jumps to a particular box (using e.g. ji) also showed emails from other boxes. I had already switched off the display of threads (using (setq mu4e-headers-show-threads nil) or P), but it turns out by default mu4e displays all emails in the selected directory and all other emails that share a thread with them. (setq mu4e-headers-include-related nil) fixed that for me. It took me a long time to figure this one out...

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.