-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathtest.sh
More file actions
executable file
·173 lines (152 loc) · 5.5 KB
/
Copy pathtest.sh
File metadata and controls
executable file
·173 lines (152 loc) · 5.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
#!/bin/sh
# automated smoke test for the minimail container
# builds the image, starts it standalone and asserts postfix + dovecot come up
set -eu
IMAGE=minimail-test
NAME=minimail-test-run
FAILED=0
fail() {
echo "FAIL: $*" >&2
FAILED=1
}
cleanup() {
echo ">> cleanup: removing container $NAME"
docker rm -f "$NAME" >/dev/null 2>&1 || true
}
trap cleanup EXIT INT TERM
# grab the first line a tcp service sends, retrying while it spins up
# usage: grab_banner <port>
grab_banner() {
_port="$1"
_n=0
while [ "$_n" -lt 15 ]; do
_line=$(docker exec "$NAME" sh -c "nc -w 3 127.0.0.1 $_port </dev/null | head -n1" 2>/dev/null || true)
if [ -n "$_line" ]; then
echo "$_line"
return 0
fi
_n=$((_n + 1))
sleep 1
done
return 1
}
echo ">> building image $IMAGE"
docker build -t "$IMAGE" .
echo ">> (re)starting container $NAME"
docker rm -f "$NAME" >/dev/null 2>&1 || true
# the account domain deliberately EQUALS MAIL_FQDN's host: this guards the
# 'mydestination =' config. with it, delivery stays virtual (works); without it
# postfix would treat the domain as local and bounce mail as "unknown user".
docker run -d --name "$NAME" \
-e MAIL_FQDN=mail.example.com \
-e ACONF_USER_ACCOUNT_NAME_tester='tester@mail.example.com' \
-e ACONF_USER_PASSWORD_HASH_tester='{PLAIN}secret' \
"$IMAGE"
echo ">> waiting for services to start (up to ~60s)"
READY=0
i=0
while [ "$i" -lt 30 ]; do
if ! docker ps --format '{{.Names}}' | grep -q "^${NAME}$"; then
echo "!! container is not running anymore, dumping logs:" >&2
docker logs "$NAME" >&2 2>&1 || true
fail "container exited during startup"
break
fi
if docker exec "$NAME" ps aux 2>/dev/null | grep -q '[p]ostfix/master' \
&& docker exec "$NAME" ps aux 2>/dev/null | grep -qE '[d]ovecot -F'; then
READY=1
break
fi
i=$((i + 1))
sleep 2
done
if [ "$READY" -ne 1 ] && [ "$FAILED" -eq 0 ]; then
echo "!! services did not come up in time, dumping logs:" >&2
docker logs "$NAME" >&2 2>&1 || true
fail "timed out waiting for postfix/dovecot"
fi
# only run the deeper assertions if the container is still up
if docker ps --format '{{.Names}}' | grep -q "^${NAME}$"; then
echo ">> assert: container is running"
docker ps --format '{{.Names}}' | grep -q "^${NAME}$" \
&& echo "ok - container running" || fail "container not running"
echo ">> assert: postfix/master process present"
if docker exec "$NAME" ps aux | grep -q '[p]ostfix/master'; then
echo "ok - postfix/master running"
else
fail "postfix/master process not found"
fi
echo ">> assert: dovecot process present"
if docker exec "$NAME" ps aux | grep -qE '[d]ovecot -F'; then
echo "ok - dovecot running"
else
fail "dovecot process not found"
fi
echo ">> assert: postfix check exits 0"
if docker exec "$NAME" postfix check; then
echo "ok - postfix check passed"
else
fail "postfix check returned non-zero"
fi
echo ">> assert: doveconf -n has no Fatal/Error"
DOVECONF=$(docker exec "$NAME" doveconf -n 2>&1 || true)
if echo "$DOVECONF" | grep -E 'Fatal|Error'; then
fail "doveconf -n reported Fatal/Error"
else
echo "ok - doveconf -n clean"
fi
echo ">> assert: SMTP on port 25 returns 220 banner"
SMTP_BANNER=$(grab_banner 25 || true)
if echo "$SMTP_BANNER" | grep -q '^220'; then
echo "ok - SMTP banner: $SMTP_BANNER"
else
fail "SMTP did not return a 220 banner (got: '$SMTP_BANNER')"
fi
echo ">> assert: IMAP on port 143 returns * OK greeting"
IMAP_GREETING=$(grab_banner 143 || true)
if echo "$IMAP_GREETING" | grep -q '^\* OK'; then
echo "ok - IMAP greeting: $IMAP_GREETING"
else
fail "IMAP did not return a '* OK' greeting (got: '$IMAP_GREETING')"
fi
echo ">> assert: user can actually authenticate (passdb passwd-file)"
if docker exec "$NAME" doveadm auth test tester@mail.example.com secret 2>&1 | grep -q 'auth succeeded'; then
echo "ok - user login works"
else
fail "doveadm auth test failed for tester@mail.example.com"
fi
echo ">> assert: mail actually gets delivered (smtp -> dovecot lmtp -> maildir)"
MB=tester@mail.example.com
BEFORE=$(docker exec "$NAME" doveadm mailbox status -u "$MB" messages INBOX 2>/dev/null | grep -oE 'messages=[0-9]+' | cut -d= -f2 || true)
BEFORE=${BEFORE:-0}
docker exec "$NAME" sh -c "printf 'Subject: testsuite\r\nFrom: s@ext.test\r\nTo: $MB\r\n\r\ndelivery check\r\n' | sendmail -f s@ext.test $MB"
DELIVERED=0
d=0
while [ "$d" -lt 15 ]; do
AFTER=$(docker exec "$NAME" doveadm mailbox status -u "$MB" messages INBOX 2>/dev/null | grep -oE 'messages=[0-9]+' | cut -d= -f2 || true)
AFTER=${AFTER:-0}
if [ "$AFTER" -gt "$BEFORE" ]; then DELIVERED=1; break; fi
d=$((d + 1))
sleep 1
done
if [ "$DELIVERED" -eq 1 ]; then
echo "ok - mail delivered (INBOX $BEFORE -> $AFTER)"
else
fail "mail was not delivered to INBOX"
fi
echo ">> assert: unknown recipient is rejected (no local catch-all)"
RCPT_REPLY=$({ sleep 2; printf 'EHLO test\r\n'; sleep 1; printf 'MAIL FROM:<s@ext.test>\r\n'; sleep 2; printf 'RCPT TO:<ghost@mail.example.com>\r\n'; sleep 2; printf 'QUIT\r\n'; sleep 1; } | docker exec -i "$NAME" nc -w 10 127.0.0.1 25 2>/dev/null | tr -d '\r')
if echo "$RCPT_REPLY" | grep -qi '550.*[Uu]ser unknown'; then
echo "ok - unknown recipient rejected (550 User unknown)"
else
fail "unknown recipient not rejected as expected; got: $(echo "$RCPT_REPLY" | grep '^5' | tail -1)"
fi
fi
echo
if [ "$FAILED" -eq 0 ]; then
echo "ALL TESTS PASSED"
exit 0
else
echo "SOME TESTS FAILED"
exit 1
fi