From the Gnus website:
Gnus is a flexible message reader running under GNU Emacs. It supports reading and composing both news and mail. In addition, it is able to use a number of web-based sources as inputs for its groups.
The main Gnus goal is to provide the user with an efficient and extensible interface towards dealing with large numbers of messages, no matter the form they may have or wherever they may come from.
Gnus is a fully MIME-compliant and supports reading and composing messages using any charset that GNU Emacs supports.
The same, but said differently: nearly any communication medium which can be represented as a collection of trees of messages could be plugged in to a single highly-customisable Emacs-based interface, and this interface can be customized like any other Emacs application.
Another quote from the Gnus documentation:
You know that Gnus gives you all the opportunity you'd ever want for shooting yourself in the foot. Some people call it flexibility. Gnus is also customizable to a great extent, which means that the user has a say on how Gnus behaves. Other newsreaders might unconditionally shoot you in your foot, but with Gnus, you have a choice!
Malleable Systems like Emacs provide the technically engaged end-user with a nearly endless arsenal of tools, and infinite ways to combine those tools. Emacs is not a tool so much as an workshop of ideas, a set of tools to design the ideal workshop.
Below I describe a core configuration for the Gnus message reader as a part of The Complete Computing Environment and my Email and News and Information Pipelines. It includes, as well, a set of Evil Mode bindings which will allow me to use Gnus with the same idioms as the rest of my system. I aim to describe source-specific configuration in other documents, this module will be "pluggable" in that regard, designed to integrate in this CCE system. I also configure and describe a unique feature of Gnus, the Gnus Scoring System and the Adaptive Scoring engine but individual scoring decisions are left as an excercise to the reader.
provide 'cce/gnus) (
You know who I am, you know my primary email alias:
setq user-mail-address "ryan@whatthefuck.computer"
("Ryan Rix") user-full-name
A Somewhat Aesthetically Pleasing Summary Buffer
Despite all assumptions, I want to work with things which are aesthetically appealing. Gnus can use unicode line-drawing symbols to present threads in a more-legible fashion, and I configure that below, based on configuration taken from the Spacemacs Gnus Layer. Additionally, I configure the gnus-summary-line-format to be slightly more compact than the default configuration.
setq gnus-summary-line-format "%*%U%R%z %(%&user-date; %-15,15f %B%s%)\n"
('gnus-gather-threads-by-references
gnus-summary-thread-gathering-function ""
gnus-sum-thread-tree-false-root " "
gnus-sum-thread-tree-indent "├► "
gnus-sum-thread-tree-leaf-with-other ""
gnus-sum-thread-tree-root "╰► "
gnus-sum-thread-tree-single-leaf "│"
gnus-sum-thread-tree-vertical t . "%d %b %Y %H:%M"))) gnus-user-date-format-alist '((
Custom Window Configurations
Gnus has a reasonable UI by default and it is of course wildly customisable, every Gnus buffer can be configured to be displayed in a different configuration, this is described in gnus-buffer-configuration. I modify the windowing configuration slightly: I do not need to see the group buffer (the buffer which has the full list of groups) when I am looking at articles, so I override it:
require 'gnus-win)
('gnus-buffer-configuration
(add-to-list
'(article 1.0
(horizontal ;; (org-todo 0.3)
1.0
(vertical 0.25 point)
(summary 1.0)))))
(article
'gnus-buffer-configuration
(add-to-list
'(group 1.0
(horizontal ;; (org-todo 0.3)
1.0 point))))
(group
'gnus-buffer-configuration
(add-to-list
'(summary 1.0
(horizontal ;; (org-todo 0.3)
1.0 point))))
(summary
'gnus-window-to-buffer '(org-todo . "emails.org"))
(add-to-list 'org-agenda
(with-eval-after-load 'org-agenda-files "~/org/emails.org")) (add-to-list
Use fill-column
to wrap HTML text in
Gnus buffers:
'gnus-article-mode-hook
(add-hook lambda ()
(cond
(
((cce/external-display-connected)setq fill-column 120
(nil))
shr-use-fonts equal (system-name) "MeadowCrush")
((setq fill-column 75
(t))
shr-use-fonts equal (system-name) "tres-ebow")
((setq fill-column 90
(t))
shr-use-fonts t
(setq fill-column 120
(t))))) shr-use-fonts
Rich Text, HTML mail, and Images
I want to not look at HTML unless I have to, and I want it to not load images unless they're embedded
I do not want my client to display HTML or rich-text by default and
to prefer plain text. This is not simply an ideological choice: Gnus has
access to a limited selection of HTML renderers, configurable in mm-text-html-renderer, the default
and my preferred is to use the shr
engine
which is included by default in Emacs and is also used by EWW. This
engine supports a simple limited HTML subset, supports images, and
doesn't require any software to be installed.
I certainly don't want to view the HTML rendering by default, though,
especially if you're sending me crapware/advertisement/newsletter mail.
shr
can be configured to not load remote
images, preventing tracking pixels or other remote content from loading,
but it's often a much less legible interface than a simple text
encoding, even if buttons or links rarely work by default. As of Gnus
5.13 ([2020-04-30]), when gnus-inhibit-images
is set to true Gnus will
skip loading all images, but this is not actually what
I want: my Universal Aggregator tool will re-write remote images from
RSS feeds to use cid:
URLs and embed the
images in the MIME container. So, following the Gnus
HTML documentation and the logic in gnus-html-wash-images from gnus-html.el, I am
setting gnus-blocked-images
to a
constantly-matching regular expression ".". This is the default behavior
but I encode it here explicitly because it is an explicit decision.
'mml
(with-eval-after-load require 'mm-decode)
(setq mm-discouraged-alternatives '("text/html" "text/richtext")
(remove "text/html" mm-automatic-display))
mm-automatic-display (setq mm-text-html-renderer 'shr
("."
gnus-blocked-images nil)) gnus-inhibit-images
Configuring Usenet as the Default Access Method
I access many mailing lists through the Gmane service, a proxy service which presents many user mailing lists as usenet groups and I can subscribe to them only in this client, not busying other mailboxes with a bunch of mailing lists, keeping filters up to date, etc.
(setq gnus-select-method '(nntp "news.gmane.io"))
Local Maildir access with the Dovecot IMAP command
I use mbsync to move mail from my server
to Maildirs on my laptop, desktop, and GPD Pocket. Gnus provides a
native backend for reading maildirs, but it performs quite poorly and
the universal suggestion is to use an IMAP daemon configured in some
fashion to access that directory using the much quicker nnimap
connector.
Rather than deal with the full authentication stack and having an
IMAP server running locally on all my laptops, Gnus can use a
shell-program which takes IMAP commands on stdin and outputs results on
stdout. Dovecot ships one of these in its libexec
folder, and with a tweaked mail_location
setting it can use my mbsync
folders without issue.
mail_location = maildir:~/Maildir/:LAYOUT=fs:INBOX=~/Maildir/fastmail/INBOX
protocols = imap
protocol imap {
listen = 127.0.0.1:143
}
auth_mechanisms = anonymous
That configuration file is stashed in my system-path with home-manager in a wrapper called dovecot-local-imap
:
{pkgs, config, ...}:
let
dovecotLocalConf = ../files/dovecot-noauth.conf;
dovecotLocalImap = pkgs.writeScriptBin "dovecot-local-imap" ''
#!${pkgs.stdenv.shell}
${pkgs.dovecot}/libexec/dovecot/imap -c ${dovecotLocalConf}
'';
in {
home.packages = [ dovecotLocalImap ];
home.activation = {
gnus-newsrc =
pkgs.lib.mkActivationLocalLink config"~/sync/private-files/.newsrc"
".newsrc";
gnus-newsrc_eld =
pkgs.lib.mkActivationLocalLink config"~/sync/private-files/.newsrc.eld"
".newsrc.eld";
# gnus-feeds =
# pkgs.lib.mkActivationLocalLink config
# "~/Maildir/endpoint/feeds"
# "Maildir/feeds";
# gnus-fastmail =
# pkgs.lib.mkActivationLocalLink config
# "~/Maildir/endpoint/fastmail"
# "Maildir/fastmail";
};
}
Finally, this ugly function and sharp-quoted setq
tries to find an IMAP which works. On my
non-Nix systems it could be in any number of places depending on distro
packages..
defun cce/find-dovecot ()
(cond ((executable-find "dovecot-local-imap") (executable-find "dovecot-local-imap"))
("/usr/lib/dovecot/imap") "/usr/lib/dovecot/imap")
((file-exists-p "/usr/libexec/dovecot/imap") "/usr/libexec/dovecot/imap")))
((file-exists-p
setq gnus-secondary-select-methods
("maildir"
`((nnimap
(nnimap-stream shell)cond ((equal "work" (system-name))
(nnimap-inbox ,("gmail/Inbox")
t "fastmail/INBOX")))
(
(nnir-search-engine imap)
(nnimap-shell-program ,(cce/find-dovecot)));; (nnttrss "tt"
;; (nnttrss-address "https://feeds.whatthefuck.computer/api")
;; (nnttrss-user "rrix")
;; (nnttrss-password "FP5WW2hcGoeTTz")
;; )
))
NEXT move mbsync here
NEXT move msmtp here
Put All Together With Noweb
All of the code presented above is inserted in to a use-package
block1.
use-package gnus
(nil
:ensure
:config
<<image-conf>>
<<no-group-in-article>>
<<shr-wrap>>
<<summary-appearance>>
<<gmane>> )
This is considered a "minimum viable" gnus configuration for my purposes, the sort of core-behavior of the Gnus system. There is more configuration for my configuration stack linked from Email and News and Information Pipelines, some of which is specific to Gnus: