mirror of
https://github.com/SqrtMinusOne/dotfiles.git
synced 2025-12-10 11:13:04 +03:00
feat(mail): davmail, offlineimap, notmuch extensions
This commit is contained in:
parent
1be22593a4
commit
9f4a0b1e09
10 changed files with 396 additions and 55 deletions
|
|
@ -1,5 +1,6 @@
|
|||
(specifications->manifest
|
||||
'(
|
||||
"openjdk"
|
||||
"node"
|
||||
"git-filter-repo"
|
||||
"virt-manager"
|
||||
|
|
|
|||
|
|
@ -3,4 +3,5 @@
|
|||
"msmtp"
|
||||
"parallel"
|
||||
"notmuch"
|
||||
"offlineimap"
|
||||
"python-lieer"))
|
||||
|
|
|
|||
|
|
@ -77,6 +77,13 @@
|
|||
#:start (make-forkexec-constructor '("/home/pavel/bin/scripts/vpn-start"))
|
||||
#:stop (make-kill-destructor)))
|
||||
|
||||
(define davmail
|
||||
(make <service>
|
||||
#:provides '(davmail)
|
||||
#:respawn? #t
|
||||
#:start (make-forkexec-constructor '("/home/pavel/bin/davmail"))
|
||||
#:stop (make-kill-destructor)))
|
||||
|
||||
(register-services
|
||||
mpd
|
||||
mpd-watcher
|
||||
|
|
@ -88,8 +95,9 @@
|
|||
xsettingsd
|
||||
discord-rich-presence
|
||||
polkit-gnome
|
||||
vpn)
|
||||
vpn
|
||||
davmail)
|
||||
|
||||
(action 'shepherd 'daemonize)
|
||||
|
||||
(for-each start '(mpd mpd-watcher mcron aw-server aw-watcher-afk aw-watcher-window pulseeffects xsettingsd discord-rich-presence polkit-gnome))
|
||||
(for-each start '(mpd mpd-watcher mcron aw-server aw-watcher-afk aw-watcher-window pulseeffects xsettingsd discord-rich-presence polkit-gnome davmail))
|
||||
|
|
|
|||
|
|
@ -1,11 +1,12 @@
|
|||
(setq user-mail-address "thexcloud@gmail.com")
|
||||
(setq user-full-name "Pavel Korytov")
|
||||
|
||||
(let ((default-directory "/home/pavel/.guix-extra-profiles/mail/mail/share/emacs/site-lisp"))
|
||||
(normal-top-level-add-subdirs-to-load-path))
|
||||
|
||||
(my-leader-def "am" 'notmuch)
|
||||
|
||||
(use-package notmuch
|
||||
;; :ensure nil
|
||||
:commands (notmuch)
|
||||
:commands (notmuch notmuch-search)
|
||||
:config
|
||||
(setq mail-specify-envelope-from t)
|
||||
(setq message-sendmail-envelope-from 'header)
|
||||
|
|
@ -14,20 +15,47 @@
|
|||
(setq sendmail-program (executable-find "msmtp"))
|
||||
(setq send-mail-function #'sendmail-send-it)
|
||||
(setq mml-secure-openpgp-sign-with-sender t)
|
||||
(setq notmuch-mua-user-agent-function 'notmuch-mua-user-agent-full)
|
||||
(add-hook 'notmuch-hello-mode-hook
|
||||
(lambda () (display-line-numbers-mode 0)))
|
||||
(setq notmuch-saved-searches
|
||||
'((:name "inbox (main)" :query "tag:inbox AND tag:main")
|
||||
(:name "unread (main)" :query "tag:unread AND tag:main")
|
||||
(:name "sent (main)" :query "tag:sent AND tag:main")
|
||||
(:name "all mail (main)" :query "tag:main")
|
||||
(:name "inbox (progin)" :query "tag:inbox AND tag:progin")
|
||||
(:name "unread (progin)" :query "tag:unread AND tag:progin")
|
||||
(:name "sent (progin)" :query "tag:sent AND tag:progin")
|
||||
(:name "all main (progin)" :query "tag:progin")
|
||||
(:name "drafts" :query "tag:draft")))
|
||||
(custom-set-faces
|
||||
`(notmuch-wash-cited-text ((t (:foreground ,(doom-color 'yellow)))))))
|
||||
(lambda () (display-line-numbers-mode 0))))
|
||||
|
||||
(my-leader-def
|
||||
:infix "am"
|
||||
"" '(:which-key "notmuch")
|
||||
"m" 'notmuch)
|
||||
|
||||
(setq notmuch-saved-searches
|
||||
'((:name "drafts" :query "tag:draft")
|
||||
(:name "main (inbox)" :query "tag:main AND tag:inbox")
|
||||
(:name "main (unread)" :query "tag:main AND tag:unread")
|
||||
(:name "main (sent)" :query "tag:main AND tag:sent")
|
||||
(:name "main (all mail)" :query "tag:main")
|
||||
(:name "progin (inbox)" :query "tag:progin AND tag:inbox")
|
||||
(:name "progin (unread)" :query "tag:progin AND tag:unread")
|
||||
(:name "progin (sent)" :query "tag:progin AND tag:sent")
|
||||
(:name "progin (all mail)" :query "tag:progin")
|
||||
(:name "pvkorytov (inbox)" :query "tag:pvkorytov AND tag:inbox")
|
||||
(:name "pvkorytov (unread)" :query "tag:pvkorytov AND tag:unread")
|
||||
(:name "pvkorytov (sent)" :query "tag:pvkorytov AND tag:sent")
|
||||
(:name "pvkorytov (all mail)" :query "tag:pvkorytov")))
|
||||
|
||||
(my-leader-def
|
||||
:infix "am"
|
||||
"t" '(:which-key "thexcloud@gmail.com")
|
||||
"ti" '((lambda () (interactive) (notmuch-search "tag:main AND tag:inbox")) :which-key "inbox")
|
||||
"tu" '((lambda () (interactive) (notmuch-search "tag:main AND tag:unread")) :which-key "unread")
|
||||
"ts" '((lambda () (interactive) (notmuch-search "tag:main AND tag:sent")) :which-key "sent")
|
||||
"ta" '((lambda () (interactive) (notmuch-search "tag:main")) :which-key "all mail")
|
||||
"p" '(:which-key "progin6304@gmail.com")
|
||||
"pi" '((lambda () (interactive) (notmuch-search "tag:progin AND tag:inbox")) :which-key "inbox")
|
||||
"pu" '((lambda () (interactive) (notmuch-search "tag:progin AND tag:unread")) :which-key "unread")
|
||||
"ps" '((lambda () (interactive) (notmuch-search "tag:progin AND tag:sent")) :which-key "sent")
|
||||
"pa" '((lambda () (interactive) (notmuch-search "tag:progin")) :which-key "all mail")
|
||||
"e" '(:which-key "pvkorytov@etu.ru")
|
||||
"ei" '((lambda () (interactive) (notmuch-search "tag:pvkorytov AND tag:inbox")) :which-key "inbox")
|
||||
"eu" '((lambda () (interactive) (notmuch-search "tag:pvkorytov AND tag:unread")) :which-key "unread")
|
||||
"es" '((lambda () (interactive) (notmuch-search "tag:pvkorytov AND tag:sent")) :which-key "sent")
|
||||
"ea" '((lambda () (interactive) (notmuch-search "tag:pvkorytov")) :which-key "all mail"))
|
||||
|
||||
(with-eval-after-load 'notmuch
|
||||
(add-hook 'message-setup-hook 'mml-secure-sign-pgpmime))
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ other_email=progin6304@gmail.com;
|
|||
# [[file:Mail.org::*Config][Config:3]]
|
||||
[new]
|
||||
tags=new;
|
||||
ignore=.osync_workdir
|
||||
ignore=.osync_workdir;.mbsyncstate;.uidvalidity;.lock;/.*gmailieer\.json.*/
|
||||
# Config:3 ends here
|
||||
|
||||
# [[file:Mail.org::*Config][Config:4]]
|
||||
|
|
|
|||
18
Desktop.org
18
Desktop.org
|
|
@ -24,6 +24,7 @@ Parts prefixed with (OFF) are not used, but kept for historic purposes. For some
|
|||
- [[#colors-in-xresources][Colors in Xresources]]
|
||||
- [[#fonts][Fonts]]
|
||||
- [[#themes][Themes]]
|
||||
- [[#device-specific-settings][Device-specific settings]]
|
||||
- [[#i3wm][i3wm]]
|
||||
- [[#general-settings][General settings]]
|
||||
- [[#managing-windows][Managing windows]]
|
||||
|
|
@ -98,6 +99,8 @@ Parts prefixed with (OFF) are not used, but kept for historic purposes. For some
|
|||
- [[#pulseeffects][PulseEffects]]
|
||||
- [[#xsettingsd][xsettingsd]]
|
||||
- [[#discord-rich-presence][Discord rich presence]]
|
||||
- [[#polkit-authentication-agent][Polkit Authentication agent]]
|
||||
- [[#vpn][VPN]]
|
||||
- [[#shepherd-config][Shepherd config]]
|
||||
- [[#sync][Sync]]
|
||||
- [[#guix-settings][Guix settings]]
|
||||
|
|
@ -2105,6 +2108,7 @@ This section generates manifests for various desktop software that I'm using.
|
|||
| dev | virt-manager |
|
||||
| dev | git-filter-repo |
|
||||
| dev | node |
|
||||
| dev | openjdk |
|
||||
** Manifests
|
||||
#+NAME: packages
|
||||
#+begin_src emacs-lisp :tangle no :var category=""
|
||||
|
|
@ -2352,6 +2356,15 @@ Run my [[file:Guix.org::*VPN][OpenVPN setup]]. Not lauching this automatially, a
|
|||
#:start (make-forkexec-constructor '("/home/pavel/bin/scripts/vpn-start"))
|
||||
#:stop (make-kill-destructor)))
|
||||
#+end_src
|
||||
** Davmail
|
||||
#+begin_src scheme
|
||||
(define davmail
|
||||
(make <service>
|
||||
#:provides '(davmail)
|
||||
#:respawn? #t
|
||||
#:start (make-forkexec-constructor '("/home/pavel/bin/davmail"))
|
||||
#:stop (make-kill-destructor)))
|
||||
#+end_src
|
||||
** Shepherd config
|
||||
Register services
|
||||
#+begin_src scheme
|
||||
|
|
@ -2366,7 +2379,8 @@ Register services
|
|||
xsettingsd
|
||||
discord-rich-presence
|
||||
polkit-gnome
|
||||
vpn)
|
||||
vpn
|
||||
davmail)
|
||||
#+end_src
|
||||
|
||||
Daemonize shepherd
|
||||
|
|
@ -2376,7 +2390,7 @@ Daemonize shepherd
|
|||
|
||||
Run services
|
||||
#+begin_src scheme
|
||||
(for-each start '(mpd mpd-watcher mcron aw-server aw-watcher-afk aw-watcher-window pulseeffects xsettingsd discord-rich-presence polkit-gnome))
|
||||
(for-each start '(mpd mpd-watcher mcron aw-server aw-watcher-afk aw-watcher-window pulseeffects xsettingsd discord-rich-presence polkit-gnome davmail))
|
||||
#+end_src
|
||||
** Sync
|
||||
| Guix dependency |
|
||||
|
|
|
|||
312
Mail.org
312
Mail.org
|
|
@ -7,12 +7,15 @@
|
|||
#+PROPERTY: header-args:conf-space :comments link
|
||||
#+PROPERTY: header-args:bash :tangle-mode (identity #o755) :comments link :shebang "#!/usr/bin/env bash"
|
||||
|
||||
My email configuration with [[https://notmuchmail.org/][notmuch]] + [[https://github.com/gauteh/lieer][lieer]] + [[https://marlam.de/msmtp/][msmtp]]. My problem with any particular mail setup was that I use Gmail labels quite extensively, and handling these over IMAP is rather awkward. Hence this choice of software.
|
||||
My email configration. Currently uses [[https://github.com/gauteh/lieer][lieer]] to fetch emails from Gmail, [[http://davmail.sourceforge.net/][davmail]] & [[http://www.offlineimap.org/][offlineimap]] to fetch emails from MS Exchange, [[https://notmuchmail.org/][notmuch]] to index, [[https://marlam.de/msmtp/][msmtp]] to send emails. Also using notmuch frontend from Emacs.
|
||||
|
||||
My problem with any particular mail setup was that I use Gmail labels quite extensively, and handling these over IMAP is rather awkward. Notmuch seems to be the only software which provides the same first-class support for labels.
|
||||
|
||||
But I also have an Exchange account, with which I communicate via IMAP/SMTP adapter, and in this case I syncronize notmuch tags and IMAP folders.
|
||||
|
||||
References:
|
||||
- [[https://sqrtminusone.xyz/posts/2021-02-27-gmail/][My post]] about email configuration. I wrote it some time ago, but the general idea remains.
|
||||
|
||||
|
||||
* Contents
|
||||
:PROPERTIES:
|
||||
:TOC: :include all
|
||||
|
|
@ -20,14 +23,18 @@ References:
|
|||
:CONTENTS:
|
||||
- [[#contents][Contents]]
|
||||
- [[#lieer][Lieer]]
|
||||
- [[#davmail][DavMail]]
|
||||
- [[#offlineimap][OfflineIMAP]]
|
||||
- [[#notmuch][Notmuch]]
|
||||
- [[#config][Config]]
|
||||
- [[#hooks][Hooks]]
|
||||
- [[#pre_new][pre_new]]
|
||||
- [[#post_new][post_new]]
|
||||
- [[#sync-script][Sync script]]
|
||||
- [[#mstp][MSTP]]
|
||||
- [[#msmtp][MSMTP]]
|
||||
- [[#emacs][Emacs]]
|
||||
- [[#saved-filters-and-keybindings][Saved filters and keybindings]]
|
||||
- [[#signing-messages][Signing messages]]
|
||||
- [[#mailcap][mailcap]]
|
||||
- [[#guix-settings][Guix settings]]
|
||||
:END:
|
||||
|
|
@ -53,6 +60,74 @@ gmi set --ignore-tags-local new
|
|||
#+end_example
|
||||
|
||||
Running =gmi sync= in the required directory performs the synchronization. The first sync takes a while, the subsequent syncs are pretty fast.
|
||||
* DavMail
|
||||
[[davmail.sourceforge.net][DavMail]] is a gateway bettwen MS Exchange and the rest of the world, which uses IMAP/SMTP/LDAP/etc. As I have one corporate MS Exchange address, this is just the program I need. As of yet, it isn't packaged for Guix, but it's easy enough to download.
|
||||
|
||||
It has a GUI mode, but I prefer headless config.
|
||||
#+begin_src conf-unix :tangle ~/bin/davmail-6.0.0-3375/davmail.properties
|
||||
davmail.server=true
|
||||
davmail.mode=Auto
|
||||
davmail.url=https://mail.etu.ru/owa/
|
||||
|
||||
davmail.caldavPort=1080
|
||||
davmail.imapPort=1143
|
||||
davmail.ldapPort=1389
|
||||
davmail.popPort=1110
|
||||
davmail.smtpPort=1025
|
||||
|
||||
davmail.imapAutoExpunge=false
|
||||
davmail.enableKeepalive=false
|
||||
#+end_src
|
||||
|
||||
Also it's a bit of problem to get it launched as it looks for some jars in pwd, so here is a script.
|
||||
#+begin_src bash :tangle ~/bin/davmail
|
||||
cd $HOME/bin/davmail-6.0.0-3375
|
||||
./davmail davmail.properties
|
||||
#+end_src
|
||||
|
||||
Shepherd service is defined in [[file:Desktop.org::*Davmail][Desktop.org]].
|
||||
* OfflineIMAP
|
||||
| Guix dependency |
|
||||
|-----------------|
|
||||
| offlineimap |
|
||||
|
||||
[[https://github.com/OfflineIMAP/offlineimap][OfflineIMAP]] is a program which can syncronize IMAP mailbox and maildir. Lieer does everything by itself, but my pirate Exchange IMAP needs this program. There is also [[https://isync.sourceforge.io/][isync]], but I had some weird issues with duplicate UIDs, which don't occur for OfflineIMAP.
|
||||
|
||||
I have a few options of setting username and password. First, I can run =pass= in =remotepasswordeval=, and this is fine, but it will keep by keyring unlocked, because I want to run =offlineimap= every couple of minutes.
|
||||
|
||||
Another option is to use noweb and not push the file below to the version control. Then I have a plaintext password of email on my computer, but I think it's lesser evil than the entire keyring.
|
||||
|
||||
#+NAME: mail-username
|
||||
#+begin_src emacs-lisp
|
||||
(password-store-get-field "Job/Infrastructure/pvkorytov@etu.ru" "username")
|
||||
#+end_src
|
||||
|
||||
#+NAME: mail-password
|
||||
#+begin_src emacs-lisp
|
||||
(password-store-get "Job/Infrastructure/pvkorytov@etu.ru")
|
||||
#+end_src
|
||||
|
||||
#+begin_src conf-unix :tangle ~/.offlineimaprc :noweb yes
|
||||
[general]
|
||||
accounts = pvkorytov
|
||||
|
||||
[Account pvkorytov]
|
||||
localrepository = pvkorytov-local
|
||||
remoterepository = pvkorytov-remote
|
||||
|
||||
[Repository pvkorytov-local]
|
||||
type = Maildir
|
||||
localfolders = ~/Mail/pvkorytov_etu/
|
||||
|
||||
[Repository pvkorytov-remote]
|
||||
type = IMAP
|
||||
remotehost = localhost
|
||||
remoteuser = <<mail-username()>>
|
||||
remotepass = <<mail-password()>>
|
||||
remoteport = 1143
|
||||
starttls = no
|
||||
ssl = no
|
||||
#+end_src
|
||||
* Notmuch
|
||||
| Guix dependency |
|
||||
|-----------------|
|
||||
|
|
@ -87,7 +162,7 @@ A list of tags which will be added by =notmuch new= and directory names which wi
|
|||
#+begin_src conf-unix
|
||||
[new]
|
||||
tags=new;
|
||||
ignore=.osync_workdir
|
||||
ignore=.osync_workdir;.mbsyncstate;.uidvalidity;.lock;/.*gmailieer\.json.*/
|
||||
#+end_src
|
||||
|
||||
Exclude these tags from search by default.
|
||||
|
|
@ -103,24 +178,123 @@ synchronize_flags=true
|
|||
#+end_src
|
||||
|
||||
** Hooks
|
||||
Now, we have to link up lieer and notmuch. This is done via the notmuch hook system, which allows to run custom scripts before and after any command.
|
||||
Now we have to link up lieer & maildir and with notmuch. This is done via the notmuch hook system, which allows to run custom scripts before and after any command.
|
||||
|
||||
With lieer and Gmail, it is enough to simply run the program, because Gmail has first-class support for tags. Maildir does not, so I decide to syncronize notmuch tags and IMAP folders. In essence, the idea is to:
|
||||
- move mails to their folders by tags /before/ the syncronization
|
||||
- tag mails by their folders /after/ the syncronization
|
||||
|
||||
The problem is that with that approach one email can have only one tag, but it's better than nothing.
|
||||
|
||||
So, here are the rules which match tags & folders:
|
||||
#+NAME: pvkorytov_tags
|
||||
| tag | folder |
|
||||
|--------------------------+--------------------------|
|
||||
| inbox | INBOX |
|
||||
| sent | Sent |
|
||||
| spam | Junk |
|
||||
| trash | Trash |
|
||||
| job.digital | Job_Digital |
|
||||
| job.digital.docs | Job_Digital.Docs |
|
||||
| job.digital.support | Job_Digital.Support |
|
||||
| job.digital.superservice | Job_Digital.Superservice |
|
||||
|
||||
And below is a noweb function, which generates the following commands for notmuch to execute:
|
||||
- /before/ sync:
|
||||
- =notmuch search --output files "NOT path:[PATH] AND tag:[TAG] AND tag:[ROOT_TAG]" | xargs -I ! mv ! [PATH]=
|
||||
Move emails with =TAG= but outside the matching =PATH= to the latter
|
||||
- =notmuch search --output=files "NOT path:[ARCHIVE_PATH] AND tag:[ROOT_TAG] AND NOT tag:[TAG1] ... AND NOT tag:[TAGN]" | xargs -I ! mv ! [ARCHIVE_PATH]=
|
||||
Move untagged emails to the =ARCHIVE_PATH=
|
||||
- /after/ sync:
|
||||
- =notmuch tag +[TAG] "path:[PATH] AND NOT tag:[TAG]"=
|
||||
Tag emails in =PATH= which do not yet have the matching =TAG=
|
||||
- =notmuch tag -[TAG] "NOT path:[PATH] AND tag:[TAG] AND tag:[ROOT_TAG]"=
|
||||
Remove =TAG= from emails which are outside the matching =PATH=
|
||||
|
||||
These rules are getting included in the respective hooks.
|
||||
|
||||
#+NAME: mail-tags
|
||||
#+begin_src emacs-lisp :var tags=pvkorytov_tags root="pvkorytov_etu" root_tag="pvkorytov" make_tag="" remove="" move="" archive_root=""
|
||||
(setq my/maildir-root "~/Mail")
|
||||
|
||||
(let ((rules '()))
|
||||
(dolist (row tags)
|
||||
(let ((tag (nth 0 row))
|
||||
(folder (nth 1 row)))
|
||||
(unless (string-empty-p make_tag)
|
||||
(add-to-list
|
||||
'rules
|
||||
(format "notmuch tag +%s \"path:%s/%s/cur/** AND NOT tag:%s\""
|
||||
tag root folder tag)
|
||||
t))
|
||||
(unless (string-empty-p remove)
|
||||
(add-to-list
|
||||
'rules
|
||||
(format "notmuch tag -%s \"NOT path:%s/%s/cur/** AND tag:%s AND tag:%s\""
|
||||
tag root folder tag root_tag)
|
||||
t))
|
||||
(unless (string-empty-p move)
|
||||
(add-to-list
|
||||
'rules
|
||||
(concat
|
||||
(format "notmuch search --output=files \"NOT path:%s/%s/cur/** AND tag:%s AND tag:%s\""
|
||||
root folder tag root_tag)
|
||||
(format " | xargs -I ! mv ! %s/%s/%s/cur/" my/maildir-root root folder))
|
||||
t))))
|
||||
(unless (string-empty-p archive_root)
|
||||
(add-to-list
|
||||
'rules
|
||||
(concat
|
||||
(format "notmuch search --output=files \"NOT path:%s/%s/cur/** AND %s AND tag:%s\""
|
||||
root archive_root
|
||||
(mapconcat
|
||||
(lambda (row)
|
||||
(format "NOT tag:%s" (car row)))
|
||||
tags
|
||||
" AND ")
|
||||
root_tag)
|
||||
(format " | xargs -I ! mv ! %s/%s/%s/cur/" my/maildir-root root archive_root))
|
||||
t))
|
||||
(string-join rules "\n"))
|
||||
#+end_src
|
||||
|
||||
*** =pre_new=
|
||||
This hook runs fetch from Gmail in parallel before the =notmuch new= command.
|
||||
This hook runs fetch from Gmail & offlineimap in parallel before the =notmuch new= command. The =parallel= command is provided by [[https://www.gnu.org/software/parallel/][GNU Parallel]].
|
||||
|
||||
The =parallel= command is provided by [[https://www.gnu.org/software/parallel/][GNU Parallel]].
|
||||
It isn't necessary to run =cd= for offlineimap, but it's easier to write that way.
|
||||
|
||||
#+begin_src bash :tangle ~/Mail/.notmuch/hooks/pre-new
|
||||
#+NAME: pre-new-pvkorytov-tags
|
||||
#+begin_src emacs-lisp :var tags=pvkorytov_tags
|
||||
(my/mail-format-tags-rules tags "pvkorytov_etu" "pvkorytov" nil nil t "Archive")
|
||||
#+end_src
|
||||
|
||||
#+begin_src bash :tangle ~/Mail/.notmuch/hooks/pre-new :noweb yes
|
||||
# GMI="/home/pavel/Programs/miniconda3/envs/mail/bin/gmi"
|
||||
GMI="gmi"
|
||||
parallel -j0 "(cd /home/pavel/Mail/{}/ && $GMI sync)" ::: thexcloud progin6304
|
||||
|
||||
echo "Running pre-new filters"
|
||||
<<mail-tags(move="t",archive_root="Archive")>>
|
||||
echo "Pre-new filters done"
|
||||
|
||||
parallel --link -j0 "(cd /home/pavel/Mail/{1}/ && {2} {3})" ::: thexcloud progin6304 pvkorytov_etu ::: "$GMI" "$GMI" "offlineimap" ::: sync sync ""
|
||||
#+end_src
|
||||
|
||||
*** =post_new=
|
||||
And this hook tags different mailboxes with different tags.
|
||||
|
||||
#+begin_src bash :tangle ~/Mail/.notmuch/hooks/post-new
|
||||
#+NAME: post-new-pvkorytov-tags
|
||||
#+begin_src emacs-lisp :var tags=pvkorytov_tags
|
||||
(my/mail-format-tags-rules tags "pvkorytov_etu" "pvkorytov" t t)
|
||||
#+end_src
|
||||
|
||||
#+begin_src bash :tangle ~/Mail/.notmuch/hooks/post-new :noweb yes
|
||||
notmuch tag +main "path:thexcloud/** AND tag:new"
|
||||
notmuch tag +progin "path:progin6304/** AND tag:new"
|
||||
notmuch tag +pvkorytov "path:pvkorytov_etu/** AND tag:new"
|
||||
|
||||
echo "Running post-new filters"
|
||||
<<mail-tags(make_tag="t",remove="t")>>
|
||||
echo "Post-new filters done"
|
||||
notmuch tag -new "tag:new"
|
||||
#+end_src
|
||||
* Sync script
|
||||
|
|
@ -143,10 +317,12 @@ ALL_UNREAD=$(notmuch count "$ALL_QUERY")
|
|||
if [ $NEW_UNREAD -gt 0 ]; then
|
||||
MAIN_UNREAD=$(notmuch count "tag:unread AND tag:main")
|
||||
PROGIN_UNREAD=$(notmuch count "tag:unread AND tag:progin")
|
||||
ETU_UNREAD=$(notmuch count "tag:unread AND tag:pvkorytov")
|
||||
read -r -d '' NOTIFICATION <<EOM
|
||||
$NEW_UNREAD new messages
|
||||
$MAIN_UNREAD thexcloud@gmail.com
|
||||
$PROGIN_UNREAD progin6304@gmail.com
|
||||
$ETU_UNREAD pvkorytov@etu.ru
|
||||
$ALL_UNREAD total
|
||||
EOM
|
||||
notify-send "New Mail" "$NOTIFICATION"
|
||||
|
|
@ -159,7 +335,7 @@ The script is ran via GNU Mcron every 5 minutes.
|
|||
#+begin_src scheme :tangle ~/.config/cron/mail.guile
|
||||
(job "*/5 * * * * " "~/bin/scripts/check-email")
|
||||
#+end_src
|
||||
* MSTP
|
||||
* MSMTP
|
||||
| Guix dependency |
|
||||
|-----------------|
|
||||
| msmtp |
|
||||
|
|
@ -186,26 +362,38 @@ port 587
|
|||
from progin6304@gmail.com
|
||||
user progin6304@gmail.com
|
||||
passwordeval "pass show My_Online/ETU/progin6304@gmail.com | head -n 1"
|
||||
|
||||
account pvkorytov
|
||||
tls off
|
||||
auth plain
|
||||
host localhost
|
||||
port 1025
|
||||
from pvkorytov@etu.ru
|
||||
user pvkorytov
|
||||
passwordeval "pass show Job/Infrastructure/pvkorytov@etu.ru | head -n 1"
|
||||
#+end_src
|
||||
* Emacs
|
||||
:PROPERTIES:
|
||||
:header-args+: :tangle ~/.emacs.d/mail.el
|
||||
:END:
|
||||
Finally, Emacs configuration.
|
||||
Finally, Emacs configuration. Let's start with some variables:
|
||||
#+begin_src emacs-lisp
|
||||
(setq user-mail-address "thexcloud@gmail.com")
|
||||
(setq user-full-name "Pavel Korytov")
|
||||
#+end_src
|
||||
|
||||
The problem with my Guix setup is that Emacs by default doesn't see the elisp files of notmuch, so here is a small workaround:
|
||||
Then, the problem with my Guix setup is that Emacs by default doesn't see the elisp files of notmuch, so here is a small workaround:
|
||||
#+begin_src emacs-lisp
|
||||
(let ((default-directory "/home/pavel/.guix-extra-profiles/mail/mail/share/emacs/site-lisp"))
|
||||
(normal-top-level-add-subdirs-to-load-path))
|
||||
|
||||
(my-leader-def "am" 'notmuch)
|
||||
#+end_src
|
||||
|
||||
And the proper notmuch settings:
|
||||
Finally the proper notmuch settings:
|
||||
#+begin_src emacs-lisp
|
||||
(use-package notmuch
|
||||
;; :ensure nil
|
||||
:commands (notmuch)
|
||||
:commands (notmuch notmuch-search)
|
||||
:config
|
||||
(setq mail-specify-envelope-from t)
|
||||
(setq message-sendmail-envelope-from 'header)
|
||||
|
|
@ -214,24 +402,90 @@ And the proper notmuch settings:
|
|||
(setq sendmail-program (executable-find "msmtp"))
|
||||
(setq send-mail-function #'sendmail-send-it)
|
||||
(setq mml-secure-openpgp-sign-with-sender t)
|
||||
(setq notmuch-mua-user-agent-function 'notmuch-mua-user-agent-full)
|
||||
(add-hook 'notmuch-hello-mode-hook
|
||||
(lambda () (display-line-numbers-mode 0)))
|
||||
(setq notmuch-saved-searches
|
||||
'((:name "inbox (main)" :query "tag:inbox AND tag:main")
|
||||
(:name "unread (main)" :query "tag:unread AND tag:main")
|
||||
(:name "sent (main)" :query "tag:sent AND tag:main")
|
||||
(:name "all mail (main)" :query "tag:main")
|
||||
(:name "inbox (progin)" :query "tag:inbox AND tag:progin")
|
||||
(:name "unread (progin)" :query "tag:unread AND tag:progin")
|
||||
(:name "sent (progin)" :query "tag:sent AND tag:progin")
|
||||
(:name "all main (progin)" :query "tag:progin")
|
||||
(:name "drafts" :query "tag:draft")))
|
||||
(custom-set-faces
|
||||
`(notmuch-wash-cited-text ((t (:foreground ,(doom-color 'yellow)))))))
|
||||
(lambda () (display-line-numbers-mode 0))))
|
||||
#+end_src
|
||||
|
||||
The file to which this is tangled is read in the init.el.
|
||||
** Saved filters and keybindings
|
||||
I want to have the saved filters available in both notmuch interface as as keybindings. So a bit more of abusing org tables.
|
||||
|
||||
Root keybindings:
|
||||
#+begin_src emacs-lisp
|
||||
(my-leader-def
|
||||
:infix "am"
|
||||
"" '(:which-key "notmuch")
|
||||
"m" 'notmuch)
|
||||
#+end_src
|
||||
|
||||
#+NAME: root_tags
|
||||
| Root tag | Prefix | Keybinding description |
|
||||
|-----------+--------+------------------------|
|
||||
| main | t | thexcloud@gmail.com |
|
||||
| progin | p | progin6304@gmail.com |
|
||||
| pvkorytov | e | pvkorytov@etu.ru |
|
||||
|
||||
#+NAME: filter_tags
|
||||
| Tag | Prefix | Name |
|
||||
|--------+--------+----------|
|
||||
| inbox | i | inbox |
|
||||
| unread | u | unread |
|
||||
| sent | s | sent |
|
||||
| | a | all mail |
|
||||
|
||||
The following formats the tables above to a proper syntax for =setq notmuch-saved-searches=:
|
||||
#+NAME: format-notmuch-saved-searches
|
||||
#+begin_src emacs-lisp :var root_tags=root_tags filter_tags=filter_tags :tangle no
|
||||
(let ((searches '()))
|
||||
(dolist (root_tag root_tags)
|
||||
(dolist (tag filter_tags)
|
||||
(add-to-list
|
||||
'searches
|
||||
(format "(:name \"%s\" :query \"%s\")"
|
||||
(format "%s (%s)"
|
||||
(nth 0 root_tag)
|
||||
(nth 2 tag))
|
||||
(concat "tag:" (nth 0 root_tag)
|
||||
(unless (string-empty-p (nth 0 tag))
|
||||
(concat " AND tag:" (nth 0 tag)))))
|
||||
t)))
|
||||
(string-join searches "\n"))
|
||||
#+end_src
|
||||
|
||||
And the following does the same for my general.el definer:
|
||||
#+NAME: format-notmuch-keybindings
|
||||
#+begin_src emacs-lisp :var root_tags=root_tags filter_tags=filter_tags :tangle no
|
||||
(let ((bindings '()))
|
||||
(dolist (root_tag root_tags)
|
||||
(add-to-list
|
||||
'bindings
|
||||
(format "\"%s\" '(:which-key \"%s\")"
|
||||
(nth 1 root_tag)
|
||||
(nth 2 root_tag))
|
||||
t)
|
||||
(dolist (tag filter_tags)
|
||||
(add-to-list
|
||||
'bindings
|
||||
(format "\"%s\" '((lambda () (interactive) (notmuch-search \"%s\")) :which-key \"%s\")"
|
||||
(concat (nth 1 root_tag) (nth 1 tag))
|
||||
(concat "tag:" (nth 0 root_tag)
|
||||
(unless (string-empty-p (nth 0 tag))
|
||||
(concat " AND tag:" (nth 0 tag))))
|
||||
(nth 2 tag))
|
||||
t)))
|
||||
(string-join bindings "\n"))
|
||||
#+end_src
|
||||
|
||||
#+begin_src emacs-lisp :noweb yes
|
||||
(setq notmuch-saved-searches
|
||||
'((:name "drafts" :query "tag:draft")
|
||||
<<format-notmuch-saved-searches()>>))
|
||||
|
||||
(my-leader-def
|
||||
:infix "am"
|
||||
<<format-notmuch-keybindings()>>)
|
||||
#+end_src
|
||||
** Signing messages
|
||||
#+begin_src emacs-lisp
|
||||
(with-eval-after-load 'notmuch
|
||||
|
|
|
|||
|
|
@ -1,6 +1,26 @@
|
|||
#!/usr/bin/env bash
|
||||
# [[file:../../../Mail.org::*=post_new=][=post_new=:1]]
|
||||
# [[file:../../../Mail.org::*=post_new=][=post_new=:2]]
|
||||
notmuch tag +main "path:thexcloud/** AND tag:new"
|
||||
notmuch tag +progin "path:progin6304/** AND tag:new"
|
||||
notmuch tag +pvkorytov "path:pvkorytov_etu/** AND tag:new"
|
||||
|
||||
echo "Running post-new filters"
|
||||
notmuch tag +inbox "path:pvkorytov_etu/INBOX/cur/** AND NOT tag:inbox"
|
||||
notmuch tag -inbox "NOT path:pvkorytov_etu/INBOX/cur/** AND tag:inbox AND tag:pvkorytov"
|
||||
notmuch tag +sent "path:pvkorytov_etu/Sent/cur/** AND NOT tag:sent"
|
||||
notmuch tag -sent "NOT path:pvkorytov_etu/Sent/cur/** AND tag:sent AND tag:pvkorytov"
|
||||
notmuch tag +spam "path:pvkorytov_etu/Junk/cur/** AND NOT tag:spam"
|
||||
notmuch tag -spam "NOT path:pvkorytov_etu/Junk/cur/** AND tag:spam AND tag:pvkorytov"
|
||||
notmuch tag +trash "path:pvkorytov_etu/Trash/cur/** AND NOT tag:trash"
|
||||
notmuch tag -trash "NOT path:pvkorytov_etu/Trash/cur/** AND tag:trash AND tag:pvkorytov"
|
||||
notmuch tag +job.digital "path:pvkorytov_etu/Job_Digital/cur/** AND NOT tag:job.digital"
|
||||
notmuch tag -job.digital "NOT path:pvkorytov_etu/Job_Digital/cur/** AND tag:job.digital AND tag:pvkorytov"
|
||||
notmuch tag +job.digital.docs "path:pvkorytov_etu/Job_Digital.Docs/cur/** AND NOT tag:job.digital.docs"
|
||||
notmuch tag -job.digital.docs "NOT path:pvkorytov_etu/Job_Digital.Docs/cur/** AND tag:job.digital.docs AND tag:pvkorytov"
|
||||
notmuch tag +job.digital.support "path:pvkorytov_etu/Job_Digital.Support/cur/** AND NOT tag:job.digital.support"
|
||||
notmuch tag -job.digital.support "NOT path:pvkorytov_etu/Job_Digital.Support/cur/** AND tag:job.digital.support AND tag:pvkorytov"
|
||||
notmuch tag +job.digital.superservice "path:pvkorytov_etu/Job_Digital.Superservice/cur/** AND NOT tag:job.digital.superservice"
|
||||
notmuch tag -job.digital.superservice "NOT path:pvkorytov_etu/Job_Digital.Superservice/cur/** AND tag:job.digital.superservice AND tag:pvkorytov"
|
||||
echo "Post-new filters done"
|
||||
notmuch tag -new "tag:new"
|
||||
# =post_new=:1 ends here
|
||||
# =post_new=:2 ends here
|
||||
|
|
|
|||
|
|
@ -1,6 +1,19 @@
|
|||
#!/usr/bin/env bash
|
||||
# [[file:../../../Mail.org::*=pre_new=][=pre_new=:1]]
|
||||
# [[file:../../../Mail.org::*=pre_new=][=pre_new=:2]]
|
||||
# GMI="/home/pavel/Programs/miniconda3/envs/mail/bin/gmi"
|
||||
GMI="gmi"
|
||||
parallel -j0 "(cd /home/pavel/Mail/{}/ && $GMI sync)" ::: thexcloud progin6304
|
||||
# =pre_new=:1 ends here
|
||||
|
||||
echo "Running pre-new filters"
|
||||
notmuch search --output=files "NOT path:pvkorytov_etu/INBOX/cur/** AND tag:inbox AND tag:pvkorytov" | xargs -I ! mv ! ~/Mail/pvkorytov_etu/INBOX/cur/
|
||||
notmuch search --output=files "NOT path:pvkorytov_etu/Sent/cur/** AND tag:sent AND tag:pvkorytov" | xargs -I ! mv ! ~/Mail/pvkorytov_etu/Sent/cur/
|
||||
notmuch search --output=files "NOT path:pvkorytov_etu/Junk/cur/** AND tag:spam AND tag:pvkorytov" | xargs -I ! mv ! ~/Mail/pvkorytov_etu/Junk/cur/
|
||||
notmuch search --output=files "NOT path:pvkorytov_etu/Trash/cur/** AND tag:trash AND tag:pvkorytov" | xargs -I ! mv ! ~/Mail/pvkorytov_etu/Trash/cur/
|
||||
notmuch search --output=files "NOT path:pvkorytov_etu/Job_Digital/cur/** AND tag:job.digital AND tag:pvkorytov" | xargs -I ! mv ! ~/Mail/pvkorytov_etu/Job_Digital/cur/
|
||||
notmuch search --output=files "NOT path:pvkorytov_etu/Job_Digital.Docs/cur/** AND tag:job.digital.docs AND tag:pvkorytov" | xargs -I ! mv ! ~/Mail/pvkorytov_etu/Job_Digital.Docs/cur/
|
||||
notmuch search --output=files "NOT path:pvkorytov_etu/Job_Digital.Support/cur/** AND tag:job.digital.support AND tag:pvkorytov" | xargs -I ! mv ! ~/Mail/pvkorytov_etu/Job_Digital.Support/cur/
|
||||
notmuch search --output=files "NOT path:pvkorytov_etu/Job_Digital.Superservice/cur/** AND tag:job.digital.superservice AND tag:pvkorytov" | xargs -I ! mv ! ~/Mail/pvkorytov_etu/Job_Digital.Superservice/cur/
|
||||
notmuch search --output=files "NOT path:pvkorytov_etu/Archive/cur/** AND NOT tag:inbox AND NOT tag:sent AND NOT tag:spam AND NOT tag:trash AND NOT tag:job.digital AND NOT tag:job.digital.docs AND NOT tag:job.digital.support AND NOT tag:job.digital.superservice AND tag:pvkorytov" | xargs -I ! mv ! ~/Mail/pvkorytov_etu/Archive/cur/
|
||||
echo "Pre-new filters done"
|
||||
|
||||
parallel --link -j0 "(cd /home/pavel/Mail/{1}/ && {2} {3})" ::: thexcloud progin6304 pvkorytov_etu ::: "$GMI" "$GMI" "offlineimap" ::: sync sync ""
|
||||
# =pre_new=:2 ends here
|
||||
|
|
|
|||
|
|
@ -16,10 +16,12 @@ ALL_UNREAD=$(notmuch count "$ALL_QUERY")
|
|||
if [ $NEW_UNREAD -gt 0 ]; then
|
||||
MAIN_UNREAD=$(notmuch count "tag:unread AND tag:main")
|
||||
PROGIN_UNREAD=$(notmuch count "tag:unread AND tag:progin")
|
||||
ETU_UNREAD=$(notmuch count "tag:unread AND tag:pvkorytov")
|
||||
read -r -d '' NOTIFICATION <<EOM
|
||||
$NEW_UNREAD new messages
|
||||
$MAIN_UNREAD thexcloud@gmail.com
|
||||
$PROGIN_UNREAD progin6304@gmail.com
|
||||
$ETU_UNREAD pvkorytov@etu.ru
|
||||
$ALL_UNREAD total
|
||||
EOM
|
||||
notify-send "New Mail" "$NOTIFICATION"
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue