aboutsummaryrefslogtreecommitdiffstats
path: root/tests/pullimap/t
blob: e5087848462d3c2de2d02b687517c4fc14773a34 (plain)
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=60
N=2048

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 "$fields" mailbox-guid "$guid" uid "$uid" | sha256sum
    done < <(doveadm -u "$u" search mailbox "$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 --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 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 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 mailbox "$MAILBOX" all >"$TMPDIR/messages"
[ ! -s "$TMPDIR/messages" ] || error "messages left"
step_done

# vim: set filetype=bash :