diff --git a/.gitignore b/.gitignore
index 319c0355..1ad63838 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,5 +1,4 @@
.DS_Store
docker-compose.yml
postfix/ssl/*
-assert.sh*
letsencrypt/
diff --git a/Dockerfile b/Dockerfile
index 6f94a855..5f53147d 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -10,7 +10,7 @@ RUN apt-get autoclean && rm -rf /var/lib/apt/lists/*
# Configures Saslauthd
RUN rm -rf /var/run/saslauthd && ln -s /var/spool/postfix/var/run/saslauthd /var/run/saslauthd
RUN adduser postfix sasl
-RUN echo 'NAME="saslauthd"\nSTART=yes\nMECHANISMS="sasldb"\nTHREADS=0\nPWDIR=/var/spool/postfix/var/run/saslauthd\nPIDFILE="${PWDIR}/saslauthd.pid"\nOPTIONS="-n 0 -r -m /var/spool/postfix/var/run/saslauthd"' > /etc/default/saslauthd
+RUN echo 'NAME="saslauthd"\nSTART=yes\nMECHANISMS="sasldb"\nTHREADS=0\nPWDIR=/var/spool/postfix/var/run/saslauthd\nPIDFILE="${PWDIR}/saslauthd.pid"\nOPTIONS="-n 0 -c -m /var/spool/postfix/var/run/saslauthd"' > /etc/default/saslauthd
# Configures Courier
RUN sed -i -r 's/daemons=5/daemons=1/g' /etc/courier/authdaemonrc
diff --git a/Makefile b/Makefile
index e049fd92..a019057e 100644
--- a/Makefile
+++ b/Makefile
@@ -12,7 +12,7 @@ run:
cp test/virtual postfix/
# Run container
docker run -d --name mail -v "`pwd`/postfix":/tmp/postfix -v "`pwd`/spamassassin":/tmp/spamassassin -v "`pwd`/test":/tmp/test -h mail.my-domain.com -t $(NAME):$(VERSION)
- sleep 15
+ sleep 25
prepare:
# Reinitialize logs
diff --git a/assert.sh b/assert.sh
new file mode 100644
index 00000000..ffd2b955
--- /dev/null
+++ b/assert.sh
@@ -0,0 +1,186 @@
+#!/bin/bash
+# assert.sh 1.1 - bash unit testing framework
+# Copyright (C) 2009-2015 Robert Lehmann
+#
+# http://github.com/lehmannro/assert.sh
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as published
+# by the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with this program. If not, see .
+
+export DISCOVERONLY=${DISCOVERONLY:-}
+export DEBUG=${DEBUG:-}
+export STOP=${STOP:-}
+export INVARIANT=${INVARIANT:-}
+export CONTINUE=${CONTINUE:-}
+
+args="$(getopt -n "$0" -l \
+ verbose,help,stop,discover,invariant,continue vhxdic $*)" \
+|| exit -1
+for arg in $args; do
+ case "$arg" in
+ -h)
+ echo "$0 [-vxidc]" \
+ "[--verbose] [--stop] [--invariant] [--discover] [--continue]"
+ echo "`sed 's/./ /g' <<< "$0"` [-h] [--help]"
+ exit 0;;
+ --help)
+ cat < [stdin]
+ (( tests_ran++ )) || :
+ [[ -z "$DISCOVERONLY" ]] || return
+ expected=$(echo -ne "${2:-}")
+ result="$(eval 2>/dev/null $1 <<< ${3:-})" || true
+ if [[ "$result" == "$expected" ]]; then
+ [[ -z "$DEBUG" ]] || echo -n .
+ return
+ fi
+ result="$(sed -e :a -e '$!N;s/\n/\\n/;ta' <<< "$result")"
+ [[ -z "$result" ]] && result="nothing" || result="\"$result\""
+ [[ -z "$2" ]] && expected="nothing" || expected="\"$2\""
+ _assert_fail "expected $expected${_indent}got $result" "$1" "$3"
+}
+
+assert_raises() {
+ # assert_raises [stdin]
+ (( tests_ran++ )) || :
+ [[ -z "$DISCOVERONLY" ]] || return
+ status=0
+ (eval $1 <<< ${3:-}) > /dev/null 2>&1 || status=$?
+ expected=${2:-0}
+ if [[ "$status" -eq "$expected" ]]; then
+ [[ -z "$DEBUG" ]] || echo -n .
+ return
+ fi
+ _assert_fail "program terminated with code $status instead of $expected" "$1" "$3"
+}
+
+_assert_fail() {
+ # _assert_fail
+ [[ -n "$DEBUG" ]] && echo -n X
+ report="test #$tests_ran \"$2${3:+ <<< $3}\" failed:${_indent}$1"
+ if [[ -n "$STOP" ]]; then
+ [[ -n "$DEBUG" ]] && echo
+ echo "$report"
+ exit 1
+ fi
+ tests_errors[$tests_failed]="$report"
+ (( tests_failed++ )) || :
+}
+
+skip_if() {
+ # skip_if
+ (eval $@) > /dev/null 2>&1 && status=0 || status=$?
+ [[ "$status" -eq 0 ]] || return
+ skip
+}
+
+skip() {
+ # skip (no arguments)
+ shopt -q extdebug && tests_extdebug=0 || tests_extdebug=1
+ shopt -q -o errexit && tests_errexit=0 || tests_errexit=1
+ # enable extdebug so returning 1 in a DEBUG trap handler skips next command
+ shopt -s extdebug
+ # disable errexit (set -e) so we can safely return 1 without causing exit
+ set +o errexit
+ tests_trapped=0
+ trap _skip DEBUG
+}
+_skip() {
+ if [[ $tests_trapped -eq 0 ]]; then
+ # DEBUG trap for command we want to skip. Do not remove the handler
+ # yet because *after* the command we need to reset extdebug/errexit (in
+ # another DEBUG trap.)
+ tests_trapped=1
+ [[ -z "$DEBUG" ]] || echo -n s
+ return 1
+ else
+ trap - DEBUG
+ [[ $tests_extdebug -eq 0 ]] || shopt -u extdebug
+ [[ $tests_errexit -eq 1 ]] || set -o errexit
+ return 0
+ fi
+}
+
+
+_assert_reset
+: ${tests_suite_status:=0} # remember if any of the tests failed so far
+_assert_cleanup() {
+ local status=$?
+ # modify exit code if it's not already non-zero
+ [[ $status -eq 0 && -z $CONTINUE ]] && exit $tests_suite_status
+}
+trap _assert_cleanup EXIT
diff --git a/postfix/main.cf b/postfix/main.cf
index b4114b1f..32ba810e 100644
--- a/postfix/main.cf
+++ b/postfix/main.cf
@@ -43,7 +43,7 @@ smtpd_tls_exclude_ciphers = aNULL, LOW, EXP, MEDIUM, ADH, AECDH, MD5, DSS, ECDSA
smtpd_sasl_auth_enable = yes
smtpd_sasl_path = smtpd
smtpd_sasl_type = cyrus
-smtpd_sasl_security_options = noanonymous, noplaintext
+smtpd_sasl_security_options = noanonymous
smtpd_sasl_local_domain = $myhostname
cyrus_sasl_config_path = /etc/postfix/sasl
broken_sasl_auth_clients = yes
diff --git a/postfix/master.cf b/postfix/master.cf
index c782b3da..8804f632 100644
--- a/postfix/master.cf
+++ b/postfix/master.cf
@@ -73,7 +73,7 @@ smtp-amavis unix - - - - 2 smtp
-o disable_dns_lookups=yes
-o max_use=20
-127.0.0.1:10025 inet n - - - - smtpd
+127.0.0.1:10025 inet n - n - - smtpd
-o content_filter=
-o local_recipient_maps=
-o relay_recipient_maps=
diff --git a/postfix/sasl/smtpd.conf b/postfix/sasl/smtpd.conf
index 75293ec9..f02eb91d 100644
--- a/postfix/sasl/smtpd.conf
+++ b/postfix/sasl/smtpd.conf
@@ -1,3 +1,4 @@
pwcheck_method: auxprop
-mech_list: digest-md5 cram-md5
-log_level: 7
\ No newline at end of file
+auxprop_plugin: sasldb
+mech_list: PLAIN LOGIN CRAM-MD5 DIGEST-MD5
+log_level: 7
diff --git a/start-mailserver.sh b/start-mailserver.sh
index 22ecdc53..8edb783b 100644
--- a/start-mailserver.sh
+++ b/start-mailserver.sh
@@ -104,6 +104,7 @@ esac
echo "Fixing permissions"
chown -R 5000:5000 /var/mail
mkdir -p /var/log/clamav && chown -R clamav:root /var/log/clamav
+chown postfix.sasl /etc/sasldb2
echo "Creating /etc/mailname"
echo $(hostname -d) > /etc/mailname
diff --git a/test/test.sh b/test/test.sh
index 43bce4f1..13a648ee 100644
--- a/test/test.sh
+++ b/test/test.sh
@@ -14,6 +14,10 @@ assert_raises "docker exec mail ps aux --forest | grep '/usr/sbin/amavisd-new'"
assert_raises "docker exec mail nc -w 1 0.0.0.0 143 | grep '* OK' | grep 'STARTTLS' | grep 'Courier-IMAP ready'" 0
assert_raises "docker exec mail /bin/sh -c 'nc -w 1 0.0.0.0 143 < /tmp/test/email-templates/test-imap.txt'" 0
+# Testing SASL
+assert_raises "docker exec mail testsaslauthd -u user2 -r otherdomain.tld -p mypassword | grep 'OK \"Success.\"'" 0
+assert_raises "docker exec mail testsaslauthd -u user2 -r otherdomain.tld -p BADPASSWORD | grep 'NO \"authentication failed\"'" 0
+
# Testing user creation
assert "docker exec mail sasldblistusers2" "user1@localhost.localdomain: userPassword\nuser2@otherdomain.tld: userPassword"
assert "docker exec mail ls -A /var/mail/localhost.localdomain/user1" "cur\nnew\ntmp"