% Test environment setup
% [Guilhem Moulin](mailto:guilhem@fripost.org)

Introduction
============

This document describes how to create dummy mail storage for
[`interimap`(1)] and/or [`pullimap`(1)] development, using
[Dovecot](https://dovecot.org) as [IMAP4rev1] server.  Start by creating
a new temporary directory:

    $ BASEDIR="$(mktemp --tmpdir --directory)"

(The leading `$ ` in this document are command-line prompt strings, and
are not part of the command themselves.)


Dovecot configuration
=====================

Create a file `$BASEDIR/dovecot.conf`, which will be used as
configuration for the various Dovecot commands (the system configuration
will be skipped).

    $ cat >"$BASEDIR/dovecot.conf" <<-EOF
		log_path      = "$BASEDIR/dovecot.log"
		ssl           = no
		mail_home     = "$BASEDIR/%u"
		mail_location = maildir:~/mail
	EOF

Here are some details on the above:

`log_path`

  : Dovecot [logs to syslog](https://wiki.dovecot.org/Logging) by default.
    It's annoying to clutter syslog with test entries, so instead we make it
    log to a file under `$BASEDIR`.

`ssl`

  : Not required, but turned off here so dumping the configuration with
    `` `doveconf -c "$BASEDIR/dovecot.conf" -n` `` doesn't spew a warning.

`mail_home`

  : Dovecot needs the name of the user to (pre-)authenticate.  It is shown
    in the greeting line, and also used in [`%`-variable] expansion.
    Several [`doveadm`(1)] sub-commands have a `-u` (or `-d`) option which
    can be used to determine the username.  When this option is not set,
    the username is taken from the `USER` environment variable.  If that
    environment variable is unset as well, then the return string of
    [`getlogin`(3)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/getlogin.html)
    is used.

    Similarly, the user's home directory is used in (`~`- and)
    [`%`-variable] expansion.  It's taken from the `HOME` environment
    variable when the `mail_home` setting is left unset in the Dovecot
    configuration (and not overridden by the [user database](https://wiki.dovecot.org/UserDatabase)).

    `mail_home` can therefore be left unset if the `HOME` environment
    variable is consistently set to `$BASEDIR/$USER`.  However it's
    safer to explicitly set it in the configuration file: otherwise a
    command run in a non-curated environment might mess up with your own
    mail storage…

`mail_location`

  : The user's mail storage resides — in [Maildir](https://wiki.dovecot.org/MailLocation/Maildir)
    format — in a directory `mail` under their home directory.  This is
    enough if you're fine with the default IMAP hierarchy delimiter
    (which depends on the mail format) is used, and if you need a single
    [IMAP namespace](https://tools.ietf.org/html/rfc2342).  For more
    complex setups you'll need one or more
    [`namespace {…}` block](https://wiki.dovecot.org/Namespaces).


Mail storage access
===================

Feel free to point a mail client at the dummy mail storage.  To start a
pre-authenticated [IMAP4rev1] in the test environment for username
`testuser`, list mailboxes, and exit, run:

    $ env -i PATH="/usr/bin:/bin" USER="testuser" \
        doveadm -c "$BASEDIR/dovecot.conf" exec imap
    * PREAUTH [CAPABILITY IMAP4rev1 …] Logged in as testuser
    a LIST "" "*"
    * LIST (\HasNoChildren) "." INBOX
    a OK List completed (0.002 + 0.000 + 0.001 secs).
    q LOGOUT
    q OK Logout completed (0.001 + 0.000 secs).

For mailbox (create, delete, rename) and message (add, flag update)
manipulation you can use your mail client, the relevant [IMAP4rev1]
commands, or simply the [`doveadm`(1)] tools.  Here is an example using
the latter to create a mailbox `foo`, add a sample message to it, and
finally mark it as `\Seen`.

    $ env -i PATH="/usr/bin:/bin" USER="testuser" \
        doveadm -c "$BASEDIR/dovecot.conf" mailbox create "foo"
<!-- -->
    $ env -i PATH="/usr/bin:/bin" USER="testuser" HOME="$BASEDIR/testuser" \
        doveadm -c "$BASEDIR/dovecot.conf" exec dovecot-lda -e -m "foo" <<-EOF
			From: <sender@example.net>
			To: <recipient@example.net>
			Subject: Hello world!
			Date: $(date -R)
			Message-ID: <$(</proc/sys/kernel/random/uuid)@example.net>

			Hello world!
		EOF
<!-- -->
    $ env -i PATH="/usr/bin:/bin" USER="testuser" \
        doveadm -c "$BASEDIR/dovecot.conf" flags add "\\Seen" mailbox "foo" "*"

Normally [`dovecot-lda`(1)](https://wiki.dovecot.org/LDA) tries to do a
userdb lookup in order to determine the user's home directory.  Since we
didn't configure a user database we need to explicitly set the `HOME`
environment variable.


InterIMAP configuration and test
================================

In this example the peers to synchronize are sharing the same Dovecot
configuration file `$BASEDIR/dovecot.conf`.  Of course, it's also
possible to use a different configuration on each “server”, for instance
in order to specify different hierarchy delimiters, namespaces, or mail
storage format.

Create an [`interimap`(1)] configuration file to synchronize the `local`
and `remote` accounts.

    $ cat >"$BASEDIR/interimap.conf" <<-EOF
		database = $BASEDIR/interimap.db

		[local]
		type = tunnel
		command = env -i PATH="$PATH" USER="local" doveadm -c "$BASEDIR/dovecot.conf" exec imap

		[remote]
		type = tunnel
		command = env -i PATH="$PATH" USER="remote" doveadm -c "$BASEDIR/dovecot.conf" exec imap
	EOF

Run [`interimap`(1)] without `--watch` in order to create the database.

    $ env -i PATH="$PATH" perl -I./lib -T ./interimap --config="$BASEDIR/interimap.conf"
    Creating new schema in database file …/interimap.db
    database: Created mailbox INBOX
    […]

You can now run [`interimap`(1)] with `--watch` set, here to one second
to observe synchronisation steps early.

    $ env -i PATH="$PATH" perl -I./lib -T ./interimap --config="$BASEDIR/interimap.conf" \
        --watch=1 --debug

Use instructions from the [previous section][Mail storage access]
(substituting `testuser` with `local` or `remote`) in order to simulate
activity on either end to synchronize.  If you run these commands in
another shell, then make sure to re-set the `BASEDIR` environment
variable!


PullIMAP configuration and test
===============================

Create a [`pullimap`(1)] configuration file with as section `[foo]`.

    $ cat >"$BASEDIR/pullimap.conf" <<-EOF
		[foo]
		type = tunnel
		command = env -i PATH="$PATH" USER="testuser" doveadm -c "$BASEDIR/dovecot.conf" exec imap
		statefile = $BASEDIR/pullimap.foo
	EOF

Run [`pullimap`(1)] without `--idle` in order to create the state file.

    $ env -i PATH="$PATH" perl -I./lib -T ./pullimap --config="$BASEDIR/pullimap.conf" \
        --no-delivery foo

You can now run [`pullimap`(1)] with `--idle` set.

    $ env -i PATH="$PATH" perl -I./lib -T ./pullimap --config="$BASEDIR/pullimap.conf" \
        --no-delivery --idle --debug foo

Use instructions from the [previous section][Mail storage access]
in order to simulate activity on the “remote” server (in the relevant
mailbox — `INBOX` by default).  If you run these commands in another
shell, then make sure to re-set the `BASEDIR` environment variable!


Cleanup
=======

To remove temporary directories and the message they contain, simply
recursively remove the directory `$BASEDIR`.

    $ rm -rf -- "$BASEDIR"


[IMAP4rev1]: https://tools.ietf.org/html/rfc3501
[`interimap`(1)]: interimap.1.html
[`pullimap`(1)]: pullimap.1.html
[`doveadm`(1)]: https://wiki.dovecot.org/Tools/Doveadm
[`%`-variable]: https://wiki.dovecot.org/Variables