# Sync changes (creations/deletions) with the server
Create Both
Expunge Both
Sync All
#+end_example
Verify mbsync is working correctly with =$ mbsync work=. This will pull down work
mail to =~/.mail/work/= with a folder layout mimicking Exchange's mail folder
structure.
Some items to note:
- =Create Both= and =Expunge Both= means mbsync can *delete* messages on your mailserver. If you want to try this configuration out in read-only mode, set these values to =Create Slave= and =Expunge Slave= instead.
- The trailing slash on the local =MaildirStore==path= statement is critical!
- My experience with Exchange 365 has been chaotic. I've set a =Timeout 120= value to try to ensure there are no sync hiccups. This value has proved useful to me, but you can change it or remove it as you see fit.
- mbsync will /not/ delete mail folders on the server. Before you use this tool, it might be wise to ensure your Exchange folder hierarchy is as flat as possible. This can be done using the Outlook or OWA client.
- =PassCmd= allows you to retrieve credentials from a CLI password manager tool
Now email can be synced and retrieved from the mailserver.
**** mu4e
=mu= is a command-line mail client that provides superior mail search
capabilities. Installing this package will automatically pull down mu4e (mu 4
Emacs) as well.
***** mu4e Prerequisites
On macOS, install =mu= (which includes mu4e) and =mbsync=. Note that =mbsync=
is part of the /isync/ homebrew collection. These are both installed in the
terminal using homebrew:
#+begin_example
brew install mu
brew install isync
#+end_example
Installing from homebrew should place the required files in
=/usr/local/share/emacs/site-lisp/mu/mu4e= that will be loaded in the
configuration below.
***** Run mu
Before using =mu4e= it's a good idea to verify that =mu= works as expected,
after all, =mu4e= uses =mu= as its engine.
To validate, =mu= must first create a mail index. Run:
=$ mu index --maildir=~/.mail/work=
Once this completes, give =mu= a spin:
=$ mu find timecard=
=$ mu find from:myboss=
At this point, mail is synced, indexed, and searchable from Exchange.
**** Doom Emacs
I am thoroughly impresed with [[https://github.com/hlissner/doom-emacs][Doom
Emacs]], and use it as my base. Configuring this distribution is slightly
different from configuring =mu4e= in vanilla Emacs.
First, security:
***** Securely Store SMTP Credentials
SMTP is used to transfer outbound messages. I store my o365 creds in a
gpg-encrypted file, =~/.emacs.d/.authinfo.gpg=
****** Create authinfo file
Enter the credentials for the SMTP server in =~/.authinfo= using the format:
=machine mail.example.com login myusername port 587 password mypassword=
*Use quotes to contain the password*, for instance:
=machine smtp.office365.com login [emailprotected] password "mypassword" port
587=
****** Encrypt authinfo file
Use gpg to encrypt the authinfo file. (macOS users, install
[[https://gpgtools.org/]]. This will place a symlink to the =gpg= CLI tool in
your =/usr/local/bin= so make sure that's in your shell's =$PATH=.
I won't cover the process of creating a keypair in this article, but you can
find more information [[https://www.gnupg.org/gph/en/manual/c14.html][here]]
and [[https://help.runbox.com/creating-key-pair-on-os-x/][here.]]
Find the gpg key you want to encrypt this file with using =$ gpg --list-keys=:
#+begin_example
----------------------------------
...
pub rsa4096 2019-01-22 [SC] [expires: 2023-01-22]
315998993D8B8B1BA4AD5D209332E13A9A79C3D5
uid [ultimate] Chris Lockard < [emailprotected]>
sub rsa4096 2019-01-22 [E] [expires: 2023-01-22]
sub rsa4096 2019-09-09 [S] [expires: 2023-09-08]
sub rsa4096 2019-09-09 [E] [expires: 2023-09-08]
sub rsa4096 2019-09-09 [A] [expires: 2023-09-08]
#+end_example
Now encrypt =~/.authinfo= using the following:
=$ gpg -se ~/.authinfo=
This prompts for the key to use, so either enter = [emailprotected]= or the
key signature - =A9A79C3D5=. The output of this program is an encrypted file,
=~/.authinfo.gpg=. For added security, set the permissions on this file to
=chmod 600 ~/.authinfo.gpg=.
Finally, move this file with =mv .authinfo.gpg ~/.emacs.d= and cleanup the file
containing cleartext credentials with =rm .authinfo=. Emacs will automatically
know to look for =~/.emacs.d/authinfo.gpg= which will help later when
configuring SMTP.
***** Doom Emacs Configuration
I store my Doom configuration files in my github and link them thusly:
* [[https://skeptric.com/emacs-email/][Don't manage work email with Emacs ·]] :website:
[2021-12-05 Sun 21:44]
** Article
I do a lot of work in Emacs and at the command line, and I get quite a few
emails so it would be great if I could handle my emails there too. Email in
Emacs can be surprisingly featureful and handles HTML markup, images and can
even send [[https://kitchingroup.cheme.cmu.edu/blog/2016/10/29/Sending-html-emails-from-org-mode-with-org-mime/][org markup with images and equations]] all from the comfort of an Emacs
buffer. However it can be a whole /heap/ of work, and as you get deeper into the
features your mail client provides the amount of custom integration required
grows very rapidly. It's a good way to appreciate all the features of your
current mail client, but you may be able to find a better use of your time.
Getting the basics of synchronising emails from an IMAP or Exchange server may
take some time to setting up (and in some circumstances take a /lot/ of time),
but once they're working it will be pretty smooth. Dealing with HTML and images
and attachments works pretty well out of the box, unless you get a lot of
custom office drawings in your email. Building an address book of frequent
contacts is a bit of a pain, but with some work is possible. Synchronising
email addresses from the server can be difficult, and may need to be done in
batches - but you might be able to manually. Getting calendar invites is
possible with a bit of hacking, but seeing other people's calendars is very
difficult. Finally if the server configuration is changed (like changing an
authentication provider) you may have to spend a lot of time setting it up all
over again.
The benefits are that it tends to be faster to get through emails (because they
are on the local filesystem), you don't need to change environments to use them
and you can use all your favourite CLI tools on them. But unless email is a
very large part of your working life (and it seems to be slowly losing out to
instant messaging clients) it's probably not worth the investment (unless you
want to build a custom email automation tool one day!).
I'll share some of my experience doing this for those who are hard to
discourage.
*** Operating Environment
If you want to set up email from the command line or Emacs you'll want to be
working in a POSIXy environment, because that's where all the tooling is. If
your working environment supports Linux or Mac computers then it's happy times.
However if you're working in Windows you have a few options.
The best Windows option is [[https://docs.microsoft.com/en-us/windows/wsl/faq][Windows Subsystem for Linux]] - it lets you run a
whole Linux environment and works pretty well with Windows. There are a couple
of creaky edges, mainly the filesystem is slow (which should be fixed in [[https://docs.microsoft.com/en-us/windows/wsl/wsl2-index][WSL2]]),
but overall it's the best solution *if* you can get the [[https://docs.microsoft.com/en-us/windows/wsl/install-win10][feature enabled]].
If you can't then working in a [[https://www.virtualbox.org][Virtualbox VM]] for Linux is the next best option;
and you can configure it to be fairly seamless. However you can't use it if
there's any other virtualisation on your machine like Docker for Windows. In
fact some organisations use security software that uses virtualisation making
it impossible to install Virtualbox. But if you can get Virtualbox running (or
your organisation supports another virtualisation product) then it's generally
a good solution.
When all else fails there is good ol' [[https://www.cygwin.com/][Cygwin]]. It doesn't require any special
permissions, so as long as you can run external applications on your computer
it should work. It's a bit clunky, and you may need to build some utilities
(like =isync=, see below) yourself, but with a bit of work you can get a usable
environment. I've heard [[https://www.msys2.org/][msys2]] is better but have never taken the time to
understand it.
*** Synchronising email
You now need a way to pull email to your local filesystem and push emails back
out. For pushing emails [[file:www.postfix.org][Postfix]] works great (and has a =sendmail= interface) and
I've never needed anything else. For pulling emails you can run a email server
like [[https://www.dovecot.org/][Dovecot]], but it's quite a bit of effort to set up. The easiest solution is
to use [[http://isync.sourceforge.net/][isync/mbsync]], or it's slower cousin [[http://www.offlineimap.org/][offlineimap]].
Both [[http://isync.sourceforge.net/mbsync.html#CONFIGURATION][mbsync]] and [[https://github.com/OfflineIMAP/offlineimap/blob/master/offlineimap.conf][offlineimap]] have gnarly configuration options that will make
you learn quite a bit about the low level details of email authentication and
[[https://en.wikipedia.org/wiki/Maildir][Maildir]]. And if you set the wrong options you might accidentally delete your
whole email; so spend a lot of time reading through them and try it out on a
test account before you run it on your precious emails. To get authentication
details for your email provider the easiest thing to do is to search the web,
and if you have a common email provider (like Gmail, Office365, Fastmail)
you'll likely find a blog with a sample configuration. If you've got an
uncommon provider look in their documentation/settings for SMTP and IMAP; if
the Auth method isn't clear it's best to try to set it up with [[https://www.thunderbird.net/en-US/][Thunderbird]]
first because it has some magic to automatically detect these settings and is
more likely to work out of the box.
If your email provider doesn't have IMAP enabled then you're probably out of
luck - unless it's an exchange server. If you can't get app passwords and need
to use two factor authentication you may spend a /lot/ of time trying to get this
set up (and may have to implement the feature!).
If you're on an Exchange server or on Office365 but can't access IMAP then you
can use the fantastic [[http://davmail.sourceforge.net/][Davmail]]. Davmail also supports CalDAV and CardDAV for
calendar and contacts (more on this later). The only issue is finding the
Exchange server settings can take some sleuthing (or a beer with your local
sysadmin). As before it's best to get it working in Thunderbird before trying
another synchronising tool, because it's easiest to get working there.
*** Setting up a mail interface
So now you've got all your emails sitting in a maildir folder it'd be handy to
have a tool for reading and writing email.
If you're a serious vim user [[http://www.mutt.org/][mutt]] may be a good option. [[https://notmuchmail.org/][notmuch]] has a powerful
tag system, but you have to manually sync it yourself between servers (and the
[[https://notmuchmail.org/notmuch-emacs/][Emacs mode]] has too many special screens for my liking). In Emacs [[https://www.gnu.org/software/emacs/manual/html_node/gnus/Maildir.html][gnus]] is
built-in, but has a byzantine configuration system that you could spend the
rest of your life tweaking (like this [[https://github.com/jwiegley/dot-emacs/blob/master/gnus-settings.el][John Wiegley's]]). But gnus is apparently
good if you're on a lot of mailing lists. However for me [[https://www.djcbsoftware.nl/code/mu/][mu]] and it's Emacs
counterpart [[https://www.djcbsoftware.nl/code/mu/mu4e.html][mu4e]] work fantastically well - you just have to take the time to
learn yet another query language (and if you use evil-mode there are mu4e
keybindings in [[https://github.com/emacs-evil/evil-collection/][evil-collection]]).
This is generally pretty straightforward (especially if you can crib a
configuration file that is close to what you need), but there are some traps
like if you use mbsync and mu4e you need to set
=mu4e-change-filenames-when-moving= to true or you'll get all sorts of errors
when trying to sync. You can then spend a bunch of time configuring [[https://www.reddit.com/r/emacs/comments/9ep5o1/mu4e_stop_emails_setting_backgroundforeground/][how HTML is
rendered]], [[http://pragmaticemacs.com/emacs/master-your-inbox-with-mu4e-and-org-mode/][storing links to emails in org-mode]] and [[https://kitchingroup.cheme.cmu.edu/blog/2016/10/29/Sending-html-emails-from-org-mode-with-org-mime/][sending email from org-mode]].
*** Dealing with contacts
Now you can write email you may want to store the addresses of people you want
to contact. Many email providers support the [[https://en.wikipedia.org/wiki/CardDAV][CardDav]] format and you can
synchronise it locally with a tool like [[https://asynk.io/][ASynK]] or [[https://github.com/pimutils/vdirsyncer][vdirsyncer]]. You can then
import them into org contacts with [[https://github.com/flexibeast/org-vcard][org-vcard]] and [[https://www.djcbsoftware.nl/code/mu/mu4e/Maintaining-an-address_002dbook-with-org_002dcontacts.html][configure mu4e]] to use them for
auto-completion. Or use them with [[https://www.jwz.org/bbdb/][BBDB]] for Emacs email clients that support
them, or write a script to convert them to [[https://gitlab.com/muttmua/mutt/-/wikis/MuttGuide/Aliases][Mutt aliases]].
One problem is if you work for an enterprise with thousands of people that's
going to be a lot of email addresses, and the syncing or the interface may
choke. You can probably get away with just manually copying the addresses of
the people you email most often into the configuration of whatever tool you
use. But once in a while you'll want to email someone in your organisation and
you may have to fall back to another tool to get the address book.
*** Calendars and meeting invites
Calendars is something where Outlook groupware really shines. You can see
everyone's calendar and schedule a meeting in free time using the scheduling
assistant (and book meeting rooms!). While this can lead to the problem of
[[https://jack.ofspades.com/calendar-tetris-is-an-antipattern/][calendar tetris]] where other people unilaterally fill the blanks in your
Calendar, it's generally a useful organisational feature and can sometimes even
be used to list and book available meeting rooms.
[[/images/outlook_scheduling_assistant.png]]
I haven't found anything that quite substitutes for it in an office
environment. You could manage your calendar with a command line tool in
[[https://github.com/pimutils/khal][khal]] or in Emacs with
Part 4 of [[/series/emacs-productivity/][Emacs For Productivity]]
I get a lot of email. I'm also pretty sure you get a lot of email. However,
email is still not a solved problem This is evidenced by the fact that a quick
Google search yields no less than ten viable options for email clients on my
Mac. . Each potential email client is acceptable on it's own, yet none of them
satisfied all of my desired features:
This is evidenced by the fact that a quick Google search yields no less than
ten viable options for email clients on my Mac.
- The ability to access my email without an internet connection I travel quite a lot, so this was very important to me. .
- Easily move messages between different folders, which is how I keep all of my emails organized by project.
- Quick yet powerful search of all my mail messages.
- Having an auto-updating status indicator that shows me how many unread messages I have.
- Managing multiple accounts (Gmail for personal emails and Microsoft Exchange for work emails) and syncing local changes so that my phone can still be up-to-date.
If you follow this blog, you'll recognize that I've gotten a bit carried away
with migrating the different aspects of my life to operate within the Emacs
environment. So it was only a matter of time until I finally decided to give it
a shot, and I converged upon a solution which happily satisfies all of the
above constraints. Every email service is a bit different so YMMV, but this
setup works for me.
Here's a screenshot of what we'll be setting up:
A screenshot of the mu4e interface after searching for recent emails from
Amazon. Notice that I've "marked" a number of messages for deletion =d=,
archiving =r=, and moving =m=. I also have an icon at the bottom right corner that
[[https://disqus.com/?ref_noscript][comments powered by Disqus.]]
* [[https://www.tomica.net/blog/2020/12/sending-mail-using-multiple-mu4e-contexts-in-emacs/][Sending mail using multiple Mu4e contexts in Emacs | Ivan Tomica]] :website:
* [[https://www.djcbsoftware.nl/code/mu/mu4e/Contexts-example.html][Contexts example (Mu4e 1.6.0 user manual)]] :website:
[2021-12-18 Sat 09:42]
** Article
<<Contexts-example>>
Previous: [[file:Contexts-and-special-folders.html][Contexts and special folders]], Up: [[file:Contexts.html][Contexts]] [ [[file:index.html#SEC_Contents][Contents]]]
--------------
<<Example>>
*** 9.4 Example
Let's explain how contexts work by looking at an example. We define two contexts, ‘Private' and ‘Work' for a fictional user /Alice Derleth/.
Note that in this case, we automatically switch to the first context when starting; see the discussion in the previous section.
;; set `mu4e-context-policy` and `mu4e-compose-policy` to tweak when mu4e
should
;; guess or ask the correct context, e.g.
;; start with the first (default) context;
;; default is to ask-if-none (ask when there's no context yet, and none match)
;; (setq mu4e-context-policy 'pick-first)
;; compose with the current context is no context matches; default is to ask
;; (setq mu4e-compose-context-policy nil)
#+end_src
A couple of notes about this example:
- You can manually switch the context use =M-x mu4e-context-switch=, by default bound to ; in headers, view and main mode. The current context appears in the mode-line.
- Normally, =M-x mu4e-context-switch= does not call the enter or leave functions if the 'new' context is the same as the old one. However, with a prefix-argument ( C-u), you can force mu4e to invoke those function even in that case.
- The function =mu4e-context-current= returns the current-context; the current context is also visible in the mode-line when in headers, view or main mode.
- You can set any kind of variable; including settings for mail servers etc. However, settings such as =mu4e-mu-home= are not changeable after they have been set without quitting mu4e first.
- =leave-func= (if defined) for the context we are leaving, is invoked before the =enter-func= (if defined) of the context we are entering.
- =enter-func= (if defined) is invoked before setting the variables.
- =match-func= (if defined) is invoked just before =mu4e-compose-pre-hook=.
- See the variables =mu4e-context-policy= and =mu4e-compose-context-policy= to tweak what mu4e should do when no context matches (or if you always want to be asked).
- Finally, be careful to get the quotations right --- backticks, single quotes and commas and note the '.' between variable name and its value.
--------------
Previous: [[file:Contexts-and-special-folders.html][Contexts and special