% 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: To: Subject: Hello world! Date: $(date -R) Message-ID: <$( 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/