f4e44e63697b016decc7226c440af9d2a427c207
[~bandali/configs] / .emacs.d / lisp / bandali-gnus.el
1 ;;; bandali-gnus.el --- bandali's Gnus setup -*- lexical-binding: t; -*-
2
3 ;; Copyright (C) 2018-2022 Amin Bandali
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
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
43 (setq
44 mail-user-agent 'gnus-user-agent
45 read-mail-command 'gnus
46
47 gnus-select-method '(nnnil "")
48 gnus-secondary-select-methods
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")))
57 '((nnimap
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
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")
84 ;; spam
85 ("X-Spam_action" "reject" "Junk")
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")
92 ;; fsf
93 (list ".*<\\(.*\\)\\.fsf\\.org>.*" "l.\\1")
94 ;; debian
95 (list ".*<\\(.*\\)\\.alioth-lists\\.debian\\.net>.*" "l.\\1")
96 ;; gnus
97 (list ".*<\\(.*\\)\\.gnus\\.org>.*" "l.\\1")
98 ;; libreplanet
99 (list ".*<\\(.*\\)\\.libreplanet\\.org>.*" "l.\\1")
100 ;; iana (e.g. tz-announce)
101 (list ".*<\\(.*\\)\\.iana\\.org>.*" "l.\\1")
102 ;; mailop
103 (list ".*<\\(.*\\)\\.mailop\\.org>.*" "l.\\1")
104 ;; sdlu
105 (list ".*<\\(.*\\)\\.spammers\\.dontlike\\.us>.*" "l.sdlu")
106 ;; bitfolk
107 (from ".*@\\(.+\\)?bitfolk\\.com>.*" "bitfolk")
108 ;; haskell
109 (list ".*<\\(.*\\)\\.haskell\\.org>.*" "l.\\1")
110 ;; *.lists.sr.ht, omitting one dot if present
111 ;; add more \\.?\\([^.]*\\) if needed
112 (list ".*<~\\(.*\\)/\\([^.]*\\)\\.?\\([^.]*\\)\\.lists\\.sr\\.ht>.*" "l.~\\1.\\2\\3")
113 ;; webmasters
114 (from "webmasters\\(-comment\\)?@gnu\\.org" "webmasters")
115 ;; other
116 ("subject" "nagios-fsf:.*" "nagios-fsf")
117 (list ".*atreus.freelists.org" "l.atreus")
118 (list ".*deepspec.lists.cs.princeton.edu" "l.deepspec")
119 ;; (list ".*haskell-art.we.lurk.org" "l.haskell.art") ;d
120 ;; (list ".*notmuch.notmuchmail.org" "l.notmuch") ;u
121 (list ".*dev.lists.parabola.nu" "l.parabola-dev")
122 ;; ----------------------------------
123 ;; legend: (u)nsubscribed | (d)ead
124 ;; ----------------------------------
125 ;; otherwise, leave mail in INBOX
126 "INBOX")))
127 (nnimap
128 "uwaterloo"
129 (nnimap-stream plain)
130 (nnimap-address "127.0.0.1")
131 (nnimap-server-port 143)
132 (nnimap-authenticator plain)
133 (nnimap-user "abandali@uwaterloo.local")
134 (nnimap-inbox "INBOX")
135 (nnimap-split-methods 'nnimap-split-fancy)
136 (nnimap-split-fancy
137 (|
138 ;; (: gnus-registry-split-fancy-with-parent)
139 ;; se212-f19
140 ("subject" "SE\\s-?212" "course.se212-f19")
141 (from "SE\\s-?212" "course.se212-f19")
142 ;; catch-all
143 "INBOX")))
144 (nnimap
145 "csc"
146 (nnimap-stream plain)
147 (nnimap-address "127.0.0.1")
148 (nnimap-server-port 143)
149 (nnimap-authenticator plain)
150 (nnimap-user "abandali@csclub.uwaterloo.local")
151 (nnimap-inbox "INBOX")
152 (nnimap-split-methods 'nnimap-split-fancy)
153 (nnimap-split-fancy
154 (|
155 ;; cron reports and other messages from root
156 (from "root@\\(.*\\.\\)?csclub\\.uwaterloo\\.ca" "INBOX")
157 ;; spam
158 ("X-Spam-Flag" "YES" "Junk")
159 ;; catch-all
160 "INBOX")))
161 (nnimap
162 "sfl"
163 (nnimap-stream plain)
164 (nnimap-address "127.0.0.1")
165 (nnimap-server-port 143)
166 (nnimap-authenticator plain)
167 (nnimap-user "amin.bandali@savoirfairelinux.local")))))
168 gnus-message-archive-group "nnimap+gnu:INBOX"
169 gnus-parameters
170 '(("l\\.deepspec"
171 (to-address . "deepspec@lists.cs.princeton.edu")
172 (to-list . "deepspec@lists.cs.princeton.edu")
173 (list-identifier . "\\[deepspec\\]"))
174 ("l\\.fencepost-users"
175 (to-address . "fencepost-users@gnu.org")
176 (to-list . "fencepost-users@gnu.org")
177 (list-identifier . "\\[Fencepost-users\\]"))
178 ("l\\.haskell-cafe"
179 (to-address . "haskell-cafe@haskell.org")
180 (to-list . "haskell-cafe@haskell.org")
181 (list-identifier . "\\[Haskell-cafe\\]"))
182 ("gnu.*"
183 (gcc-self . t)))
184 ;; nnimap-record-commands t
185 ;; gnus-large-newsgroup 50
186 ;; gnus-process-mark-toggle t
187 gnus-home-directory (b/var "gnus/")
188 gnus-directory (concat gnus-home-directory "news/")
189 message-directory (concat gnus-home-directory "mail/")
190 nndraft-directory (concat gnus-home-directory "drafts/")
191 gnus-save-newsrc-file nil
192 gnus-read-newsrc-file nil
193 gnus-search-use-parsed-queries t
194 gnus-interactive-exit nil
195 gnus-gcc-mark-as-read t)
196
197 (with-eval-after-load 'gnus
198 (when (version< emacs-version "27")
199 (with-eval-after-load 'nnmail
200 (add-to-list
201 'nnmail-split-abbrev-alist
202 '(list . "list-id\\|list-post\\|x-mailing-list\\|x-beenthere\\|x-loop")
203 t)))
204
205 ;; (require 'gnus-registry)
206 ;; (setq gnus-registry-max-entries 2500)
207 ;; (setq gnus-registry-ignored-groups
208 ;; (append gnus-registry-ignored-groups
209 ;; '(("^nnimap:gnu\\.l" t)
210 ;; ("webmasters$" t))))
211 ;; (gnus-registry-initialize)
212
213 (with-eval-after-load 'recentf
214 (add-to-list 'recentf-exclude gnus-home-directory))
215
216 ;; hooks
217 (add-hook 'gnus-group-mode-hook #'gnus-topic-mode)
218 (add-hook 'gnus-group-mode-hook #'gnus-agent-mode))
219 ;; global key bindings
220 (global-set-key (kbd "C-c g") #'gnus-plugged)
221 (global-set-key (kbd "C-c G") #'gnus-unplugged)
222
223 (with-eval-after-load 'gnus-art
224 (setq
225 gnus-buttonized-mime-types '("multipart/\\(signed\\|encrypted\\)")
226 gnus-sorted-header-list '("^From:"
227 "^X-RT-Originator"
228 "^Newsgroups:"
229 "^Subject:"
230 "^Date:"
231 "^Envelope-To:"
232 "^Followup-To:"
233 "^Reply-To:"
234 "^Organization:"
235 "^Summary:"
236 "^Abstract:"
237 "^Keywords:"
238 "^To:"
239 "^[BGF]?Cc:"
240 "^Posted-To:"
241 "^Mail-Copies-To:"
242 "^Mail-Followup-To:"
243 "^Apparently-To:"
244 "^Resent-From:"
245 "^User-Agent:"
246 "^X-detected-operating-system:"
247 "^X-Spam_action:"
248 "^X-Spam_bar:"
249 "^Message-ID:"
250 ;; "^References:"
251 "^List-Id:"
252 "^Gnus-Warning:")
253 gnus-visible-headers (mapconcat #'identity
254 gnus-sorted-header-list
255 "\\|")
256 ;; local-lapsed article dates
257 ;; from https://www.emacswiki.org/emacs/GnusFormatting#toc11
258 gnus-article-date-headers '(user-defined)
259 gnus-article-time-format
260 (lambda (time)
261 (let* ((date (format-time-string "%a, %d %b %Y %T %z" time))
262 (local (article-make-date-line date 'local))
263 (combined-lapsed (article-make-date-line date
264 'combined-lapsed))
265 (lapsed (progn
266 (string-match " (.+" combined-lapsed)
267 (match-string 0 combined-lapsed))))
268 (concat local lapsed))))
269 ;; local key bindings
270 (declare-function org-store-link "ol" (arg &optional interactive?))
271 (define-key gnus-article-mode-map (kbd "M-L") #'org-store-link))
272
273 (with-eval-after-load 'gnus-sum
274 (setq gnus-thread-sort-functions '(gnus-thread-sort-by-number
275 gnus-thread-sort-by-subject
276 gnus-thread-sort-by-date))
277 ;; local key bindings
278 (define-key gnus-summary-mode-map (kbd "M-L") #'org-store-link)
279 ;; (define-key gnus-summary-mode-map (kbd "r")
280 ;; #'gnus-summary-reply-with-original)
281 ;; (define-key gnus-summary-mode-map (kbd "R")
282 ;; #'gnus-summary-wide-reply-with-original)
283 (defvar b/gnus-summary-prefix-map)
284 (define-prefix-command 'b/gnus-summary-prefix-map)
285 (define-key gnus-summary-mode-map (kbd "v")
286 'b/gnus-summary-prefix-map)
287 (define-key b/gnus-summary-prefix-map (kbd "r")
288 #'gnus-summary-reply)
289 (define-key b/gnus-summary-prefix-map (kbd "w")
290 #'gnus-summary-wide-reply)
291 (define-key b/gnus-summary-prefix-map (kbd "v")
292 #'gnus-summary-show-raw-article))
293 ;; hooks
294 (add-hook 'gnus-summary-mode-hook #'b/no-mouse-autoselect-window)
295
296 (defvar b/sfl-p nil)
297 (with-eval-after-load 'gnus-msg
298 (let ((bandali "Amin Bandali (https://kelar.org/~bandali)"))
299 (defvar b/csc-signature
300 (mapconcat
301 #'identity
302 `(,bandali
303 "Systems Committee <syscom@csclub.uwaterloo.ca>"
304 "Computer Science Club of the University of Waterloo")
305 "\n"))
306 (defvar b/sfl-signature
307 (mapconcat
308 #'identity
309 `(,bandali
310 "Volunteer, Savoir-faire Linux"
311 "jami:bandali")
312 "\n")))
313 (setq
314 gnus-message-replysign t
315 gnus-posting-styles
316 '((".*"
317 (address "bandali@gnu.org")
318 ("X-Message-SMTP-Method" "smtp fencepost.gnu.org 587"))
319 ((header "subject" "ThankCRM")
320 (to "webmasters-comment@gnu.org")
321 (body ""))
322 ("nnimap\\+kelar:.*"
323 (address "bandali@kelar.org")
324 ("X-Message-SMTP-Method" "smtp mail.kelar.org 587")
325 (gcc "nnimap+kelar:Sent"))
326 ("nnimap\\+shemshak:.*"
327 (address "amin@shemshak.org")
328 ("X-Message-SMTP-Method" "smtp mail.shemshak.org 587")
329 (gcc "nnimap+shemshak:Sent"))
330 ("nnimap\\+canonical:.*"
331 (address "amin.bandali@canonical.com")
332 ("X-Message-SMTP-Method" "smtp smtp.canonical.com 587")
333 (signature nil)
334 (gcc "nnimap+canonical:Sent"))
335 ("nnimap\\+csc:.*"
336 (address "bandali@csclub.uwaterloo.ca")
337 ("X-Message-SMTP-Method" "smtp mail.csclub.uwaterloo.ca 587")
338 (signature b/csc-signature)
339 (gcc "nnimap+csc:Sent"))
340 ("nnimap\\+sfl:.*"
341 (address "amin.bandali@savoirfairelinux.com")
342 ("X-Message-SMTP-Method" "smtp mail.savoirfairelinux.com 587")
343 (signature b/sfl-signature)
344 (eval (setq-local b/sfl-p t))
345 (gcc "nnimap+sfl:Sent")))))
346 ;; hooks
347 ;; (with-eval-after-load 'gnus
348 ;; (add-hook 'gnus-message-setup-hook
349 ;; (lambda ()
350 ;; (unless (or (mml-secure-is-encrypted-p)
351 ;; b/sfl-p)
352 ;; (mml-secure-message-sign)))))
353
354 (with-eval-after-load 'gnus-topic
355 (setq
356 gnus-topic-line-format "%i[ %A: %(%{%n%}%) ]%v\n"
357 gnus-topic-topology
358 `(("Gnus" visible nil nil)
359 (("misc" visible nil nil))
360 ,@(if (string= (system-name) "darya")
361 '((("canonical" visible nil nil)))
362 '((("csc" visible nil nil))
363 (("uwaterloo" visible nil nil))
364 (("kelar" visible nil nil))
365 (("shemshak" visible nil nil))
366 (("gnu" visible nil nil))
367 (("old-gnu" visible nil nil))
368 (("sfl" visible nil nil)))))))
369
370 (with-eval-after-load 'gnus-agent
371 (setq gnus-agent-synchronize-flags 'ask))
372
373 (with-eval-after-load 'gnus-group
374 (setq gnus-permanently-visible-groups "\\(:INBOX$\\|:gnu$\\)"))
375
376 (with-eval-after-load 'gnus-win
377 (setq gnus-use-full-window nil))
378
379 (with-eval-after-load 'gnus-dired
380 (add-hook 'dired-mode-hook 'gnus-dired-mode))
381
382 (with-eval-after-load 'mm-decode
383 (setq
384 ;; mm-attachment-override-types `("text/x-diff" "text/x-patch"
385 ;; ,@mm-attachment-override-types)
386 mm-discouraged-alternatives '("text/html" "text/richtext")
387 mm-decrypt-option 'known
388 mm-verify-option 'known))
389
390 (with-eval-after-load 'mm-uu
391 (when (version< "27" emacs-version)
392 (set-face-attribute 'mm-uu-extract nil :extend t))
393 (when (version< emacs-version "27")
394 (setq mm-uu-diff-groups-regexp ".")))
395
396 (with-eval-after-load 'mml-sec
397 (setq mml-secure-openpgp-encrypt-to-self t
398 mml-secure-openpgp-sign-with-sender t))
399
400 (provide 'bandali-gnus)
401 ;;; bandali-gnus.el ends here