Various mail-related updates and cleanups
[~bandali/configs] / .emacs.d / lisp / bandali-gnus.el
CommitLineData
4c05c418
AB
1;;; bandali-gnus.el --- bandali's Gnus setup -*- lexical-binding: t; -*-
2
78d731e1 3;; Copyright (C) 2018-2022 Amin Bandali
4c05c418
AB
4
5;; Author: Amin Bandali <bandali@gnu.org>
6;; Keywords: mail, news
7
8;; This program is free software; you can redistribute it and/or modify
9;; it under the terms of the GNU General Public License as published by
10;; the Free Software Foundation, either version 3 of the License, or
11;; (at your option) any later version.
12
13;; This program is distributed in the hope that it will be useful,
14;; but WITHOUT ANY WARRANTY; without even the implied warranty of
15;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16;; GNU General Public License for more details.
17
18;; You should have received a copy of the GNU General Public License
19;; along with this program. If not, see <https://www.gnu.org/licenses/>.
20
21;;; Commentary:
22
23;; My trusty super awesome Gnus setup.
24
25;;; Code:
26
2087ae39
AB
27(defvar b/maildir (expand-file-name "~/mail/"))
28(with-eval-after-load 'recentf
29 (add-to-list 'recentf-exclude b/maildir))
30
31(defvar b/gnus-init-file (b/etc "gnus"))
32
33(eval-when-compile
34 (progn
35 (defvar nndraft-directory)
36 (defvar gnus-read-newsrc-file)
37 (defvar gnus-save-newsrc-file)
38 (defvar gnus-gcc-mark-as-read)
39 (defvar nnmail-split-abbrev-alist)))
40
41(declare-function article-make-date-line "gnus-art" (date type))
42
78d731e1 43(setq
c84be134
AB
44 mail-user-agent 'gnus-user-agent
45 read-mail-command 'gnus
46
47 gnus-select-method '(nnnil "")
48 gnus-secondary-select-methods
f1b31451
AB
49 `(,@(if (string= (system-name) "darya")
50 '((nnimap
51 "canonical"
52 (nnimap-stream plain)
53 (nnimap-address "127.0.0.1")
54 (nnimap-server-port 143)
55 (nnimap-authenticator plain)
56 (nnimap-user "bandali@canonical.local")))
8ab693f8 57 '((nnimap
3d36fc1a
AB
58 "kelar"
59 (nnimap-stream plain)
60 (nnimap-address "127.0.0.1")
61 (nnimap-server-port 143)
62 (nnimap-authenticator plain)
63 (nnimap-user "bandali@kelar.local"))
64 (nnimap
8ab693f8
AB
65 "shemshak"
66 (nnimap-stream plain)
67 (nnimap-address "127.0.0.1")
68 (nnimap-server-port 143)
69 (nnimap-authenticator plain)
70 (nnimap-user "bandali@shemshak.local"))
71 (nnimap
72 "gnu"
73 (nnimap-stream plain)
74 (nnimap-address "127.0.0.1")
75 (nnimap-server-port 143)
76 (nnimap-authenticator plain)
77 (nnimap-user "bandali@gnu.local")
78 (nnimap-inbox "INBOX")
79 (nnimap-split-methods 'nnimap-split-fancy)
80 (nnimap-split-fancy
81 (|
82 ;; (: gnus-registry-split-fancy-with-parent)
83 ;; (: gnus-group-split-fancy "INBOX" t "INBOX")
ae80aec8
AB
84 ;; spam
85 ("X-Spam_action" "reject" "Junk")
8ab693f8
AB
86 ;; keep debbugs emails in INBOX
87 (list ".*<\\(.*\\)\\.debbugs\\.gnu\\.org>.*" "INBOX")
88 ;; list moderation emails
89 (from ".+-\\(owner\\|bounces\\)@\\(non\\)?gnu\\.org" "listmod")
90 ;; gnu
91 (list ".*<\\(.*\\)\\.\\(non\\)?gnu\\.org>.*" "l.\\1")
3d36fc1a
AB
92 ;; fsf
93 (list ".*<\\(.*\\)\\.fsf\\.org>.*" "l.\\1")
8ab693f8
AB
94 ;; gnus
95 (list ".*<\\(.*\\)\\.gnus\\.org>.*" "l.\\1")
96 ;; libreplanet
97 (list ".*<\\(.*\\)\\.libreplanet\\.org>.*" "l.\\1")
98 ;; iana (e.g. tz-announce)
99 (list ".*<\\(.*\\)\\.iana\\.org>.*" "l.\\1")
3d36fc1a
AB
100 ;; mailop
101 (list ".*<\\(.*\\)\\.mailop\\.org>.*" "l.\\1")
102 ;; sdlu
103 (list ".*<\\(.*\\)\\.spammers\\.dontlike\\.us>.*" "l.sdlu")
104 ;; bitfolk
105 (from ".*@\\(.+\\)?bitfolk\\.com>.*" "bitfolk")
8ab693f8
AB
106 ;; haskell
107 (list ".*<\\(.*\\)\\.haskell\\.org>.*" "l.\\1")
108 ;; *.lists.sr.ht, omitting one dot if present
109 ;; add more \\.?\\([^.]*\\) if needed
110 (list ".*<~\\(.*\\)/\\([^.]*\\)\\.?\\([^.]*\\)\\.lists\\.sr\\.ht>.*" "l.~\\1.\\2\\3")
111 ;; webmasters
112 (from "webmasters\\(-comment\\)?@gnu\\.org" "webmasters")
113 ;; other
114 ("subject" "nagios-fsf:.*" "nagios-fsf")
115 (list ".*atreus.freelists.org" "l.atreus")
116 (list ".*deepspec.lists.cs.princeton.edu" "l.deepspec")
117 ;; (list ".*haskell-art.we.lurk.org" "l.haskell.art") ;d
118 ;; (list ".*notmuch.notmuchmail.org" "l.notmuch") ;u
119 (list ".*dev.lists.parabola.nu" "l.parabola-dev")
120 ;; ----------------------------------
121 ;; legend: (u)nsubscribed | (d)ead
122 ;; ----------------------------------
8ab693f8
AB
123 ;; otherwise, leave mail in INBOX
124 "INBOX")))
125 (nnimap
126 "uwaterloo"
127 (nnimap-stream plain)
128 (nnimap-address "127.0.0.1")
129 (nnimap-server-port 143)
130 (nnimap-authenticator plain)
131 (nnimap-user "abandali@uwaterloo.local")
132 (nnimap-inbox "INBOX")
133 (nnimap-split-methods 'nnimap-split-fancy)
134 (nnimap-split-fancy
135 (|
136 ;; (: gnus-registry-split-fancy-with-parent)
137 ;; se212-f19
138 ("subject" "SE\\s-?212" "course.se212-f19")
139 (from "SE\\s-?212" "course.se212-f19")
140 ;; catch-all
141 "INBOX")))
142 (nnimap
143 "csc"
144 (nnimap-stream plain)
145 (nnimap-address "127.0.0.1")
146 (nnimap-server-port 143)
147 (nnimap-authenticator plain)
148 (nnimap-user "abandali@csclub.uwaterloo.local")
149 (nnimap-inbox "INBOX")
150 (nnimap-split-methods 'nnimap-split-fancy)
151 (nnimap-split-fancy
152 (|
153 ;; cron reports and other messages from root
154 (from "root@\\(.*\\.\\)?csclub\\.uwaterloo\\.ca" "INBOX")
155 ;; spam
156 ("X-Spam-Flag" "YES" "Junk")
157 ;; catch-all
f1b31451
AB
158 "INBOX")))
159 ;; (nnimap
160 ;; "sfl"
161 ;; (nnimap-stream tls)
162 ;; (nnimap-address "mail.savoirfairelinux.com")
163 ;; (nnimap-user "amin.bandali"))
164 )))
c84be134
AB
165 gnus-message-archive-group "nnimap+gnu:INBOX"
166 gnus-parameters
9867e4bb 167 '(("l\\.deepspec"
c84be134
AB
168 (to-address . "deepspec@lists.cs.princeton.edu")
169 (to-list . "deepspec@lists.cs.princeton.edu")
170 (list-identifier . "\\[deepspec\\]"))
c84be134
AB
171 ("l\\.fencepost-users"
172 (to-address . "fencepost-users@gnu.org")
173 (to-list . "fencepost-users@gnu.org")
174 (list-identifier . "\\[Fencepost-users\\]"))
c84be134
AB
175 ("l\\.haskell-cafe"
176 (to-address . "haskell-cafe@haskell.org")
177 (to-list . "haskell-cafe@haskell.org")
178 (list-identifier . "\\[Haskell-cafe\\]"))
c84be134 179 ("gnu.*"
c84be134
AB
180 (gcc-self . t)))
181 ;; nnimap-record-commands t
41fb7da0 182 ;; gnus-large-newsgroup 50
52b7a57a 183 ;; gnus-process-mark-toggle t
c84be134
AB
184 gnus-home-directory (b/var "gnus/")
185 gnus-directory (concat gnus-home-directory "news/")
186 message-directory (concat gnus-home-directory "mail/")
187 nndraft-directory (concat gnus-home-directory "drafts/")
188 gnus-save-newsrc-file nil
189 gnus-read-newsrc-file nil
adba94a7 190 gnus-search-use-parsed-queries t
c84be134
AB
191 gnus-interactive-exit nil
192 gnus-gcc-mark-as-read t)
193
194(with-eval-after-load 'gnus
2087ae39
AB
195 (when (version< emacs-version "27")
196 (with-eval-after-load 'nnmail
197 (add-to-list
198 'nnmail-split-abbrev-alist
199 '(list . "list-id\\|list-post\\|x-mailing-list\\|x-beenthere\\|x-loop")
200 t)))
201
6b09fc8a
AB
202 ;; (require 'gnus-registry)
203 ;; (setq gnus-registry-max-entries 2500)
204 ;; (setq gnus-registry-ignored-groups
205 ;; (append gnus-registry-ignored-groups
206 ;; '(("^nnimap:gnu\\.l" t)
207 ;; ("webmasters$" t))))
2087ae39
AB
208 ;; (gnus-registry-initialize)
209
210 (with-eval-after-load 'recentf
c84be134
AB
211 (add-to-list 'recentf-exclude gnus-home-directory))
212
213 ;; hooks
214 (add-hook 'gnus-group-mode-hook #'gnus-topic-mode)
215 (add-hook 'gnus-group-mode-hook #'gnus-agent-mode))
216;; global key bindings
55ac7968
AB
217(global-set-key (kbd "C-c g") #'gnus-plugged)
218(global-set-key (kbd "C-c G") #'gnus-unplugged)
2087ae39 219
c84be134 220(with-eval-after-load 'gnus-art
78d731e1 221 (setq
2087ae39
AB
222 gnus-buttonized-mime-types '("multipart/\\(signed\\|encrypted\\)")
223 gnus-sorted-header-list '("^From:"
224 "^X-RT-Originator"
225 "^Newsgroups:"
226 "^Subject:"
227 "^Date:"
228 "^Envelope-To:"
229 "^Followup-To:"
230 "^Reply-To:"
231 "^Organization:"
232 "^Summary:"
233 "^Abstract:"
234 "^Keywords:"
235 "^To:"
236 "^[BGF]?Cc:"
237 "^Posted-To:"
238 "^Mail-Copies-To:"
239 "^Mail-Followup-To:"
240 "^Apparently-To:"
241 "^Resent-From:"
242 "^User-Agent:"
243 "^X-detected-operating-system:"
6b09fc8a
AB
244 "^X-Spam_action:"
245 "^X-Spam_bar:"
2087ae39
AB
246 "^Message-ID:"
247 ;; "^References:"
248 "^List-Id:"
249 "^Gnus-Warning:")
f1b31451 250 gnus-visible-headers (mapconcat #'identity
2087ae39
AB
251 gnus-sorted-header-list
252 "\\|")
253 ;; local-lapsed article dates
254 ;; from https://www.emacswiki.org/emacs/GnusFormatting#toc11
255 gnus-article-date-headers '(user-defined)
256 gnus-article-time-format
257 (lambda (time)
258 (let* ((date (format-time-string "%a, %d %b %Y %T %z" time))
259 (local (article-make-date-line date 'local))
260 (combined-lapsed (article-make-date-line date
261 'combined-lapsed))
262 (lapsed (progn
263 (string-match " (.+" combined-lapsed)
264 (match-string 0 combined-lapsed))))
265 (concat local lapsed))))
c84be134 266 ;; local key bindings
41fb7da0 267 (declare-function org-store-link "ol" (arg &optional interactive?))
c84be134
AB
268 (define-key gnus-article-mode-map (kbd "M-L") #'org-store-link))
269
270(with-eval-after-load 'gnus-sum
78d731e1
AB
271 (setq gnus-thread-sort-functions '(gnus-thread-sort-by-number
272 gnus-thread-sort-by-subject
273 gnus-thread-sort-by-date))
c84be134
AB
274 ;; local key bindings
275 (define-key gnus-summary-mode-map (kbd "M-L") #'org-store-link)
5efecfcd
AB
276 ;; (define-key gnus-summary-mode-map (kbd "r")
277 ;; #'gnus-summary-reply-with-original)
278 ;; (define-key gnus-summary-mode-map (kbd "R")
279 ;; #'gnus-summary-wide-reply-with-original)
c84be134
AB
280 (defvar b/gnus-summary-prefix-map)
281 (define-prefix-command 'b/gnus-summary-prefix-map)
282 (define-key gnus-summary-mode-map (kbd "v")
283 'b/gnus-summary-prefix-map)
284 (define-key b/gnus-summary-prefix-map (kbd "r")
285 #'gnus-summary-reply)
286 (define-key b/gnus-summary-prefix-map (kbd "w")
287 #'gnus-summary-wide-reply)
288 (define-key b/gnus-summary-prefix-map (kbd "v")
289 #'gnus-summary-show-raw-article))
290;; hooks
291(add-hook 'gnus-summary-mode-hook #'b/no-mouse-autoselect-window)
292
293(defvar b/sfl-p nil)
294(with-eval-after-load 'gnus-msg
f1b31451
AB
295 (let ((bandali "Amin Bandali (https://kelar.org/~bandali)"))
296 (defvar b/canonical-signature
297 (mapconcat
298 #'identity
299 `(,bandali
300 "Software Engineer (Desktop), Canonical")
301 "\n"))
302 (defvar b/csc-signature
303 (mapconcat
304 #'identity
305 `(,bandali
306 "Systems Committee <syscom@csclub.uwaterloo.ca>"
307 "Computer Science Club of the University of Waterloo")
308 "\n"))
309 (defvar b/sfl-signature
310 (mapconcat
311 #'identity
312 `(,bandali
313 "Volunteer, Savoir-faire Linux"
314 "jami:bandali")
315 "\n")))
78d731e1 316 (setq
c84be134
AB
317 gnus-message-replysign t
318 gnus-posting-styles
319 '((".*"
a220fb5b
AB
320 (address "bandali@gnu.org")
321 ("X-Message-SMTP-Method" "smtp fencepost.gnu.org 587"))
c84be134
AB
322 ((header "subject" "ThankCRM")
323 (to "webmasters-comment@gnu.org")
f1b31451 324 (body ""))
3d36fc1a
AB
325 ("nnimap\\+kelar:.*"
326 (address "bandali@kelar.org")
327 ("X-Message-SMTP-Method" "smtp mail.kelar.org 587")
f1b31451 328 (gcc "nnimap+kelar:Sent"))
c84be134
AB
329 ("nnimap\\+shemshak:.*"
330 (address "amin@shemshak.org")
a220fb5b 331 ("X-Message-SMTP-Method" "smtp mail.shemshak.org 587")
f1b31451
AB
332 (gcc "nnimap+shemshak:Sent"))
333 ("nnimap\\+canonical:.*"
334 (address "amin.bandali@canonical.com")
335 ("X-Message-SMTP-Method" "smtp smtp.canonical.com 587")
336 (signature b/canonical-signature)
337 (gcc "nnimap+canonical:Sent"))
c84be134
AB
338 ("nnimap\\+csc:.*"
339 (address "bandali@csclub.uwaterloo.ca")
a220fb5b 340 ("X-Message-SMTP-Method" "smtp mail.csclub.uwaterloo.ca 587")
c84be134
AB
341 (signature b/csc-signature)
342 (gcc "nnimap+csc:Sent"))
343 ("nnimap\\+sfl:.*"
344 (address "amin.bandali@savoirfairelinux.com")
a220fb5b 345 ("X-Message-SMTP-Method" "smtp mail.savoirfairelinux.com 587")
f1b31451
AB
346 (signature b/sfl-signature)
347 (eval (setq-local b/sfl-p t))
348 (gcc "nnimap+sfl:Sent")))))
c84be134 349;; hooks
9867e4bb
AB
350;; (with-eval-after-load 'gnus
351;; (add-hook 'gnus-message-setup-hook
352;; (lambda ()
353;; (unless (or (mml-secure-is-encrypted-p)
354;; b/sfl-p)
355;; (mml-secure-message-sign)))))
c84be134
AB
356
357(with-eval-after-load 'gnus-topic
78d731e1 358 (setq
41fb7da0 359 gnus-topic-line-format "%i[ %A: %(%{%n%}%) ]%v\n"
8ab693f8
AB
360 gnus-topic-topology
361 `(("Gnus" visible nil nil)
362 (("misc" visible nil nil))
f1b31451
AB
363 ,@(if (string= (system-name) "darya")
364 '((("canonical" visible nil nil)))
8ab693f8
AB
365 '((("csc" visible nil nil))
366 (("uwaterloo" visible nil nil))
3d36fc1a 367 (("kelar" visible nil nil))
8ab693f8
AB
368 (("shemshak" visible nil nil))
369 (("gnu" visible nil nil))
f1b31451
AB
370 (("old-gnu" visible nil nil))
371 (("sfl" visible nil nil)))))))
c84be134
AB
372
373(with-eval-after-load 'gnus-agent
78d731e1 374 (setq gnus-agent-synchronize-flags 'ask))
c84be134
AB
375
376(with-eval-after-load 'gnus-group
78d731e1 377 (setq gnus-permanently-visible-groups "\\(:INBOX$\\|:gnu$\\)"))
2087ae39 378
bc04a4d4 379(with-eval-after-load 'gnus-win
78d731e1 380 (setq gnus-use-full-window nil))
2087ae39 381
c84be134 382(with-eval-after-load 'gnus-dired
2087ae39
AB
383 (add-hook 'dired-mode-hook 'gnus-dired-mode))
384
c84be134 385(with-eval-after-load 'mm-decode
78d731e1
AB
386 (setq
387 ;; mm-attachment-override-types `("text/x-diff" "text/x-patch"
388 ;; ,@mm-attachment-override-types)
389 mm-discouraged-alternatives '("text/html" "text/richtext")
390 mm-decrypt-option 'known
391 mm-verify-option 'known))
c84be134
AB
392
393(with-eval-after-load 'mm-uu
2087ae39
AB
394 (when (version< "27" emacs-version)
395 (set-face-attribute 'mm-uu-extract nil :extend t))
7c558c9b 396 (when (version< emacs-version "27")
78d731e1 397 (setq mm-uu-diff-groups-regexp ".")))
c84be134
AB
398
399(with-eval-after-load 'mml-sec
78d731e1
AB
400 (setq mml-secure-openpgp-encrypt-to-self t
401 mml-secure-openpgp-sign-with-sender t))
c84be134 402
2087ae39 403(provide 'bandali-gnus)
4c05c418 404;;; bandali-gnus.el ends here