aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore4
-rw-r--r--Changelog47
-rw-r--r--Makefile135
-rw-r--r--README6
-rwxr-xr-xbenchmark/run5
-rw-r--r--doc/benchmark.md4
-rw-r--r--doc/build.md65
-rw-r--r--doc/development.md12
-rw-r--r--doc/getting-started.md5
-rwxr-xr-xinterimap17
-rw-r--r--interimap.service3
-rw-r--r--interimap@.service3
-rw-r--r--lib/Net/IMAP/InterIMAP.pm7
-rwxr-xr-xpullimap7
-rw-r--r--pullimap@.service3
-rwxr-xr-xtests/certs/generate18
-rw-r--r--tests/certs/openssl.cnf4
-rw-r--r--tests/config/dovecot/ssl.conf3
-rw-r--r--tests/db-exclusive-lock/t4
-rw-r--r--tests/db-no-create--watch/t2
-rw-r--r--tests/interimap.list (renamed from tests/list)3
-rw-r--r--tests/pullimap.list2
-rw-r--r--tests/pullimap/t45
-rwxr-xr-xtests/run20
-rwxr-xr-xtests/run-all3
-rw-r--r--tests/tls-protocols/openssl.cnf2
-rw-r--r--[l---------]tests/tls-protocols/remote.conf5
-rw-r--r--tests/tls-rsa+ecdsa/t2
28 files changed, 294 insertions, 142 deletions
diff --git a/.gitignore b/.gitignore
index 2267ea4..e8f355e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,6 +1,4 @@
*~
*.bak
-/doc/*.1
-/doc/*.html
-!/doc/template.html
+/build/
/.pc/
diff --git a/Changelog b/Changelog
index f82f68b..e7b9520 100644
--- a/Changelog
+++ b/Changelog
@@ -1,3 +1,50 @@
+interimap (0.5.7) upstream;
+
+ * interimap: create database with mode 0600 (but don't change mode of
+ existing databases). The file was previously created with mode 0644
+ minus umask restrictions, which for permissive umask(2)s is too open.
+ That being said its parent directory is created with restricted mode
+ 0700 so the impact is limited. pullimap, on the other hand, already
+ used mode 0600 for state file creation.
+ * Major Makefile refactoring: improve DESTDIR= handling, add new
+ targets 'all-nodoc', 'install-nodoc', and 'installcheck'. Also,
+ rename 'test' target to 'check'.
+ * `make install` now installs Net/IMAP/InterIMAP.pm to
+ /usr/local/lib/site_perl by default rather than /usr/local/share/perl5
+ (which is not in @INC as of perl 5.34.0-3 from Debian sid). The
+ installation directory is configurable with sitelib=.
+ * Refactor test harness so one can check the source with `tests/run
+ foo`; what's been built with `INTERIMAP_I=./lib INTERIMAP_PATH=./build
+ ./tests/run foo`, and what's installed with `INTERIMAP_I=""
+ INTERIMAP_PATH=/usr/bin tests/run foo`.
+ * Split interimap and pullimap test suites.
+ + Improve message for missing untagged UIDNEXT responses, which we
+ require but are omitted from some servers.
+ + tests/tls-protocols: downgrade OpenSSL security level to 0, which is
+ required to test TLS version <1.2 on systems with higher security
+ levels, see SSL_CTX_set_security_level(3ssl). Adapted from a patch
+ from <xnox> for Unbuntu.
+ + tests/tls-*: bump Dovecot's ssl_min_protocol to TLSv1.2, which is the
+ default as of dovecot 1:2.3.18+dfsg1-1 from Debian sid.
+ + `make clean` now cleans test certificates and key material.
+ + Add 'use lib "./lib";' to interimap and pullimap, so the programs can
+ be run directly from the source directory. The directory is
+ substituted with $(sitelib) at compile time (and the line is commented
+ out if $(sitelib) is found in @INC).
+ + doc/build.md: update documentation, and add a new section for how to
+ install without root privileges.
+ + Add Documentation=https://guilhem.org/interimap/... URIs to .service
+ files.
+ - Don't hardcode path to interimap/pullimap in .service files, and
+ instead use $(bindir) (expanded at compile time).
+ - tests/certs/generate: redirect known error output to the standard
+ output.
+ - tests/certs/generate: use custom openssl.cnf to avoid depending on
+ the system default.
+ - tests/pullimap: allow easy exclusion of --idle'ing tests.
+
+ -- Guilhem Moulin <guilhem@fripost.org> Sun, 27 Feb 2022 16:24:31 +0100
+
interimap (0.5.6) upstream;
- Bump required Net::SSLeay version to 1.86_06 as it's when get_version()
diff --git a/Makefile b/Makefile
index 9f4702d..1d09ff2 100644
--- a/Makefile
+++ b/Makefile
@@ -1,80 +1,117 @@
-DESTDIR ?= /usr/local
-BUILD_DOCDIR ?= ./doc
+srcdir ?= .
+builddir ?= build
+prefix ?= /usr/local
+exec_prefix ?= $(prefix)
+bindir ?= $(exec_prefix)/bin
+libdir ?= $(exec_prefix)/lib
+sitelib ?= $(libdir)/site_perl
+datarootdir ?= $(prefix)/share
+mandir ?= $(datarootdir)/man
+man1dir ?= $(mandir)/man1
+systemd_userunitdir ?= $(libdir)/systemd/user
+
CSS ?= /usr/share/javascript/bootstrap4/css/bootstrap.css
-HTML_TEMPLATE ?= ./doc/template.html
+HTML_TEMPLATE ?= $(srcdir)/doc/template.html
-HTML_FILES = $(addprefix $(BUILD_DOCDIR)/,$(patsubst ./doc/%.md,%.html,$(wildcard ./doc/*.md)))
-MANUAL_FILES = $(addprefix $(BUILD_DOCDIR)/,$(patsubst ./doc/%.md,%,$(wildcard ./doc/*.[1-9].md)))
+PROGRAMS = $(addprefix $(builddir)/,interimap pullimap)
+HTML_FILES = $(patsubst $(srcdir)/doc/%.md,$(builddir)/doc/%.html,$(wildcard $(srcdir)/doc/*.md))
+MANUAL_FILES = $(patsubst $(srcdir)/doc/%.md,$(builddir)/doc/%,$(wildcard $(srcdir)/doc/*.[1-9].md))
+SERVICE_FILES = $(patsubst $(srcdir)/%.service,$(builddir)/%.service,$(wildcard $(srcdir)/*.service))
-all: manual
+all: all-nodoc manual
+all-nodoc: $(PROGRAMS) $(SERVICE_FILES)
+doc: manual html
manual: $(MANUAL_FILES)
html: $(HTML_FILES)
+$(PROGRAMS): $(builddir)/%: $(srcdir)/%
+ @mkdir -vp $(dir $@)
+ perl -Te "print \"\$$_\\0\" foreach @INC;" | grep -Fxzq -e "$(sitelib)" && prefix="#" || prefix=""; \
+ sed -r "0,/^(use\\s+\lib\\s+)([\"'])[^\"']*\\2\\s*;/ s||$$prefix\\1\"$(sitelib)\";|" <"$<" >"$@"
+ chmod --reference="$<" -- "$@"
+
# upper case the headers and remove the links
-$(MANUAL_FILES): $(BUILD_DOCDIR)/%: ./doc/%.md
- pandoc -f markdown -t json -- "$<" | ./pandoc2man.jq | pandoc -s -f json -t man -o "$@"
+$(MANUAL_FILES): $(builddir)/doc/%: $(srcdir)/doc/%.md
+ @mkdir -vp $(dir $@)
+ pandoc -f markdown -t json -- "$<" | $(srcdir)/pandoc2man.jq | pandoc -s -f json -t man -o "$@"
+
+$(SERVICE_FILES): $(builddir)/%.service: $(srcdir)/%.service
+ @mkdir -vp $(dir $@)
+ sed "s|@bindir@|$(bindir)|" <"$<" >"$@"
-test:
- ./tests/certs/generate
- ./tests/run-all
+testcerts:
+ $(srcdir)/tests/certs/generate
+
+check: check-interimap check-pullimap
+check-interimap: $(builddir)/interimap testcerts
+ INTERIMAP_I=$(srcdir)/lib INTERIMAP_PATH=$(builddir) $(srcdir)/tests/run-all interimap.list
+check-pullimap: $(builddir)/pullimap testcerts
+ INTERIMAP_I=$(srcdir)/lib INTERIMAP_PATH=$(builddir) $(srcdir)/tests/run-all pullimap.list
+
+installcheck: installcheck-interimap installcheck-pullimap
+installcheck-interimap: testcerts
+ INTERIMAP_I="" INTERIMAP_PATH=$(bindir) $(srcdir)/tests/run-all interimap.list
+installcheck-pullimap: testcerts
+ INTERIMAP_I="" INTERIMAP_PATH=$(bindir) $(srcdir)/tests/run-all pullimap.list
release:
- @if ! git diff HEAD --quiet -- ./Changelog ./interimap ./pullimap ./lib/Net/IMAP/InterIMAP.pm; then \
+ @if ! git -C $(srcdir) diff --quiet HEAD -- Changelog interimap pullimap lib/Net/IMAP/InterIMAP.pm; then \
echo "Dirty state, refusing to release!" >&2; \
exit 1; \
fi
- VERS=$$(dpkg-parsechangelog -l Changelog -SVersion 2>/dev/null) && \
- if git rev-parse -q --verify "refs/tags/v$$VERS" >/dev/null; then echo "tag exists" 2>/dev/null; exit 1; fi && \
- sed -ri "0,/^( -- .*) .*/ s//\\1 $(shell date -R)/" ./Changelog && \
+ VERS=$$(dpkg-parsechangelog -l $(srcdir)/Changelog -SVersion 2>/dev/null) && \
+ if git -C $(srcdir) rev-parse -q --verify "refs/tags/v$$VERS" >/dev/null; then echo "tag exists" 2>/dev/null; exit 1; fi && \
+ sed -ri "0,/^( -- .*) .*/ s//\\1 $(shell date -R)/" $(srcdir)/Changelog && \
sed -ri "0,/^(our\\s+\\\$$VERSION\\s*=\\s*)'[0-9.]+'\\s*;/ s//\\1'$$VERS';/" \
- -- ./interimap ./pullimap && \
+ -- $(srcdir)/interimap $(srcdir)/pullimap && \
sed -ri "0,/^(package\\s+Net::IMAP::InterIMAP\\s+)v[0-9.]+\\s*;/ s//\\1v$$VERS;/" \
- -- ./lib/Net/IMAP/InterIMAP.pm && \
+ -- $(srcdir)/lib/Net/IMAP/InterIMAP.pm && \
sed -ri "0,/^(use\\s+Net::IMAP::InterIMAP\\s+)[0-9.]+(\\s|\\$$)/ s//\\1$$VERS\\2/" \
- -- ./interimap ./pullimap && \
- git commit -m "Prepare new release v$$VERS." \
- -- ./Changelog ./interimap ./pullimap ./lib/Net/IMAP/InterIMAP.pm && \
- git tag -sm "Release version $$VERS" "v$$VERS"
-
-## make html CSS="https://guilhem.org/static/css/bootstrap.min.css" BUILD_DOCDIR="$XDG_RUNTIME_DIR/Downloads"
-$(HTML_FILES): $(BUILD_DOCDIR)/%.html: ./doc/%.md $(HTML_TEMPLATE)
- mtime="$$(git --no-pager log -1 --pretty="format:%ct" -- "$<" 2>/dev/null)"; \
+ -- $(srcdir)/interimap $(srcdir)/pullimap && \
+ git -C $(srcdir) commit -m "Prepare new release v$$VERS." \
+ -- Changelog interimap pullimap lib/Net/IMAP/InterIMAP.pm && \
+ git -C $(srcdir) tag -sm "Release version $$VERS" "v$$VERS"
+
+$(HTML_FILES): $(builddir)/doc/%.html: $(srcdir)/doc/%.md $(HTML_TEMPLATE)
+ @mkdir -vp $(dir $@)
+ mtime="$$(git -C $(srcdir) --no-pager log -1 --pretty="format:%ct" -- "$<" 2>/dev/null)"; \
[ -n "$$mtime" ] || mtime="$$(date +%s -r "$<")"; \
- [ "$<" = "doc/index.md" ] && parent="" || parent="./index.html"; \
pandoc -sp -f markdown -t html+smart --css=$(CSS) --template=$(HTML_TEMPLATE) \
--variable=date:"$$(LC_TIME=C date +"Last modified on %a, %d %b %Y at %T %z" -d @"$$mtime")" \
--variable=keywords:"interimap" \
--variable=lang:"en" \
- --variable=parent:"$$parent" \
+ --variable=parent:"$(if $(filter $@,$(builddir)/doc/index.html),,./index.html)" \
--output="$@" -- "$<"
-doc: manual html
+INSTALL ?= install
+INSTALL_PROGRAM ?= $(INSTALL)
+INSTALL_DATA ?= $(INSTALL) -m0644
-prefix ?= $(DESTDIR)
-exec_prefix ?= $(prefix)
-bindir ?= $(exec_prefix)/bin
-libdir ?= $(exec_prefix)/lib
-datarootdir ?= $(prefix)/share
-mandir ?= $(datarootdir)/man
-man1dir ?= $(mandir)/man1
+install: install-nodoc
+ -$(INSTALL_DATA) -vDt $(DESTDIR)$(man1dir) $(builddir)/doc/interimap.1 $(builddir)/doc/pullimap.1
+ $(INSTALL_DATA) -vDt $(DESTDIR)$(datarootdir)/doc/pullimap $(srcdir)/pullimap.sample
+ $(INSTALL_DATA) -vDt $(DESTDIR)$(datarootdir)/doc/interimap $(srcdir)/interimap.sample \
+ $(srcdir)/doc/getting-started.md $(srcdir)/doc/multi-account.md $(srcdir)/README
-install: all
- install -m0755 -vDt $(bindir) ./interimap ./pullimap
- install -m0644 -vDT ./lib/Net/IMAP/InterIMAP.pm $(datarootdir)/perl5/Net/IMAP/InterIMAP.pm
- install -m0644 -vDt $(man1dir) $(BUILD_DOCDIR)/interimap.1 $(BUILD_DOCDIR)/pullimap.1
- install -m0644 -vDt $(datarootdir)/doc/pullimap ./pullimap.sample
- install -m0644 -vDt $(datarootdir)/doc/interimap ./interimap.sample ./doc/getting-started.md ./doc/multi-account.md README
- install -m0644 -vDt $(libdir)/systemd/user ./*.service
+install-nodoc: all-nodoc
+ $(INSTALL_PROGRAM) -vDt $(DESTDIR)$(bindir) $(builddir)/interimap $(builddir)/pullimap
+ $(INSTALL_DATA) -vDT $(srcdir)/lib/Net/IMAP/InterIMAP.pm $(DESTDIR)$(sitelib)/Net/IMAP/InterIMAP.pm
+ $(INSTALL_DATA) -vDt $(DESTDIR)$(systemd_userunitdir) $(SERVICE_FILES)
uninstall:
- rm -vf -- $(bindir)/interimap $(man1dir)/interimap.1 $(libdir)/systemd/user/interimap*.service
- rm -vf -- $(bindir)/pullimap $(man1dir)/pullimap.1 $(libdir)/systemd/user/pullimap*.service
- rm -vf -- $(datarootdir)/perl5/Net/IMAP/InterIMAP.pm
- rm -rvf -- $(datarootdir)/doc/interimap $(datarootdir)/doc/pullimap
- rm -vf -- $(BUILD_DOCDIR)/interimap.1 $(BUILD_DOCDIR)/pullimap.1
+ rm -vf -- $(DESTDIR)$(bindir)/interimap $(DESTDIR)$(man1dir)/interimap.1 $(DESTDIR)$(systemd_userunitdir)/interimap*.service
+ rm -vf -- $(DESTDIR)$(bindir)/pullimap $(DESTDIR)$(man1dir)/pullimap.1 $(DESTDIR)$(systemd_userunitdir)/pullimap*.service
+ rm -vf -- $(DESTDIR)$(sitelib)/Net/IMAP/InterIMAP.pm
+ rm -rvf -- $(DESTDIR)$(datarootdir)/doc/interimap $(DESTDIR)$(datarootdir)/doc/pullimap
clean:
- rm -vf -- $(MANUAL_FILES) $(HTML_FILES)
+ rm -vf -- $(PROGRAMS) $(MANUAL_FILES) $(HTML_FILES) $(SERVICE_FILES)
+ rm -vf -- $(srcdir)/tests/certs/*.key $(srcdir)/tests/certs/*.crt $(srcdir)/tests/certs/*.pem
+ -rmdir -vp --ignore-fail-on-non-empty -- $(builddir)/doc
-.PHONY: all manual html doc test release install uninstall clean
+.PHONY: all all-nodoc manual html doc release testcerts \
+ check check-interimap check-pullimap \
+ install install-nodoc \
+ installcheck installcheck-interimap installcheck-pullimap \
+ uninstall clean
diff --git a/README b/README
index c241486..85562d4 100644
--- a/README
+++ b/README
@@ -77,6 +77,6 @@ sockets (type=imaps or type=imap).
______________________________________________________________________________
-InterIMAP is Copyright© 2015-2020 Guilhem Moulin ⟨guilhem@fripost.org⟩, and
-licensed for use under the GNU General Public License version 3 or later. See
-‘COPYING’ for specific terms and distribution information.
+InterIMAP is Copyright © 2015-2022 Guilhem Moulin ⟨guilhem@fripost.org⟩, and
+is licensed for use under the GNU General Public License version 3 or later.
+See ‘COPYING’ for specific terms and distribution information.
diff --git a/benchmark/run b/benchmark/run
index 4a83c68..650270a 100755
--- a/benchmark/run
+++ b/benchmark/run
@@ -198,9 +198,10 @@ cat >"$ROOTDIR/dev/shm/nobody/.offlineimaprc" <<-EOF
EOF
# install interimap's development version
-install -oroot -groot -m0755 -Dt "/$ROOTDIR/usr/bin" \
+install -oroot -groot -m0755 -Dt "$ROOTDIR/usr/bin" \
./interimap ./benchmark/random_maildir.pl
-install -oroot -groot -Dm0644 \
+sed -ri "0,/^(use\\s+\lib\\s+)([\"'])[^\"']*\\2\\s*;/ s||#&|" -- "$ROOTDIR/usr/bin/interimap"
+install -oroot -groot -m0644 -DT \
./lib/Net/IMAP/InterIMAP.pm "$ROOTDIR/usr/share/perl5/Net/IMAP/InterIMAP.pm"
# create a random mail store at mdbox:~/mail.back
diff --git a/doc/benchmark.md b/doc/benchmark.md
index 72f51a4..f2f6cda 100644
--- a/doc/benchmark.md
+++ b/doc/benchmark.md
@@ -48,8 +48,8 @@ by placing packet counters on the interface.
[OfflineIMAP]: https://www.offlineimap.org/
[benchmark-script]: https://git.guilhem.org/interimap/plain/benchmark/run
[Dovecot]: https://dovecot.org
-[dbox]: https://wiki.dovecot.org/MailboxFormat/dbox
-[maildir]: https://wiki.dovecot.org/MailboxFormat/Maildir
+[dbox]: https://doc.dovecot.org/admin_manual/mailbox_formats/dbox/
+[maildir]: https://doc.dovecot.org/admin_manual/mailbox_formats/maildir/
-----------------------------------------------------------------------
diff --git a/doc/build.md b/doc/build.md
index 2e4e511..b40760e 100644
--- a/doc/build.md
+++ b/doc/build.md
@@ -38,10 +38,10 @@ Additional packages are required in order to run the test suite:
$ sudo apt install dovecot-imapd dovecot-lmtpd openssl procps sqlite3 xxd
<!-- -->
- $ make test
+ $ make check
-(The test suite also needs to bind to TCP ports 10024, 10143 and 10993
-on the loopback interface.)
+(Note also that the test suite needs to bind to TCP ports 10024, 10143
+and 10993 on the loopback interface.)
Generate documentation
======================
@@ -51,32 +51,53 @@ Yet another set of packages is needed to generate the documentation:
$ sudo apt install jq pandoc
Run `` `make manual` `` (or just `` `make` ``) in order to generate the
-manpages. You'll find them at `doc/*.[1-9]`. Use for instance `` `man
--l doc/interimap.1` `` in order to read your copy of the [`interimap`(1)]
-manpage.
+manuals. You'll find them at `build/doc/*.[1-9]`. Then use for
+instance `` `man -l build/doc/interimap.1` `` to read your local copy of
+the [`interimap`(1)] manual.
-The HTML documentation can be built with `` `make html` ``. HTML files
-are generated alongside their Markdown source by default, but you can
-choose another target directory using the `HTML_ROOTDIR` environment
-variable (the value of which defaults to `./doc`). Moreover the
-[`libjs-bootstrap`](https://tracker.debian.org/libjs-bootstrap) is
-needed by default for the local CSS file; this can be controlled with
-the `CSS` environment variable (the value of which defaults to
-`/usr/share/javascript/bootstrap/css/bootstrap.min.css`).
+The HTML documentation can be built with `` `make html` ``. By default
+HTML files are generated at `build/doc/*.html`, and a local CSS file is
+used — namely `/usr/share/javascript/bootstrap4/css/bootstrap.css`,
+shipped the by [`libjs-bootstrap`](https://tracker.debian.org/libjs-bootstrap)
+package. But this is configurable: use for instance
-For instance, use
+ $ make html builddir="$XDG_RUNTIME_DIR/interimap" \
+ CSS="https://cdn.jsdelivr.net/npm/bootstrap@4.6.1/dist/css/bootstrap.min.css"
- $ env CSS="https://guilhem.org/static/css/bootstrap.min.css" \
- HTML_ROOTDIR="$XDG_RUNTIME_DIR/interimap" \
- make html
+to generate the HTML documentation under `$XDG_RUNTIME_DIR/interimap/doc`
+using a remote CSS file.
-to generate the HTML documentation under directory `$XDG_RUNTIME_DIR/interimap`
-(which needs to exist) using a remote CSS file.
-
-The `doc` target generates all documentation, manpages as well as HTML
+The `doc` target generates all documentation, manuals as well as HTML
pages.
+Installation without root privileges
+====================================
+
+By default `` `make install` `` installs [`interimap`(1)] under
+`/usr/local`, hence requires root privileges. However another prefix
+can be used in order to perform the (un)installation as an unprivileged
+user. For instance
+
+ $ install -m0700 -vd ${XDG_DATA_HOME:-~/.local/share}/interimap
+ $ make install-nodoc \
+ prefix=$HOME/.local \
+ sitelib=${XDG_DATA_HOME:-~/.local/share}/interimap/lib \
+ systemd_userunitdir=${XDG_DATA_HOME:-~/.local/share}/systemd/user
+
+skips documentation and installs
+
+ * executables into `~/.local/bin` (instead of `/usr/local/bin`);
+ * libraries into `$XDG_DATA_HOME/interimap/lib` or `~/.local/share/interimap/lib`
+ (instead of `/usr/local/lib/site_perl`); and
+ * [systemd user unit files][`systemd.unit`(5)] into `$XDG_DATA_HOME/systemd/user`
+ or `~/.local/share/systemd/user` (instead of `/usr/local/lib/systemd/user`).
+
+Note that for uninstallation one must call `` `make uninstall prefix=…` ``
+with the very same assignment(s) used for installation.
+
+[`systemd.unit`(5)]: https://www.freedesktop.org/software/systemd/man/systemd.unit.html
+
Build custom Debian packages
============================
diff --git a/doc/development.md b/doc/development.md
index f4578b9..0fe54f4 100644
--- a/doc/development.md
+++ b/doc/development.md
@@ -136,7 +136,7 @@ and `remote` accounts.
Run [`interimap`(1)] without `--watch` in order to create the database.
- $ env -i PATH="$PATH" perl -I./lib -T ./interimap --config="$BASEDIR/interimap.conf"
+ $ env -i PATH="$PATH" perl -T ./interimap --config="$BASEDIR/interimap.conf"
Creating new schema in database file …/interimap.db
database: Created mailbox INBOX
[…]
@@ -144,7 +144,7 @@ Run [`interimap`(1)] without `--watch` in order to create the database.
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" \
+ $ env -i PATH="$PATH" perl -T ./interimap --config="$BASEDIR/interimap.conf" \
--watch=1 --debug
Use instructions from the [previous section][Mail storage access]
@@ -168,12 +168,12 @@ Create a [`pullimap`(1)] configuration file with as section `[foo]`.
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" \
+ $ 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 -I./lib -T ./pullimap --config="$BASEDIR/pullimap.conf" \
+ $ 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]
@@ -194,10 +194,10 @@ recursively remove the directory `$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
+[Dovecot LDA]: https://doc.dovecot.org/configuration_manual/protocols/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
+[Maildir]: https://doc.dovecot.org/configuration_manual/mail_location/Maildir/
[RFC 2342]: https://tools.ietf.org/html/rfc2342
[Dovecot Namespaces]: https://doc.dovecot.org/configuration_manual/namespace/
[`interimap`(1)]: interimap.1.html
diff --git a/doc/getting-started.md b/doc/getting-started.md
index 74fc8da..7a77a6b 100644
--- a/doc/getting-started.md
+++ b/doc/getting-started.md
@@ -84,7 +84,7 @@ mailbox delivery) then don't disable them, and modify Dovecot's system
wide configuration instead. Same thing if your mail client isn't able
to spawn a command for IMAP communication, and instead insists on
connecting to a network socket (in that case you'll even need to
-configure [user authentication](https://wiki.dovecot.org/Authentication)
+configure [user authentication](https://doc.dovecot.org/configuration_manual/authentication/)
for the IMAP service, which is out of scope for the present document).
Run the following command to terminate and disable the system-wide
@@ -113,7 +113,8 @@ Some remarks on the above:
running `` `doveconf -nc ${XDG_CONFIG_HOME:-~/.config}/dovecot/dovecot.conf` ``.
* Messages will be stored in Maildir format under `~/Mail`. Ensure
the directory is either *empty* or *doesn't exist* before
- continuing! You may want to choose a different [format](https://wiki.dovecot.org/MailboxFormat)
+ continuing! You may want to choose a different
+ [format](https://doc.dovecot.org/admin_manual/mailbox_formats/)
here, or simply append `:LAYOUT=fs` to the `mail_location` value in
order to use a nicer (File System like) Maildir layout.
* The `separator` setting defines the IMAP hierarchy delimiter. This
diff --git a/interimap b/interimap
index 7525f9f..ac9550f 100755
--- a/interimap
+++ b/interimap
@@ -2,7 +2,7 @@
#----------------------------------------------------------------------
# Fast bidirectional synchronization for QRESYNC-capable IMAP servers
-# Copyright © 2015-2020 Guilhem Moulin <guilhem@fripost.org>
+# Copyright © 2015-2022 Guilhem Moulin <guilhem@fripost.org>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -22,17 +22,18 @@ use v5.14.2;
use strict;
use warnings;
-our $VERSION = '0.5.6';
+our $VERSION = '0.5.7';
my $NAME = 'interimap';
my $DATABASE_VERSION = 1;
use Getopt::Long qw/:config posix_default no_ignore_case gnu_compat
bundling auto_version/;
use DBI ':sql_types';
use DBD::SQLite::Constants ':file_open';
-use Fcntl qw/F_GETFD F_SETFD FD_CLOEXEC/;
+use Fcntl qw/O_WRONLY O_CREAT O_EXCL F_GETFD F_SETFD FD_CLOEXEC/;
use List::Util 'first';
-use Net::IMAP::InterIMAP 0.5.6 qw/xdg_basedir read_config compact_set/;
+use lib "./lib";
+use Net::IMAP::InterIMAP 0.5.7 qw/xdg_basedir read_config compact_set/;
# Clean up PATH
$ENV{PATH} = join ':', qw{/usr/bin /bin};
@@ -159,6 +160,12 @@ $SIG{TERM} = sub { cleanup(); exit 0; };
# Open (and maybe create) the database
{
+ # don't auto-create in long-lived mode
+ unless ($CONFIG{watch} or -e $DBFILE) {
+ sysopen(my $fh, $DBFILE, O_WRONLY | O_CREAT | O_EXCL, 0600) or die "Can't create $DBFILE: $!";
+ close $fh or warn "close: $!";
+ }
+
my $dbi_data_source = "dbi:SQLite:dbname=".$DBFILE;
my %dbi_attrs = (
AutoCommit => 0,
@@ -166,8 +173,6 @@ $SIG{TERM} = sub { cleanup(); exit 0; };
sqlite_use_immediate_transaction => 1,
sqlite_open_flags => SQLITE_OPEN_READWRITE
);
- # don't auto-create in long-lived mode
- $dbi_attrs{sqlite_open_flags} |= SQLITE_OPEN_CREATE unless defined $CONFIG{watch};
$DBH = DBI::->connect($dbi_data_source, undef, undef, \%dbi_attrs);
$DBH->sqlite_busy_timeout(250);
diff --git a/interimap.service b/interimap.service
index 6d7fa45..6abc874 100644
--- a/interimap.service
+++ b/interimap.service
@@ -1,11 +1,12 @@
[Unit]
Description=Fast bidirectional synchronization for QRESYNC-capable IMAP servers
Documentation=man:interimap(1)
+Documentation=https://guilhem.org/interimap/interimap.1.html
Wants=network-online.target
After=network-online.target
[Service]
-ExecStart=/usr/bin/interimap --watch=60
+ExecStart=@bindir@/interimap --watch=60
RestartSec=10min
Restart=on-failure
diff --git a/interimap@.service b/interimap@.service
index 6957b79..f870065 100644
--- a/interimap@.service
+++ b/interimap@.service
@@ -1,12 +1,13 @@
[Unit]
Description=Fast bidirectional synchronization for QRESYNC-capable IMAP servers (instance %i)
Documentation=man:interimap(1)
+Documentation=https://guilhem.org/interimap/interimap.1.html
PartOf=interimap.service
Wants=network-online.target
After=network-online.target
[Service]
-ExecStart=/usr/bin/interimap --config=%i --watch=60
+ExecStart=@bindir@/interimap --config=%i --watch=60
RestartSec=10min
Restart=on-failure
diff --git a/lib/Net/IMAP/InterIMAP.pm b/lib/Net/IMAP/InterIMAP.pm
index a171554..55a18a0 100644
--- a/lib/Net/IMAP/InterIMAP.pm
+++ b/lib/Net/IMAP/InterIMAP.pm
@@ -1,6 +1,6 @@
#----------------------------------------------------------------------
# A minimal IMAP4 client for QRESYNC-capable servers
-# Copyright © 2015-2020 Guilhem Moulin <guilhem@fripost.org>
+# Copyright © 2015-2022 Guilhem Moulin <guilhem@fripost.org>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -16,7 +16,7 @@
# along with this program. If not, see <https://www.gnu.org/licenses/>.
#----------------------------------------------------------------------
-package Net::IMAP::InterIMAP v0.5.6;
+package Net::IMAP::InterIMAP v0.5.7;
use v5.20.0;
use warnings;
use strict;
@@ -1312,7 +1312,8 @@ sub pull_new_messages($$&@) {
# 2^32-1: don't use '*' since the highest UID can be known already
$range .= "$since:4294967295";
- $UIDNEXT = $cache->{UIDNEXT} // $self->panic(); # sanity check
+ $UIDNEXT = $cache->{UIDNEXT} //
+ $self->panic("Unknown UIDNEXT value - non-compliant server?");
$self->fetch($range, "($attrs)", sub($) {
my $mail = shift;
$UIDNEXT = $mail->{UID} + 1 if $UIDNEXT <= $mail->{UID};
diff --git a/pullimap b/pullimap
index 6abd787..8be78da 100755
--- a/pullimap
+++ b/pullimap
@@ -2,7 +2,7 @@
#----------------------------------------------------------------------
# Pull mails from an IMAP mailbox and deliver them to an SMTP session
-# Copyright © 2016-2020 Guilhem Moulin <guilhem@fripost.org>
+# Copyright © 2016-2022 Guilhem Moulin <guilhem@fripost.org>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -22,7 +22,7 @@ use v5.20.2;
use strict;
use warnings;
-our $VERSION = '0.5.6';
+our $VERSION = '0.5.7';
my $NAME = 'pullimap';
use Errno 'EINTR';
@@ -31,7 +31,8 @@ use Getopt::Long qw/:config posix_default no_ignore_case gnu_getopt auto_version
use List::Util 'first';
use Socket qw/PF_INET PF_INET6 SOCK_STREAM IPPROTO_TCP/;
-use Net::IMAP::InterIMAP 0.5.6 qw/xdg_basedir read_config compact_set/;
+use lib "./lib";
+use Net::IMAP::InterIMAP 0.5.7 qw/xdg_basedir read_config compact_set/;
# Clean up PATH
$ENV{PATH} = join ':', qw{/usr/bin /bin};
diff --git a/pullimap@.service b/pullimap@.service
index a9ce09a..4f9518b 100644
--- a/pullimap@.service
+++ b/pullimap@.service
@@ -1,11 +1,12 @@
[Unit]
Description=Pull mails from an IMAP mailbox and deliver them to an SMTP session (instance %i)
Documentation=man:pullimap(1)
+Documentation=https://guilhem.org/interimap/pullimap.1.html
Wants=network-online.target
After=network-online.target
[Service]
-ExecStart=/usr/bin/pullimap --idle %i
+ExecStart=@bindir@/pullimap --idle %i
RestartSec=2min
Restart=always
diff --git a/tests/certs/generate b/tests/certs/generate
index de379a0..8e9c451 100755
--- a/tests/certs/generate
+++ b/tests/certs/generate
@@ -8,12 +8,20 @@ BASEDIR="$(dirname -- "$0")"
OU="InterIMAP test suite"
cd "$BASEDIR"
+OPENSSL_CONF="./openssl.cnf"
+export OPENSSL_CONF
+
cadir="$(mktemp --tmpdir --directory)"
trap 'rm -rf -- "$cadir"' EXIT INT TERM
+genpkey() {
+ local key="$1"
+ shift
+ openssl genpkey -out "$key" "$@" 2>&1
+}
# generate CA (we intentionally throw away the private key and serial
# file to avoid reuse)
-openssl genpkey -algorithm RSA -out "$cadir/ca.key"
+genpkey "$cadir/ca.key" -algorithm RSA
openssl req -new -x509 -rand /dev/urandom -subj "/OU=$OU/CN=Fake Root CA" -key "$cadir/ca.key" -out ./ca.crt
SERIAL=1
@@ -31,14 +39,14 @@ new() {
printf "subjectAltName = %s\\n" "$3" >>"$cadir/new-ext.cnf"
fi
openssl x509 -req -in "$cadir/new.csr" -CA ./ca.crt -CAkey "$cadir/ca.key" \
- -CAserial "$cadir/ca.srl" -CAcreateserial -extfile "$cadir/new-ext.cnf"
+ -CAserial "$cadir/ca.srl" -CAcreateserial -extfile "$cadir/new-ext.cnf" 2>&1
}
-openssl genpkey -algorithm RSA -out ./dovecot.rsa.key
+genpkey ./dovecot.rsa.key -algorithm RSA
new ./dovecot.rsa.key "localhost" "DNS:localhost,DNS:ip6-localhost,IP:127.0.0.1,IP:::1" >./dovecot.rsa.crt
-openssl genpkey -algorithm EC -pkeyopt ec_paramgen_curve:P-256 -pkeyopt ec_param_enc:named_curve -out ./dovecot.ecdsa.key
+genpkey ./dovecot.ecdsa.key -algorithm EC -pkeyopt ec_paramgen_curve:P-256 -pkeyopt ec_param_enc:named_curve
new ./dovecot.ecdsa.key "localhost" >./dovecot.ecdsa.crt
-openssl genpkey -algorithm RSA -out ./dovecot.rsa2.key
+genpkey ./dovecot.rsa2.key -algorithm RSA
new ./dovecot.rsa2.key "imap.example.net" "DNS:imap.example.net,DNS:localhost" >./dovecot.rsa2.crt
diff --git a/tests/certs/openssl.cnf b/tests/certs/openssl.cnf
new file mode 100644
index 0000000..b1af7b8
--- /dev/null
+++ b/tests/certs/openssl.cnf
@@ -0,0 +1,4 @@
+[ req ]
+distinguished_name = req_distinguished_name
+
+[ req_distinguished_name ]
diff --git a/tests/config/dovecot/ssl.conf b/tests/config/dovecot/ssl.conf
index 3fd99d5..1f3a698 100644
--- a/tests/config/dovecot/ssl.conf
+++ b/tests/config/dovecot/ssl.conf
@@ -2,4 +2,5 @@ ssl = required
ssl_cert = <dovecot.rsa.crt
ssl_key = <dovecot.rsa.key
ssl_dh = <dhparams.pem
-ssl_min_protocol = TLSv1
+ssl_min_protocol = TLSv1.2
+ssl_cipher_list = DEFAULT@SECLEVEL=2
diff --git a/tests/db-exclusive-lock/t b/tests/db-exclusive-lock/t
index c2df4b5..837d21b 100644
--- a/tests/db-exclusive-lock/t
+++ b/tests/db-exclusive-lock/t
@@ -10,7 +10,7 @@ sleep .5
# subsequent runs fail as we can't acquire the exclusive lock
! interimap || error
-grep -Fx "DBD::SQLite::db do failed: database is locked at ./interimap line 176." <"$STDERR" \
- || error "Is \$DBH->do(\"PRAGMA locking_mode = EXCLUSIVE\"); at line 176?"
+grep -Ex "DBD::SQLite::db do failed: database is locked at (\S+/)?interimap line 181\." <"$STDERR" \
+ || error "Is \$DBH->do(\"PRAGMA locking_mode = EXCLUSIVE\"); at line 181?"
# vim: set filetype=sh :
diff --git a/tests/db-no-create--watch/t b/tests/db-no-create--watch/t
index a8ea07e..37fc6cb 100644
--- a/tests/db-no-create--watch/t
+++ b/tests/db-no-create--watch/t
@@ -1,6 +1,6 @@
! interimap --watch=60 || error
-grep -Ex "DBI connect\(.*\) failed: unable to open database file at \./interimap line 172\." <"$STDERR" || error
+grep -Ex "DBI connect\(.*\) failed: unable to open database file at (\S+/)?interimap line 177\." <"$STDERR" || error
test \! -e "$XDG_DATA_HOME/interimap/remote.db" || error
# vim: set filetype=sh :
diff --git a/tests/list b/tests/interimap.list
index d1058ba..559daed 100644
--- a/tests/list
+++ b/tests/interimap.list
@@ -61,6 +61,3 @@ split-set Split large sets to avoid extra-long command lines
sync-live-crippled local/remote simulation (crippled remote)
sync-live-tls local/remote simulation (TLS remote)
sync-live-multi local/remote1+remote2+remote3 simulation (3 local namespaces)
-
-. pullimap
- ... pullimap
diff --git a/tests/pullimap.list b/tests/pullimap.list
new file mode 100644
index 0000000..f4304b9
--- /dev/null
+++ b/tests/pullimap.list
@@ -0,0 +1,2 @@
+. pullimap
+ ... pullimap
diff --git a/tests/pullimap/t b/tests/pullimap/t
index 0dfe634..58a19ca 100644
--- a/tests/pullimap/t
+++ b/tests/pullimap/t
@@ -6,6 +6,13 @@ step_start "\`pullimap --idle\` refuses to create the state file"
! pullimap --idle "remote" || error
step_done
+step_start "\`pullimap\` creates statefile with mode 0600"
+pullimap "remote" || error
+if ! st="$(stat -c"%#a" -- "$XDG_DATA_HOME/pullimap/remote")" || [ "$st" != "0600" ]; then
+ error "$XDG_DATA_HOME/pullimap/remote has mode $st != 0600"
+fi
+step_done
+
# compare mailboxes (can't compare the RFC 3501 TEXT as the LMTPd inconditionally
# adds a Return-Path: header -- and also Delivered-To: and Received: to by default)
list_mails_sha256() {
@@ -104,29 +111,31 @@ doveadm -u "remote" search mailbox "$MAILBOX" unseen >"$TMPDIR/unseen"
step_done
-step_start "--idle (${TIMEOUT}s)"
+if [ $TIMEOUT -gt 0 ]; then
+ step_start "--idle (${TIMEOUT}s)"
-pullimap --idle "remote" & PID=$!
-trap "ptree_abort $PID" EXIT INT TERM
+ pullimap --idle "remote" & PID=$!
+ trap "ptree_abort $PID" EXIT INT TERM
-timer=$(( $(date +%s) + TIMEOUT ))
-while [ $(date +%s) -le $timer ]; do
- n="$(shuf -n1 -i1-5)"
- for (( i=0; i < n; i++)); do
- sample_message | deliver -u "remote" -- -m "$MAILBOX"
- done
+ timer=$(( $(date +%s) + TIMEOUT ))
+ while [ $(date +%s) -le $timer ]; do
+ n="$(shuf -n1 -i1-5)"
+ for (( i=0; i < n; i++)); do
+ sample_message | deliver -u "remote" -- -m "$MAILBOX"
+ done
- s=$(shuf -n1 -i1-1500)
- [ $s -ge 1000 ] && s="$(printf "1.%03d" $((s-1000)))" || s="$(printf "0.%03d" $s)"
- sleep "$s"
-done
+ s=$(shuf -n1 -i1-1500)
+ [ $s -ge 1000 ] && s="$(printf "1.%03d" $((s-1000)))" || s="$(printf "0.%03d" $s)"
+ sleep "$s"
+ done
-sleep 5
-ptree_abort $PID
-trap - EXIT INT TERM
+ sleep 5
+ ptree_abort $PID
+ trap - EXIT INT TERM
-check
-step_done
+ check
+ step_done
+fi
step_start "Purging"
diff --git a/tests/run b/tests/run
index 1eaad54..eed77df 100755
--- a/tests/run
+++ b/tests/run
@@ -38,6 +38,12 @@ fi
# cleanup environment
unset OPENSSL_CONF SSL_CERT_FILE SSL_CERT_DIR
+if [ -z "${INTERIMAP_PATH+x}" ]; then
+ INTERIMAP_PATH="./"
+elif [ -n "$INTERIMAP_PATH" ]; then
+ INTERIMAP_PATH="${INTERIMAP_PATH%/}/"
+fi
+
ROOTDIR="$(mktemp --tmpdir="${TMPDIR:-/dev/shm}" --directory "$1.XXXXXXXXXX")"
declare -a DOVECOT_SERVER=()
trap cleanup EXIT INT TERM
@@ -206,26 +212,32 @@ prepare
interimap() { _interimap_cmd "interimap" "$@"; }
pullimap() { _interimap_cmd "pullimap" "$@"; }
_interimap_cmd() {
- declare -a ENVIRON=()
+ declare -a ENVIRON=() args=()
local script="$1" rv=0
shift
environ_set "local"
[ -z "${OPENSSL_CONF+x}" ] || ENVIRON+=( OPENSSL_CONF="$OPENSSL_CONF" )
[ -z "${SSL_CERT_FILE+x}" ] || ENVIRON+=( SSL_CERT_FILE="$SSL_CERT_FILE" )
[ -z "${SSL_CERT_DIR+x}" ] || ENVIRON+=( SSL_CERT_DIR="$SSL_CERT_DIR" )
- env -i "${ENVIRON[@]}" perl -I./lib -T "./$script" "$@" 2>"$STDERR" || rv=$?
+ [ -z "${INTERIMAP_I:+x}" ] || args+=( perl -I"$INTERIMAP_I" -T )
+ args+=( "$INTERIMAP_PATH$script" "$@" )
+ #printf "I: Running \`%s\`\\n" "${args[*]}" >&3
+ env -i "${ENVIRON[@]}" "${args[@]}" 2>"$STDERR" || rv=$?
cat <"$STDERR" >&2
return $rv
}
interimap_init() {
local u="${1-remote}"
- local db="$XDG_DATA_HOME/interimap/$u.db"
+ local db="$XDG_DATA_HOME/interimap/$u.db" st
local cfg="config${u#remote}"
test \! -e "$db" || error "Database already exists" 1
interimap --config "$cfg" || error "Couldn't initialize interimap" 1
test -f "$db" || error "Database is still missing" 1
grep -Fx "Creating new schema in database file $db" <"$STDERR" || error "DB wasn't created" 1
+ if ! st="$(stat -c"%#a" -- "$db")" || [ "$st" != "0600" ]; then
+ error "$db has mode $st != 0600" 1
+ fi
}
doveadm() {
if [ $# -le 2 ] || [ "$1" != "-u" ]; then
@@ -449,7 +461,7 @@ passed() {
# Run test in a sub-shell
declare -a ENVIRON=()
environ_set "local"
-export TMPDIR TESTDIR STDERR "${ENVIRON[@]}"
+export TMPDIR TESTDIR INTERIMAP_PATH INTERIMAP_I STDERR "${ENVIRON[@]}"
export -f environ_set doveadm interimap interimap_init pullimap _interimap_cmd
export -f sqlite3 sample_message deliver ptree_abort step_start step_done passed
export -f check_mailbox_status check_mailbox_status_values check_mailbox_status2
diff --git a/tests/run-all b/tests/run-all
index d13f689..79e62d1 100755
--- a/tests/run-all
+++ b/tests/run-all
@@ -24,6 +24,7 @@ export PATH
BASEDIR="$(dirname -- "$0")"
RUN="$BASEDIR/run"
+list="$1"
failed=0
@@ -54,7 +55,7 @@ while IFS="" read -r x; do
fi
INDENT="$indent" "$RUN" "$t" ${desc+"$desc"} || failed=$(( failed+1 ))
-done <"$BASEDIR/list"
+done <"$BASEDIR/$list"
if [ $failed -eq 0 ]; then
printf "All tests passed.\\n"
diff --git a/tests/tls-protocols/openssl.cnf b/tests/tls-protocols/openssl.cnf
index 980097d..3d9769d 100644
--- a/tests/tls-protocols/openssl.cnf
+++ b/tests/tls-protocols/openssl.cnf
@@ -11,4 +11,4 @@ system_default = system_default_sect
[system_default_sect]
MinProtocol = None
-CipherString = DEFAULT
+CipherString = DEFAULT@SECLEVEL=0
diff --git a/tests/tls-protocols/remote.conf b/tests/tls-protocols/remote.conf
index 6029749..96b3713 120000..100644
--- a/tests/tls-protocols/remote.conf
+++ b/tests/tls-protocols/remote.conf
@@ -1 +1,4 @@
-../tls/remote.conf \ No newline at end of file
+!include conf.d/imapd.conf
+!include conf.d/ssl.conf
+ssl_min_protocol = TLSv1
+ssl_cipher_list = DEFAULT@SECLEVEL=0
diff --git a/tests/tls-rsa+ecdsa/t b/tests/tls-rsa+ecdsa/t
index c9f5b96..fd2b1be 100644
--- a/tests/tls-rsa+ecdsa/t
+++ b/tests/tls-rsa+ecdsa/t
@@ -28,7 +28,7 @@ interimap_init
check_mailbox_status "INBOX"
interimap --debug || error
-# which peer certificate is used is up to libssl
+# which peer certificate is used is up to libssl
grep -Fx -e "remote: Peer certificate fingerprint: sha256\$$X509_SHA256" \
-e "remote: Peer certificate fingerprint: sha256\$$X509_ALT_SHA256" \
<"$STDERR" || error