1 ;;; bandali-gnus.el --- bandali's Gnus setup -*- lexical-binding: t; -*-
3 ;; Copyright (C) 2018-2022 Amin Bandali
5 ;; Author: Amin Bandali <bandali@gnu.org>
6 ;; Keywords: mail, news
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.
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.
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/>.
23 ;; My trusty super awesome Gnus setup.
27 (defvar b
/maildir
(expand-file-name "~/mail/"))
28 (with-eval-after-load 'recentf
29 (add-to-list 'recentf-exclude b
/maildir
))
31 (defvar b
/gnus-init-file
(b/etc
"gnus"))
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
)))
41 (declare-function article-make-date-line
"gnus-art" (date type
))
44 mail-user-agent
'gnus-user-agent
45 read-mail-command
'gnus
47 gnus-select-method
'(nnnil "")
48 gnus-secondary-select-methods
49 `(,@(if (string= (system-name) "darya")
53 (nnimap-address "127.0.0.1")
54 (nnimap-server-port 143)
55 (nnimap-authenticator plain
)
56 (nnimap-user "bandali@canonical.local")))
60 (nnimap-address "127.0.0.1")
61 (nnimap-server-port 143)
62 (nnimap-authenticator plain
)
63 (nnimap-user "bandali@kelar.local"))
67 (nnimap-address "127.0.0.1")
68 (nnimap-server-port 143)
69 (nnimap-authenticator plain
)
70 (nnimap-user "bandali@shemshak.local"))
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
)
82 ;; (: gnus-registry-split-fancy-with-parent)
83 ;; (: gnus-group-split-fancy "INBOX" t "INBOX")
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")
91 (list ".*<\\(.*\\)\\.\\(non\\)?gnu\\.org>.*" "l.\\1")
93 (list ".*<\\(.*\\)\\.fsf\\.org>.*" "l.\\1")
95 (list ".*<\\(.*\\)\\.alioth-lists\\.debian\\.net>.*" "l.\\1")
97 (list ".*<\\(.*\\)\\.gnus\\.org>.*" "l.\\1")
99 (list ".*<\\(.*\\)\\.libreplanet\\.org>.*" "l.\\1")
100 ;; iana (e.g. tz-announce)
101 (list ".*<\\(.*\\)\\.iana\\.org>.*" "l.\\1")
103 (list ".*<\\(.*\\)\\.mailop\\.org>.*" "l.\\1")
105 (list ".*<\\(.*\\)\\.spammers\\.dontlike\\.us>.*" "l.sdlu")
107 (from ".*@\\(.+\\)?bitfolk\\.com>.*" "bitfolk")
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")
114 (from "webmasters\\(-comment\\)?@gnu\\.org" "webmasters")
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
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
)
138 ;; (: gnus-registry-split-fancy-with-parent)
140 ("subject" "SE\\s-?212" "course.se212-f19")
141 (from "SE\\s-?212" "course.se212-f19")
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
)
155 ;; cron reports and other messages from root
156 (from "root@\\(.*\\.\\)?csclub\\.uwaterloo\\.ca" "INBOX")
158 ("X-Spam-Flag" "YES" "Junk")
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"
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\\]"))
179 (to-address .
"haskell-cafe@haskell.org")
180 (to-list .
"haskell-cafe@haskell.org")
181 (list-identifier .
"\\[Haskell-cafe\\]"))
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
)
197 (with-eval-after-load 'gnus
198 (when (version< emacs-version
"27")
199 (with-eval-after-load 'nnmail
201 'nnmail-split-abbrev-alist
202 '(list .
"list-id\\|list-post\\|x-mailing-list\\|x-beenthere\\|x-loop")
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)
213 (with-eval-after-load 'recentf
214 (add-to-list 'recentf-exclude gnus-home-directory
))
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
)
223 (with-eval-after-load 'gnus-art
225 gnus-buttonized-mime-types
'("multipart/\\(signed\\|encrypted\\)")
226 gnus-sorted-header-list
'("^From:"
246 "^X-detected-operating-system:"
253 gnus-visible-headers
(mapconcat #'identity
254 gnus-sorted-header-list
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
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
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
))
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
))
294 (add-hook 'gnus-summary-mode-hook
#'b
/no-mouse-autoselect-window
)
297 (with-eval-after-load 'gnus-msg
298 (let ((bandali "Amin Bandali (https://kelar.org/~bandali)"))
299 (defvar b
/csc-signature
303 "Systems Committee <syscom@csclub.uwaterloo.ca>"
304 "Computer Science Club of the University of Waterloo")
306 (defvar b
/sfl-signature
310 "Volunteer, Savoir-faire Linux"
314 gnus-message-replysign t
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")
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")
334 (gcc "nnimap+canonical:Sent"))
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"))
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")))))
347 ;; (with-eval-after-load 'gnus
348 ;; (add-hook 'gnus-message-setup-hook
350 ;; (unless (or (mml-secure-is-encrypted-p)
352 ;; (mml-secure-message-sign)))))
354 (with-eval-after-load 'gnus-topic
356 gnus-topic-line-format
"%i[ %A: %(%{%n%}%) ]%v\n"
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
)))))))
370 (with-eval-after-load 'gnus-agent
371 (setq gnus-agent-synchronize-flags
'ask
))
373 (with-eval-after-load 'gnus-group
374 (setq gnus-permanently-visible-groups
"\\(:INBOX$\\|:gnu$\\)"))
376 (with-eval-after-load 'gnus-win
377 (setq gnus-use-full-window nil
))
379 (with-eval-after-load 'gnus-dired
380 (add-hook 'dired-mode-hook
'gnus-dired-mode
))
382 (with-eval-after-load 'mm-archive
385 '("application/gzip" nil
"gunzip" "-S" ".zip" "-kd" "%f" "-r")))
387 (with-eval-after-load 'mm-decode
389 ;; mm-attachment-override-types `("text/x-diff" "text/x-patch"
390 ;; ,@mm-attachment-override-types)
391 mm-discouraged-alternatives
'("text/html" "text/richtext")
392 mm-decrypt-option
'known
393 mm-verify-option
'known
)
395 'mm-inline-media-tests
396 `("application/gzip" mm-archive-dissect-and-inline identity
))
397 (add-to-list 'mm-inlined-types
"application/gzip" 'append
))
399 (with-eval-after-load 'mm-uu
400 (when (version< "27" emacs-version
)
401 (set-face-attribute 'mm-uu-extract nil
:extend t
))
402 (when (version< emacs-version
"27")
403 (setq mm-uu-diff-groups-regexp
".")))
405 (with-eval-after-load 'mml-sec
406 (setq mml-secure-openpgp-encrypt-to-self t
407 mml-secure-openpgp-sign-with-sender t
))
409 (provide 'bandali-gnus
)
410 ;;; bandali-gnus.el ends here