added dovecot quota feature

add postfix service quota check


check-for-changes on quotas


setquota command


fix checkforchanges quota


addquota verify user exists


add setquota in setup.sh


merging addquota into setquota


test quota commands


add ldap tests for dovecot quota


fix smtp only quota postfix rules


test postfix conf


add quota test integration


add quota exceeded test


add wait analyze


fix tests


fix setup typo


add test fixes


fix error output


wip


update startup rules


fix setup


fix setup tests


fix output commands


remove quota on remove user


try to fix sync limit mails


check if file exists


fix path


change used quota user


fix post size


check if quota file exists


update tests


configure virtualmailbox limit for dovecot


last fix


fix quota expr


relax dovecot tests


auto create dovecot-quotas


fix dovecot apply quota test


wip quota warning


trying to fix get dovadm quota


dovecot applies fix


fix quota warning lda path


test count mail on quota


fix quota warning permissiosn


fix test
This commit is contained in:
youtous 2020-04-24 14:55:32 +02:00
parent 6cb3069c60
commit 2527ebfaf2
No known key found for this signature in database
GPG key ID: 592173AE8CD254A5
17 changed files with 581 additions and 11 deletions

View file

@ -124,6 +124,7 @@ RUN echo "0 */6 * * * clamav /usr/bin/freshclam --quiet" > /etc/cron.d/clamav-fr
# Configures Dovecot # Configures Dovecot
COPY target/dovecot/auth-passwdfile.inc target/dovecot/??-*.conf /etc/dovecot/conf.d/ COPY target/dovecot/auth-passwdfile.inc target/dovecot/??-*.conf /etc/dovecot/conf.d/
COPY target/dovecot/scripts/quota-warning.sh /usr/local/bin/quota-warning.sh
WORKDIR /usr/share/dovecot WORKDIR /usr/share/dovecot
# hadolint ignore=SC2016,SC2086 # hadolint ignore=SC2016,SC2086
RUN sed -i -e 's/include_try \/usr\/share\/dovecot\/protocols\.d/include_try \/etc\/dovecot\/protocols\.d/g' /etc/dovecot/dovecot.conf && \ RUN sed -i -e 's/include_try \/usr\/share\/dovecot\/protocols\.d/include_try \/etc\/dovecot\/protocols\.d/g' /etc/dovecot/dovecot.conf && \

View file

@ -155,4 +155,4 @@ clean:
sudo rm -rf test/config ;\ sudo rm -rf test/config ;\
mv testconfig.bak test/config ;\ mv testconfig.bak test/config ;\
fi fi
-sudo rm -rf test/onedir test/alias test/relay test/config/dovecot-lmtp/userdb test/config/key* test/config/opendkim/keys/domain.tld/ test/config/opendkim/keys/example.com/ test/config/opendkim/keys/localdomain2.com/ test/config/postfix-aliases.cf test/config/postfix-receive-access.cf test/config/postfix-receive-access.cfe test/config/postfix-send-access.cf test/config/postfix-send-access.cfe test/config/relay-hosts/chksum test/config/relay-hosts/postfix-aliases.cf -sudo rm -rf test/onedir test/alias test/quota test/relay test/config/dovecot-lmtp/userdb test/config/key* test/config/opendkim/keys/domain.tld/ test/config/opendkim/keys/example.com/ test/config/opendkim/keys/localdomain2.com/ test/config/postfix-aliases.cf test/config/postfix-receive-access.cf test/config/postfix-receive-access.cfe test/config/dovecot-quotas.cf test/config/postfix-send-access.cf test/config/postfix-send-access.cfe test/config/relay-hosts/chksum test/config/relay-hosts/postfix-aliases.cf

3
config/dovecot-quotas.cf Normal file
View file

@ -0,0 +1,3 @@
# define user's quota in this file
# E.g;
# user@domain:50M

View file

@ -8,7 +8,7 @@ CRI=
_check_root() { _check_root() {
if [[ $EUID -ne 0 ]]; then if [[ $EUID -ne 0 ]]; then
echo "Curently docker-mailserver doesn't support podman's rootless mode, please run this script as root user." echo "Curently docker-mailserver doesn't support podman's rootless mode, please run this script as root user."
exit 1 exit 1
fi fi
} }
@ -75,7 +75,7 @@ _usage() {
OPTIONS: OPTIONS:
-i IMAGE_NAME The name of the docker-mailserver image, by default -i IMAGE_NAME The name of the docker-mailserver image, by default
'tvial/docker-mailserver:latest' for docker, and 'tvial/docker-mailserver:latest' for docker, and
'docker.io/tvial/docker-mailserver:latest' for podman. 'docker.io/tvial/docker-mailserver:latest' for podman.
-c CONTAINER_NAME The name of the running container. -c CONTAINER_NAME The name of the running container.
@ -97,6 +97,10 @@ SUBCOMMANDS:
$0 alias del <email> <recipient> $0 alias del <email> <recipient>
$0 alias list $0 alias list
quota:
$0 quota set <email> [<quota>]
$0 quota del <email>
config: config:
$0 config dkim <keysize> (default: 2048) $0 config dkim <keysize> (default: 2048)
@ -252,6 +256,23 @@ case $1 in
esac esac
;; ;;
quota)
shift
case $1 in
set)
shift
_docker_image setquota $@
;;
del)
shift
_docker_image delquota $@
;;
*)
_usage
;;
esac
;;
config) config)
shift shift
case $1 in case $1 in

View file

@ -2,6 +2,7 @@
DATABASE=${DATABASE:-/tmp/docker-mailserver/postfix-accounts.cf} DATABASE=${DATABASE:-/tmp/docker-mailserver/postfix-accounts.cf}
ALIAS_DATABASE="/tmp/docker-mailserver/postfix-virtual.cf" ALIAS_DATABASE="/tmp/docker-mailserver/postfix-virtual.cf"
QUOTA_DATABASE="/tmp/docker-mailserver/dovecot-quotas.cf"
usage() { usage() {
echo "Usage: delmailuser <-y> <user@domain> <user2@anotherdomain> ..." echo "Usage: delmailuser <-y> <user@domain> <user2@anotherdomain> ..."
@ -51,6 +52,11 @@ shift $((OPTIND-1))
-e "s/,"$USER"//g" \ -e "s/,"$USER"//g" \
-e "s/"$USER",//g" $ALIAS_DATABASE -e "s/"$USER",//g" $ALIAS_DATABASE
[ $? = 0 ] && echo "$USER and potential aliases deleted." || errex "Aliases for $USER couldn't be deleted in $ALIAS_DATABASE. $?" [ $? = 0 ] && echo "$USER and potential aliases deleted." || errex "Aliases for $USER couldn't be deleted in $ALIAS_DATABASE. $?"
# remove quota directives
if [ -f "$QUOTA_DATABASE" ]; then
sed -i -e "/^$USER:.*$/d" $QUOTA_DATABASE || errex "Quota for $USER couldn't be deleted in $QUOTA_DATABASE. $?"
fi
if [ "$MAILDEL" != "y" ]; then if [ "$MAILDEL" != "y" ]; then
read -p "Do you want to delete the mailbox as well(all mails will be removed)?(y/n) " MAILDEL read -p "Do you want to delete the mailbox as well(all mails will be removed)?(y/n) " MAILDEL
echo echo

28
target/bin/delquota Executable file
View file

@ -0,0 +1,28 @@
#! /bin/bash
DATABASE=${DATABASE:-/tmp/docker-mailserver/dovecot-quotas.cf}
USER_DATABASE=${USER_DATABASE:-/tmp/docker-mailserver/postfix-accounts.cf}
USER="$1"
usage() {
echo "Usage: delquota <username@domain>"
}
errex() {
echo "$@" 1>&2
exit 1
}
escape() {
echo "${1//./\\.}"
}
[ -z "$USER" ] && { usage; errex "No username specified"; }
expr index "$USER" "@" >/dev/null || { usage; errex "username must include the domain"; }
if ! grep -qE "^$USER\|" "$USER_DATABASE"; then
usage; errex "user $USER does not exist"
fi
[ -s "$DATABASE" ] || exit 0
sed -i -e "/^$USER:.*$/d" $DATABASE

49
target/bin/setquota Executable file
View file

@ -0,0 +1,49 @@
#! /bin/bash
DATABASE=${DATABASE:-/tmp/docker-mailserver/dovecot-quotas.cf}
USER_DATABASE=${USER_DATABASE:-/tmp/docker-mailserver/postfix-accounts.cf}
USER="$1"
shift
QUOTA="$@"
usage() {
echo "Usage: setquota <user@domain> [<quota>]"
}
errex() {
echo "$@" 1>&2
exit 1
}
[ -z "$USER" ] && { usage; errex "no username specified"; }
expr index "$USER" "@" >/dev/null || { usage; errex "username must include the domain"; }
if ! grep -qE "^$USER\|" "$USER_DATABASE"; then
usage; errex "user $USER does not exist"
fi
# check quota
if [ -n "$QUOTA" ] && ! echo "$QUOTA" | grep -qE "^([0-9]+(B|k|M|G|T)|0)\$"; then
usage; errex "invalid quota format. e.g. 302M (B (byte), k (kilobyte), M (megabyte), G (gigabyte) or T (terabyte))"
fi
# Protect config file with lock to avoid race conditions
touch $DATABASE
(
flock -e 200
if [ -z "$QUOTA" ]; then
read -s "Enter quota (e.g. 10M): " QUOTA
echo
[ -z "$QUOTA" ] && errex "Quota must not be empty. Use 0 for unlimited quota"
fi
# check quota
if [ -n "$QUOTA" ] && ! echo "$QUOTA" | grep -qE "^([0-9]+(B|k|M|G|T)|0)\$"; then
usage; errex "invalid quota format. e.g. 302M (B (byte), k (kilobyte), M (megabyte), G (gigabyte) or T (terabyte))"
fi
delquota "$USER"
echo "$USER:$QUOTA" >> $DATABASE
) 200<$DATABASE

View file

@ -32,7 +32,7 @@ echo "${log_date} Using postmaster address ${PM_ADDRESS}"
# Create an array of files to monitor, must be the same as in start-mailserver.sh # Create an array of files to monitor, must be the same as in start-mailserver.sh
declare -a cf_files=() declare -a cf_files=()
for file in postfix-accounts.cf postfix-virtual.cf postfix-aliases.cf; do for file in postfix-accounts.cf postfix-virtual.cf postfix-aliases.cf dovecot-quotas.cf; do
[ -f "$file" ] && cf_files+=("$file") [ -f "$file" ] && cf_files+=("$file")
done done
@ -119,14 +119,26 @@ if [[ $chksum == *"FAIL"* ]]; then
# Setting variables for better readability # Setting variables for better readability
user=$(echo ${login} | cut -d @ -f1) user=$(echo ${login} | cut -d @ -f1)
domain=$(echo ${login} | cut -d @ -f2) domain=$(echo ${login} | cut -d @ -f2)
user_attributes=""
# test if user has a defined quota
if [ -f /tmp/docker-mailserver/dovecot-quotas.cf ]; then
user_quota=($(grep "${user}@${domain}:" -i /tmp/docker-mailserver/dovecot-quotas.cf | tr ':' '\n'))
if [ ${#user_quota[@]} -eq 2 ]; then
user_attributes="${user_attributes}userdb_quota_rule=*:bytes=${user_quota[1]}"
fi
fi
# Let's go! # Let's go!
echo "${login} ${domain}/${user}/" >> /etc/postfix/vmailbox echo "${login} ${domain}/${user}/" >> /etc/postfix/vmailbox
# User database for dovecot has the following format: # User database for dovecot has the following format:
# user:password:uid:gid:(gecos):home:(shell):extra_fields # user:password:uid:gid:(gecos):home:(shell):extra_fields
# Example : # Example :
# ${login}:${pass}:5000:5000::/var/mail/${domain}/${user}::userdb_mail=maildir:/var/mail/${domain}/${user} # ${login}:${pass}:5000:5000::/var/mail/${domain}/${user}::userdb_mail=maildir:/var/mail/${domain}/${user}
echo "${login}:${pass}:5000:5000::/var/mail/${domain}/${user}::" >> /etc/dovecot/userdb echo "${login}:${pass}:5000:5000::/var/mail/${domain}/${user}::${user_attributes}" >> /etc/dovecot/userdb
mkdir -p /var/mail/${domain}/${user} mkdir -p /var/mail/${domain}/${user}
# Copy user provided sieve file, if present # Copy user provided sieve file, if present
test -e /tmp/docker-mailserver/${login}.dovecot.sieve && cp /tmp/docker-mailserver/${login}.dovecot.sieve /var/mail/${domain}/${user}/.dovecot.sieve test -e /tmp/docker-mailserver/${login}.dovecot.sieve && cp /tmp/docker-mailserver/${login}.dovecot.sieve /var/mail/${domain}/${user}/.dovecot.sieve
echo ${domain} >> /tmp/vhost.tmp echo ${domain} >> /tmp/vhost.tmp

View file

@ -205,7 +205,7 @@ mail_privileged_group = docker
# Space separated list of plugins to load for all services. Plugins specific to # Space separated list of plugins to load for all services. Plugins specific to
# IMAP, LDA, etc. are added to this list in their own .conf files. # IMAP, LDA, etc. are added to this list in their own .conf files.
#mail_plugins = mail_plugins = $mail_plugins quota
## ##
## Mailbox handling optimizations ## Mailbox handling optimizations

View file

@ -0,0 +1,4 @@
protocol imap {
# allow IMAP clients to ask quota usage
mail_plugins = $mail_plugins imap_quota
}

View file

@ -0,0 +1,50 @@
plugin {
# debug quota using `doveadm quota get -u user@domain`
# recompute quota using `doveadm quota recalc -u user@domain`
# Track the current quota usage in Dovecots index files.
quota = count:User quota
# Use virtual sizes for count
quota_vsizes = yes
# define the maximum message size to be saved, sync with postfix
quota_max_mail_size = 10000M
# default quota per mailbox, sync with postfix
quota_rule = *:storage=128M
# allow user to delete messages
quota_rule2 = Trash:storage=+50M
quota_grace = 10%%
# 10% is the default
quota_warning = storage=95%% quota-warning 95 %u %d
quota_warning2 = storage=80%% quota-warning 80 %u %d
quota_warning3 = -storage=100%% quota-warning below %u %d # user is no longer over quota
quota_status_success=DUNNO
quota_status_nouser=DUNNO
quota_status_overquota = "552 5.2.2 Mailbox is full"
}
service quota-warning {
executable = script /usr/local/bin/quota-warning.sh
unix_listener quota-warning {
user = dovecot
group = dovecot
mode = 0660
}
}
# allow postfix to query quota
service quota-status {
executable = quota-status -p postfix
inet_listener {
port = 65265
# You can choose any port you want
}
client_limit = 1
}

View file

@ -0,0 +1,14 @@
#!/usr/bin/env sh
# Report a quota usage warning to an user
PERCENT=$1
USER=$2
DOMAIN=$3
cat << EOF | /usr/lib/dovecot/dovecot-lda -d "$USER" -o "plugin/quota=maildir:User quota:noenforcing"
From: postmaster@$DOMAIN
Subject: quota warning
Your mailbox is now $PERCENT% full.
EOF

View file

@ -99,6 +99,7 @@ function register_functions() {
if [ "$SMTP_ONLY" != 1 ]; then if [ "$SMTP_ONLY" != 1 ]; then
_register_setup_function "_setup_dovecot" _register_setup_function "_setup_dovecot"
_register_setup_function "_setup_dovecot_dhparam" _register_setup_function "_setup_dovecot_dhparam"
_register_setup_function "_setup_dovecot_quota"
_register_setup_function "_setup_dovecot_local_user" _register_setup_function "_setup_dovecot_local_user"
fi fi
@ -501,7 +502,7 @@ function _setup_chksum_file() {
pushd /tmp/docker-mailserver pushd /tmp/docker-mailserver
declare -a cf_files=() declare -a cf_files=()
for file in postfix-accounts.cf postfix-virtual.cf postfix-aliases.cf; do for file in postfix-accounts.cf postfix-virtual.cf postfix-aliases.cf dovecot-quotas.cf; do
[ -f "$file" ] && cf_files+=("$file") [ -f "$file" ] && cf_files+=("$file")
done done
@ -630,6 +631,43 @@ function _setup_dovecot() {
chmod -f +x /usr/lib/dovecot/sieve-pipe/* chmod -f +x /usr/lib/dovecot/sieve-pipe/*
} }
function _setup_dovecot_quota() {
notify 'task' 'Setting up Dovecot quota'
if [ "$ENABLE_LDAP" = 1 ]; then
notify 'inf' "Dovecot quota is not implemented with LDAP."
if [ -f /etc/dovecot/conf.d/90-quota.conf ]; then
mv /etc/dovecot/conf.d/90-quota.conf /etc/dovecot/conf.d/90-quota.conf.disab
sed -i "s/mail_plugins = \$mail_plugins quota/mail_plugins = \$mail_plugins/g" /etc/dovecot/conf.d/10-mail.conf
sed -i "s/mail_plugins = \$mail_plugins imap_quota/mail_plugins = \$mail_plugins/g" /etc/dovecot/conf.d/20-imap.conf
fi
else
if [ -f /etc/dovecot/conf.d/90-quota.conf.disab ]; then
mv /etc/dovecot/conf.d/90-quota.conf.disab /etc/dovecot/conf.d/90-quota.conf
sed -i "s/mail_plugins = \$mail_plugins/mail_plugins = \$mail_plugins quota/g" /etc/dovecot/conf.d/10-mail.conf
sed -i "s/mail_plugins = \$mail_plugin/mail_plugins = \$mail_plugins imap_quota/g" /etc/dovecot/conf.d/20-imap.conf
fi
message_size_limit_mb=$((DEFAULT_VARS["POSTFIX_MESSAGE_SIZE_LIMIT"] / 1000000))
mailbox_limit_mb=$((DEFAULT_VARS["POSTFIX_MAILBOX_SIZE_LIMIT"] / 1000000))
sed -i "s/quota_max_mail_size =.*/quota_max_mail_size = ${message_size_limit_mb}$([ "$message_size_limit_mb" == 0 ] && echo "" || echo "M")/g" /etc/dovecot/conf.d/90-quota.conf
sed -i "s/quota_rule = \*:storage=.*/quota_rule = *:storage=${mailbox_limit_mb}$([ "$mailbox_limit_mb" == 0 ] && echo "" || echo "M")/g" /etc/dovecot/conf.d/90-quota.conf
if [ ! -f /tmp/docker-mailserver/dovecot-quotas.cf ]; then
notify 'inf' "'config/docker-mailserver/dovecot-quotas.cf' is not provided. Using default quotas."
echo -n >/tmp/docker-mailserver/dovecot-quotas.cf
fi
fi
if [ "$SMTP_ONLY" = 1 ]; then
sed -i "s/check_policy_service inet:localhost:65265//g" /etc/postfix/main.cf
else
sed -i "s/reject_unknown_recipient_domain, reject_rbl_client zen.spamhaus.org/reject_unknown_recipient_domain, check_policy_service inet:localhost:65265, reject_rbl_client zen.spamhaus.org/g" /etc/postfix/main.cf
fi
}
function _setup_dovecot_local_user() { function _setup_dovecot_local_user() {
notify 'task' 'Setting up Dovecot Local User' notify 'task' 'Setting up Dovecot Local User'
echo -n > /etc/postfix/vmailbox echo -n > /etc/postfix/vmailbox
@ -657,15 +695,28 @@ function _setup_dovecot_local_user() {
# Setting variables for better readability # Setting variables for better readability
user=$(echo ${login} | cut -d @ -f1) user=$(echo ${login} | cut -d @ -f1)
domain=$(echo ${login} | cut -d @ -f2) domain=$(echo ${login} | cut -d @ -f2)
user_attributes=""
# test if user has a defined quota
if [ -f /tmp/docker-mailserver/dovecot-quotas.cf ]; then
user_quota=($(grep "${user}@${domain}:" -i /tmp/docker-mailserver/dovecot-quotas.cf | tr ':' '\n'))
if [ ${#user_quota[@]} -eq 2 ]; then
user_attributes="${user_attributes}userdb_quota_rule=*:bytes=${user_quota[1]}"
fi
fi
# Let's go! # Let's go!
notify 'inf' "user '${user}' for domain '${domain}' with password '********'" notify 'inf' "user '${user}' for domain '${domain}' with password '********', attr=${user_attributes}"
echo "${login} ${domain}/${user}/" >> /etc/postfix/vmailbox echo "${login} ${domain}/${user}/" >> /etc/postfix/vmailbox
# User database for dovecot has the following format: # User database for dovecot has the following format:
# user:password:uid:gid:(gecos):home:(shell):extra_fields # user:password:uid:gid:(gecos):home:(shell):extra_fields
# Example : # Example :
# ${login}:${pass}:5000:5000::/var/mail/${domain}/${user}::userdb_mail=maildir:/var/mail/${domain}/${user} # ${login}:${pass}:5000:5000::/var/mail/${domain}/${user}::userdb_mail=maildir:/var/mail/${domain}/${user}
echo "${login}:${pass}:5000:5000::/var/mail/${domain}/${user}::" >> /etc/dovecot/userdb echo "${login}:${pass}:5000:5000::/var/mail/${domain}/${user}::${user_attributes}" >> /etc/dovecot/userdb
mkdir -p /var/mail/${domain}/${user} mkdir -p /var/mail/${domain}/${user}
# Copy user provided sieve file, if present # Copy user provided sieve file, if present
test -e /tmp/docker-mailserver/${login}.dovecot.sieve && cp /tmp/docker-mailserver/${login}.dovecot.sieve /var/mail/${domain}/${user}/.dovecot.sieve test -e /tmp/docker-mailserver/${login}.dovecot.sieve && cp /tmp/docker-mailserver/${login}.dovecot.sieve /var/mail/${domain}/${user}/.dovecot.sieve
echo ${domain} >> /tmp/vhost.tmp echo ${domain} >> /tmp/vhost.tmp
@ -775,6 +826,8 @@ function _setup_postfix_sizelimits() {
postconf -e "message_size_limit = ${DEFAULT_VARS["POSTFIX_MESSAGE_SIZE_LIMIT"]}" postconf -e "message_size_limit = ${DEFAULT_VARS["POSTFIX_MESSAGE_SIZE_LIMIT"]}"
notify 'inf' "Configuring postfix mailbox size limit" notify 'inf' "Configuring postfix mailbox size limit"
postconf -e "mailbox_size_limit = ${DEFAULT_VARS["POSTFIX_MAILBOX_SIZE_LIMIT"]}" postconf -e "mailbox_size_limit = ${DEFAULT_VARS["POSTFIX_MAILBOX_SIZE_LIMIT"]}"
notify 'inf' "Configuring postfix virtual mailbox size limit"
postconf -e "virtual_mailbox_limit = ${DEFAULT_VARS["POSTFIX_MAILBOX_SIZE_LIMIT"]}"
} }
function _setup_postfix_smtputf8() { function _setup_postfix_smtputf8() {

View file

@ -47,6 +47,11 @@ function teardown_file() {
assert_failure assert_failure
} }
@test "checking configuration: dovecot quota absent in postconf (disabled using SMTP_ONLY)" {
run docker exec mail_smtponly /bin/bash -c "postconf | grep 'check_policy_service inet:localhost:65265'"
assert_failure
}
# #
# smtp # smtp
# #
@ -75,4 +80,4 @@ function teardown_file() {
@test "last" { @test "last" {
skip 'this test is only there to reliably mark the end for the teardown_file' skip 'this test is only there to reliably mark the end for the teardown_file'
} }

View file

@ -168,6 +168,17 @@ function teardown_file() {
assert_success assert_success
} }
@test "checking dovecot: quota plugin is disabled" {
run docker exec mail_with_ldap /bin/sh -c "grep '\$mail_plugins quota' /etc/dovecot/conf.d/10-mail.conf"
assert_failure
run docker exec mail_with_ldap /bin/sh -c "grep '\$mail_plugins imap_quota' /etc/dovecot/conf.d/20-imap.conf"
assert_failure
run docker exec mail_with_ldap ls /etc/dovecot/conf.d/90-quota.conf
assert_failure
run docker exec mail_with_ldap ls /etc/dovecot/conf.d/90-quota.conf.disab
assert_success
}
@test "checking spoofing: rejects sender forging" { @test "checking spoofing: rejects sender forging" {
run docker exec mail_with_ldap /bin/sh -c "nc 0.0.0.0 25 < /tmp/docker-mailserver-test/auth/ldap-smtp-auth-spoofed.txt | grep 'Sender address rejected: not owned by user'" run docker exec mail_with_ldap /bin/sh -c "nc 0.0.0.0 25 < /tmp/docker-mailserver-test/auth/ldap-smtp-auth-spoofed.txt | grep 'Sender address rejected: not owned by user'"
assert_success assert_success

View file

@ -0,0 +1,25 @@
HELO mail.external.tld
MAIL FROM: user@external.tld
RCPT TO: quotauser@otherdomain.tld
DATA
From: Docker Mail Server <user@external.tld>
To: Existing Local User <quotauser@otherdomain.tld>
Date: Sat, 22 May 2010 07:43:25 -0400
Subject: Test Message saturating your mailbox
This is a test mail with a lot of data
Lorem ipsum dolor sit amet. Et quidem architecto id Quis saepe vel corporis odit aut nesciunt nisi. Et voluptatem exercitationem ut enim veritatis et nostrum optio aut magni eius et perspiciatis magnam et ipsam illo. 33 inventore unde est voluptatem exercitationem aut dolores nesciunt aut porro facere voluptatem quisquam hic corrupti culpa. 33 dicta sapiente eum rerum harum aut facere nobis in expedita debitis. Hic velit provident et laborum debitis eos tempore quaerat et iste tempora ut perferendis enim rem maxime incidunt qui quas sequi. Et voluptate enim qui explicabo tempora quo sint sequi sit enim quam aut eaque placeat At maiores doloribus. Qui doloremque consequatur eos voluptates ipsa eum placeat internos est eius internos ut aperiam necessitatibus et excepturi neque a nobis praesentium. Non alias omnis qui eaque dignissimos ea voluptates maiores aut inventore nihil. Ut quaerat voluptatem qui assumenda labore et magni harum sed possimus sint et minus voluptatibus eum veritatis error eos minus eaque! Qui commodi explicabo eos repellat enim hic nisi commodi qui nulla rerum hic debitis tempore. Qui autem praesentium ab cupiditate accusantium velit voluptatibus. Aut tempore molestiae qui doloribus molestias aut ipsum obcaecati At laborum asperiores qui sint architecto. Et voluptatem porro ut repellendus odio eum voluptatem facere cum mollitia obcaecati aut tempore adipisci hic quisquam aliquam. Ad mollitia amet a accusantium magni At provident obcaecati id laudantium odit et dolorum voluptatum!
Cum accusamus corporis ut nemo dolores ut porro odio ipsam quibusdam et culpa esse et dolor fugit. Aut illo et laudantium voluptate et asperiores nobis sit autem atque est eius amet. A quasi quam eum galisum quia ea tempora veniam non incidunt ratione in natus culpa quo Quis doloremque ut quia reiciendis. Aut sunt nihil et nihil quas fuga laborum et assumenda esse. Et quisquam quod qui necessitatibus doloremque sit dicta sapiente sed vero laborum aut magnam omnis et eveniet incidunt non asperiores repudiandae! Aut consectetur galisum ab laboriosam quas eos omnis necessitatibus. Sed dolores distinctio hic maiores voluptatem rem facilis soluta a labore dolorum. Non voluptas commodi non aperiam voluptatem aut blanditiis illum et commodi ipsum in sint voluptatem sit corrupti architecto et quia quia. Qui possimus voluptatem eos repellat veritatis velit quia eos fugit repellat qui reprehenderit dolorem 33 animi dolorem. In deserunt repellat ea totam impedit et sint temporibus vel explicabo expedita id earum assumenda ex eaque enim et sint incidunt. Aut totam eveniet et aspernatur maiores est cumque dolorem sit officiis doloribus. Hic nesciunt rerum ut sint sint ad veritatis omnis ut maxime exercitationem. Sit natus voluptatum 33 dolorem consequatur ab perspiciatis enim et voluptas molestias sed iste perferendis eum tempore eligendi. Et enim ratione ut autem atque eum dolore neque sit necessitatibus quibusdam ab illum explicabo eum excepturi debitis!
Aut galisum Quis ab neque ducimus sed laboriosam veniam et tempora ratione. Vel molestiae blanditiis et molestiae Quis ut eius dolorum aut voluptatem obcaecati quo alias iusto est fugiat galisum. In doloremque eligendi qui similique facere aut quibusdam consequatur est perferendis voluptate. Quo molestiae consequatur ut autem praesentium sit perspiciatis vitae sed voluptate dolores. Et velit modi vel consequuntur accusamus et rerum dolor! In voluptas libero rem sunt dolorem ut officiis exercitationem sit dignissimos quia ut aliquid quos ex iste distinctio est molestias cumque. Qui repellendus voluptates sit totam sequi aut deserunt ipsum et dolores possimus et corporis possimus qui praesentium autem. Ea eaque veritatis vel quis voluptas ut voluptas dicta non minus suscipit. Sed culpa tempore necessitatibus omnis eum assumenda modi non iusto assumenda 33 sint molestiae ut consequatur libero. Eos accusantium similique ut natus eaque non omnis repellat est maxime quibusdam! Est accusantium facilis sit voluptas et voluptas officia ab repellat veritatis eum commodi animi ut omnis veniam. Est ratione Quis aut velit vitae ut eaque dignissimos qui perspiciatis voluptate est optio voluptatem sit cumque quia. Aut ratione eligendi et sequi nihil ut sunt quasi sed beatae dolore. Et iusto reprehenderit ab Quis voluptas eum suscipit dolor aut autem sint!
Et illo molestiae eum impedit voluptatum aut dignissimos numquam qui culpa quia ut delectus delectus. Qui voluptatem amet et quia velit ut debitis possimus. In similique molestiae ut minima error et placeat molestiae ab quasi fugiat qui minima quibusdam. Sit porro aperiam aut fugiat quis ut ullam dolores quo maiores voluptas aut reiciendis quibusdam id eaque modi! Cum minima dicta eos molestiae veritatis est excepturi neque non magni galisum. Sit reiciendis aspernatur ut amet doloribus aut velit tempora quo quasi veritatis est voluptatem illum eos repellendus eius et beatae iure. Est voluptates totam et mollitia reprehenderit est sequi doloremque et eius odit At officia dolorem. Sed magnam quidem eum ipsa consectetur quo consequatur ipsa ad internos rerum.
Et voluptatum nobis ut odio voluptatem et quibusdam fugit ut libero sapiente vel quia voluptatem. Et voluptas quaerat vel quasi commodi At minus itaque? A similique voluptatem ut porro dolor cum voluptatem facere et provident odit. Et odio eligendi rem necessitatibus adipisci ut distinctio rerum sed accusantium nemo. In ipsum nostrum aut praesentium voluptates eum velit quis At rerum consequatur cum reprehenderit assumenda aut quibusdam delectus et aliquam voluptates. Ut possimus harum aut molestiae consequatur in fugiat voluptate non temporibus galisum qui ullam distinctio. Qui quia sequi non nobis veniam est sint facere qui enim laudantium. Qui repellendus sunt id soluta illum qui voluptatem enim. Ut praesentium vero cum fuga architecto est velit pariatur. Ut necessitatibus doloremque At delectus voluptatem ab dignissimos dolorem. Ut maxime repudiandae et repellat suscipit et delectus quia rem corrupti temporibus est doloribus veritatis et facilis beatae et harum alias. Quo reiciendis vero cum dolor natus ut nisi tenetur non quia quia est iste internos. Qui earum dignissimos qui earum vero eos dignissimos expedita id officiis architecto sit corporis inventore et quisquam nesciunt. A dolorem doloribus et quia unde hic minus voluptatem.
Sit sint obcaecati et reiciendis tenetur aut dolorum culpa. Ab veritatis maxime qui necessitatibus facilis eum voluptate asperiores non totam omnis. Nam modi officia in reiciendis odit sit rerum laudantium est rerum voluptatem ut fugit cupiditate! Sit atque sint aut delectus omnis ut asperiores enim quo reprehenderit quae! In quasi nemo ut error totam ut quia harum ut commodi tenetur? Non quod dolorum eum explicabo labore vel asperiores quas est perferendis nulla eum nemo tenetur. Ut libero blanditiis ex voluptatibus repudiandae ab reiciendis nemo id debitis impedit hic quia incidunt sed quam excepturi ut magnam odit. Qui dolor deleniti aut sunt voluptas aut blanditiis distinctio nam omnis deleniti hic omnis rerum eum magni voluptatem. Nam labore facere eum molestiae dolorum ea consectetur praesentium ut cupiditate iste ad magnam aut neque maiores! Et excepturi ducimus ut nemo voluptas eum voluptas nihil hic perferendis quos vel quasi nesciunt est praesentium dolore hic quia quis. Et maxime ducimus ea cupiditate voluptatem ad quia dolores!
Sed quos quaerat vel aperiam minus non sapiente quia ut ratione dolore eum officiis rerum. Non dolor vitae qui facilis dignissimos aut voluptate odit et ullam consequuntur. Et laudantium perspiciatis sit nisi temporibus a temporibus itaque ut iure dolor a voluptatum mollitia eos officia nobis et quibusdam voluptas. Amet eligendi eos nulla corporis et blanditiis nihil vel eveniet veritatis et sunt perferendis id molestiae eius! Quo harum quod aut nemo autem ut adipisci sint sed quia sunt. Aut voluptas error ut quae perferendis eos adipisci internos. Nam rerum fugiat aut minima nostrum quo repellendus quas exercitationem tenetur. Et molestiae architecto id quibusdam reprehenderit et magnam aliquam! Quo tempora veritatis At dolorem sint ex nulla blanditiis At voluptas laudantium est molestiae exercitationem et sequi voluptates aut ipsa atque. Et animi ipsum aut atque recusandae ea nemo ullam non quisquam quos sit libero sint vel libero delectus. Eos labore quidem a velit obcaecati nam explicabo consequatur eos maxime blanditiis? Et ipsam molestiae non quia explicabo ex galisum repudiandae et tempora veniam. Sed optio repellendus ut consequatur temporibus et harum quas hic ipsa officia? Aut dolores ipsum sit nulla dignissimos id quia perferendis aut dolores dolor et quibusdam porro aut Quis consequatur.
.
QUIT

View file

@ -1,6 +1,6 @@
load 'test_helper/bats-support/load' load 'test_helper/bats-support/load'
load 'test_helper/bats-assert/load' load 'test_helper/bats-assert/load'
load 'test_helper/common'
# #
# shared functions # shared functions
@ -934,6 +934,240 @@ EOF
[ ! -z "$output" ] [ ! -z "$output" ]
} }
@test "checking quota: setquota user must be existing" {
run docker exec mail /bin/sh -c "addmailuser quota_user@domain.tld mypassword"
assert_success
run docker exec mail /bin/sh -c "setquota quota_user 50M"
assert_failure
run docker exec mail /bin/sh -c "setquota quota_user@domain.tld 50M"
assert_success
run docker exec mail /bin/sh -c "setquota username@fulldomain 50M"
assert_failure
run docker exec mail /bin/sh -c "delmailuser -y quota_user@domain.tld"
assert_success
}
@test "checking quota: setquota <quota> must be well formatted" {
run docker exec mail /bin/sh -c "addmailuser quota_user@domain.tld mypassword"
assert_success
run docker exec mail /bin/sh -c "setquota quota_user@domain.tld 26GIGOTS"
assert_failure
run docker exec mail /bin/sh -c "setquota quota_user@domain.tld 123"
assert_failure
run docker exec mail /bin/sh -c "setquota quota_user@domain.tld M"
assert_failure
run docker exec mail /bin/sh -c "setquota quota_user@domain.tld -60M"
assert_failure
run docker exec mail /bin/sh -c "setquota quota_user@domain.tld 10B"
assert_success
run docker exec mail /bin/sh -c "setquota quota_user@domain.tld 10k"
assert_success
run docker exec mail /bin/sh -c "setquota quota_user@domain.tld 10M"
assert_success
run docker exec mail /bin/sh -c "setquota quota_user@domain.tld 10G"
assert_success
run docker exec mail /bin/sh -c "setquota quota_user@domain.tld 10T"
assert_success
run docker exec mail /bin/sh -c "delmailuser -y quota_user@domain.tld"
assert_success
}
@test "checking quota: delquota user must be existing" {
run docker exec mail /bin/sh -c "addmailuser quota_user@domain.tld mypassword"
assert_success
run docker exec mail /bin/sh -c "delquota uota_user@domain.tld"
assert_failure
run docker exec mail /bin/sh -c "delquota quota_user"
assert_failure
run docker exec mail /bin/sh -c "delquota dontknowyou@domain.tld"
assert_failure
run docker exec mail /bin/sh -c "setquota quota_user@domain.tld 10T"
assert_success
run docker exec mail /bin/sh -c "delquota quota_user@domain.tld"
assert_success
run docker exec mail /bin/sh -c "grep -i 'quota_user@domain.tld' /tmp/docker-mailserver/dovecot-quotas.cf"
assert_failure
run docker exec mail /bin/sh -c "delmailuser -y quota_user@domain.tld"
assert_success
}
@test "checking quota: delquota allow when no quota for existing user" {
run docker exec mail /bin/sh -c "addmailuser quota_user@domain.tld mypassword"
assert_success
run docker exec mail /bin/sh -c "grep -i 'quota_user@domain.tld' /tmp/docker-mailserver/dovecot-quotas.cf"
assert_failure
run docker exec mail /bin/sh -c "delquota quota_user@domain.tld"
assert_success
run docker exec mail /bin/sh -c "delquota quota_user@domain.tld"
assert_success
run docker exec mail /bin/sh -c "delmailuser -y quota_user@domain.tld"
assert_success
}
@test "checking quota: dovecot quota present in postconf" {
run docker exec mail /bin/bash -c "postconf | grep 'check_policy_service inet:localhost:65265'"
assert_success
}
@test "checking quota: dovecot mailbox max size must be equal to postfix mailbox max size" {
postfix_mailbox_size=$(docker exec mail sh -c "postconf | grep -Po '(?<=mailbox_size_limit = )[0-9]+'")
run echo "$postfix_mailbox_size"
refute_output ""
# dovecot relies on virtual_mailbox_size by default
postfix_virtual_mailbox_size=$(docker exec mail sh -c "postconf | grep -Po '(?<=virtual_mailbox_limit = )[0-9]+'")
assert_equal "$postfix_virtual_mailbox_size" "$postfix_mailbox_size"
postfix_mailbox_size_mb=$(($postfix_mailbox_size / 1000000))
dovecot_mailbox_size_mb=$(docker exec mail sh -c "doveconf | grep -oP '(?<=quota_rule \= \*\:storage=)[0-9]+'")
run echo "$dovecot_mailbox_size_mb"
refute_output ""
assert_equal "$postfix_mailbox_size_mb" "$dovecot_mailbox_size_mb"
}
@test "checking quota: dovecot message max size must be equal to postfix messsage max size" {
postfix_message_size=$(docker exec mail sh -c "postconf | grep -Po '(?<=message_size_limit = )[0-9]+'")
run echo "$postfix_message_size"
refute_output ""
postfix_message_size_mb=$(($postfix_message_size / 1000000))
dovecot_message_size_mb=$(docker exec mail sh -c "doveconf | grep -oP '(?<=quota_max_mail_size = )[0-9]+'")
run echo "$dovecot_message_size_mb"
refute_output ""
assert_equal "$postfix_message_size_mb" "$dovecot_message_size_mb"
}
@test "checking quota: quota directive is removed when mailbox is removed" {
run docker exec mail /bin/sh -c "addmailuser quserremoved@domain.tld mypassword"
assert_success
run docker exec mail /bin/sh -c "setquota quserremoved@domain.tld 12M"
assert_success
run docker exec mail /bin/sh -c 'cat /tmp/docker-mailserver/dovecot-quotas.cf | grep -E "^quserremoved@domain.tld\:12M\$" | wc -l | grep 1'
assert_success
run docker exec mail /bin/sh -c "delmailuser -y quserremoved@domain.tld"
assert_success
run docker exec mail /bin/sh -c 'cat /tmp/docker-mailserver/dovecot-quotas.cf | grep -E "^quserremoved@domain.tld\:12M\$"'
assert_failure
}
@test "checking quota: dovecot applies user quota" {
sleep 15 # wait until any other change has finished
run docker exec mail /bin/sh -c "doveadm quota get -u 'user1@localhost.localdomain' | grep 'User quota STORAGE'"
assert_output --partial "- 0"
# set a quota
originalChangesProcessed=$(count_processed_changes mail)
run docker exec mail /bin/sh -c "setquota user1@localhost.localdomain 50M"
assert_success
# wait until change detector has processed the change
count=0
while [ "${originalChangesProcessed}" = "$(count_processed_changes mail)" ]
do
((count++)) && ((count==60)) && break
sleep 1
done
[ "${originalChangesProcessed}" != "$(count_processed_changes mail)" ]
assert_success
# let dovecot breathe
sleep 5
run docker exec mail /bin/sh -c 'doveadm quota get -u user1@localhost.localdomain | grep "User quota STORAGE"'
assert_output --partial '51200'
assert_success
# remove the quota
originalChangesProcessed=$(count_processed_changes mail)
run docker exec mail /bin/sh -c "delquota user1@localhost.localdomain"
assert_success
# wait until change detector has processed the change
count=0
while [ "${originalChangesProcessed}" = "$(count_processed_changes mail)" ]
do
((count++)) && ((count==60)) && break
sleep 1
done
[ "${originalChangesProcessed}" != "$(count_processed_changes mail)" ]
assert_success
# let dovecot breathe
sleep 5
run docker exec mail /bin/sh -c 'doveadm quota get -u user1@localhost.localdomain | grep "User quota STORAGE"'
assert_output --partial '- 0'
assert_success
}
@test "checking quota: warn message received when quota exceeded" {
sleep 15 # wait until any other change has finished
originalChangesProcessed=$(count_processed_changes mail)
# create user
run docker exec mail /bin/sh -c "addmailuser quotauser@otherdomain.tld mypassword && setquota quotauser@otherdomain.tld 10k"
assert_success
count=0
while [ "${originalChangesProcessed}" = "$(count_processed_changes mail)" ]
do
((count++)) && ((count==60)) && break
sleep 1
done
[ "${originalChangesProcessed}" != "$(count_processed_changes mail)" ]
assert_success
# let dovecot breathe
sleep 5
run docker exec mail /bin/sh -c 'doveadm quota get -u quotauser@otherdomain.tld | grep "User quota STORAGE"'
assert_output --partial '10'
assert_success
# send some big emails
run docker exec mail /bin/sh -c "nc 0.0.0.0 25 < /tmp/docker-mailserver-test/email-templates/quota-exceeded.txt"
run docker exec mail /bin/sh -c "nc 0.0.0.0 25 < /tmp/docker-mailserver-test/email-templates/quota-exceeded.txt"
run docker exec mail /bin/sh -c "nc 0.0.0.0 25 < /tmp/docker-mailserver-test/email-templates/quota-exceeded.txt"
assert_success
# check for quota warn message existence
run repeat_until_success_or_timeout 20 sh -c "docker exec mail sh -c 'grep \"Subject: quota warning\" /var/mail/otherdomain.tld/quotauser/new/ -R'"
assert_success
# ensure only the first big message and the warn message are present (other messages are rejected: mailbox is full)
run docker exec mail sh -c 'ls /var/mail/otherdomain.tld/quotauser/new/ | wc -l'
assert_success
assert_output "2"
run docker exec mail /bin/sh -c "delmailuser -y quotauser@otherdomain.tld"
assert_success
}
# #
# PERMIT_DOCKER mynetworks # PERMIT_DOCKER mynetworks
# #
@ -1119,6 +1353,60 @@ EOF
assert_failure assert_failure
} }
# quota
@test "checking setup.sh: setup.sh setquota" {
mkdir -p ./test/quota/config && echo "" > ./test/quota/config/dovecot-quotas.cf
run ./setup.sh -p ./test/quota/config email add quota_user@example.com test_password
run ./setup.sh -p ./test/quota/config email add quota_user2@example.com test_password
run ./setup.sh -p ./test/quota/config quota set quota_user@example.com 12M
assert_success
run ./setup.sh -p ./test/quota/config quota set 51M quota_user@example.com
assert_failure
run ./setup.sh -p ./test/quota/config quota set unknown@domain.com 150M
assert_failure
run ./setup.sh -p ./test/quota/config quota set quota_user2 51M
assert_failure
run /bin/sh -c 'cat ./test/quota/config/dovecot-quotas.cf | grep -E "^quota_user@example.com\:12M\$" | wc -l | grep 1'
assert_success
run ./setup.sh -p ./test/quota/config quota set quota_user@example.com 26M
assert_success
run /bin/sh -c 'cat ./test/quota/config/dovecot-quotas.cf | grep -E "^quota_user@example.com\:26M\$" | wc -l | grep 1'
assert_success
run grep "quota_user2@example.com" ./test/alias/config/dovecot-quotas.cf
assert_failure
}
@test "checking setup.sh: setup.sh delquota" {
mkdir -p ./test/quota/config && echo "" > ./test/quota/config/dovecot-quotas.cf
run ./setup.sh -p ./test/quota/config email add quota_user@example.com test_password
run ./setup.sh -p ./test/quota/config email add quota_user2@example.com test_password
run ./setup.sh -p ./test/quota/config quota set quota_user@example.com 12M
assert_success
run /bin/sh -c 'cat ./test/quota/config/dovecot-quotas.cf | grep -E "^quota_user@example.com\:12M\$" | wc -l | grep 1'
assert_success
run ./setup.sh -p ./test/quota/config quota del unknown@domain.com
assert_failure
run /bin/sh -c 'cat ./test/quota/config/dovecot-quotas.cf | grep -E "^quota_user@example.com\:12M\$" | wc -l | grep 1'
assert_success
run ./setup.sh -p ./test/quota/config quota del quota_user@example.com
assert_success
run grep "quota_user@example.com" ./test/alias/config/dovecot-quotas.cf
assert_failure
}
# config # config
@test "checking setup.sh: setup.sh config dkim" { @test "checking setup.sh: setup.sh config dkim" {
run ./setup.sh -c mail config dkim run ./setup.sh -c mail config dkim