If you are jaunty masochist fascinated by use ‘n cry email readers, or you were just searching for something about white-tailed gnus and you found this article - sorry to dissapoint you - that’s definitely wrong place.

On the other hand, if you value your time, simplicity and usability, and the only thing that comes to your mind when talking about GNU is GNU’s Not Unix, you’re welcomed to read further. You will find out how set up awesome email/news reader (Gnus) on great operating system with faulty editor (Emacs).

Introduction

A few words about Gnus. Its look and feel, configuration and number of available options causes random ventricular fibrillation at first attempt. Yes, it’s not easy, but Gnus configured once lives for ever.

What you get in return (after half a year of digging in configuration files) is following:

  • email/news handling (imap supported!)
  • receving/sending from multiple accounts
  • articles expiring
  • scoring based on actually everything you can imagine
  • advanced searching (even more advanced when used together with mairix)
  • threads filtering
  • splitting incoming emails into configured groups
  • bbdb-based address book (or even better - org-contacts)
  • signing and enrcypting
  • finally, lisp hooks for almost every action

General customization

A small note at the beginning. Our goal here is to refine Gnus look and feel (to be not ashamed by outlook users) rather than to analyze its imap/smtp/nntp confguration.

Half of success on the way to get beautiful Gnus is improving Emacs colors. I suggest zen burn color theme (by Bozhidar Batsov) to make Emacs look better than average screen-locker (hello VI users :)

Next thing is smartly chosen font. Nice semigraphic symbols make Gnus a lighting star (or even a supernova) comparing to other (ugly) email clients.

This is what I added to my ~/.Xresources (linux):

Emacs.FontBackend: xft
Emacs*font: DejaVu Sans Mono-9

DejaVu font is highly recommened because of huge number of supported national characters and fancy Unicode symbols.

If you use linux and you have just modified your .Xresources, time to reload it: xrdb -load ~/.Xresources

Groups configuration

Groups are exactly what you see on first screenshot above. These are “folders” containing articles from different sources. As you can see, they can be additionally grouped under common topics. I have splitted sources of my articles to make them visually separated. Polish NNTP servers are grouped under usenet topic, articles coming from Gmane are under gmane and results of recent searches go into searches topic.

Creating, modification of topics and moving groups between them is pretty simple and is described here.

However, the most interesting is the look of our groups. It’s configurable (as everything else in Gnus) through appropriate variable set in ~/.gnus file:

(setq gnus-group-line-format "%P%M%St%(%g%) (%y)n")

Description of formatting characters you may find here.

Ok, Gnus looks much better now. But there is one little caveat. Everytime when Gnus starts, it tries to actualize our groups connecting to servers that groups are based on. It’s nothing wrong when you have one or two groups, but having them more may cause a long, irritating delay. Thanks God, there is something called levels, which modifies a bit this behaviour.

How do levels work? They are assigned to each group and instruct Gnus, among others, when to update the content. If given level is equal or below the value assigned to gnus-activate-level variable, the group it is assigned to updates itself automatically at startup. Higher value says “leave me alone, I will update myself right after I get selected”.

Let’s set the default activation level to 3:

(setq gnus-activate-level 3)

Now, each group which doesn’t need to be updated automatically should have level > 3 assigned. To do that, it’s enough to highlight the group, press S l shortcut, and adjust level. You will soon notice visual difference between “automatically updated” and “lazy” groups. First ones show number of collected articles, second ones show only meaningless “*”.

Additionally, each group has variable associated with styling (faces).

;; Mailing groups
gnus-group-mail-1    gnus-group-mail-1-empty
gnus-group-mail-2    gnus-group-mail-2-empty
gnus-group-mail-3    gnus-group-mail-3-empty

;; News groups
gnus-group-news-1    gnus-group-news-1-empty
gnus-group-news-2    gnus-group-news-2-empty
gnus-group-news-3    gnus-group-news-3-empty
gnus-group-news-4    gnus-group-news-4-empty
gnus-group-news-5    gnus-group-news-5-empty

So, to have blue empty mailing group, we need to set in ~/.gnus something like this:

(set-face-foreground 'gnus-group-mail-1-empty "blue")

One note here. Empty groups mean those with 0 articles AND those lazy ones which do not update the content automatically.

Configuration of articles list

List of articles is something you see after choosing the group. And this is the place which we may deeply customize. First of all, let’s format the way how articles are presented. To do that, I suggest to modify gnus-summary-line-format variable:

(setq gnus-summary-line-format "%1{%U%R%z: %}%2{%d%}%5{ %[%4i%] %}%4{%-24,24n%}%6{%-4,4ur%}%5{| %}%(%1{%B%}%s%)n")

Again, full description of used characters you may find here.

Now, a few words of explanation. Text between %( and %) will be highlighted using gnus-mouse-face immediately when mouse pointer hovers over given article. In our example %(%1{%B%}%s%) means that we want article subject (%s) and a corresponding part of thread’s tree (%B) highlighted on mouse hover. By default, thread is presented with plain ascii characters, just like this:

->
| +->
|->
+->

Obviously, it’s nothing really amazing. Fortunately, Emacs (in contrast to Mutt for example) gives a possibility to adjust every single character of that tree. Using that (and UTF symbols), we may get interesting effect:

(when window-system
  (setq
    gnus-sum-thread-tree-root "● "
    gnus-sum-thread-tree-false-root "▷ "
    gnus-sum-thread-tree-single-indent ""
    gnus-sum-thread-tree-leaf-with-other "├─►"
    gnus-sum-thread-tree-vertical "│ "
    gnus-sum-thread-tree-single-leaf "└─►"))

What (when window-system …) does is limiting above change to GUI version of Emacs only, this change won’t be applied to Gnus run in console.

Let’s look again at out gnus-summary-line-format. Something strange hides there inside: %6{%-4,4ur%}

What does it mean? As manual says, %u and following letter corresponds to user defined function gnus-user-format-function-X (where X is a symbol which goes right after %u). So, %ur will be used to inject the return value from gnus-user-format-function-r and $-4,4 instructs to align this value to length of 4 characters. Prepending %6 suggests to apply gnus-face-6 to everything inside curly parentheses.

Ok, I guess it’s clear more or less, but there is still question: what it that combination used for?

I bet you have already seen labels in GMail. Yes, it’s one of these addicting little things that you can’t live without. Moreover, such a label makes your searches and filtering much easier! So why not to try it out with Gnus?

Here is the result:

Red 4-letter labels distinguish interesting emails from the overall noise. This is realised exactly by previously mentioned snippet %6{%-4,4ur%} put inside our gnus-summary-line-format. As we remember %-4,4ur injects result of gnus-user-format-function-r function. This is how this function looks like:

(defun rs-gnus-get-label (header)
  "Returns label from X-Label header"
  (or (cdr (assq 'X-Label (mail-header-extra header))) ""))

(defalias 'gnus-user-format-function-r 'rs-gnus-get-label)

Additionally, we need to list this header in nnmail-extra-headers variable:

(setq nnmail-extra-headers '(To X-Label Newsgroups Content-Type))

…and apply red color:

(copy-face 'default 'face-label)
(set-face-foreground 'face-label "red")
(setq gnus-face-6 'face-label)

How about filtering ?

Nice. Now, let’s try to filter our mails by given label. Here is the function we will use (written by Reiner Steib):

(defun rs-gnus-summary-limit-to-label (regexp &optional not-matching)
  "Limit the summary buffer to articles that match a label."
  (interactive
   (list (read-string
     (format "%s label (regexp): "
     (if current-prefix-arg "Exclude" "Limit to"))) current-prefix-arg))
  (gnus-summary-limit-to-extra 'X-Label regexp not-matching))

Next, invoke this function M-x rs-gnus-summary-limit-to-label providing the label you want to filter by (use tab to autocomplete!) and enjoy with result:

Simple and easy, isn’t it?

Let’s get also list of articles sorted from the newest to the oldest ones, and filter out unnecessary headers from detailed view:

(setq
  gnus-thread-sort-functions '(lambda (t1 t2) (not (gnus-thread-sort-by-date t1 t2)))
  gnus-visible-headers "^From:|^To:|^Subject:|^Newsgroups:|^Date:|^Organization:|^X-Newsreader:|^User-Agent:"
  gnus-extra-headers '(To Newsgroups Content-Type))

Grand finale

Last thing last - nasty HTML emails. This is something we definitely don’t like but there are always people around who love to bomb us with tons of HTML.

How can we handle this sh^H^H ehm.. this kind of emails with beloved Gnus?

w3m is the answer. It’s an external html viewer which Emacs can nicely integrate with using w3m package. Here is detailed description.

(add-to-list 'load-path "/usr/share/emacs/site-lisp/w3m")
(setq
  mm-text-html-renderer 'w3m
  w3m-display-inline-image t)

Using mm-text-html-renderer we point at w3m as preferred web browser which is responsible for converting and formating HTML to something that Emacs is able to digest.

This is end of the Gnus story, but as you probably noticed it’s only the humble introduction of that beast. I hope it encouraged you to further researches.