EOM a.k.a End of Mail a.k.a Emacs + offlineimap + mu4e

tagged under   linux   emacs  


Here is how to install and configure emacs + offlineimap + mu4e for a complete email client (including instructions for multiple accounts).

What do each of them do ?

  • offlineimap, as the name implies, is used to fetch mail from the mail server into a local folder.
  • mu4e, is an emacs package that is built over "mu", and is used to index emails already downloaded using offlineimap, for quick searching.
  • Emacs is obviously where mu4e can be used.

Fetching email using offlineimap

Let us first install offlineimap as below

$ git clone git://github.com/OfflineIMAP/offlineimap.git
$ cd offlineimap
$ make
$ sudo python setup.py install

Installation should be very quick. Let us now configure offlineimap for use with gmail(multiple accounts are discussed later).

Create the file ~/.offlineimaprc with the following contents.

[general]
accounts = Gmail
maxsyncaccounts = 3

[Account Gmail]
localrepository = GmailLocal
remoterepository = GmailRemote

[Repository GmailLocal]
type = Maildir
localfolders = ~/Maildir/Gmail

[Repository GmailRemote]
type = IMAP
remotehost = imap.gmail.com
remoteuser = youremail@gmail.com
remotepass = yourpassword
ssl = yes
sslcacertfile = /etc/ssl/certs/ca-certificates.crt
maxconnections = 1
realdelete = yes

Replace youremail and yourpassword with your actual gmail userid and password. Next create a directory to store your emails locally.

Needless to say, make ~/.offlineimaprc readable by only you (chmod go-rwx ~/.offlineimaprc) since it contains plain-text password.

$ mkdir -p ~/Maildir/Gmail

That is it. You are ready to fetch email. Run

$ cd ~ && offlineimap

The first time is going to take long depending on the number of emails you have on the server. Subsequent times are much quicker fetching incrementally.

Installing mu4e

On Ubuntu based distros, mu4e along with the base "mu" program can be installed with

$ sudo apt-get install mu4e

Let us now go ahead and index the emails for fast searching.

$ mu index --maildir=~/Maildir

The above command is not actually required to be run standalone. mu4e does it for you within emacs when you ask it to refresh emails. Anyway lets do it to confirm that things are working as intended.

Setting up emacs as an email client

Finally, we need to setup emacs as an email client that uses mu4e. But first, let us install a few other programs that emacs needs for rendering emails and sending emails.

$ sudo apt-get install gnutls-bin html2text

Now, let us configure emacs. Add the following to your emacs init file.

(require 'mu4e)
(require 'smtpmail)

(setq mu4e-drafts-folder "/Gmail/[Gmail].Drafts"
      mu4e-sent-folder   "/Gmail/[Gmail].Sent Mail"
      mu4e-trash-folder  "/Gmail/[Gmail].Trash"
      mu4e-sent-messages-behavior 'delete
      mu4e-get-mail-command "offlineimap"
      mu4e-update-interval 60
      user-mail-address "youremail@gmail.com"
      user-full-name  "yourname"
      mu4e-maildir-shortcuts
            '( ("/Gmail/INBOX"               . ?i)
               ("/Gmail/[Gmail].Sent Mail"   . ?s)
               ("/Gmail/[Gmail].Trash"       . ?t)
               ("/Gmail/[Gmail].All Mail"    . ?a))

     message-send-mail-function 'smtpmail-send-it
     smtpmail-stream-type 'starttls
     smtpmail-default-smtp-server "smtp.gmail.com"
     smtpmail-smtp-server "smtp.gmail.com"
     smtpmail-smtp-service 587
     message-kill-buffer-on-exit t)

(setq mu4e-view-show-images t)
(when (fboundp 'imagemagick-register-types)
  (imagemagick-register-types))
(setq mu4e-view-prefer-html t)
(setq mu4e-html2text-command "html2text -utf8 -width 72")
(setq mail-user-agent 'mu4e-user-agent)

That is it. Reload your emacs config. Launch mu4e from Alt-x list. You will be presented with the mu4e main view which shows the key bindings for some of the most used operations, which I have listed below for the sake of completion.

Some imp key bindings

j<char> - jump to a particular folder within Maildir
jo      - ask for which directory within Maildir to enter
U       - refresh emails
C       - Compose email
s       - search
bu      - view unread messages
q       - quit any view

In the headers view (view which lists all your emails inside a particular folder), the following key bindings are useful.

n       - next email
p       - prev email
y       - toggle between headers view and the message view
          (which shows the email contents)
d       - mark email for moving to trash
D       - mark email for deleting permanently
!       - mark email as read
?       - mark email as unread
+,-     - star an email
t       - only mark current thread
T       - mark whole thread
x       - apply all marked actions
e       - extract attachments(saved to ~/ by default)
R       - reply to email
C-S-u   - refresh email

Now that we have a single account setup and running like charm, let us add another account to the mix.

Managing multiple accounts

Modify your ~/.offlineimaprc as below, to include Account2.

[general]
accounts = Gmail, Account2
maxsyncaccounts = 3

[Account Gmail]
localrepository = GmailLocal
remoterepository = GmailRemote

[Repository GmailLocal]
type = Maildir
localfolders = ~/Maildir/Gmail

[Repository GmailRemote]
type = IMAP
remotehost = imap.gmail.com
remoteuser = youremail
remotepass = yourpassword
ssl = yes
sslcacertfile = /etc/ssl/certs/ca-certificates.crt
maxconnections = 1
realdelete = yes

[Account Account2]
localrepository = Account2Local
remoterepository = Account2Remote

[Repository Account2Local]
type = Maildir
localfolders = ~/Maildir/Account2

[Repository Account2Remote]
type = IMAP
remotehost = mail.xyz.com
remoteuser = youremail
remotepass = yourpassword
ssl = yes
sslcacertfile = /etc/ssl/certs/ca-certificates.crt
maxconnections = 1
realdelete = yes

Fetch your emails.

$ mkdir -p ~/Maildir/Account2
$ cd ~ && offlineimap

Index them (not compulsory)

$ mu index --maildir=~/Maildir

Modify your emacs init file as below to include the second account.

(require 'mu4e)
(require 'smtpmail)

(setq mu4e-drafts-folder "/Gmail/[Gmail].Drafts"
      mu4e-sent-folder   "/Gmail/[Gmail].Sent Mail"
      mu4e-trash-folder  "/Gmail/[Gmail].Trash"
      mu4e-sent-messages-behavior 'delete
      mu4e-get-mail-command "offlineimap"
      mu4e-update-interval 60
      user-mail-address "youremail@gmail.com"
      user-full-name  "yourname"
      mu4e-maildir-shortcuts
            '( ("/Gmail/INBOX"               . ?i)
               ("/Gmail/[Gmail].Sent Mail"   . ?s)
               ("/Gmail/[Gmail].Trash"       . ?t)
               ("/Gmail/[Gmail].All Mail"    . ?a)
               ("/Account2/INBOX"            . ?k)
               ("/Account2/Sent Items"       . ?x)
               ("/Account2/Trash"            . ?f))

     message-send-mail-function 'smtpmail-send-it
     smtpmail-stream-type 'starttls
     smtpmail-default-smtp-server "smtp.gmail.com"
     smtpmail-smtp-server "smtp.gmail.com"
     smtpmail-smtp-service 587
     message-kill-buffer-on-exit t)

;; define only variables that differ for the two accounts
(defvar my-mu4e-account-alist
  '(("Gmail"
     (mu4e-drafts-folder "/Gmail/[Gmail].Drafts")
     (mu4e-sent-folder   "/Gmail/[Gmail].Sent Mail")
     (mu4e-trash-folder  "/Gmail/[Gmail].Trash")
     (user-mail-address  "youremail@gmail.com")
     (smtpmail-default-smtp-server "smtp.gmail.com")
     (smtpmail-smtp-server "smtp.gmail.com")
     (smtpmail-smtp-service 587))
    ("Cisco"
     (mu4e-drafts-folder "/Account2/Drafts")
     (mu4e-sent-folder   "/Account2/Sent Items")
     (mu4e-trash-folder  "/Account2/Trash")
     (user-mail-address  "youremail@abc.com")
     (smtpmail-default-smtp-server "outgoing.server.com")
     (smtpmail-smtp-server "outgoing.server.com")
     (smtpmail-smtp-service 25))))

(defun my-mu4e-set-account ()
  "Set the account for composing a message."
  (let* ((account
    (if mu4e-compose-parent-message
      (let ((maildir (mu4e-message-field mu4e-compose-parent-message :maildir)))
        (string-match "/\\(.*?\\)/" maildir)
        (match-string 1 maildir))
        (completing-read (format "Compose with account: (%s) "
          (mapconcat #'(lambda (var) (car var)) my-mu4e-account-alist "/"))
          (mapcar #'(lambda (var) (car var)) my-mu4e-account-alist)
          nil t nil nil (caar my-mu4e-account-alist))))
        (account-vars (cdr (assoc account my-mu4e-account-alist))))
    (if account-vars
        (mapc #'(lambda (var)
                  (set (car var) (cadr var)))
              account-vars)
      (error "No email account found"))))

(add-hook 'mu4e-compose-pre-hook 'my-mu4e-set-account)

(setq mu4e-view-show-images t)
(when (fboundp 'imagemagick-register-types)
  (imagemagick-register-types))
(setq mu4e-view-prefer-html t)
(setq mu4e-html2text-command "html2text -utf8 -width 72")
(setq mail-user-agent 'mu4e-user-agent)

Modify your email address and the outgoing mail server accordingly. You are ready to roll. Reload your emacs config and M-x mu4e to start working with your emails from both accounts. You can extend your emacs init file and .offlineimaprc to include more accounts accordingly.

Any suggestions, queries, improvements are welcome.


« older posts newer posts »



other articles you might like
  • Android reverse USB tethering
  • Linux command line tools and tricks - Part 3
  • Basic dwm setup in (L)ubuntu
  • Basic Xmonad setup in (L)ubuntu
  • First attempt at developing a Firefox addon
  • Bash script to perform super-fast file transfer using netcat and tar
  • Jekyll : Handling Github page build failure and Jekyll plugins on Github
  • Emacs newbie cheat sheet -- from a vim convert
  • ncmpcpp : ncurses based music player for Linux
  • How to create a custom CWM recovery flash-able android apps zip file in Linux via command line
  • Task Warrior - The best CLI task manager for Linux
  • Custom kernel in Ubuntu (also generate .deb package)
  • Linux command line tools and tricks - Part 2
  • Superb Linux command line tools and tricks for Linux geeks
  • RSA encryption using Tcl



  • Share this post ⇒  





    blog comments powered by Disqus