Subject: | get_bodystructure() breaks with ALTERNATIVE and MIXED messages |
get_bodystructure() method breaks when called upon a
multipart/alternative message. I tracked it a bit and it seems to be a
problem in the grammar for BodyStructure.
For non-alternative messages, the answer to a BODYSTRUCTURE fetch is
something like:
* 23 FETCH (UID 58 BODYSTRUCTURE ("TEXT" "PLAIN" ("charset" "iso-8859-1")
which parses correctly. OTOH, when the message has ALTERNATIVE, the
parser breaks, like with the following (as got from Gmail, so you can
verify easily):
* 1 FETCH (UID 1 BODYSTRUCTURE (("TEXT" "PLAIN" ("charset" "ISO-8859-1")
NIL NIL "quoted-printable" 1744 0)("TEXT" "HTML" ("charset"
"ISO-8859-1") NIL NIL "quoted-printable" 1967 0) "ALTERNATIVE"))
I'm attaching the RD_TRACE for the parsing of the above string. There is
a similar issue with MIXED messages as well.
I'm also attaching a script that allows you to verify the bug. You'll
need a gmail account with some messages in the inbox; you can call it as
follows:
shell$ perl imap-bug.pl yourname yourpass
to get the list of messages (so that you can take the UID of the message
you want to investigate), and:
shell$ perl imap-bug.pl yourname yourpass uid
to call get_bodystructure().
Subject: | imap-bug.pl |
#!/usr/bin/env perl
use strict;
use warnings;
use Mail::IMAPClient;
use IO::Socket::SSL;
use List::Util qw( first );
my ($username, $password, $uid) = @ARGV;
# Connect to the IMAP server via SSL and get rid of server greeting message
my $socket = IO::Socket::SSL->new(
PeerAddr => 'imap.gmail.com',
PeerPort => 993,
)
or die "socket(): $@";
# Build up a client attached to the SSL socket and login
my $client = Mail::IMAPClient->new(
Socket => $socket,
User => $username,
Password => $password,
)
or die "new(): $@";
print "I'm authenticated\n" if $client->IsAuthenticated();
my $folder = 'Inbox';
$client->select($folder) or die "Could not select: $@";
my $msgcount = $client->message_count($folder);
die "could not message_count(): $@" unless defined $msgcount;
print "there are $msgcount (s) in $folder\n";
if ($uid) {
my $s = $client->get_bodystructure($uid)
or die "you hit a bug!\n";
require Data::Dumper;
print Data::Dumper::Dumper($s);
}
else {
print first {m/BODYSTRUCTURE\s+\(/i} $client->fetch($_, 'BODYSTRUCTURE')
for $client->search('ALL');
}
$client->logout();
Subject: | rdtrace |
Message body not shown because it is not plain text.