% 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] as
[IMAP4rev1] server.  Start by creating a new temporary directory:

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


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

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

    $ cat >"$BASEDIR/dovecot.conf" <<-EOF
		dovecot_config_version = 2.4.0
		dovecot_storage_version = 2.4.0
		log_path    = "$BASEDIR/dovecot.log"
		ssl         = no

		mail_home   = "$BASEDIR/%{user | username | lower}"
		mail_driver = maildir
		mail_path   = ~/Mail
	EOF

Here are some details on the above:

`log_path`

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

`mail_home`

  : Dovecot needs the name of the user to (pre-)authenticate.  It is shown
    in the greeting line, and also used in [settings variables] expansion.
    Several [`doveadm`(1)] sub-commands have a `-u` (or `-d`) option which
    can be used to determine the username.  To avoid performing the userdb
    lookup one can pass `--no-userdb-lookup` instead, in which case the
    username is taken from the `USER` environment variable.

    Similarly, the user's home directory is used in (`~`- and)
    [settings variables] 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][User Databases].

    `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_driver`

  : Use the [Maildir] format for mail storage..

`mail_path`:

  : The user's mail storage resides 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][RFC 2342].  For more complex
    setups you'll need one or more [`namespace {…}` block][Dovecot 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
    S: * PREAUTH [CAPABILITY IMAP4rev1 …] Logged in as testuser
    C: a LIST "" "*"
    S: * LIST (\HasNoChildren) "." INBOX
    S: a OK List completed (0.002 + 0.000 + 0.001 secs).
    C: q LOGOUT
    S: * BYE Logging out
    S: 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 --no-userdb-lookup "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 --no-userdb-lookup "\\Seen" mailbox "foo" "*"

Normally [`dovecot-lda`(1)][Dovecot 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 -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 synchronization steps early.

    $ env -i PATH="$PATH" perl -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 -T ./pullimap --config="$BASEDIR/pullimap.conf" \
		--no-delivery foo

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

    $ env -i PATH="$PATH" perl -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
[Dovecot]: https://dovecot.org
[Dovecot Logging]: https://doc.dovecot.org/latest/core/admin/logging.html#dovecot-logging
[Dovecot LDA]: https://doc.dovecot.org/latest/core/config/delivery/lda.html
[User Databases]: https://doc.dovecot.org/latest/core/config/auth/userdb.html
[Maildir]: https://doc.dovecot.org/latest/core/config/mailbox_formats/maildir.html
[RFC 2342]: https://tools.ietf.org/html/rfc2342
[Dovecot Namespaces]: https://doc.dovecot.org/latest/core/config/namespaces.html
[`interimap`(1)]: interimap.1.html
[`pullimap`(1)]: pullimap.1.html
[`doveadm`(1)]: https://doc.dovecot.org/latest/core/man/doveadm.1.html
[settings variables]: https://doc.dovecot.org/latest/core/settings/variables.html
