Recently, I’ve been using Google Inbox. Since I have previously setup my Google account to send and receive mail from my other email accounts, I can use it as my primary email service for all of my mail. While Google Inbox isn’t really “revolutionary”, it re-evaluates which UI elements of an email client should be emphasized. Instead of heavily emphasizing folders, categorization, flagging, etc., Inbox values the message list, and your basic activities are: read, act, and done. You read the message easily. Then you act on the message. That may mean actually dealing with it, or it may mean snoozing it. Once you’ve dealt with the message, you hit “Done” and it goes away from your inbox. But, it’s never gone for good, and you can always get back to old messages with a simple search.
I appreciate this perspective on mail. It turns my inbox into a something of a task list. In Gmail, I had this preoccupation with my huge tree of labels. Everything had to be categorized properly before being removed from the inbox. It was terrible, because nobody likes categorizing each email that arrives, several times per day. Naturally, my inbox would accrue hundreds of messages before I bit the bullet and cleared it out (spending easily an hour on the categorization, which is actually pretty quick thanks to Gmail’s keyboard shortcuts). The Inbox perspective removes the burden of categorization. It’s as simple as “is the task done?” If so, it’s out of the inbox. And if I was wrong, I can always find it again with a search. It’s about time I let the computers take control of my organization!
Long story short, I like Inbox. However, not every computer is ready to spin up a modern browser and load a Javascript-laden email interface. I use quite a few computers that have very modest capabilities, and Emacs outperforms web browsers on them. So, I took it upon myself to get Emacs to the point where I could send and receive mail easily, in a manner that feels like it belongs in Emacs, while also being reasonably true to the Google Inbox approach. This configuration does the trick for me. It’s based on Gnus, which is actually a newsgroup reader for Emacs, but has been adapted to work with email. Due to the fact that Gnus was made for newsgroups, it feels awkward using it with email, and it has a ton of extra features. My configuration is highly customized, and aims to make Gnus look and feel more like a simple mail client.
If you were to take this configuration for yourself, you would need to do the following to get email send/receive working:
- (If you’re not me) Change references to my name and email address to your own. You may need to modify IMAP/SMTP settings if you aren’t using Gmail.
- Create a
~/.authinfo
file containing your passwords for IMAP and SMTP (just your Gmail password, or an application-specific password if you do 2-factor auth, which you should). There is an example further down, in the “Imap, SMTP, and User INFO” section, which you can use to get started. Make sure you set this file to 600 permissions. - Run
M-x gnus
. If you have a lot of folders, it should take a long time “subscribing” to each of them. This is a first-run sort of thing, we’ll fix it in a bit. Once it’s finished, hitq
to close it, and runM-x gnus
again. This time, it will start pretty much instantly, and it will show a list of folders. - Using
C-k
, kill every folder you don’t want to see ever. I killed everything except INBOX and [Gmail]/All Mail, because that’s pretty much how Google Inbox does it. - On every folder you’d like Gnus to check at startup (fewer=better), put point
on that group, and run the command
S l 1
. This changes the folder’s “level” to 1. I set INBOX’s level to 1. - Everything that you’d like to be able to view, but not check on startup, leave alone. I left [Gmail]/All Mail alone. If you’re confused about the last couple steps, and you want to understand what’s going on in the background, check out the Folder Selection section.
To get your contacts imported into Emacs so that you can get name completion in the “To:” field, do this:
- Go to Google contacts and export as a VCard File. You probably only want to export “My Contacts”, not all of them, because you’ll have a lot of strange, spurious entries with all of them.
- Install
bbdb-vcard
(M-x package-install RET bbdb-vcard RET
). - Run
M-x bbdb-vcard-import-file RET [filename-here] RET
. - Afterwards, you can view your contact list by running
M-x bbdb RET RET
.- Use
n
andp
to scroll through by each contact instead of each line. - Hit
d
(and typey
to confirm) on any spurious contacts you’d like to delete. - Hit
e
on any field to edit its contents.
- Use
- In my contacts, a few contacts had names that ended with “(imported-xxxx)”.
I’m not sure why. You’ll want to
C-s
to ISearch through the buffer for instances of the word “imported”, then edit and remove those occurrences. I only had around 3 of them.
You can use Gnus to search for messages on the IMAP server. Thankfully, there’s no additional setup for this.
Gnus is primarily a news reader that happens to support email. So, it has some weird idiosyncracies, which I’ve tried to eliminate in my configuration below.
There are three views in Gnus. The Group view, the Summary view, and the Article view.
When you load up Gnus, you see the Group view. You can navigate without using
the Control key, with n
and p
, or arrow keys. You can refresh the unread
counts by hitting g
. Hit enter on the group (this is basically a synonym for
folder) you want to open. You can also left click on a group name to open it.
This brings you to the Summary view, which shows your messages in that folder.
If you have a lot of messages in that folder, you may be prompted for how many
to load. More means longer loading time.
In the Summary view, you can navigate with just the n
and p
buttons, which I
find helpful. You can hit enter to open up a message. This will split your
window so that you can see the message (in the Article view) and the Summary
view at the same time. It keeps your point in the Summary, which is usually
nice. You can delete a message using the delete key (type yes to confirm). You
can refresh the list by hitting g
. Reply to a message with r
. If you want
to quote the original, use R
. Reply all (Wide reply) using w
, and
similarly, include a quote with W
. Exit the summary (and any opened articles)
with q
.
The Article view is tied to the Summary view, which is why it’s usually split
from the Summary view. You can do all the reply shortcuts in the Article view,
and you can also scroll using normal keys. I find that once I open an article
view and read the message, I want to get rid of the window so I have a clean
Summary mode. If your point is currently in the Article, just use C-x 0
. If
your point is in the Summary mode, use the shortcut v x
to bury the current
article window. Also, if you hit q
in the Article mode, it will exit out of
both the article and the summary view.
Anywhere within Gnus, you can hit m
to start writing a message. Anywhere
else, you can use C-x m
to compose a message as well.
Be careful to not use many other keys in Gnus. Gnus has a ton of key bindings,
and you could accidentally use one that you don’t understand, and is very
confusing. If you find yourself lost in Gnus, hit q
until everything is
exited, and start it up again.
One of the things that makes Google Inbox nice is search. You can search for
messages that aren’t in your inbox. You can use Gnus to search for messages on
the server as well. In Gnus, search operates on a specific folder, so you’ll
want to have your “[Gmail]/All Mail” folder visible in the Group buffer. Just
put your point on that group, and hit G G
to open a search prompt. Type your
search query, and you’ll get a Summary buffer full of results. Very handy.
Note that you can only do this when you’re in the Group view, and you have to put your cursor on the group you want to search (typically, All Mail).
Gnus is installed by default in Emacs. BBDB, on the other hand, is not. You should be fine using this configuration, even if you never actually use BBDB, so it’s best to leave it here in case you do start using it for your contacts.
(require-package '(bbdb))
(require 'nnir)
I actually copied a lot of this from the Emacs Wiki article on Gnus, and modified it for my own uses. You’ll need to modify email addresses and names, and also server info if you don’t use Google Inbox/Gmail.
(setq gnus-select-method
'(nnimap "gmail"
(nnimap-address "imap.gmail.com")
(nnimap-server-port 993)
(nnimap-stream ssl)
(nnir-search-engine imap)))
(setq message-send-mail-function 'smtpmail-send-it
smtpmail-starttls-credentials '(("smtp.gmail.com" 587 nil nil))
smtpmail-auth-credentials '(("smtp.gmail.com" 587
"brenns10@gmail.com" nil))
smtpmail-default-smtp-server "smtp.gmail.com"
smtpmail-smtp-server "smtp.gmail.com"
smtpmail-smtp-service 587
gnus-ignored-newsgroups "^to\\.\\|^[0-9. ]+\\( \\|$\\)\\|^[\"]\"[#'()]")
You definitely don’t want to store an email password in an Emacs config file
(especially if you’ll then put it on GitHub!). So, you should use a
~/.authinfo
file with entries for the SMTP and IMAP servers. This file should
definitely have 600 permissions (meaning, nobody except you can read it. You
can set these permissions with the bash command chmod 600 ~/.authinfo
). The
file should look something like this:
<<authinfo>>
machine imap.gmail.com login [email] password [password] port 993 machine smtp.gmail.com login [email] password [password] port 587
This sets information about who you are – it goes into your From field for all your messages. Definitely edit it, unless you’re me.
(setq user-full-name "Stephen Brennan"
user-mail-address "brenns10@gmail.com")
Vanilla Gnus is meant to be a news reader. So, message lists don’t look anything like you’re accustomed to in an email list. The below code makes the message lists look more like an email list. The code is cut and pasted from Starter Kit Gnus.
; http://groups.google.com/group/gnu.emacs.gnus/browse_thread/thread/a673a74356e7141f
(when window-system
(setq gnus-sum-thread-tree-indent " ")
(setq gnus-sum-thread-tree-root "") ;; "● ")
(setq gnus-sum-thread-tree-false-root "") ;; "◯ ")
(setq gnus-sum-thread-tree-single-indent "") ;; "◎ ")
(setq gnus-sum-thread-tree-vertical "│")
(setq gnus-sum-thread-tree-leaf-with-other "├─► ")
(setq gnus-sum-thread-tree-single-leaf "╰─► "))
(setq gnus-summary-line-format
(concat
"%0{%U%R%z%}"
"%3{│%}" "%1{%d%}" "%3{│%}" ;; date
" "
"%4{%-20,20f%}" ;; name
" "
"%3{│%}"
" "
"%1{%B%}"
"%s\n"))
(setq gnus-summary-display-arrow t)
As a consequence of being a news reader, Gnus assumes that once you’ve read a message, you’re pretty much done with it. That’s very bad for email, and a completely unexpected behavior for most people. So, this will ensure that Gnus will always show messages, even if they’re read. It also makes sure that you always have access to the Inbox group, even when there are no unread messages.
(setq gnus-parameters
'((".*"
(display . all)
(gnus-use-scoring nil))))
(setq gnus-permanently-visible-groups "INBOX")
This has Gnus display the newest emails first (again, this isn’t normal behavior for Gnus due to being a news reader).
(setq gnus-thread-sort-functions
'(gnus-thread-sort-by-most-recent-number))
This little snippet enables topic mode for the Group view. This essentially allows you to group folders into topics. Of course, with Google Inbox, this really doesn’t matter. You can completely get rid of this snippet. I happen to like having the topic heading, even though there’s only one and I haven’t customized it. I guess everyone has their idiosyncracies.
(add-hook 'gnus-group-mode-hook 'gnus-topic-mode)
<<folderselection>>
By the design of Gnus, whenever it starts up, it needs to check every folder
you’re “subscribed” to, and get a list of messages in there. Then, it checks it
against your ~/.newsrc
file to see what you’ve read. It’s a really silly and
really slow system that stems from the age of news readers. The Gnus developers
know it can be pretty slow, so they made a way for you to say which folders
you’d like checked on startup, by setting their “level” (1-9). It’s actually
reasonably complex, but allows for plenty of customization. My customization is
as follows:
- I decided that I only want Gnus to query the server about my Inbox. So, I set
my Inbox to level 1, (
S l 1
in the Group buffer, with point on INBOX), and then set the correct variable accordingly:(setq gnus-activate-level 1)
- I would like to see some other folders in my Group view (like All Mail), but I don’t want Gnus to check them every time. Thankfully, the threshold for a folder showing up by default in the Group view is 5. So, any value from 2 to 5 will be good. I set “[Gmail]/All Mail” to be level 2.
- I don’t want to see any other folders. Furthermore, I don’t want Gnus to even
try to track them. So, I “killed” them using
C-k
in the Group view. This gave them a level of 9.
These commands give me easier access to PGP encryption services. Basically, if you open a signed or encrypted message, this will automatically verify or decrypt it for you. Also, when you decide to encrypt your messages, it will ask you to select recipient keys from a list, which is very nice.
(setq mm-verify-option 'always)
(setq mm-decrypt-option 'always)
(setq mm-encrypt-option 'guided)
(setq gnus-buttonized-mime-types '("multipart/signed"))
This will automatically quit Gnus non-interactively when Emacs exits, so I don’t need to worry about correctly exiting it myself.
(setq gnus-interactive-exit nil)
(add-hook 'kill-emacs-hook (lambda ()
(when (boundp 'gnus-group-exit)
(gnus-group-exit))))
Don’t let Gnus take the entire window **every time I open something**.
(setq gnus-use-full-window nil)
Some keys and mouse gestures that make mail navigation easier:
- Use “n” and “p” for navigation, without control button.
- Create a shortcut “v x” that will close the open article buffer.
- Use middle click on article buffer to close it. Since there is already functionality to middle click on message and view it (in Summary view), this makes mouse navigation nice using middle click.
- Use the delete key to delete a message, instead of
B <delete>
, which was a bit annoying. This will still prompt for confirmation, but you can disable that by settinggnus-novice-user
tonil
.
(defun stemacs-switch-close ()
"Switch window and close it."
(interactive)
(progn
(other-window 1)
(delete-window)))
(defun stemacs-mouse-close (event)
"Switch to the clicked window and close it."
(interactive "e")
(let ((w (posn-window (event-start event))))
(if (window-valid-p w)
(delete-window (select-window w))
nil)))
(add-hook 'gnus-group-mode-hook
(lambda ()
(progn
(define-key gnus-group-mode-map (kbd "n") 'gnus-group-next-group)
(define-key gnus-group-mode-map (kbd "p") 'gnus-group-prev-group))))
(add-hook 'gnus-summary-mode-hook
(lambda ()
(progn
(define-key gnus-summary-mode-map (kbd "v x") 'stemacs-switch-close)
(define-key gnus-summary-mode-map (kbd "n") 'next-line)
(define-key gnus-summary-mode-map (kbd "p") 'previous-line)
(define-key gnus-summary-mode-map (kbd "<delete>") 'gnus-summary-delete-article)
(define-key gnus-summary-mode-map (kbd "g") 'gnus-summary-insert-new-articles))))
(add-hook 'gnus-article-mode-hook
(lambda ()
(progn
(define-key gnus-article-mode-map [down-mouse-2] 'stemacs-mouse-close)
(define-key gnus-article-mode-map (kbd "<delete>") 'gnus-summary-delete-article))))
For contacts, I’m using BBDB. This seems to work for me. I downloaded my Google Contacts in VCF, and used bbdb-vcard to import them.
;;; bbdb
(require 'bbdb)
(bbdb-initialize 'gnus 'message)
(setq
bbdb-file "~/.bbdb"
bbdb-offer-save 'auto
bbdb-notice-auto-save-file t
bbdb-expand-mail-aliases t
bbdb-canonicalize-redundant-nets-p t
bbdb-always-add-addresses t
bbdb-complete-name-allow-cycling t
)