title:A Locally Running Dovecot in Guix
date: 2021-06-08 01:41
tags: guile scheme dovecot
summary: Dovecot provides a faster searching experience for Gnus
---

So, I have been wanting to set up a locally running dovecot server for a LONG
time now.  Essentially I have an email account at [dismail.de](dismail.de), and
Emacs' [Gnus](https://www.gnu.org/software/emacs/manual/html_node/gnus/) is
pretty slow at searching for my emails.  I could switch to using mu4e or
notmuch, which ARE BLAZINGLY fast at searching your emails, BUT after listening
to John Wiegley, who is one of the current
[Emacs](https://www.gnu.org/software/emacs/) maintainers, talk about how Emacs'
Gnus mode is so cool...I've been using Gnus ever since.  Essentially Gnus is a
newsreader.  It is a way to handle lots news that is similar to reddit.  In
Gnus, after you've read a message, you do not see it again by default.  This is
handy, because since you are getting so much email, it's useful to only see
messages that you have not read.

Emacs's Gnus is actually the best way I've seen at handling LOTS of email,
particularly mailing lists.  For example, I am currently subscribed to
[guix-devel](https://lists.gnu.org/mailman/listinfo/guix-devel),
[help-guix](https://lists.gnu.org/mailman/listinfo/help-guix), and
[bug-hurd](https://lists.gnu.org/mailman/listinfo/bug-hurd).  With Gnus, I can
open up these email folders and I only see messages that I have not read, AND
the emails are organized by threads NOT date:


![Image](./images/gnus-thread.png)



With my cursor on the top of the thread, pressing C-k, will kill the entire
thread.  So when I open up this folder again, I will not see that thread.  Let's
suppose that I've read all of the messages in that thread "Re: website: A little
help running the website locally".  So that now Gnus looks like this when I open
it up:


![Image](./images/gnus-thread-all-but-one.png)



Pressing Shift-A-Shift-T, will pull up the entire thread, so that I can re-read
the whole conversation:


![Image](./images/gnus-thread-all-but-one-reopened.png)



Anyway, the main problem that I have had with Gnus (for years...I should have
fixed this a long time ago), is that it is REALLY slow and pretty much not
responsive at searching for my email.  I could try to search for my email with
Gnus, but it would typically fail.  I guess that something with dismail's
servers are wonky, because I did not have this problem when I had a paid
[fastmail](fastmail.com) account.

So, one solution to continue using Gnus, but have decent searching is to have a
locally running [dovecot](https://www.dovecot.org/) server that will serve my
emails.  I'll also be querying that local server instead of the remote one.
Sounds plausible.  Here's what you need to do:

First you need to fetch your remote email and put it in a local
[maildir](https://en.wikipedia.org/wiki/Maildir). I prefer
[mbsync](https://isync.sourceforge.io/mbsync.html), because it is what all the
cool kids are doing.

Here is my  `~/.mbsyncrc`

```
IMAPAccount dismail
# Address to connect to
Host imap.dismail.de
User jbranso@dismail.de
Pass VERYSECRETPASSWORD
# To store the password in an encrypted file use PassCmd instead of Pass
# PassCmd "gpg2 -q --for-your-eyes-only --no-tty -d ~/.mailpass.gpg"
#
# Use SSL
SSLType IMAPS
CertificateFile /etc/ssl/certs/ca-certificates.crt

IMAPStore dismail-remote
Account dismail

MaildirStore dismail-local
Subfolders Verbatim
# The trailing "/" is important
Path ~/.mail/dismail.de/
Inbox ~/.mail/dismail.de/Inbox

Channel dismail
Master :dismail-remote:
Slave :dismail-local:
# show all folders
Patterns *
# Automatically create missing mailboxes, both locally and on the server
Create Both
# Save the synchronization state files in the relevant directory
SyncState *
```

`mbsync -a`  running in a cron job, syncs up my email.  The config in guix for
that looks like so:

```scheme
(define mbsync-every-5-minutes
  ;; The job's action is a shell command.
  #~(job "*/5 * * * *"            ;Vixie cron syntax
         "mbsync -Va"
         #:user "joshua"))

...
(operating-system
...
(services
    (append
        (list
            (service mcron-service-type
                (mcron-configuration
                     (jobs (list mbsync-every-5-minutes)))))
     %desktop-services)))
```

Now all we need is the configuration for a locally running dovecot server, which
looks like so:

```scheme
(dovecot-service #:config
                     (dovecot-configuration
                      (mail-location "maildir:~/.mail/dismail.de:LAYOUT=fs")
                      (listen '("127.0.0.1"))
                      ;; I do not need ssl support in a locally running dovecot.  :)
                      (ssl? "no")
                      (protocols
                       (list (protocol-configuration
                              (name "imap")
                              (mail-max-userip-connections 1))))
                      (services (list
                                 (service-configuration
                                  (kind "imap")
                                  (client-limit 1)))))
```

The bit that really got me confused for a while was that I needed **LAYOUT=fs**
in the mail-location line.  Essentially, isync creates a maildir in a slightly
different format than what dovecot expects.  Adding in the "LAYOUT=fs" fixes this.

The last bit is we have to tell Emacs how to connect to the server:

```scheme
(setq
 user-mail-address "myemailaccount@dismail.de"
 user-full-name	"Joshua Branson")

(setq gnus-secondary-select-methods
     '((nnimap "localDismail"
               (nnimap-address "localhost")
               (nnimap-stream network)
               (nnimap-server-port 143)
               )))
```

Pretty cool stuff?  Right!?
