Subject: | Failed to open IMAP4 folder using Mail::Box::Manager: Couldn't select IMAP4 folder |
Problem describtion
===================
I can successfully open an IMAP4 folder, using Mail::Box::IMAP4 directly
in the following way:
use Mail::Box::IMAP4;
my $imaphost = 'mail.example.org';
my $imapuser = 'USER';
my $imappass = 'PASS';
my $mailbox = 'INBOX';
my $folder= new Mail::Box::IMAP4(server_name => $imaphost,
username => $imapuser,
password => $imappass,
folder => $mailbox);
print $folder->nrMessages, " messages\n";
But when I try to use Mail::Box::Manager instead, the following code
fails:
use Mail::Box::Manager;
my $imaphost = 'mail.example.org';
my $imapuser = 'USER';
my $imappass = 'PASS';
my $mailbox = 'INBOX';
my $url = "imap4://$imapuser:$imappass\@$imaphost/$mailbox";
my $mgr = Mail::Box::Manager->new;
my $folder = $mgr->open(folder => $url);
print $folder->nrMessages, " messages\n";
I get the following error message:
ERROR: Couldn't select IMAP4 folder imap4://USER@mail.example.org:143
ERROR: Couldn't select IMAP4 folder imap4://USER@mail.example.org:143
WARNING: Folder does not exist, failed opening imap4 folder
imap4://USER@mail.example.org:143.
Analysis
========
The problem seem to be caused by the differences in the semantic of
the 'folder' argument between Mail::Box::Manager and Mail::Box::IMAP4.
In Mail::Box::Manager assumes the "folder" argument to be the url,
while Mail::Box::IMAP4 assumes the folder to be just the IMAP4 mailbox
part, "/INBOX" in this example.
Digging through the code, I see that Mail::Box::Manager correctly
decodes the folder url in sub open in line 141:
my %decoded = $self->decodeFolderURL($name);
if(keys %decoded)
{ # accept decoded info
@args{keys %decoded} = values %decoded;
}
which results in
%args = (
authentication => 'AUTO',
folder => '/INBOX'
password => 'PASS',
server_name => 'mail.example.org',
server_port => undef,
type => 'imap4',
username => 'USER',
);
This is just fine and could perfectly be passed to Mail::Box::IMAP4
this way. But then, Mail::Box::Manager overwrites the folder in line
174:
elsif($type eq 'imap4')
{ my $un = $args{username} ||= $ENV{USER} || $ENV{LOGIN};
my $srv = $args{server_name} ||= 'localhost';
my $port = $args{server_port} ||= 143;
$args{folder} = $name = "imap4://$un\@$srv:$port";
}
This is just plain wrong. As a consequence, Mail::Box::IMAP4->new
gets called with the following arguments:
%args = (
access => 'r',
authentication => 'AUTO',
folder => 'imap4://USER@mail.example.org:143',
folderdir => '.',
manager => Mail::Box::Manager=HASH(0x1409580),
password => 'PASS',
server_name => 'mail.example.org',
server_port => 143,
type => 'imap4',
username => 'USER',
);
which obviously leads to the above-mentioned error.
Fix
===
Do not overwrite the folder in Mail::Box::Manager, see attached patch.
After applying the patch, opening an IMAP4 folder using
Mail::Box::Manager with the example code above works fine for me.
Note: the code code for POP3 in Mail::Box::Manager looks similar and
might contain the same error. But I do not have access to any POP3
server, so I can't try this out.
Subject: | Mail-Box-IMAP-folder.patch |
--- lib/Mail/Box/Manager.pm.orig 2012-11-28 12:28:35.000000000 +0100
+++ lib/Mail/Box/Manager.pm 2013-01-27 15:26:51.312252501 +0100
@@ -171,7 +171,7 @@
{ my $un = $args{username} ||= $ENV{USER} || $ENV{LOGIN};
my $srv = $args{server_name} ||= 'localhost';
my $port = $args{server_port} ||= 143;
- $args{folder} = $name = "imap4://$un\@$srv:$port";
+ $name = "imap4://$un\@$srv:$port";
}
unless(defined $name && length $name)