39c9af82839950210b064bbf9af924af4530c5b6
[~bandali/configs] / lisp / bandali-gnus.el
1 ;;; bandali-gnus.el --- bandali's Gnus setup -*- lexical-binding: t; -*-
2
3 ;; Copyright (C) 2018-2020 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 (csetq
44 mail-user-agent 'gnus-user-agent
45 read-mail-command 'gnus
46
47 gnus-select-method '(nnnil "")
48 gnus-secondary-select-methods
49 '((nnimap "shemshak"
50 (nnimap-stream plain)
51 (nnimap-address "127.0.0.1")
52 (nnimap-server-port 143)
53 (nnimap-authenticator plain)
54 (nnimap-user "bandali@shemshak.local"))
55 (nnimap "gnu"
56 (nnimap-stream plain)
57 (nnimap-address "127.0.0.1")
58 (nnimap-server-port 143)
59 (nnimap-authenticator plain)
60 (nnimap-user "bandali@gnu.local")
61 (nnimap-inbox "INBOX")
62 (nnimap-split-methods 'nnimap-split-fancy)
63 (nnimap-split-fancy (|
64 ;; (: gnus-registry-split-fancy-with-parent)
65 ;; (: gnus-group-split-fancy "INBOX" t "INBOX")
66 ;; keep debbugs emails in INBOX
67 (list ".*<\\(.*\\)\\.debbugs\\.gnu\\.org>.*" "INBOX")
68 ;; gnu
69 (list ".*<\\(.*\\)\\.\\(non\\)?gnu\\.org>.*" "l.\\1")
70 ;; gnus
71 (list ".*<\\(.*\\)\\.gnus\\.org>.*" "l.\\1")
72 ;; libreplanet
73 (list ".*<\\(.*\\)\\.libreplanet\\.org>.*" "l.\\1")
74 ;; iana (e.g. tz-announce)
75 (list ".*<\\(.*\\)\\.iana\\.org>.*" "l.\\1")
76 ;; orbitalfox (e.g. gemini)
77 (list ".*<\\(.*\\)\\.lists\\.orbitalfox\\.eu>.*" "l.\\1")
78 ;; *.lists.sr.ht, omitting one dot if present
79 ;; add more \\.?\\([^.]*\\) if needed
80 (list ".*<~\\(.*\\)/\\([^.]*\\)\\.?\\([^.]*\\)\\.lists\\.sr\\.ht>.*" "l.~\\1.\\2\\3")
81 ;; webmasters
82 (from "webmasters\\(-comment\\)?@gnu\\.org" "webmasters")
83 ;; other
84 (list ".*atreus.freelists.org" "l.atreus")
85 (list ".*deepspec.lists.cs.princeton.edu" "l.deepspec")
86 ;; (list ".*haskell-art.we.lurk.org" "l.haskell.art") ;d
87 (list ".*haskell-cafe.haskell.org" "l.haskell-cafe")
88 ;; (list ".*notmuch.notmuchmail.org" "l.notmuch") ;u
89 (list ".*dev.lists.parabola.nu" "l.parabola-dev")
90 ;; ----------------------------------
91 ;; legend: (u)nsubscribed | (d)ead
92 ;; ----------------------------------
93 ;; spam
94 ("X-Spam_action" "reject" "Junk")
95 ;; otherwise, leave mail in INBOX
96 "INBOX")))
97 (nnimap "uwaterloo"
98 (nnimap-stream plain)
99 (nnimap-address "127.0.0.1")
100 (nnimap-server-port 143)
101 (nnimap-authenticator plain)
102 (nnimap-user "abandali@uwaterloo.local")
103 (nnimap-inbox "INBOX")
104 (nnimap-split-methods 'nnimap-split-fancy)
105 (nnimap-split-fancy (|
106 ;; (: gnus-registry-split-fancy-with-parent)
107 ;; se212-f19
108 ("subject" "SE\\s-?212" "course.se212-f19")
109 (from "SE\\s-?212" "course.se212-f19")
110 ;; catch-all
111 "INBOX")))
112 (nnimap "csc"
113 (nnimap-stream plain)
114 (nnimap-address "127.0.0.1")
115 (nnimap-server-port 143)
116 (nnimap-authenticator plain)
117 (nnimap-user "abandali@csclub.uwaterloo.local")
118 (nnimap-inbox "INBOX")
119 (nnimap-split-methods 'nnimap-split-fancy)
120 (nnimap-split-fancy (|
121 ;; cron reports and other messages from root
122 (from "root@\\(.*\\.\\)?csclub\\.uwaterloo\\.ca" "INBOX")
123 ;; spam
124 ("X-Spam-Flag" "YES" "Junk")
125 ;; catch-all
126 "INBOX")))
127 (nnimap "sfl"
128 (nnimap-stream tls)
129 (nnimap-address "mail.savoirfairelinux.com")
130 (nnimap-user "amin.bandali")))
131 gnus-message-archive-group "nnimap+gnu:INBOX"
132 gnus-parameters
133 '(("l\\.atreus"
134 (to-address . "atreus@freelists.org")
135 (to-list . "atreus@freelists.org"))
136 ("l\\.deepspec"
137 (to-address . "deepspec@lists.cs.princeton.edu")
138 (to-list . "deepspec@lists.cs.princeton.edu")
139 (list-identifier . "\\[deepspec\\]"))
140 ("l\\.emacs-devel"
141 (to-address . "emacs-devel@gnu.org")
142 (to-list . "emacs-devel@gnu.org"))
143 ("l\\.help-gnu-emacs"
144 (to-address . "help-gnu-emacs@gnu.org")
145 (to-list . "help-gnu-emacs@gnu.org"))
146 ("l\\.info-gnu-emacs"
147 (to-address . "info-gnu-emacs@gnu.org")
148 (to-list . "info-gnu-emacs@gnu.org"))
149 ("l\\.emacs-orgmode"
150 (to-address . "emacs-orgmode@gnu.org")
151 (to-list . "emacs-orgmode@gnu.org")
152 (list-identifier . "\\[O\\]"))
153 ("l\\.emacs-tangents"
154 (to-address . "emacs-tangents@gnu.org")
155 (to-list . "emacs-tangents@gnu.org"))
156 ("l\\.emacsconf-committee"
157 (to-address . "emacsconf-committee@gnu.org")
158 (to-list . "emacsconf-committee@gnu.org"))
159 ("l\\.emacsconf-discuss"
160 (to-address . "emacsconf-discuss@gnu.org")
161 (to-list . "emacsconf-discuss@gnu.org"))
162 ("l\\.emacsconf-org"
163 (to-address . "emacsconf-org@gnu.org")
164 (to-list . "emacsconf-org@gnu.org"))
165 ("l\\.emacsconf-org-private"
166 (to-address . "emacsconf-org-private@gnu.org")
167 (to-list . "emacsconf-org-private@gnu.org"))
168 ("l\\.emacsconf-register"
169 (to-address . "emacsconf-register@gnu.org")
170 (to-list . "emacsconf-register@gnu.org"))
171 ("l\\.emacsconf-submit"
172 (to-address . "emacsconf-submit@gnu.org")
173 (to-list . "emacsconf-submit@gnu.org"))
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\\.gnewsense-art"
179 (to-address . "gnewsense-art@nongnu.org")
180 (to-list . "gnewsense-art@nongnu.org")
181 (list-identifier . "\\[gNewSense-art\\]"))
182 ("l\\.gnewsense-dev"
183 (to-address . "gnewsense-dev@nongnu.org")
184 (to-list . "gnewsense-dev@nongnu.org")
185 (list-identifier . "\\[Gnewsense-dev\\]"))
186 ("l\\.gnewsense-users"
187 (to-address . "gnewsense-users@nongnu.org")
188 (to-list . "gnewsense-users@nongnu.org")
189 (list-identifier . "\\[gNewSense-users\\]"))
190 ("l\\.gnunet-developers"
191 (to-address . "gnunet-developers@gnu.org")
192 (to-list . "gnunet-developers@gnu.org")
193 (list-identifier . "\\[GNUnet-developers\\]"))
194 ("l\\.help-gnunet"
195 (to-address . "help-gnunet@gnu.org")
196 (to-list . "help-gnunet@gnu.org")
197 (list-identifier . "\\[Help-gnunet\\]"))
198 ("l\\.bug-gnuzilla"
199 (to-address . "bug-gnuzilla@gnu.org")
200 (to-list . "bug-gnuzilla@gnu.org")
201 (list-identifier . "\\[Bug-gnuzilla\\]"))
202 ("l\\.gnuzilla-dev"
203 (to-address . "gnuzilla-dev@gnu.org")
204 (to-list . "gnuzilla-dev@gnu.org")
205 (list-identifier . "\\[Gnuzilla-dev\\]"))
206 ("l\\.guile-devel"
207 (to-address . "guile-devel@gnu.org")
208 (to-list . "guile-devel@gnu.org"))
209 ("l\\.guile-user"
210 (to-address . "guile-user@gnu.org")
211 (to-list . "guile-user@gnu.org"))
212 ("l\\.guix-devel"
213 (to-address . "guix-devel@gnu.org")
214 (to-list . "guix-devel@gnu.org"))
215 ("l\\.help-guix"
216 (to-address . "help-guix@gnu.org")
217 (to-list . "help-guix@gnu.org"))
218 ("l\\.info-guix"
219 (to-address . "info-guix@gnu.org")
220 (to-list . "info-guix@gnu.org"))
221 ("l\\.savannah-hackers-public"
222 (to-address . "savannah-hackers-public@gnu.org")
223 (to-list . "savannah-hackers-public@gnu.org"))
224 ("l\\.savannah-users"
225 (to-address . "savannah-users@gnu.org")
226 (to-list . "savannah-users@gnu.org"))
227 ("l\\.www-commits"
228 (to-address . "www-commits@gnu.org")
229 (to-list . "www-commits@gnu.org"))
230 ("l\\.www-discuss"
231 (to-address . "www-discuss@gnu.org")
232 (to-list . "www-discuss@gnu.org"))
233 ("l\\.haskell-art"
234 (to-address . "haskell-art@we.lurk.org")
235 (to-list . "haskell-art@we.lurk.org")
236 (list-identifier . "\\[haskell-art\\]"))
237 ("l\\.haskell-cafe"
238 (to-address . "haskell-cafe@haskell.org")
239 (to-list . "haskell-cafe@haskell.org")
240 (list-identifier . "\\[Haskell-cafe\\]"))
241 ("l\\.notmuch"
242 (to-address . "notmuch@notmuchmail.org")
243 (to-list . "notmuch@notmuchmail.org"))
244 ("l\\.parabola-dev"
245 (to-address . "dev@lists.parabola.nu")
246 (to-list . "dev@lists.parabola.nu")
247 (list-identifier . "\\[Dev\\]"))
248 ("l\\.~bandali\\.public-inbox"
249 (to-address . "~bandali/public-inbox@lists.sr.ht")
250 (to-list . "~bandali/public-inbox@lists.sr.ht"))
251 ("l\\.~sircmpwn\\.free-writers-club"
252 (to-address . "~sircmpwn/free-writers-club@lists.sr.ht")
253 (to-list . "~sircmpwn/free-writers-club@lists.sr.ht"))
254 ("l\\.~sircmpwn\\.srht-admins"
255 (to-address . "~sircmpwn/sr.ht-admins@lists.sr.ht")
256 (to-list . "~sircmpwn/sr.ht-admins@lists.sr.ht"))
257 ("l\\.~sircmpwn\\.srht-announce"
258 (to-address . "~sircmpwn/sr.ht-announce@lists.sr.ht")
259 (to-list . "~sircmpwn/sr.ht-announce@lists.sr.ht"))
260 ("l\\.~sircmpwn\\.srht-dev"
261 (to-address . "~sircmpwn/sr.ht-dev@lists.sr.ht")
262 (to-list . "~sircmpwn/sr.ht-dev@lists.sr.ht"))
263 ("l\\.~sircmpwn\\.srht-discuss"
264 (to-address . "~sircmpwn/sr.ht-discuss@lists.sr.ht")
265 (to-list . "~sircmpwn/sr.ht-discuss@lists.sr.ht"))
266 ("webmasters"
267 (to-address . "webmasters@gnu.org")
268 (to-list . "webmasters@gnu.org"))
269 ("gnu.*"
270 (gcc-self . t))
271 ("l\\."
272 (subscribed . t))
273 ("nnimap\\+uwaterloo:.*"
274 (gcc-self . t)))
275 ;; nnimap-record-commands t
276 gnus-large-newsgroup 50
277 gnus-home-directory (b/var "gnus/")
278 gnus-directory (concat gnus-home-directory "news/")
279 message-directory (concat gnus-home-directory "mail/")
280 nndraft-directory (concat gnus-home-directory "drafts/")
281 gnus-save-newsrc-file nil
282 gnus-read-newsrc-file nil
283 gnus-interactive-exit nil
284 gnus-gcc-mark-as-read t)
285
286 (with-eval-after-load 'gnus
287 (when (version< emacs-version "27")
288 (with-eval-after-load 'nnmail
289 (add-to-list
290 'nnmail-split-abbrev-alist
291 '(list . "list-id\\|list-post\\|x-mailing-list\\|x-beenthere\\|x-loop")
292 t)))
293
294 ;; (require 'gnus-registry)
295 ;; (setq gnus-registry-max-entries 2500)
296 ;; (setq gnus-registry-ignored-groups
297 ;; (append gnus-registry-ignored-groups
298 ;; '(("^nnimap:gnu\\.l" t)
299 ;; ("webmasters$" t))))
300 ;; (gnus-registry-initialize)
301
302 (with-eval-after-load 'recentf
303 (add-to-list 'recentf-exclude gnus-home-directory))
304
305 ;; hooks
306 (add-hook 'gnus-group-mode-hook #'gnus-topic-mode)
307 (add-hook 'gnus-group-mode-hook #'gnus-agent-mode))
308 ;; global key bindings
309 (global-set-key (kbd "s-m") #'gnus-plugged)
310 (global-set-key (kbd "s-M") #'gnus-unplugged)
311 (global-set-key (kbd "C-c a m") #'gnus-plugged)
312 (global-set-key (kbd "C-c a M") #'gnus-unplugged)
313
314 (with-eval-after-load 'gnus-art
315 (csetq
316 gnus-buttonized-mime-types '("multipart/\\(signed\\|encrypted\\)")
317 gnus-sorted-header-list '("^From:"
318 "^X-RT-Originator"
319 "^Newsgroups:"
320 "^Subject:"
321 "^Date:"
322 "^Envelope-To:"
323 "^Followup-To:"
324 "^Reply-To:"
325 "^Organization:"
326 "^Summary:"
327 "^Abstract:"
328 "^Keywords:"
329 "^To:"
330 "^[BGF]?Cc:"
331 "^Posted-To:"
332 "^Mail-Copies-To:"
333 "^Mail-Followup-To:"
334 "^Apparently-To:"
335 "^Resent-From:"
336 "^User-Agent:"
337 "^X-detected-operating-system:"
338 "^X-Spam_action:"
339 "^X-Spam_bar:"
340 "^Message-ID:"
341 ;; "^References:"
342 "^List-Id:"
343 "^Gnus-Warning:")
344 gnus-visible-headers (mapconcat 'identity
345 gnus-sorted-header-list
346 "\\|")
347 ;; local-lapsed article dates
348 ;; from https://www.emacswiki.org/emacs/GnusFormatting#toc11
349 gnus-article-date-headers '(user-defined)
350 gnus-article-time-format
351 (lambda (time)
352 (let* ((date (format-time-string "%a, %d %b %Y %T %z" time))
353 (local (article-make-date-line date 'local))
354 (combined-lapsed (article-make-date-line date
355 'combined-lapsed))
356 (lapsed (progn
357 (string-match " (.+" combined-lapsed)
358 (match-string 0 combined-lapsed))))
359 (concat local lapsed))))
360 ;; local key bindings
361 (define-key gnus-article-mode-map (kbd "M-L") #'org-store-link))
362
363 (with-eval-after-load 'gnus-sum
364 (csetq gnus-thread-sort-functions '(gnus-thread-sort-by-number
365 gnus-thread-sort-by-subject
366 gnus-thread-sort-by-date))
367 ;; local key bindings
368 (define-key gnus-summary-mode-map (kbd "M-L") #'org-store-link)
369 (defvar b/gnus-summary-prefix-map)
370 (define-prefix-command 'b/gnus-summary-prefix-map)
371 (define-key gnus-summary-mode-map (kbd "v")
372 'b/gnus-summary-prefix-map)
373 (define-key b/gnus-summary-prefix-map (kbd "r")
374 #'gnus-summary-reply)
375 (define-key b/gnus-summary-prefix-map (kbd "w")
376 #'gnus-summary-wide-reply)
377 (define-key b/gnus-summary-prefix-map (kbd "v")
378 #'gnus-summary-show-raw-article))
379 ;; hooks
380 (add-hook 'gnus-summary-mode-hook #'b/no-mouse-autoselect-window)
381
382 (defvar b/sfl-p nil)
383 (with-eval-after-load 'gnus-msg
384 (defvar b/shemshak-signature "Amin Bandali
385 https://shemshak.org/~bandali")
386 (defvar b/uwaterloo-signature "Amin Bandali, MMath
387 https://bndl.org")
388 (defvar b/csc-signature "Amin Bandali (https://bndl.org)
389 Systems Committee <syscom@csclub.uwaterloo.ca>
390 Computer Science Club of the University of Waterloo")
391 (defvar b/sfl-signature "Amin Bandali
392 Free Software Consultant
393 Savoir-faire Linux
394 GNU Jami: bandali")
395 (csetq
396 gnus-message-replysign t
397 gnus-posting-styles
398 '((".*"
399 (address "bandali@gnu.org"))
400 ("nnimap\\+gnu:l\\..*"
401 (signature nil))
402 ("nnimap\\+gnu:.*"
403 (organization "GNU"))
404 ((header "subject" "ThankCRM")
405 (to "webmasters-comment@gnu.org")
406 (body "")
407 (eval (setq b/message-cite-say-hi nil)))
408 ("nnimap\\+shemshak:.*"
409 (address "amin@shemshak.org")
410 (body "\nBest,\n")
411 (signature b/shemshak-signature)
412 (gcc "nnimap+shemshak:Sent")
413 (eval (setq b/message-cite-say-hi t)))
414 ("nnimap\\+uwaterloo:.*"
415 (address "bandali@uwaterloo.ca")
416 (body "\nBest,\n")
417 (signature b/uwaterloo-signature))
418 ("nnimap\\+uwaterloo:INBOX"
419 (gcc "\"nnimap+uwaterloo:Sent Items\""))
420 ("nnimap\\+csc:.*"
421 (address "bandali@csclub.uwaterloo.ca")
422 (signature b/csc-signature)
423 (gcc "nnimap+csc:Sent"))
424 ("nnimap\\+sfl:.*"
425 (address "amin.bandali@savoirfairelinux.com")
426 (signature b/sfl-signature)
427 (gcc "nnimap+sfl:Sent")
428 (eval (setq-local b/sfl-p t))))))
429 ;; hooks
430 (with-eval-after-load 'gnus
431 (add-hook 'gnus-message-setup-hook
432 (lambda ()
433 (unless (or (mml-secure-is-encrypted-p)
434 b/sfl-p)
435 (mml-secure-message-sign)))))
436
437 (with-eval-after-load 'gnus-topic
438 (csetq gnus-topic-line-format "%i[ %A: %(%{%n%}%) ]%v\n"))
439
440 (with-eval-after-load 'gnus-agent
441 (csetq gnus-agent-synchronize-flags 'ask))
442
443 (with-eval-after-load 'gnus-group
444 (csetq gnus-permanently-visible-groups "\\(:INBOX$\\|:gnu$\\)"))
445
446 (comment
447 ;; problematic with ebdb's popup, *EBDB-Gnus*
448 (with-eval-after-load 'gnus-win
449 (csetq gnus-use-full-window nil)))
450
451 (with-eval-after-load 'gnus-dired
452 (add-hook 'dired-mode-hook 'gnus-dired-mode))
453
454 (comment
455 (with-eval-after-load 'gnus-utils
456 (csetq gnus-completing-read-function 'gnus-ido-completing-read)))
457
458 (with-eval-after-load 'mm-decode
459 (csetq mm-discouraged-alternatives '("text/html" "text/richtext")
460 mm-decrypt-option 'known
461 mm-verify-option 'known))
462
463 (with-eval-after-load 'mm-uu
464 (when (version< "27" emacs-version)
465 (set-face-attribute 'mm-uu-extract nil :extend t))
466 (when (version< emacs-version "27")
467 (csetq mm-uu-diff-groups-regexp ".")))
468
469 (with-eval-after-load 'mml-sec
470 (csetq mml-secure-openpgp-encrypt-to-self t
471 mml-secure-openpgp-sign-with-sender t))
472
473 ;; (require 'gnus-article-treat-patch)
474 ;; ;; note: be sure to customize faces with `:foreground "white"' when
475 ;; ;; using a theme with a white/light background :)
476 ;; (setq ft/gnus-article-patch-conditions
477 ;; '("^@@ -[0-9]+,[0-9]+ \\+[0-9]+,[0-9]+ @@"))
478
479 (provide 'bandali-gnus)
480 ;;; bandali-gnus.el ends here