Attached please find a perl script which tests the CATENATE support in dovecot.
I used this to test my CATENATE implementation a few years ago and it runs
fine against dovecot in OS X Server. When run against dovecot-2.2.4 though it
always fails or hangs, which in some cases means we interpreted RFCs
differently and in other cases means it's finding bugs; both conditions are
worthy of scrutiny. (It's random-number driven so every run is different.) A
couple months ago I reported a few simple bugs which this script found and you
fixed them; thanks. Then it started finding problems for which it's harder to
isolate simple reproducible test cases. Vacations and other work interceded
but now Apple is pleased to give you the script itself to allow you to iterate
faster.
Here are some examples of it running. One time only, pass the --init argument
to store some template messages used by the real tests:
$ ./catenate.pl --host your.test.server --user testuser --password 1234 --init
connecting (imaps)...
capability...
logging in...
deleting old templates mailbox...
creating templates mailbox...
append1...
Append succeeded
append2...
Append succeeded
logout...
success
$ ./catenate.pl --host your.test.server --user testuser --password 1234
connecting (imaps)...
capability...
logging in...
append1...
Append failed as it should have (bad url): append1 NO [BADURL ;invalid;]
Invalid IMAP URL: Unexpected IMAP URL path segment: `;invalid;'.
append2...
Append failed as it should have (bad url): append2 NO [BADURL
/inbox/;uid=] Message not found.
append3...
Append succeeded
[...]
All tests passed.
$
If it concludes with anything other than All tests passed or hangs then it
found something that it didn't expect and that should be examined. Use the
--verbose option to see the entire client-server conversation.
We hope that you find this script helpful to harden your CATENATE code. I will
be happy to answer any questions.
#!/usr/bin/perl
# Test CATENATE support in dovecot.
# Use --init to initialize the template files in the mail store.
# Copyright (c) 2013 Apple Inc. All Rights Reserved.
#
# @APPLE_LICENSE_HEADER_START@
#
# This file contains Original Code and/or Modifications of Original Code
# as defined in and that are subject to the Apple Public Source License
# Version 2.0 (the 'License'). You may not use this file except in
# compliance with the License. Please obtain a copy of the License at
# http://www.opensource.apple.com/apsl/ and read it before using this
# file.
#
# The Original Code and all software distributed under the License are
# distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
# EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
# INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS
# FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please
# see the License for the specific language governing rights and
# limitations under the License.
#
# @APPLE_LICENSE_HEADER_END@
use strict;
use IO::Socket::INET;
use Getopt::Long;
use IPC::Open3;
use Digest::HMAC_MD5;
use APR::Base64;
use feature 'state';
sub usage
{
die EOT;
Usage: $0 --host imap-server --user name --password pw
Options:
--appends n number of APPENDs
--bufsiz n output buffer size
--buftag tag output buffer flushes
--init initialize template messages
--mailbox box append messages to this mailbox
--messages n messages per MULTIAPPEND
--parts n parts per message
--quiet
--select box select this mailbox before appending
--select-size n virtual size of message with UID=1 in selected mailbox
--store path path to mail store for the user
--verbose
EOT
}
my %opts;
GetOptions(\%opts,
'appends=i',
'bufsiz=i',
'buftag',
'host=s',
'init',
'mailbox=s',
'messages=i',
'parts=i',
'password=s',
'quiet',
'select=s',
'select-size=i',
'store=s',
'user=s',
'verbose',
) || usage();
$opts{appends} = 1000 unless defined($opts{appends});
usage() unless $opts{host};
$opts{mailbox} = INBOX unless defined($opts{mailbox});
usage() unless $opts{user};
usage() unless $opts{password};
if (defined($opts{select}) !defined($opts{'select-size'})) {
print STDERR --select needs --select-size\n;
usage();
}
my $checksizes = 0;
if (defined($opts{store})) {
my $myhost = `hostname`;
chomp $myhost;
if ($opts{host} eq 'localhost' or $opts{host} eq $myhost) {
$checksizes = 1;
} else {
die must run on server to check sizes\n;
}
}
$| = 1;
# These must match the constants in cmd-append.c (dovecot 2.2).
# Change both copies (cmd-append.c and here) for better testing coverage.
# Not sure if these apply to dovecot = 2.2.
my $MAX_URL_LITERAL_SIZE = 2048; # for testing: 20
my $MAX_CATENATE_MSG_SIZE = 4294967295; # for testing: 800
my $MAX_CATENATE_PARTS = 50; # for testing: 6
my $smallbody ='EOT';
Subject: small test message
Date: Thu, 03 Sep 2009 21:37:10 -0500 (CDT)
From: