% 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 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][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 [`%`-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)] 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][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_location`

  : The user's mail storage resides — in [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][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 "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)][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 -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 synchronization 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
[Dovecot]: https://dovecot.org
[Dovecot Logging]: https://doc.dovecot.org/admin_manual/logging/
[Dovecot LDA]: https://wiki.dovecot.org/LDA
[`getlogin`(3)]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/getlogin.html
[User Databases]: https://doc.dovecot.org/configuration_manual/authentication/user_databases_userdb/
[Maildir]: https://wiki.dovecot.org/MailLocation/Maildir
[RFC 2342]: https://tools.ietf.org/html/rfc2342
[Dovecot Namespaces]: https://doc.dovecot.org/configuration_manual/namespace/
[`interimap`(1)]: interimap.1.html
[`pullimap`(1)]: pullimap.1.html
[`doveadm`(1)]: https://wiki.dovecot.org/Tools/Doveadm
[`%`-variable]: https://doc.dovecot.org/configuration_manual/config_file/config_variables/