diff --git a/Dockerfile b/Dockerfile index 0c021ea0..5eb466e1 100644 --- a/Dockerfile +++ b/Dockerfile @@ -73,6 +73,8 @@ RUN sed -i 's/#imap_idle_notify_interval = 2 mins/imap_idle_notify_interval = 29 COPY target/dovecot/auth-passwdfile.inc /etc/dovecot/conf.d/ COPY target/dovecot/??-*.conf /etc/dovecot/conf.d/ RUN cd /usr/share/dovecot && ./mkcert.sh +RUN mkdir /usr/lib/dovecot/sieve-pipe && chmod 755 /usr/lib/dovecot/sieve-pipe +RUN mkdir /usr/lib/dovecot/sieve-filter && chmod 755 /usr/lib/dovecot/sieve-filter # Configures LDAP COPY target/dovecot/dovecot-ldap.conf.ext /etc/dovecot diff --git a/Makefile b/Makefile index 286fe70b..ede3f53c 100644 --- a/Makefile +++ b/Makefile @@ -157,6 +157,7 @@ fixtures: docker exec mail /bin/sh -c "nc 0.0.0.0 25 < /tmp/docker-mailserver-test/email-templates/existing-regexp-alias-local.txt" docker exec mail /bin/sh -c "nc 0.0.0.0 25 < /tmp/docker-mailserver-test/email-templates/existing-catchall-local.txt" docker exec mail /bin/sh -c "nc 0.0.0.0 25 < /tmp/docker-mailserver-test/email-templates/sieve-spam-folder.txt" + docker exec mail /bin/sh -c "nc 0.0.0.0 25 < /tmp/docker-mailserver-test/email-templates/sieve-pipe.txt" docker exec mail /bin/sh -c "nc 0.0.0.0 25 < /tmp/docker-mailserver-test/email-templates/non-existing-user.txt" docker exec mail_disabled_clamav_spamassassin /bin/sh -c "nc 0.0.0.0 25 < /tmp/docker-mailserver-test/email-templates/existing-user1.txt" # postfix virtual transport lmtp diff --git a/target/dovecot/90-sieve.conf b/target/dovecot/90-sieve.conf new file mode 100644 index 00000000..5e53df72 --- /dev/null +++ b/target/dovecot/90-sieve.conf @@ -0,0 +1,111 @@ +## +## Settings for the Sieve interpreter +## + +# Do not forget to enable the Sieve plugin in 15-lda.conf and 20-lmtp.conf +# by adding it to the respective mail_plugins= settings. + +plugin { + # The path to the user's main active script. If ManageSieve is used, this the + # location of the symbolic link controlled by ManageSieve. + sieve = ~/.dovecot.sieve + + # The default Sieve script when the user has none. This is a path to a global + # sieve script file, which gets executed ONLY if user's private Sieve script + # doesn't exist. Be sure to pre-compile this script manually using the sievec + # command line tool. + # --> See sieve_before fore executing scripts before the user's personal + # script. + #sieve_default = /var/lib/dovecot/sieve/default.sieve + + # Directory for :personal include scripts for the include extension. This + # is also where the ManageSieve service stores the user's scripts. + sieve_dir = ~/sieve + + # Directory for :global include scripts for the include extension. + #sieve_global_dir = + + # Path to a script file or a directory containing script files that need to be + # executed before the user's script. If the path points to a directory, all + # the Sieve scripts contained therein (with the proper .sieve extension) are + # executed. The order of execution within a directory is determined by the + # file names, using a normal 8bit per-character comparison. Multiple script + # file or directory paths can be specified by appending an increasing number. + #sieve_before = + #sieve_before2 = + #sieve_before3 = (etc...) + + # Identical to sieve_before, only the specified scripts are executed after the + # user's script (only when keep is still in effect!). Multiple script file or + # directory paths can be specified by appending an increasing number. + #sieve_after = + #sieve_after2 = + #sieve_after2 = (etc...) + + # Which Sieve language extensions are available to users. By default, all + # supported extensions are available, except for deprecated extensions or + # those that are still under development. Some system administrators may want + # to disable certain Sieve extensions or enable those that are not available + # by default. This setting can use '+' and '-' to specify differences relative + # to the default. For example `sieve_extensions = +imapflags' will enable the + # deprecated imapflags extension in addition to all extensions were already + # enabled by default. + #sieve_extensions = +notify +imapflags + sieve_extensions = +notify +imapflags +vnd.dovecot.pipe +vnd.dovecot.filter + + # Which Sieve language extensions are ONLY available in global scripts. This + # can be used to restrict the use of certain Sieve extensions to administrator + # control, for instance when these extensions can cause security concerns. + # This setting has higher precedence than the `sieve_extensions' setting + # (above), meaning that the extensions enabled with this setting are never + # available to the user's personal script no matter what is specified for the + # `sieve_extensions' setting. The syntax of this setting is similar to the + # `sieve_extensions' setting, with the difference that extensions are + # enabled or disabled for exclusive use in global scripts. Currently, no + # extensions are marked as such by default. + #sieve_global_extensions = + + # The Pigeonhole Sieve interpreter can have plugins of its own. Using this + # setting, the used plugins can be specified. Check the Dovecot wiki + # (wiki2.dovecot.org) or the pigeonhole website + # (http://pigeonhole.dovecot.org) for available plugins. + # The sieve_extprograms plugin is included in this release. + #sieve_plugins = + sieve_plugins = sieve_extprograms + + # The separator that is expected between the :user and :detail + # address parts introduced by the subaddress extension. This may + # also be a sequence of characters (e.g. '--'). The current + # implementation looks for the separator from the left of the + # localpart and uses the first one encountered. The :user part is + # left of the separator and the :detail part is right. This setting + # is also used by Dovecot's LMTP service. + #recipient_delimiter = + + + # The maximum size of a Sieve script. The compiler will refuse to compile any + # script larger than this limit. If set to 0, no limit on the script size is + # enforced. + #sieve_max_script_size = 1M + + # The maximum number of actions that can be performed during a single script + # execution. If set to 0, no limit on the total number of actions is enforced. + #sieve_max_actions = 32 + + # The maximum number of redirect actions that can be performed during a single + # script execution. If set to 0, no redirect actions are allowed. + #sieve_max_redirects = 4 + + # The maximum number of personal Sieve scripts a single user can have. If set + # to 0, no limit on the number of scripts is enforced. + # (Currently only relevant for ManageSieve) + #sieve_quota_max_scripts = 0 + + # The maximum amount of disk storage a single user's scripts may occupy. If + # set to 0, no limit on the used amount of disk storage is enforced. + # (Currently only relevant for ManageSieve) + #sieve_quota_max_storage = 0 + + # Locations of programs that can be called by the sieve_extprograms plugin + sieve_pipe_bin_dir = /usr/lib/dovecot/sieve-pipe + sieve_filter_bin_dir = /usr/lib/dovecot/sieve-filter +} diff --git a/target/start-mailserver.sh b/target/start-mailserver.sh index 1e2e1229..067196d0 100644 --- a/target/start-mailserver.sh +++ b/target/start-mailserver.sh @@ -484,6 +484,20 @@ function _setup_dovecot() { notify 'inf' "Sieve management enabled" mv /etc/dovecot/protocols.d/managesieved.protocol.disab /etc/dovecot/protocols.d/managesieved.protocol fi + + # Copy pipe and filter programs, if any + rm -f /usr/lib/dovecot/sieve-filter/* + rm -f /usr/lib/dovecot/sieve-pipe/* + if [ -d /tmp/docker-mailserver/sieve-filter ]; then + cp /tmp/docker-mailserver/sieve-filter/* /usr/lib/dovecot/sieve-filter/ + chown docker:docker /usr/lib/dovecot/sieve-filter/* + chmod 550 /usr/lib/dovecot/sieve-filter/* + fi + if [ -d /tmp/docker-mailserver/sieve-pipe ]; then + cp /tmp/docker-mailserver/sieve-pipe/* /usr/lib/dovecot/sieve-pipe/ + chown docker:docker /usr/lib/dovecot/sieve-pipe/* + chmod 550 /usr/lib/dovecot/sieve-pipe/* + fi } function _setup_dovecot_local_user() { diff --git a/test/config/sieve-pipe/pipe_to_tmp b/test/config/sieve-pipe/pipe_to_tmp new file mode 100644 index 00000000..e34e9d51 --- /dev/null +++ b/test/config/sieve-pipe/pipe_to_tmp @@ -0,0 +1,2 @@ +#!/bin/bash +cat - > /tmp/pipe-test.out diff --git a/test/config/user2@otherdomain.tld.dovecot.sieve b/test/config/user2@otherdomain.tld.dovecot.sieve new file mode 100644 index 00000000..ba048df9 --- /dev/null +++ b/test/config/user2@otherdomain.tld.dovecot.sieve @@ -0,0 +1,4 @@ +require ["copy", "vnd.dovecot.pipe"]; +if header :contains "subject" "Sieve pipe test message" { + pipe :copy "pipe_to_tmp"; +} diff --git a/test/email-templates/sieve-pipe.txt b/test/email-templates/sieve-pipe.txt new file mode 100644 index 00000000..15e56e96 --- /dev/null +++ b/test/email-templates/sieve-pipe.txt @@ -0,0 +1,12 @@ +HELO mail.external.tld +MAIL FROM: user@external.tld +RCPT TO: user2@otherdomain.tld +DATA +From: Sieve-pipe-test +To: Existing Local User +Date: Sat, 22 May 2010 07:43:25 -0400 +Subject: Sieve pipe test message +This is a test mail to sieve pipe. + +. +QUIT \ No newline at end of file diff --git a/test/tests.bats b/test/tests.bats index 27dbc56f..3114ca2d 100644 --- a/test/tests.bats +++ b/test/tests.bats @@ -271,7 +271,7 @@ load 'test_helper/bats-assert/load' @test "checking smtp: delivers mail to existing account" { run docker exec mail /bin/sh -c "grep 'postfix/lmtp' /var/log/mail/mail.log | grep 'status=sent' | grep ' Saved)' | wc -l" assert_success - assert_output 8 + assert_output 9 } @test "checking smtp: delivers mail to existing alias" { @@ -792,6 +792,12 @@ load 'test_helper/bats-assert/load' assert_failure } +@test "checking sieve: user2 should have piped 1 email to /tmp/" { + run docker exec mail /bin/sh -c "ls -A /tmp/pipe-test.out | wc -l" + assert_success + assert_output 1 +} + # # accounts #