Table of Contents

Motivation

As Emacs user I always want to use Emacs interface to edit documents. When I write e-mails, I also do, so I tried to introduce notmuch, emacs and offlineimap. As a result I feel notmuch on emacs is very useful in terms of tagging, searching, and emacs interface.

Some configurations below were not on the web, so I note here. If you follow my way to handle e-mails, this may help you.

Softwares

  • emacs
  • Notmuch

    tagging, fast searching available e-mail system

  • Offlineimap (official, community page)

    software to synchronize your local mailbox with the mail server via IMAP

Install

Refer to above links. I think you should use the package system of your OS.

Configurations

My goals are

  1. Automatically synchronize local mailbox with your gmail server
  2. Automatically assign the basic tags to some mails like Gmail.

I set up some below configurations referring to Emacs, Notmuch and Offlineimap.

Offlineimap

Offlineimap

Configure offlineimap to fetch emails from your gmail server.

  1. Copy the default config file

    $ cp offlineimap.conf.minimal ~/.offlineimaprc
    

    If you set $XDG_CONFIG_HOME, instead you should

    $ cp offlineimap.conf.minimal $XDG_CONFIG_HOME/offlineimap/config
    
  2. Edit the config file

    My config file $XDG_CONFIG_HOME/offlineimap/config is

    $XDG_CONFIG_HOME/offlineimap/config
    [general]
    accounts = Accountname
    maxsyncaccounts = 1
    
    [Account Accountname]
    localrepository = Accountname-Local
    remoterepository = Accountname-Remote
    synclabels = yes
    
    postsynchook = ~/.config/offlineimap/postsync.sh
    
    [Repository Accountname-Local]
    type = GmailMaildir
    localfolders = ~/mail/Accountname
    
    [Repository Accountname-Remote]
    type = Gmail
    remoteuser = Accountname@gmail.com
    remotepass = yourpassword
    
    sslcacertfile = /etc/ssl/certs/ca-certificates.crt
    
    folderfilter = lambda foldername: foldername in ['[Gmail]/All Mail']
    nametrans = lambda foldername: re.sub('^\[Gmail\]/All Mail$', 'all',foldername)
    

    Note that

    • To use this, we should change Accountname, yourpassword appropriately.
    • We have to change the path of postsysnchook, sslcacertfile to adjust our environment.

    Above details

    • Every time the local mailbox is synchronized, notmuch commands for refreshing and tagging should be executed. So the shell-script postsync.sh, which is described later, are hooked.

      postsynchook = ~/.config/offlineimap/postsync.sh
      
    • To synchronize Gmail account, need the certification file due to SSL connection. Put your local SSL certification file to sslcacertfile.

      sslcacertfile = /etc/ssl/certs/ca-certificates.crt
      
    • Gmail has many virtual folders linked to its tags and these folders share some e-mails. If all folders are synchronized to the local, the same e-mail is downloaded to multiple folders. Therefore, only "All Mail" on Gmail is synchronized and its local folder name is changed to "all" for simplicity.

      folderfilter = lambda foldername: foldername in ['[Gmail]/All Mail']
      nametrans = lambda foldername: re.sub('^\[Gmail\]/All Mail$', 'all',foldername)
      
    • Regarding Gmail authentication, since I don't know OAUTH2 well, I use the app password of Google 2-Step-Verification (See Sign in using App Passwords). Subsitute it in yourpassword.
  3. To see offlineimap to work well, execute

    $ offlineimap
    

    , and if ~/mail/Accountname/all/ is created and your mails are stored under the folder, it works well.

Systemd service configuration

On above settings offlineimap can fetch e-mails from your gmail server. Next offlineimap is configured to be automatically executed. I decided to use systemd.timer, which execute the target unit file periodically. The target is one-shot service that execute offlineimap.

  1. Copy installed offlineimap.timer, offlineimap-oneshot.service and mail.target to ~/.config/systemd/user/.

    $ cp offlineimap.timer offlineimap-oneshot.service mail.target ~/.config/systemd/user/
    

    If you don't have mail.target, you can create the following.

    ~/.config/systemd/user/mail.target
    
    [Unit]
    Description=Mail Target
    
    [Install]
    WantedBy=default.target
    
  2. (Optional) I edited offlineimap.timer to execute offlineimap-oneshot.service soon (1m) after systemd startup and every 5 minutes.

    ~/.config/systemd/user/offlineimap.timer
    
    [Unit]
    Description=Offlineimap Query Timer
    
    [Timer]
    OnStartupSec=1m
    OnUnitInactiveSec=5m
    Unit=offlineimap-oneshot.service
    
    [Install]
    WantedBy=mail.target
    
  3. On offlineimap-oneshot.service, comment out [Install] section to make it a static service, otherwise this service is executed on every startup and slows its process.

    ~/.config/systemd/user/offlineimap-oneshot.service
    
    [Unit]
    Description=Offlineimap Service (oneshot)
    
    [Service]
    Type=oneshot
    ExecStart=/usr/bin/offlineimap -o -u syslog
    # Give 12 seconds for offlineimap to gracefully stop before hard killing it.
    TimeoutStopSec=12
    # Restart=on-watchdog
    # WatchdogSec=300
    
    # [Install]
    # WantedBy=mail.target
    
  4. Make These files effective.

    $ systemctl --user enable mail.target
    $ systemctl --user enable offlineimap-oneshot.service
    $ systemctl --user enable offlineimap.timer
    

By these settings the 1st goal are satisfied.

Notmuch

Notmuch is an email tag system, it makes very easier to find and arrange emails. It also provides emacs interface. In this section, create its database and the folder which stores it, and configure auto refresh and auto tagging.

  1. Executing notmuch for the first time, interactive setup is appeared. Following the guide input your user name, mail address and local mail folder, which needs to be the upper directory or the same as offlineimap's local directory (I set ~/mail/), and the config file ~/.notmuch-config is created. After configuring, execute

    $ notmuch new
    

    , then the mail database file is created.

    This command also refreshes the notmuch database file.

  2. To refresh the database and tag emails every time offlineimap fetches e-mails from the server, edit postsync.sh described above.

    ~/.config/offlineimap/postsync.sh
    notmuch new
    notmuch tag -inbox +sent from:Accountname@gmail.com
    

    notmuch tag -inbox +sent from:Accountname@gmail.com means the inbox tag is removed and the sent tag is added regarding the e-mails sent from Accountname@gmail.com.

    Another way

    If you try to make many tag rules, you should write them in an external file and let notmuch tag to read it.

    ~/.config/offlineimap/postsync.sh
    notmuch new
    notmuch tag --batch --input=/home/guest/.config/offlineimap/notmuch_tag
    
    ~/.config/offlineimap/notmuch_tags
    -inbox +sent from:Accountname@gmail.com
    -inbox +promotions unsubscribe
    

emacs

Notmuch emacs interface

Notmuch emacs interface files mostly have already been installed with Notmuch. To load the interface files when the emacs command notmuch is executed, the following is added to your emacs config file (~/.emacs, ~/.emacs.el, or ~/.emacs.d/init.el).

~/.emacs, ~/.emacs.el, or ~/.emacs.d/init.el
(autoload 'notmuch "notmuch" "notmuch mail" t)

If you configure more, you should use Emacs customization interface executing the command M-x customize-group RET notmuch RET.

Message mode

Using notmuch on emacs, you will use message-mode when you compose emails. The configuration of message-mode is

~/.emacs, ~/.emacs.el, or ~/.emacs.d/init.el
;; setup the mail address and use name
(setq mail-user-agent 'message-user-agent)
(setq user-mail-address "Accountname@gmail.com"
      user-full-name "Accountname")
;; smtp config
(setq smtpmail-smtp-server "smtp.gmail.com"
      message-send-mail-function 'message-smtpmail-send-it)

;; report problems with the smtp server
(setq smtpmail-debug-info t)
;; add Cc and Bcc headers to the message buffer
(setq message-default-mail-headers "Cc: \nBcc: \n")
;; postponed message is put in the following draft directory
(setq message-auto-save-directory "~/mail/draft")
(setq message-kill-buffer-on-exit t)
;; change the directory to store the sent mail
(setq message-directory "~/mail/")

On this config the Gmail server is used as smtp server. But above settings don't provide authentication infomation, so Emacs looks into ~/.authinfo or ~/.authinfo.gpg. About these files, see Emacs Wiki: Sending Mail. Sent and draft mails should be put in the directory Notmuch can read.

offlineimap execution on emacs

Using the notmuch emacs interface, I often refresh my local mail box from emacs. Followings are the configuration to execute offlineimap on emacs.

~/.emacs, ~/.emacs.el, or ~/.emacs.d/init.el
(defun notmuch-exec-offlineimap ()
    "execute offlineimap"
    (interactive)
    (set-process-sentinel
     (start-process-shell-command "offlineimap"
                                  "*offlineimap*"
                                  "offlineimap -o")
     '(lambda (process event)
        (notmuch-refresh-all-buffers)
        (let ((w (get-buffer-window "*offlineimap*")))
          (when w
            (with-selected-window w (recenter (window-end)))))))
    (popwin:display-buffer "*offlineimap*"))

(add-to-list 'popwin:special-display-config
             '("*offlineimap*" :dedicated t :position bottom :stick t
               :height 0.4 :noselect t))

Configuration details

  • Used sentinel to refresh all notmuch-related buffers and show the end of the output of offlineimap on *offlineimap* buffer.
  • *offlineimap* buffer is shown with a popup window of emacs popwin package.
Back: kkatsuyuki's github page

Ask for your comment!

I wait for your advice, help, request, or anything you want to tell me.