From 7d8344ac8af19d7a88c3547fa0ab8ced01135e86 Mon Sep 17 00:00:00 2001 From: jao Date: Sun, 18 Apr 2021 02:55:22 +0100 Subject: email.org, with some notmuch fine-tuning --- init.org | 461 +-------------------------------------------------------------- 1 file changed, 6 insertions(+), 455 deletions(-) (limited to 'init.org') diff --git a/init.org b/init.org index 8feef8b..f511dc5 100644 --- a/init.org +++ b/init.org @@ -1494,461 +1494,6 @@ ;; for M-x biblio-lookup ;; (use-package biblio :ensure t) #+END_SRC -* Email -*** message mode -***** Customization - #+begin_src emacs-lisp - (defvar jao-mails "") - (defvar jao-mails-regexp) - (setq jao-mails-regexp (regexp-opt jao-mails)) - - (require 'message) - (setq message-send-mail-function 'message-send-mail-with-sendmail - message-sendmail-envelope-from 'header - message-sendmail-f-is-evil nil) - (setq imap-store-password t) - (setq password-cache-expiry nil) - (setq message-generate-headers-first t) - (setq message-forward-before-signature nil) - (setq message-alternative-emails jao-mails-regexp) - (setq message-dont-reply-to-names - (format "%s\\|%s" jao-mails-regexp (regexp-opt '("noreply@" "@noreply" - "no-reply@" "@no-reply" - "notifications@github")))) - (setq message-citation-line-format "On %a, %b %d %Y, %N wrote:\n") - (setq message-citation-line-function 'message-insert-formatted-citation-line) - - (setq message-user-fqdn "gnus.jao.io") - - ;; writing messages - (setq message-kill-buffer-on-exit t) - (setq message-max-buffers 5) - (setq message-insert-signature t) - (setq message-from-style 'angles - user-mail-address (car jao-mails) - mail-host-address system-name - message-syntax-checks '((sender . disabled)) - message-default-headers - (concat - "X-Attribution: jao\n" - "X-Clacks-Overhead: GNU Terry Pratchett\n" - "X-URL: \n") - message-hidden-headers - '("^References:" "^Face:" "^X-Face:" "^X-Draft-From:") - message-make-forward-subject-function 'message-forward-subject-fwd) - - (setq message-expand-name-standard-ui t) - #+end_src -***** Encryption - #+BEGIN_SRC emacs-lisp - (require 'gnutls) - ;; avoiding bogus warning - (setq gnutls-min-prime-bits nil) - (setq gnus-buttonized-mime-types - '("multipart/encrypted" "multipart/signed" "multipart/alternative")) - - (setq mm-verify-option 'always) - (setq mm-decrypt-option 'always) - - (setq mm-sign-option 'guided) - (setq mm-encrypt-option 'guided) - - (setq mml-secure-passphrase-cache-expiry (* 3600 24) - password-cache-expiry (* 3600 24)) - - (setq smime-CA-directory "/etc/ssl/certs/" - smime-certificate-directory"/home/jao/.emacs.d/gnus/Mail/certs/") - - ;; Tells Gnus to inline the part - (eval-after-load "mm-decode" - '(add-to-list 'mm-inlined-types "application/pgp$")) - ;; Tells Gnus how to display the part when it is requested - (eval-after-load "mm-decode" - '(add-to-list 'mm-inline-media-tests '("application/pgp$" - mm-inline-text identity))) - ;; Tell Gnus not to wait for a request, just display the thing - ;; straight away. - (eval-after-load "mm-decode" - '(add-to-list 'mm-automatic-display "application/pgp$")) - ;; But don't display the signatures, please. - (eval-after-load "mm-decode" - (quote (setq mm-automatic-display (remove "application/pgp-signature" - mm-automatic-display)))) - - ;; decide whether to encrypt or just sign outgoing messages - (defvar jao-message-try-sign nil) - (defun jao-message-maybe-sign () - (when (and jao-message-try-sign (y-or-n-p "Sign message? ")) - (if (y-or-n-p "Encrypt message? ") - (let ((recipient (message-fetch-field "To"))) - (if (or (pgg-lookup-key recipient) - (and (y-or-n-p (format "Fetch %s's key? " recipient)) - (pgg-fetch-key pgg-default-keyserver-address - recipient))) - (mml-secure-message-encrypt-pgp) - (mml-secure-message-sign-pgp))) - (mml-secure-message-sign-pgp)))) - - ;; for ma gnus - (eval-after-load "rfc2047" - '(add-to-list 'rfc2047-header-encoding-alist - '("User-Agent" . address-mime))) - - ;; (define-key message-mode-map [f7] 'mml-secure-message-sign-pgp) - (define-key message-mode-map [f8] 'mml-secure-message-encrypt-pgp) - #+END_SRC -***** Attach image to message - Use ~C-c C-p~ in message-mode. -***** Check attachment - #+BEGIN_SRC emacs-lisp - (defvar jao-message-attachment-regexp "\\([Ww]e send\\|[Ii] send\\|attach\\)") - (defun jao-message-check-attachment () - "Check if there is an attachment in the message if I claim it." - (save-excursion - (message-goto-body) - (when (search-forward-regexp jao-message-attachment-regexp nil t nil) - (message-goto-body) - (unless (or (search-forward "<#part" nil t nil) - (message-y-or-n-p - "No attachment. Send the message? " nil nil)) - (error "No message sent"))))) - #+END_SRC -***** Check Gcc - #+BEGIN_SRC emacs-lisp - (defun jao-message-check-gcc () - "Ask whether to keep a copy of message." - (save-excursion - (save-restriction - (message-narrow-to-headers) - (when (and (message-fetch-field "Gcc") - (not (y-or-n-p "Archive? "))) - (message-remove-header "Gcc"))))) - - (defun jao-message-toggle-gcc () - "Insert or remove the \"Gcc\" header." - (interactive) - (save-excursion - (save-restriction - (message-narrow-to-headers) - (if (message-fetch-field "Gcc") - (message-remove-header "Gcc") - (gnus-inews-insert-gcc))))) - - ;; (define-key message-mode-map [(f6)] 'jao-message-toggle-gcc) - #+END_SRC -***** Check recipient - #+begin_src emacs-lisp - (defun jao-message-check-recipient () - (save-excursion - (save-restriction - (message-narrow-to-headers) - (when-let ((to (message-fetch-field "To"))) - (when (string-match-p jao-mails-regexp to) - (unless (y-or-n-p "Message is addressed to yourself. Continue?") - (error "Message not sent"))))))) - #+end_src -***** Randomsig - #+BEGIN_SRC emacs-lisp - (when (require 'randomsig nil t) - (define-key message-mode-map (kbd "C-c s") 'randomsig-replace-sig) - (define-key message-mode-map (kbd "C-c S") 'randomsig-select-sig) - (eval-after-load "gnus-sum" - '(define-key gnus-summary-save-map "-" 'gnus/randomsig-summary-read-sig)) - (setq randomsig-dir (expand-file-name "~/etc/config/emacs")) - (setq randomsig-files '("signatures.txt")) - ;; or (setq randomsig-files (randomsig-search-sigfiles)) - ;; or (setq randomsig-files 'randomsig-search-sigfiles) - (setq message-signature 'randomsig-signature) - (setq randomsig-delimiter-pattern "^%$" - randomsig-delimiter "%")) - #+END_SRC -***** Send mail hooks - #+BEGIN_SRC emacs-lisp - (dolist (h '(jao-message-check-gcc - jao-message-check-attachment - jao-message-check-recipient - jao-message-maybe-sign)) - (add-hook 'message-send-hook h)) - #+END_SRC -*** directories - #+BEGIN_SRC emacs-lisp - (setq gnus-home-directory "~/.emacs.d/gnus" - gnus-directory gnus-home-directory) - - (defun jao-gnus-dir (dir) - (expand-file-name dir gnus-home-directory)) - - (setq smtpmail-queue-dir (jao-gnus-dir "Mail/queued-mail/")) - - (setq mail-source-directory (jao-gnus-dir "Mail/") - message-auto-save-directory (jao-gnus-dir "Mail/drafts/") - message-directory (jao-gnus-dir "Mail/")) - - (setq gnus-default-directory (expand-file-name "~") - gnus-startup-file (jao-gnus-dir "newsrc") - gnus-agent-directory (jao-gnus-dir "News/agent") - gnus-home-score-file (jao-gnus-dir "scores") - gnus-article-save-directory (jao-gnus-dir "saved/") - nntp-authinfo-file (jao-gnus-dir "authinfo") - nnmail-message-id-cache-file (jao-gnus-dir "nnmail-cache") - nndraft-directory (jao-gnus-dir "drafts") - nnrss-directory (jao-gnus-dir "rss")) - #+END_SRC -*** sendmail/smtp - #+BEGIN_SRC emacs-lisp - (require 'smtpmail) - - (defun jao-sendmail-gmail () - (setq smtpmail-auth-supported '(login cram-md5 plain)) - (setq smtpmail-smtp-server "smtp.gmail.com") - (setq smtpmail-smtp-service 587)) - - (defun jao-sendmail-local () - (setq smtpmail-auth-supported nil) ;; (cram-md5 plain login) - (setq smtpmail-smtp-server "127.0.0.1") - (setq smtpmail-smtp-service 25)) - - ;; (jao-sendmail-gmail) - (jao-sendmail-local) - #+END_SRC -*** Gnus - The core of Gnus's configuration is tangled to the usual ~gnus.el~ - from [[./gnus.org][gnus.org]]. - #+BEGIN_SRC emacs-lisp - (defalias 'jao-open-gnus-frame 'jao-afio--goto-gnus) - - (setq gnus-init-file (jao-maybe-tangle "gnus")) - - ;;;;; close gnus when closing emacs, but ask when exiting - (setq gnus-interactive-exit t) - - (defun jao-gnus-started-hook () - "use that hook for its purpose " - (add-hook 'before-kill-emacs-hook 'gnus-group-exit)) - - (add-hook 'gnus-started-hook 'jao-gnus-started-hook) - - (defun jao-gnus-after-exiting-hook () - "how about removing this hook when exiting gnus in the conventional way?" - (remove-hook 'before-kill-emacs-hook 'gnus-group-exit)) - - (add-hook 'gnus-after-exiting-gnus-hook 'jao-gnus-after-exiting-hook) - - ;; define a wrapper around the save-buffers-kill-emacs - ;; to run the new hook before: - (defadvice save-buffers-kill-emacs - (before my-save-buffers-kill-emacs activate) - "Install hook when emacs exits before emacs asks to save this and that." - (run-hooks 'before-kill-emacs-hook)) - #+END_SRC -*** mbox listing - #+begin_src emacs-lisp - (defun jao-list-mailboxes (base) - (let ((dir (expand-file-name base "~/var/mail"))) - (cl-remove-if (lambda (x) - (member x '("." ".." "sent" "inbox" "trash"))) - (directory-files dir)))) - #+end_src -*** notmuch -***** Package configuration - #+BEGIN_SRC emacs-lisp - (defun jao-notmuch--mboxes-search (box) - (mapcar (lambda (m) - `(:name ,m - :search-type tree - :query ,(format "folder:%s/%s and tag:unread" - box m))) - (jao-list-mailboxes box))) - (when (file-exists-p "~/var/mail") - (use-package notmuch - :ensure t - :init - (setq notmuch-fcc-dirs '(("jao@bigml.com" . "bigml/sent") - (".*" . "jao/sent")) - notmuch-tagging-keys - '(("a" notmuch-archive-tags "Archive") - ("u" notmuch-show-mark-read-tags "Mark read") - ("f" ("+flagged") "Flag") - ("s" ("+spam" "-inbox") "Mark as spam") - ("d" ("+deleted" "-inbox") "Delete")) - notmuch-saved-searches - `((:name "jao" :key "j" - :query "folder:jao/inbox" - :search-type tree - :count-query "folder:jao/inbox and tag:unread") - (:name "bigml" :key "b" - :count-query "folder:bigml/inbox and tag:unread" - :search-type tree - :query "folder:bigml/inbox") - ,@(jao-notmuch--mboxes-search "jao") - ,@(jao-notmuch--mboxes-search "bigml") - ,@(jao-notmuch--mboxes-search "feeds") - (:name "unread" :query "tag:unread" :key "u" :search-type tree) - (:name "sent" :query "tag:sent" :key "t" :search-type tree) - (:name "drafts" :query "tag:draft" :key "d" :search-type tree) - (:name "all mail" :query "*" :count-query "tag:unread" :key "a" - :search-type tree)) - notmuch-hello-sections - '(notmuch-hello-insert-header - notmuch-hello-insert-saved-searches - notmuch-hello-insert-alltags - notmuch-hello-insert-footer)) - :bind (:map notmuch-show-mode-map - ("C-c C-c" . jao-notmuch-goto-message-in-gnus)))) - #+END_SRC -***** notmuch -> gnus - #+begin_src emacs-lisp - (defun jao-notmuch-goto-message-in-gnus () - "Open a summary buffer containing the current notmuch article." - (interactive) - (let ((group (jao-maildir-file-to-group (notmuch-show-get-filename))) - (message-id (replace-regexp-in-string "^id:" - "" - (notmuch-show-get-message-id)))) - (if (and group message-id) - (org-gnus-follow-link group message-id) - (message "Couldn't get relevant infos for switching to Gnus.")))) - #+end_src -*** visual message fill column - #+begin_src emacs-lisp - (use-package visual-fill-column - :ensure t - :init - (setq-default fringes-outside-margins nil - visual-fill-column-width 80 - visual-fill-column-fringes-outside-margins nil) - (setq gnus-treat-fill-long-lines nil) - :config - (setq split-window-preferred-function - #'visual-fill-column-split-window-sensibly) - :bind ((:map ctl-x-map ("M-f" . visual-fill-column-mode)))) - - ;; (add-hook 'gnus-article-mode-hook #'visual-line-mode) - ;; (add-hook 'gnus-article-mode-hook #'visual-fill-column-mode) - - ;; Name may be misleading, it does not set `fill-column' (which - ;; is still used by M-q) in `message-mode', but enables - ;; auto-filling on a given column. - ;; (setq message-fill-column nil) - ;; FIXME: There is no proper way to make fill commands to unfill. - ;; (add-hook 'message-mode-hook - ;; (lambda () - ;; (setq-local fill-column most-positive-fixnum))) - ;; (when-require 'visual-fill-column - ;; (add-hook 'message-mode-hook #'visual-fill-column-mode)) - #+end_src -*** mail this buffer - #+BEGIN_SRC emacs-lisp - (defun jao-mail-this-file () - (interactive) - (let ((file (buffer-file-name))) - (compose-mail) - (save-excursion - (message-goto-subject) - (insert (file-name-nondirectory file)) - (message-goto-body) - (newline 2) - (mml-attach-file file (mm-default-file-encoding file))))) - #+END_SRC -*** mailcap - #+BEGIN_SRC emacs-lisp - (require 'mailcap) - - (add-to-list 'mailcap-mime-extensions '(".JPEG" . "image/jpeg")) - (add-to-list 'mailcap-mime-extensions '(".JPG" . "image/jpeg")) - - (let* ((apps (cdr (assoc "application" mailcap-mime-data))) - (apps (cl-remove-if (lambda (x) (string= (car x) "pdf")) apps))) - (setcdr (assoc "application" mailcap-mime-data) apps) - (mailcap-parse-mailcaps nil t)) - #+END_SRC -*** frm - #+begin_src emacs-lisp - (use-package jao-frm - :init (setq jao-frm-mail-command 'jao-open-gnus-frame)) - - (defun jao-frm--formatter (mbox n) - (apply #'format "%s/%s: %s" `(,@(last (split-string mbox "/") 2) ,n))) - - (defun jao-frm--show () - (interactive) - (jao-frm-show-mail-numbers #'jao-frm--formatter)) - - (global-set-key [(f12)] 'jao-frm--show) - (global-set-key [(f8)] 'jao-frm) - - #+end_src -*** maildirs - #+begin_src emacs-lisp - (defvar jao-maildir-maildirs nil) - (defvar jao-maildir-tracked-maildirs nil) - (use-package jao-maildir - :config - (defun jao-maildir--ensure-counts () - (when gnus-newsgroup-name - (when (string-match "^nnimap.*:\\(.+\\)" gnus-newsgroup-name) - (let ((mbox (format "/home/jao/var/mail/%s" - (match-string 1 gnus-newsgroup-name)))) - (jao-maildir-update-info-string mbox))))) - (with-eval-after-load "gnus-sum" - (add-hook 'gnus-exit-group-hook #'jao-maildir--ensure-counts))) - - (jao-maildir-setup jao-maildir-maildirs jao-maildir-tracked-maildirs -20) - #+end_src -*** BBDB - #+BEGIN_SRC emacs-lisp - (use-package bbdb - :ensure t - :init (setq bbdb-complete-name-allow-cycling t - bbdb-completion-display-record nil - bbdb-gui t - bbdb-message-all-addresses t - bbdb-complete-mail-allow-cycling t - bbdb-north-american-phone-numbers-p nil - bbdb-add-aka t - bbdb-add-name 2 - bbdb-message-all-addresses t - bbdb-mua-pop-up t ;; 'horiz - bbdb-mua-pop-up-window-size 0.3 - bbdb-layout 'multi-line - bbdb-mua-update-interactive-p '(query . create) - bbdb-mua-auto-update-p 'bbdb-select-message - bbdb-user-mail-address-re jao-mails-regexp - bbdb-auto-notes-ignore-headers - `(("From" . ,jao-mails-regexp) - ("From" . ".*@.*github\.com.*") - ("To" . ".*@.*github\.com.*") - ("Reply-to" . ".*") - ("References" . ".*")) - bbdb-auto-notes-ignore-messages - `(("To" . ".*@.*github\\.com.*") - ("From" . ".*@.*github\\.com.*") - ("From" . "info-list") - ("From" . "no-?reply\\|deploy") - ("X-Mailer" . "MailChimp")) - bbdb-accept-message-alist - `(("To" . ,jao-mails-regexp) - ("Cc" . ,jao-mails-regexp) - ("BCc" . ,jao-mails-regexp)) - bbdb-ignore-message-alist bbdb-auto-notes-ignore-messages) - :config - (add-hook 'message-setup-hook 'bbdb-mail-aliases) - ;; (add-hook 'bbdb-notice-mail-hook 'bbdb-auto-notes) - (add-hook 'bbdb-after-change-hook (lambda (arg) (bbdb-save))) - (require 'bbdb-anniv) ;; BBDB 3.x this gets birthdays in org agenda - ;; and diary - clever stuff - (add-hook 'diary-list-entries-hook 'bbdb-anniv-diary-entries) - (eval-after-load "gnus-sum" - '(progn - (define-key gnus-summary-mode-map ":" 'bbdb-mua-annotate-sender) - (define-key gnus-summary-mode-map ";" 'bbdb-mua-annotate-recipients)))) - - (require 'bbdb) - (bbdb-initialize 'gnus 'message 'pgp 'mail) - (bbdb-mua-auto-update-init 'gnus) - (setq bbdb-file (expand-file-name "bbdb" gnus-home-directory)) - - #+END_SRC * Browsing *** Variables #+begin_src emacs-lisp @@ -2169,6 +1714,12 @@ (jao-load-org "eww") ;; (jao-load-org "w3m") #+end_src +* Email + #+begin_src emacs-lisp + (setq jao-afio-mail-function 'notmuch + jao-afio-notmuch-in-web t) + (jao-load-org "email") + #+end_src * PDFs *** doc-view #+begin_src emacs-lisp -- cgit v1.2.3