123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319 |
- ;; -*- lexical-binding: t; -*-
- ;;; main email system
- (require 'jao-afio)
- (setq jao-afio-mail-function 'gnus)
- ;; (setq jao-afio-mail-function 'notmuch)
- (defvar jao-notmuch-enabled (eq jao-afio-mail-function 'notmuch))
- ;;; personal emails and others
- (defvar jao-mails)
- (defvar jao-extra-mails)
- (defvar jao-mails-regexp (regexp-opt jao-mails))
- ;;; gnus
- (setq gnus-init-file "~/.emacs.d/gnus.el"
- gnus-home-directory "~/.emacs.d/gnus"
- gnus-directory gnus-home-directory
- gnus-cache-directory (expand-file-name "cache" gnus-home-directory)
- gnus-kill-files-directory (expand-file-name "News" gnus-home-directory)
- message-directory (expand-file-name "Mail" gnus-home-directory)
- mail-source-directory (expand-file-name "Mail" gnus-home-directory))
- ;;; proton
- (use-package jao-proton-utils)
- ;;; message mode
- ;;;; customization
- (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
- (regexp-opt (append jao-mails jao-extra-mails)))
- (setq message-dont-reply-to-names
- (regexp-opt (append jao-mails '("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 "mail.jao.io")
- (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: <https://jao.io/>\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)
- ;;;; adjust bcc
- (defvar jao-message--bcc-alist
- `((,(regexp-quote "mail@jao.io") . "proton@jao.io")
- (,(regexp-quote "jao@gnu.org") . "hacking@jao.io")))
- (defun jao-message-insert-bcc ()
- (when jao-notmuch-enabled
- (let ((f (or (message-fetch-field "From") "")))
- (when-let (b (seq-some (lambda (x) (when (string-match-p (car x) f) (cdr x)))
- jao-message--bcc-alist))
- (insert "Bcc: " b "\n")))))
- ;; (when jao-notmuch-enabled
- ;; (add-hook 'message-header-setup-hook #'jao-message-insert-bcc))
- ;;;; to->from
- (defvar jao-message-to-from nil)
- (defun jao-message-adjust-from ()
- (let ((to (concat (message-fetch-field "To") (message-fetch-field "Cc"))))
- (when-let* ((tf (seq-find (lambda (tf) (string-match-p (car tf) to))
- jao-message-to-from))
- (from (message-make-from "Jose A Ortega Ruiz" (cdr tf))))
- (save-restriction
- (widen)
- (message-replace-header "From" from)))))
- (when jao-notmuch-enabled
- (add-hook 'message-header-setup-hook #'jao-message-adjust-from))
- ;;;; encryption
- (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
- (expand-file-name "certs/" gnus-directory))
- (with-eval-after-load "mm-decode"
- ;; Tells Gnus to inline the part
- (add-to-list 'mm-inlined-types "application/pgp$")
- ;; Tells Gnus how to display the part when it is requested
- (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.
- (add-to-list 'mm-automatic-display "application/pgp$")
- ;; But don't display the signatures, please.
- (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)))
- ;;;; check attachment
- (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")))))
- ;;;; check fcc/gcc
- (defun jao-message-check-gcc ()
- "Ask whether to keep a copy of message."
- (save-excursion
- (save-restriction
- (message-narrow-to-headers)
- (when (and (or (message-fetch-field "Gcc")
- (message-fetch-field "Fcc"))
- (not (y-or-n-p "Archive? ")))
- (message-remove-header "\\(?:[BFG]cc\\)")))))
- ;;;; check recipient
- (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")))))))
- ;;;; randomsig
- (with-eval-after-load "message"
- (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)
- (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 "%")))
- ;;;; send mail hooks
- (dolist (h '(jao-message-check-gcc
- jao-message-check-recipient
- jao-message-maybe-sign))
- (add-hook 'message-send-hook h))
- (unless jao-notmuch-enabled
- (add-hook 'message-send-hook #'jao-message-check-attachment))
- ;;;; keybindings
- (with-eval-after-load "message"
- ;; (define-key message-mode-map [f7] 'mml-secure-message-sign-pgp)
- (define-key message-mode-map [f8] 'mml-secure-message-encrypt-pgp)
- (define-key message-mode-map (kbd "C-c y") #'yank-media))
- ;;; sendmail/smtp
- (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 send-mail-function 'sendmail-send-it)
- (setq smtpmail-auth-supported nil) ;; (cram-md5 plain login)
- (setq smtpmail-servers-requiring-authorization nil)
- (setq smtpmail-smtp-user nil)
- (setq smtpmail-smtp-server "127.0.0.1")
- (setq smtpmail-smtp-service 25))
- (defun jao-sendmail-msmtp ()
- (setq send-mail-function 'sendmail-send-it
- sendmail-program "/usr/bin/msmtp"
- mail-specify-envelope-from t
- message-sendmail-envelope-from 'header
- mail-envelope-from 'header))
- (jao-sendmail-local)
- ;;; bbdb
- ;; (jao-load-path "bbdb/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
- (add-hook 'diary-list-entries-hook 'bbdb-anniv-diary-entries)
- (setq bbdb-file (expand-file-name "~/.emacs.d/bbdb"))
- (if jao-notmuch-enabled
- (bbdb-initialize 'message 'notmuch)
- (bbdb-initialize 'message 'pgp 'gnus)))
- ;; (load "bbdb-loaddefs")
- ;;; narrowing
- (defvar jao-mail-consult-buffer-history nil)
- (defun jao-mail-buffer-p (b)
- (or (member (buffer-name b)
- '("*Calendar*" "inbox.org" "*Org Agenda*"
- "*Fancy Diary Entries*" "diary"))
- (with-current-buffer b
- (derived-mode-p 'notmuch-show-mode
- 'notmuch-search-mode
- 'notmuch-tree-mode
- 'notmuch-hello-mode
- 'notmuch-message-mode
- 'gnus-group-mode
- 'gnus-summary-mode
- 'gnus-article-mode
- 'message-mode))))
- (defvar jao-mail-consult-source
- (list :name "mail buffer"
- :category 'buffer
- :hidden t
- :narrow (cons ?n "mail buffer")
- :history 'jao-mail-consult-buffer-history
- :action (lambda (b)
- (when (not (string-blank-p (or b "")))
- (jao-afio-goto-mail)
- (if (get-buffer-window b)
- (pop-to-buffer b)
- (pop-to-buffer-same-window b))))
- :items (lambda ()
- (mapcar #'buffer-name
- (seq-filter #'jao-mail-buffer-p (buffer-list))))))
- (jao-consult-add-buffer-source 'jao-mail-consult-source)
- (require 'jao-custom-notmuch)
- ;;; .
- (provide 'jao-custom-email)
|