Trying Gnus as an email client

I've been using Thunderbird as my primary email client throughout most of my life. Why do I say primary? Because the other one is, of course, GNU Emacs with notmuch. Although using it is quite nice, the setup has a lot of moving parts as you need an external program to fetch your email, notmuch to index/tag it and a whole lot of shell scripts to make it all work nice and tidy.

As [previously shown]({{< relref "using-go-on-gnu-emacs-29-or-later" >}}) on this blog, the 29th version of GNU Emacs is going to bring a lot of new features and some of them made me ditch third-party packages completely. Why not try this for email too? I decided to give GNUS, which can retrieve and send emails from GNU Emacs itself, a chance!

Something to keep in mind is that GNUS was released in the 80s as a newsreader and as an effect of this, you have to deal with its vocabulary. While aiming to have it first as my email client, these are the terms used:

  • Server: can be an IMAP Server
  • Group: can be an IMAP Folder, eg. Inbox
  • Article: can be a message or an email

Retrieving emails with IMAP

"Why the can be?", you must be asking. As stated on the manual, GNUS has no clue about any protocols being used. One can use the variable gnus-select-method to set a default backend or keep it empty if you want to define secondary methods, which will be my case as I may introduce my work email in the future too.

(setq gnus-select-method '(nnnil nil))
(setq gnus-secondary-select-methods
      '((nnimap "personal"
                (nnimap-address "imap.example.com")
                (nnimap-server-port "imaps")
                (nnimap-stream ssl)
                (nnir-search-engine imap)
                (nnmail-expiry-target "nnimap+home:[Example]/Trash")
                (nnmail-expiry-wait 'immediate))))

Running M-x gnus made me configure my credentials on ~/.authinfo and already gave me my email inbox!

16:*nnimap+personal:INBOX
 6: nnimap+personal:INBOX/Forges

If you got here, you were probably reading about Gnus and chances are that you stumbled upon comments complaining about its synchronous nature. Well, it is true, but one can improve things a little bit with the following tweaks:

(setq gnus-asynchronous t
      gnus-use-cache t
      gnus-use-header-prefetch t)

This should be enough to start having a better experience with Gnus, but what about sending emails from Gnus?

Sending emails with SMTP

Until this moment, we have not set a single SMTP server for our accounts. This can be done with the variable gnus-posting-styles. The documentation states: "So what if you want a different Organization and signature based on what groups you post to?". Remember, a group can be your IMAP folder!

(setq gnus-posting-styles
      '(("personal"
	 (address "email@example.com")
	 (signature "Your Name")
	 ("X-Message-SMTP-Method" "smtp smtp.example.com 587 email@example.com"))))

Do not forget to set which method should be used to send email:

(setq message-send-mail-function 'message-use-send-mail-function
      send-mail-function 'smtpmail-send-it)

And its credentials on the ~/.authinfo file:

machine smtp.example.com login email@example.com password foobar

This example1 showed up for me when I searched for gnus-posting-styles.

OK, now you reply an email and instead of having a copy stored under your Sent folder (or group, in Gnus words), it is stored in a weird group called nnfolder+archive:sent.2023-05. How can we fix this?

Using the Group Parameters feature, we can set some more values, in this case we are going to set the gcc-self with the group (again, the IMAP folder) we want to send the email to:

(setq gnus-parameters
      '(("personal"
	 (gcc-self . "nnimap+personal:Sent"))))

This will make sure that every composed email gets a copy sent to the IMAP's server Sent folder!

Working out the user interface

As previously said, I am a Thunderbird user and I really like its user interface. How about we try to make it look closer to what Thunderbird looks like?

Well, it didn't work out at all. I read the manual section about Summary Buffer Lines and spent half an hour making my summary look like Thunderbird only to realize Gnus lacks most of its visual cues. I don't know how to put it, but things just looked weird and out of place.

I ended up searching for the variables I needed and copied them from other people's configurations:

;; summary
(setq gnus-sum-thread-tree-false-root " "
      gnus-sum-thread-tree-indent "  "
      gnus-sum-thread-tree-root "r "
      gnus-sum-thread-tree-single-indent "◎ "
      gnus-sum-thread-tree-vertical        "|"
      gnus-sum-thread-tree-leaf-with-other "├─► "
      gnus-sum-thread-tree-single-leaf     "╰─► "

      ;; │06-Jan│  Sender Name  │ Email Subject
      gnus-summary-line-format (concat "%0{%U%R%z%}"
				       "%3{│%}" "%1{%d%}" "%3{│%}"
				       "  "
				       "%4{%-20,20f%}"
				       "  "
				       "%3{│%}"
				       " "
				       "%1{%B%}"
				       "%s\n"))

This will make your summary look like this:

O  │01-Feb│  Merlin Scholz         │ r Re: few feature requests
O  │05-Feb│  Theodore Keloglou     │ ╰─► Search functionality
O  │20-Feb│  Robin Jarry           │ ◎ Relicensing aerc to GPL
OA │27-Apr│  Knut Magnus Aasrud    │ r New Pimalaya app proposal
O  │27-Apr│  Clément DOUIN         │ ╰─►
O  │02-May│  Knut Magnus Aasrud    │   ╰─►
O  │21-May│  Fred Laxton           │ ◎ RSS feed link typo

Decluttering the $HOME directory

By default, Gnus stores all of its files on the $HOME directory. This was once a good idea, but nowadays the cool kids follow the XDG Base Directory Specification. While we do not have default functions and variables to deal with the specification, I set some variables myself:

;; xdg directories
(setq user-emacs-config-directory (concat (getenv "HOME") "/.config/emacs")
      user-emacs-data-directory (concat (getenv "HOME") "/.local/share/emacs")
      user-emacs-cache-directory (concat (getenv "HOME") "/.cache/emacs"))

Now, with this variables set, we can tell Gnus to stop cluttering our $HOME directory with files and directories:

(setq gnus-directory (concat user-emacs-data-directory "/gnus")
      ;; all of them depend on the `gnus-directory` variable
      gnus-startup-file (concat gnus-directory "/.newsrc")
      gnus-cache-directory (concat gnus-directory  "/news/cache")
      gnus-article-save-directory (concat gnus-directory "/news")
      gnus-kill-files-directory (concat gnus-directory "/news")
      nndraft-directory (concat gnus-directory "/mail/draft")
      nnfolder-directory (concat gnus-directory "/mail/archive"))

Useful Keybindings

This is a list of useful keybindings I'm using with Gnus:

Keybinding Where Description
AA Group list See all the hidden groups.
SL Summary list Reply to a mailing list.

This list is probably never going to stop growing.