aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Changelog2
-rwxr-xr-xpullimap11
-rw-r--r--tests/pullimap/t61
-rwxr-xr-xtests/run6
4 files changed, 65 insertions, 15 deletions
diff --git a/Changelog b/Changelog
index 1a80ebf..4a18c52 100644
--- a/Changelog
+++ b/Changelog
@@ -107,6 +107,8 @@ interimap (0.5) upstream;
for other servers the number remains 1).
- interimap: gracefully ignore messages with a NIL RFC822 attribute.
- pullimap: treat messages with a NIL RFC822 attribute as empty.
+ - pullimap: fix mangling of data lines starting with a dot (when an RFC
+ 5322 line starts with a '.', double it).
-- Guilhem Moulin <guilhem@fripost.org> Fri, 10 May 2019 00:58:14 +0200
diff --git a/pullimap b/pullimap
index fbe300e..ee2168d 100755
--- a/pullimap
+++ b/pullimap
@@ -175,17 +175,18 @@ sub sendmail($$) {
my $length = length($$rfc822);
while ((my $end = index($$rfc822, "\r\n", $offset) + 2) != 1) {
my $line = substr($$rfc822, $offset, $end-$offset);
- # RFC 5321 section 4.5.2: the character sequence "\r\n.\r\n"
- # ends the mail text and cannot be sent by the user
- $SMTP->print($line eq ".\r\n" ? "..\r\n" : $line) or die;
+ # RFC 5321 sec. 4.5.2: if the line starts with a dot, double it
+ $line = ".".$line if substr($line, 0, 1) eq ".";
+ $SMTP->print($line) or die;
$offset = $end;
}
if ($offset < $length) {
# the last line did not end with "\r\n"; add it in order to
# have the receiving SMTP server recognize the "end of data"
- # condition. See RFC 5321 section 4.1.1.4
+ # condition. See RFC 5321 sec. 4.1.1.4
my $line = substr($$rfc822, $offset);
- $SMTP->print(($line eq "." ? ".." : $line), "\r\n") or die;
+ $line = ".".$line if substr($line, 0, 1) eq ".";
+ $SMTP->print($line, "\r\n") or die;
}
$SMTP->printflush(".\r\n") or die;
}
diff --git a/tests/pullimap/t b/tests/pullimap/t
index 7ae0c5f..79da3e0 100644
--- a/tests/pullimap/t
+++ b/tests/pullimap/t
@@ -6,12 +6,9 @@ step_start "\`pullimap --idle\` refuses to create the state file"
! pullimap --idle "remote" || error
step_done
-# make sure remote UIDs are 11-bytes long
-doveadm -u "remote" mailbox update --min-next-uid 1000000000 "$MAILBOX"
-
# compare mailboxes; can't compare the RFC 3501 TEXT as LMTP adds a
# Received: header.
-# TODO unset lmtp_add_received_header once avaisable in Sid:
+# TODO unset lmtp_add_received_header once available in sid:
# https://doc.dovecot.org/settings/dovecot_core_settings/#lmtp-add-received-header
list_mails_sha256() {
local u="$1" guid uid
@@ -26,7 +23,59 @@ check() {
<( 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"
@@ -40,11 +89,11 @@ 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 # even seqnum
+ 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))
+ doveadm -u "remote" expunge mailbox "$MAILBOX" $((N-i+32+7))
sample_message | deliver -u "remote" -- -m "$MAILBOX"
done
diff --git a/tests/run b/tests/run
index 30d20f9..a34e4a9 100755
--- a/tests/run
+++ b/tests/run
@@ -235,11 +235,9 @@ sqlite3() {
# Sample (random) message
sample_message() {
local date="$(date +"%s.%N")"
- # also try non-conventional addresses for pullimap
- local sender="$(shuf -n1 -e "sender" "first.last" "foo-bar" \"\" "\"x\\\" #&\\\\y\"" )"
cat <<-EOF
- From: <$sender@example.net>
- To: <recipient@example.net>
+ From: <$(xxd -ps -l6 /dev/urandom)@example.net>
+ To: <me@example.net>
Date: $(date -R -d@"$date")
Message-ID: <$date@example.net>