Skip Menu |

This queue is for tickets about the Mail-IMAPClient CPAN distribution.

Report information
The Basics
Id: 48980
Status: resolved
Priority: 0/
Queue: Mail-IMAPClient

People
Owner: PLOBBES [...] cpan.org
Requestors: ROBN [...] cpan.org
Cc:
AdminCc:

Bug Information
Severity: Wishlist
Broken in: (no value)
Fixed in: 3.21



Gmail IMAP implements a XLIST extension that allows a client to determine which folders to use for functions such as Trash, Drafts, Sent, etc. Attached is a patch that adds two methods, "xlist" to handle the raw XLIST command, and "special_folders" as a user-friendly way to determine a mapping of "standard" folder types to actual folder names.
Subject: xlist.diff
diff --git a/lib/Mail/IMAPClient.pm b/lib/Mail/IMAPClient.pm index bda613d..2c6bc92 100644 --- a/lib/Mail/IMAPClient.pm +++ b/lib/Mail/IMAPClient.pm @@ -477,6 +477,12 @@ sub _list_or_lsub { sub list { shift->_list_or_lsub( "LIST", @_ ) } sub lsub { shift->_list_or_lsub( "LSUB", @_ ) } +sub xlist { + my ( $self ) = @_; + return undef unless $self->has_capability("XLIST"); + shift->_list_or_lsub( "XLIST", @_ ); +} + sub _folders_or_subscribed { my ( $self, $method, $what ) = @_; my @folders; @@ -531,6 +537,28 @@ sub folders { return wantarray ? @folders : \@folders; } +sub special_folders { + my ( $self ) = @_; + my $xlist = $self->xlist; + return undef unless defined $xlist; + + my $special_re = qr/\A\\(Inbox|AllMail|Trash|Drafts|Sent|Spam|Starred)\Z/; + + my %specials; + + for my $resp (@$xlist) { + my $rec = $self->_list_or_lsub_response_parse($resp); + next unless defined $rec->{name}; + for my $attr (@{$rec->{attrs}}) { + if ($attr =~ $special_re) { + $specials{$1} = $rec->{name}; + } + } + } + + return wantarray ? %specials : \%specials; +} + sub subscribed { my ( $self, $what ) = @_; my @folders = $self->_folders_or_subscribed( "lsub", $what ); @@ -1771,7 +1799,7 @@ sub _disconnect { $self; } -# LIST or LSUB Response +# LIST/XLIST or LSUB Response # Contents: name attributes, hierarchy delimiter, name # Example: * LIST (\Noselect) "/" ~/Mail/foo # NOTE: in _list_response_preprocess we append literal data so we need @@ -1784,10 +1812,10 @@ sub _list_or_lsub_response_parse { $resp =~ s/\015?\012$//; if ( - $resp =~ / ^\* \s+ (?:LIST|LSUB) \s+ # * LIST or LSUB - \( ([^\)]*) \) \s+ # (attrs) - (?: \" ([^"]*) \" | NIL ) \s # "delimiter" or NIL - (?:\s*\" (.*) \" | (.*) ) # "name" or name + $resp =~ / ^\* \s+ (?:LIST|XLIST|LSUB) \s+ # * LIST or XLIST or LSUB + \( ([^\)]*) \) \s+ # (attrs) + (?: \" ([^"]*) \" | NIL ) \s # "delimiter" or NIL + (?:\s*\" (.*) \" | (.*) ) # "name" or name /ix ) { diff --git a/lib/Mail/IMAPClient.pod b/lib/Mail/IMAPClient.pod index 1e44874..4868a9d 100644 --- a/lib/Mail/IMAPClient.pod +++ b/lib/Mail/IMAPClient.pod @@ -1269,6 +1269,75 @@ Notice that if you just want to list a folder's subfolders (and not the folder itself), then you need to include the hierarchy separator character (as returned by the L</separator> method). +=head2 special_folders + +Example: + + my $specials = $imap->special_folders + or die "Could not get special folders.\n"; + +IMAP servers implementing the XLIST extension (such as Gmail) designate +particular folders to be used for particular functions. This is useful +in the case where you want to know which folder should be used for Trash +when the actual folder name can't be predicted (eg in the case of Gmail, +the folder names change depending on the user's locale settings). + +The B<special_folders> method returns a hash listing any "special" +folder names, with the values listing the actual folders that should be +used for those names. For example, using this method with a Gmail user +using the English (US) locale might give this output from +L<Data::Dumper>: + + $VAR1 = { + 'Inbox' => 'Inbox', + 'AllMail' => '[Gmail]/All Mail', + 'Trash' => '[Gmail]/Trash', + 'Drafts' => '[Gmail]/Drafts', + 'Sent' => '[Gmail]/Sent Mail', + 'Spam' => '[Gmail]/Spam', + 'Starred' => '[Gmail]/Starred' + }; + +The same list for a user using the French locale might look like this: + + $VAR1 = { + 'Inbox' => 'Bo&AO4-te de r&AOk-ception', + 'AllMail' => '[Gmail]/Tous les messages', + 'Trash' => '[Gmail]/Corbeille', + 'Drafts' => '[Gmail]/Brouillons', + 'Sent' => '[Gmail]/Messages envoy&AOk-s', + 'Spam' => '[Gmail]/Spam', + 'Starred' => '[Gmail]/Suivis' + }; + +Mail::IMAPClient recognises the following "special" folder names: + +=over 4 + +=item Inbox + +=item AllMail + +=item Trash + +=item Drafts + +=item Sent + +=item Spam + +=item Starred + +=back + +These are currently the only ones supported by Gmail. The XLIST +extension is not documented, and there are no other known +implementations other than Gmail, so this list is based on what Gmail +provides. + +If the server does not support the XLIST extension, this method returns +undef. + =head2 has_capability Example:
Thanks for the patch, I'll look at possibly integrating this for the next release!
Any objection to changing the name 'special_folders' to 'xlist_folders' or something similar?
CC: ROBN [...] cpan.org, DJKERNEN__NO_SOLICITING__ [...] cpan.org
Subject: Re: [rt.cpan.org #48980] [PATCH] add support for XLIST extension
Date: Fri, 28 Aug 2009 11:10:16 +1000
To: Phil Lobbes via RT <bug-Mail-IMAPClient [...] rt.cpan.org>
From: Robert Norris <rob [...] cataclysm.cx>
Show quoted text
> Any objection to changing the name 'special_folders' to 'xlist_folders' > or something similar?
No objection from me. That probably makes more sense. Cheers, Rob.
Just released Mail::IMAPClient 3.21 which should resolve this bug. Methods added were xlist() and xlist_folders(). Thanks again for your contributions!