dotfiles/Mail.org

7.2 KiB

Mail

My email configuration with notmuch + lieer + 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.

References:

  • My post about email configuration. I wrote it some time ago, but the general idea remains.

Lieer

Guix dependency
python-lieer

Lieer is a program to link up Gmail and notmuch. Basically, it downloads mail from Gmail via API, stores them in Maildir, and synchronizes labels with notmuch.

I have a separate directory in my ~/Mail for each address. To init lieer, run the following command in the directory:

gmi init <address>

After which the settings will be stored in gmailieer.json and the credentials in .credentials.gmailieer.json. The latter file is stored encrypted.

My preferred settings:

gmi set --replace-slash-with-dot
gmi set --ignore-tags-local new

Running gmi sync in the required directory performs the synchronization. The first sync takes a while, the subsequent syncs are pretty fast.

Notmuch

Guix dependency
notmuch
parallel

Notmuch is an email indexer program, which handles labels in a way somewhat like Gmail. It also provides a frontend for Emacs, but it's not the only one available.

Config

Not much is going on here.

First, the database path.

[database]
path=/home/pavel/Mail

My name and list of emails. It's not like it's a secret anyhow.

[user]
name=Pavel Korytov
primary_email=thexcloud@gmail.com
other_email=progin6304@gmail.com;

A list of tags which will be added by notmuch new and directory names which will be ignored by notmuch new.

[new]
tags=new;
ignore=.osync_workdir

Exclude these tags from search by default.

[search]
exclude_tags=trash;spam;

Maildir compatibility.

[maildir]
synchronize_flags=true

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.

pre_new

This hook runs fetch from Gmail in parallel before the notmuch new command.

The parallel command is provided by GNU Parallel.

# GMI="/home/pavel/Programs/miniconda3/envs/mail/bin/gmi"
GMI="gmi"
parallel -j0 "(cd /home/pavel/Mail/{}/ && $GMI sync)" ::: thexcloud progin6304

post_new

And this hook tags different mailboxes with different tags.

notmuch tag +main "path:thexcloud/** AND tag:new"
notmuch tag +progin "path:progin6304/** AND tag:new"
notmuch tag -new "tag:new"

Sync script

A script to run notmuch new and push a notification if there is new mail.

export DISPLAY=:0
CHECK_FILE="/home/pavel/Mail/.last_check"
QUERY="tag:unread"
ALL_QUERY="tag:unread"
if [ -f "$CHECK_FILE" ]; then
    DATE=$(cat "$CHECK_FILE")
    QUERY="$QUERY and date:@$DATE.."
fi

notmuch new
NEW_UNREAD=$(notmuch count "$QUERY")
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")
    read -r -d '' NOTIFICATION <<EOM
$NEW_UNREAD new messages
$MAIN_UNREAD thexcloud@gmail.com
$PROGIN_UNREAD progin6304@gmail.com
$ALL_UNREAD total
EOM
    notify-send "New Mail" "$NOTIFICATION"
fi

echo "$(date +%s)" > $CHECK_FILE

The script is ran via GNU Mcron every 5 minutes.

(job "*/5 * * * * " "~/bin/scripts/check-email")

MSTP

Guix dependency
msmtp

Sending emails can be done with MSMTP. It automatially chooses the email address and server based on the contents of the message, which is handy if there are multiple mailboxes to be managed.

As I haven't encrypted my passwords properly yet, I encrypt the entire configuration file.

Emacs

Finally, Emacs configuration.

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:

(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)

And the proper notmuch settings:

(use-package notmuch
  ;; :ensure nil
  :commands (notmuch)
  :config
  (setq mail-specify-envelope-from t)
  (setq message-sendmail-envelope-from 'header)
  (setq mail-envelope-from 'header)
  (setq notmuch-always-prompt-for-sender t)
  (setq sendmail-program (executable-find "msmtp"))
  (setq send-mail-function #'sendmail-send-it)
  (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)))))))

The file to which this is tangled is read in the init.el.

mailcap

mailcap file is a file which defines how to read to different MIME types. Notmuch also uses it, so why not keep it here.

audio/*; mpc add %s

image/*; feh %s

application/msword; /usr/bin/xdg-open %s
application/pdf; zathura %s
application/postscript ; zathura %s

text/html; /usr/bin/xdg-open %s

Guix settings

(my/format-guix-dependencies)
(specifications->manifest
 '(
   <<packages()>>))