Test environment setup
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 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. Severaldoveadm
(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 theUSER
environment variable. If that environment variable is unset as well, then the return string ofgetlogin
(3) is used.Similarly, the user’s home directory is used in (
~
- and)%
-variable expansion. It’s taken from theHOME
environment variable when themail_home
setting is left unset in the Dovecot configuration (and not overridden by the user database.mail_home
can therefore be left unset if theHOME
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. For more complex setups you’ll need one or morenamespace {…}
block.
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) 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 (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 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"