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@csclub.uwaterloo.local")
134 (nnimap-inbox "INBOX")
135 (nnimap-split-methods 'nnimap-split-fancy
)
138 ;; cron reports and other messages from root
139 (from "root@\\(.*\\.\\)?csclub\\.uwaterloo\\.ca" "INBOX")
141 ("X-Spam-Flag" "YES" "Junk")
146 (nnimap-stream plain
)
147 (nnimap-address "127.0.0.1")
148 (nnimap-server-port 143)
149 (nnimap-authenticator plain
)
150 (nnimap-user "amin.bandali@savoirfairelinux.local")))))
151 gnus-message-archive-group
"nnimap+gnu:INBOX"
154 (to-address .
"deepspec@lists.cs.princeton.edu")
155 (to-list .
"deepspec@lists.cs.princeton.edu")
156 (list-identifier .
"\\[deepspec\\]"))
157 ("l\\.fencepost-users"
158 (to-address .
"fencepost-users@gnu.org")
159 (to-list .
"fencepost-users@gnu.org")
160 (list-identifier .
"\\[Fencepost-users\\]"))
162 (to-address .
"haskell-cafe@haskell.org")
163 (to-list .
"haskell-cafe@haskell.org")
164 (list-identifier .
"\\[Haskell-cafe\\]"))
167 ;; nnimap-record-commands t
168 ;; gnus-large-newsgroup 50
169 ;; gnus-process-mark-toggle t
170 gnus-home-directory
(b/var
"gnus/")
171 gnus-directory
(concat gnus-home-directory
"news/")
172 message-directory
(concat gnus-home-directory
"mail/")
173 nndraft-directory
(concat gnus-home-directory
"drafts/")
174 gnus-save-newsrc-file nil
175 gnus-read-newsrc-file nil
176 gnus-search-use-parsed-queries t
177 gnus-interactive-exit nil
178 gnus-gcc-mark-as-read t
)
180 (with-eval-after-load 'gnus
181 (when (version< emacs-version
"27")
182 (with-eval-after-load 'nnmail
184 'nnmail-split-abbrev-alist
185 '(list .
"list-id\\|list-post\\|x-mailing-list\\|x-beenthere\\|x-loop")
188 (setq gnus-user-agent
'(emacs gnus type
))
190 ;; (require 'gnus-registry)
191 ;; (setq gnus-registry-max-entries 2500)
192 ;; (setq gnus-registry-ignored-groups
193 ;; (append gnus-registry-ignored-groups
194 ;; '(("^nnimap:gnu\\.l" t)
195 ;; ("webmasters$" t))))
196 ;; (gnus-registry-initialize)
198 (with-eval-after-load 'recentf
199 (add-to-list 'recentf-exclude gnus-home-directory
))
202 (add-hook 'gnus-group-mode-hook
#'gnus-topic-mode
)
203 (add-hook 'gnus-group-mode-hook
#'gnus-agent-mode
))
204 ;; global key bindings
205 (global-set-key (kbd "C-c g") #'gnus-plugged
)
206 (global-set-key (kbd "C-c G") #'gnus-unplugged
)
208 (with-eval-after-load 'gnus-art
210 gnus-buttonized-mime-types
'("multipart/\\(signed\\|encrypted\\)")
211 gnus-sorted-header-list
'("^From:"
231 "^X-detected-operating-system:"
238 gnus-visible-headers
(mapconcat #'identity
239 gnus-sorted-header-list
241 ;; local-lapsed article dates
242 ;; from https://www.emacswiki.org/emacs/GnusFormatting#toc11
243 gnus-article-date-headers
'(user-defined)
244 gnus-article-time-format
246 (let* ((date (format-time-string "%a, %d %b %Y %T %z" time
))
247 (local (article-make-date-line date
'local
))
248 (combined-lapsed (article-make-date-line date
251 (string-match " (.+" combined-lapsed
)
252 (match-string 0 combined-lapsed
))))
253 (concat local lapsed
))))
254 ;; local key bindings
255 (declare-function org-store-link
"ol" (arg &optional interactive?
))
256 (define-key gnus-article-mode-map
(kbd "M-L") #'org-store-link
))
258 (with-eval-after-load 'gnus-sum
259 (setq gnus-thread-sort-functions
'(gnus-thread-sort-by-number
260 gnus-thread-sort-by-subject
261 gnus-thread-sort-by-date
))
262 (with-eval-after-load 'message
263 (setq gnus-ignored-from-addresses message-dont-reply-to-names
))
264 ;; local key bindings
265 (define-key gnus-summary-mode-map
(kbd "M-L") #'org-store-link
)
266 ;; (define-key gnus-summary-mode-map (kbd "r")
267 ;; #'gnus-summary-reply-with-original)
268 ;; (define-key gnus-summary-mode-map (kbd "R")
269 ;; #'gnus-summary-wide-reply-with-original)
270 (defvar b
/gnus-summary-prefix-map
)
271 (define-prefix-command 'b
/gnus-summary-prefix-map
)
272 (define-key gnus-summary-mode-map
(kbd "v")
273 'b
/gnus-summary-prefix-map
)
274 (define-key b
/gnus-summary-prefix-map
(kbd "r")
275 #'gnus-summary-reply
)
276 (define-key b
/gnus-summary-prefix-map
(kbd "w")
277 #'gnus-summary-wide-reply
)
278 (define-key b
/gnus-summary-prefix-map
(kbd "v")
279 #'gnus-summary-show-raw-article
))
281 (add-hook 'gnus-summary-mode-hook
#'b
/no-mouse-autoselect-window
)
284 (with-eval-after-load 'gnus-msg
285 (let ((bandali "Amin Bandali (https://kelar.org/~bandali)"))
286 (defvar b
/csc-signature
290 "Systems Committee <syscom@csclub.uwaterloo.ca>"
291 "Computer Science Club of the University of Waterloo")
293 (defvar b
/sfl-signature
297 "Volunteer, Savoir-faire Linux"
301 gnus-message-replysign t
304 (address "bandali@gnu.org")
305 ("X-Message-SMTP-Method" "smtp fencepost.gnu.org 587"))
306 ((header "subject" "ThankCRM")
307 (to "webmasters-comment@gnu.org")
310 (address "bandali@kelar.org")
311 ("X-Message-SMTP-Method" "smtp mail.kelar.org 587")
312 (gcc "nnimap+kelar:Sent"))
313 ("nnimap\\+shemshak:.*"
314 (address "amin@shemshak.org")
315 ("X-Message-SMTP-Method" "smtp mail.shemshak.org 587")
316 (gcc "nnimap+shemshak:Sent"))
317 ("nnimap\\+canonical:.*"
318 (address "bandali@canonical.com")
319 ("X-Message-SMTP-Method" "smtp smtp.canonical.com 587")
321 (gcc "nnimap+canonical:Sent"))
322 ((header "to" "amin\\.bandali@canonical\\.com")
323 (address "amin.bandali@canonical.com"))
324 ((header "cc" "amin\\.bandali@canonical\\.com")
325 (address "amin.bandali@canonical.com"))
326 ((header "list-id" ".*\\.lists.ubuntu.com")
327 (address "bandali@ubuntu.com")
328 ("X-Message-SMTP-Method" "smtp mail.kelar.org 587"))
330 (address "bandali@csclub.uwaterloo.ca")
331 ("X-Message-SMTP-Method" "smtp mail.csclub.uwaterloo.ca 587")
332 (signature b
/csc-signature
)
333 (gcc "nnimap+csc:Sent"))
335 (address "amin.bandali@savoirfairelinux.com")
336 ("X-Message-SMTP-Method" "smtp mail.savoirfairelinux.com 587")
337 (signature b
/sfl-signature
)
338 (eval (setq-local b
/sfl-p t
))
339 (gcc "nnimap+sfl:Sent")))))
341 ;; (with-eval-after-load 'gnus
342 ;; (add-hook 'gnus-message-setup-hook
344 ;; (unless (or (mml-secure-is-encrypted-p)
346 ;; (mml-secure-message-sign)))))
348 (with-eval-after-load 'gnus-topic
350 gnus-topic-line-format
"%i[ %A: %(%{%n%}%) ]%v\n"
352 `(("Gnus" visible nil nil
)
353 (("misc" visible nil nil
))
354 ,@(if (string= (system-name) "darya")
355 '((("canonical" visible nil nil
)))
356 '((("csc" visible nil nil
))
357 (("kelar" visible nil nil
))
358 (("shemshak" visible nil nil
))
359 (("gnu" visible nil nil
))
360 (("old-gnu" visible nil nil
))
361 (("sfl" visible nil nil
)))))))
363 (with-eval-after-load 'gnus-agent
364 (setq gnus-agent-synchronize-flags
'ask
))
366 (with-eval-after-load 'gnus-group
367 (setq gnus-permanently-visible-groups
"\\(:INBOX$\\|:gnu$\\)"))
369 (with-eval-after-load 'gnus-win
370 (setq gnus-use-full-window nil
))
372 (with-eval-after-load 'gnus-dired
373 (add-hook 'dired-mode-hook
'gnus-dired-mode
))
375 (with-eval-after-load 'mm-archive
378 '("application/gzip" nil
"gunzip" "-S" ".zip" "-kd" "%f" "-r")))
380 (with-eval-after-load 'gnus-start
381 (add-hook 'gnus-after-getting-new-news-hook
#'gnus-notifications
))
383 (with-eval-after-load 'mm-decode
385 ;; mm-attachment-override-types `("text/x-diff" "text/x-patch"
386 ;; ,@mm-attachment-override-types)
387 mm-discouraged-alternatives
'("text/html" "text/richtext")
388 mm-decrypt-option
'known
389 mm-verify-option
'known
)
391 'mm-inline-media-tests
392 `("application/gzip" mm-archive-dissect-and-inline identity
))
393 (add-to-list 'mm-inlined-types
"application/gzip" 'append
))
395 (with-eval-after-load 'mm-uu
396 (when (version< "27" emacs-version
)
397 (set-face-attribute 'mm-uu-extract nil
:extend t
))
398 (when (version< emacs-version
"27")
399 (setq mm-uu-diff-groups-regexp
".")))
401 (with-eval-after-load 'mml-sec
402 (setq mml-secure-openpgp-encrypt-to-self t
403 mml-secure-openpgp-sign-with-sender t
))
405 (provide 'bandali-gnus
)
406 ;;; bandali-gnus.el ends here