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
|
MAILBOX="INBOX"
TIMEOUT=0
N=64
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
step_start "\`pullimap\` locks its statefile"
pullimap --idle "remote" & PID=$!
trap "ptree_abort $PID" EXIT INT TERM
# wait a short while so we have time to lock the database (ugly and racy...)
sleep .5
! pullimap "remote" || error
grep -F "Can't lock $XDG_DATA_HOME/pullimap/remote: Resource temporarily unavailable at " <"$STDERR" || error
ptree_abort $PID
trap - EXIT INT TERM
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() {
local u="$1" guid uid
local fields="body date.sent imap.bodystructure imap.envelope"
while read guid uid; do
doveadm -u "$u" -f "flow" fetch --no-userdb-lookup "$fields" mailbox-guid "$guid" uid "$uid" | sha256sum
done < <(doveadm -u "$u" search mailbox --no-userdb-lookup "$MAILBOX") | sort -f
}
check() {
diff -u --label="local/mails" --label="remote/mails" \
<( list_mails_sha256 "local" ) \
<( list_mails_sha256 "remote" ) \
|| error "mailboxes differ"
}
message_from() {
local date="$(date +"%s.%N")" sender="$1"
cat <<-EOF
From: $sender
To: <me@example.net>
Date: $(date -R -d@"$date")
Message-ID: <$date@example.net>
EOF
xxd -ps -l8 /dev/urandom
}
step_start "Quote envelope sender address"
declare -a senders=("sender" "first.last" "foo-bar" \"\" "\"x\\\" #&\\\\y\"")
for s in "${senders[@]}"; do
message_from "$s@example.net" | deliver -u "remote" -- -m "$MAILBOX"
done
pullimap "remote" || error
check
for s in "${senders[@]}"; do
grep -F " from <$s@example.net> " <"$STDERR" || error "$s"
done
step_done
step_start "Mail without data"
deliver -u "remote" -- -m "$MAILBOX" </dev/null
pullimap "remote" || error
check
step_done
step_start "Dot-leading lines"
deliver -u "remote" -- -m "$MAILBOX" <<-EOF
From: alice@example.net
To: bob@example.net
Date: $(date -R)
Message-ID: <$(xxd -ps -l8 /dev/urandom)@example.net>
foo
.
.bar
..baz
EOF
# we can't add a test for message data not ending with CRLF, because the
# LMTP/SMTP client needs to add a CRLF so local and remote message
# bodies would differ. that said, while such a message could be added
# by IMAP and LDA, it's not valid for SMTP (RFC 5321 sec. 4.1.1.4)
pullimap "remote" || error
check
step_done
# make sure remote UIDs are 11-bytes long
doveadm -u "remote" mailbox update --no-userdb-lookup --min-next-uid 1000000000 "$MAILBOX"
# Add some messages and sync
step_start "Fetching messages"
for ((i = 0; i < 32; i++)); do
sample_message | deliver -u "remote" -- -m "$MAILBOX"
done
pullimap "remote" || error
check
# same thing, but with some missing messages
for ((i = 0; i < N; i+=2)); do
sample_message | deliver -u "remote" -- -m "$MAILBOX"
deliver -u "remote" -- -m "$MAILBOX" </dev/null # odd seqnum
done
for ((i = 0; i < N; i+=2)); do
# expunge every other message
doveadm -u "remote" expunge --no-userdb-lookup mailbox "$MAILBOX" $((N-i+32+7))
sample_message | deliver -u "remote" -- -m "$MAILBOX"
done
pullimap "remote" || error
check
# count unseen remote messages
doveadm -u "remote" search --no-userdb-lookup mailbox "$MAILBOX" unseen >"$TMPDIR/unseen"
[ ! -s "$TMPDIR/unseen" ] || error "\\Unseen messages left"
step_done
if [ $TIMEOUT -gt 0 ]; then
step_start "--idle (${TIMEOUT}s)"
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
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
check
step_done
fi
step_start "Purging"
echo "purge-after = 0" >>"$XDG_CONFIG_HOME/pullimap/config"
for ((i = 0; i < 32; i++)); do
sample_message | deliver -u "remote" -- -m "$MAILBOX"
done
pullimap "remote"
doveadm -u "remote" search --no-userdb-lookup mailbox "$MAILBOX" all >"$TMPDIR/messages"
[ ! -s "$TMPDIR/messages" ] || error "messages left"
step_done
# vim: set filetype=bash :
|