aboutsummaryrefslogtreecommitdiffstats
path: root/doc/development.md
blob: 75d549f899d3e6b27c64df43e2471098ee985bbd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
% Test environment setup for [`interimap`(1)] and [`pullimap`(1)]
% Guilhem Moulin <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)]: https://guilhem.org/man/interimap.1.html
[`pullimap`(1)]: https://guilhem.org/man/pullimap.1.html
[`doveadm`(1)]: https://wiki.dovecot.org/Tools/Doveadm
[`%`-variable]: https://wiki.dovecot.org/Variables