File Coverage

blib/lib/Net/IMAP.pm
Criterion Covered Total %
statement 13 15 86.6
branch n/a
condition n/a
subroutine 5 5 100.0
pod n/a
total 18 20 90.0


line stmt bran cond sub pod time code
1             #!/usr/local/bin/perl
2             #
3             # Copyright (c) 1997-1999 Kevin Johnson .
4             #
5             # All rights reserved. This program is free software; you can
6             # redistribute it and/or modify it under the same terms as Perl
7             # itself.
8             #
9             # $Id: IMAP.pm,v 1.2 1999/10/03 14:56:21 kjj Exp $
10              
11             require 5.005;
12              
13             package Net::IMAP;
14              
15 1     1   5110 use strict;
  1         2  
  1         43  
16              
17             =head1 NAME
18              
19             Net::IMAP - A client interface to IMAP (Internet Message Access Protocol).
20              
21             B
22             change release to release.>
23              
24             =cut
25              
26 1     1   578 use Net::xAP;
  1         3  
  1         41  
27 1     1   16 use Carp;
  1         1  
  1         73  
28 1     1   897 use MIME::Base64;
  1         847  
  1         65  
29 1     1   1559 use Digest::HMAC_MD5 qw(hmac_md5 hmac_md5_hex);
  0            
  0            
30              
31             use vars qw($VERSION @ISA $AUTOLOAD);
32              
33             $VERSION = "0.02";
34              
35             @ISA = qw(Net::xAP);
36              
37             use constant ATOM => Net::xAP::ATOM;
38             use constant ASTRING => Net::xAP::ASTRING;
39             use constant PARENS => Net::xAP::PARENS;
40             use constant SASLRESP => Net::xAP::SASLRESP;
41              
42             =head1 SYNOPSIS
43              
44             C
45              
46             =head1 DESCRIPTION
47              
48             C provides a perl interface to the client portion of IMAP
49             (Internet Message Access Protocol).
50              
51             B
52             callbacks, convenience routines>
53              
54             =head1 METHODS
55              
56             =cut
57              
58             use constant IMAP_STATE_NOT_AUTH => 1;
59             use constant IMAP_STATE_AUTH => 2;
60             use constant IMAP_STATE_SELECT => 4;
61             use constant IMAP_STATE_ANY => 7;
62              
63             my %untagged_callbacks = (
64             'ok' => [\&_default_aux_callback],
65             'bye' => [\&_default_aux_callback],
66             'bad' => [\&_default_aux_callback],
67             'no' => [\&_default_aux_callback],
68             'capability' => [undef],
69             'list' => [undef],
70             'lsub' => [undef],
71             'status' => [undef],
72             'search' => [undef],
73             'flags' => [undef],
74             'exists' => [undef],
75             'recent' => [undef],
76             'expunge' => [undef],
77             'fetch' => [undef],
78             'namespace' => [undef],
79             'acl' => [undef],
80             'listrights' => [undef],
81             'myrights' => [undef],
82             'quota' => [undef],
83             'quotaroot' => [undef],
84             );
85              
86             my %cmd_callbacks = (
87             'noop' => [undef, IMAP_STATE_ANY],
88             'capability' => [undef, IMAP_STATE_ANY],
89             'logout' => [undef, IMAP_STATE_ANY],
90             'authenticate' => ['_login_cmd_callback',
91             IMAP_STATE_NOT_AUTH],
92             'login' => ['_login_cmd_callback', IMAP_STATE_NOT_AUTH],
93             'select' => ['_select_cmd_callback',
94             IMAP_STATE_AUTH|IMAP_STATE_SELECT],
95             'examine' => ['_select_cmd_callback',
96             IMAP_STATE_AUTH|IMAP_STATE_SELECT],
97             'create' => [undef, IMAP_STATE_AUTH|IMAP_STATE_SELECT],
98             'delete' => [undef, IMAP_STATE_AUTH|IMAP_STATE_SELECT],
99             'rename' => [undef, IMAP_STATE_AUTH|IMAP_STATE_SELECT],
100             'subscribe' => [undef, IMAP_STATE_AUTH|IMAP_STATE_SELECT],
101             'list' => [undef, IMAP_STATE_AUTH|IMAP_STATE_SELECT],
102             'lsub' => [undef, IMAP_STATE_AUTH|IMAP_STATE_SELECT],
103             'status' => [undef, IMAP_STATE_AUTH|IMAP_STATE_SELECT],
104             'append' => [undef, IMAP_STATE_AUTH|IMAP_STATE_SELECT],
105             'check' => [undef, IMAP_STATE_SELECT],
106             'close' => ['_close_cmd_callback', IMAP_STATE_SELECT],
107             'expunge' => [undef, IMAP_STATE_SELECT],
108             'search' => [undef, IMAP_STATE_SELECT],
109             'fetch' => [undef, IMAP_STATE_SELECT],
110             'store' => [undef, IMAP_STATE_SELECT],
111             'copy' => [undef, IMAP_STATE_SELECT],
112             'uid copy' => [undef, IMAP_STATE_SELECT],
113             'uid fetch' => [undef, IMAP_STATE_SELECT],
114             'uid search' => [undef, IMAP_STATE_SELECT],
115             'uid store' => [undef, IMAP_STATE_SELECT],
116             # Extension commands:
117             'namespace' => [undef, IMAP_STATE_AUTH|IMAP_STATE_SELECT],
118             'setacl' => [undef, IMAP_STATE_AUTH|IMAP_STATE_SELECT],
119             'getacl' => [undef, IMAP_STATE_AUTH|IMAP_STATE_SELECT],
120             'deleteacl' => [undef, IMAP_STATE_AUTH|IMAP_STATE_SELECT],
121             'listrights' => [undef,
122             IMAP_STATE_AUTH|IMAP_STATE_SELECT],
123             'myrights' => [undef, IMAP_STATE_AUTH|IMAP_STATE_SELECT],
124             'getquota' => [undef, IMAP_STATE_AUTH|IMAP_STATE_SELECT],
125             'setquota' => [undef, IMAP_STATE_AUTH|IMAP_STATE_SELECT],
126             'getquotaroot' => [undef,
127             IMAP_STATE_AUTH|IMAP_STATE_SELECT],
128             'uid expunge' => [undef, IMAP_STATE_SELECT],
129             );
130              
131             my %_system_flags = (
132             '\seen' => 1,
133             '\answered' => 1,
134             '\flagged' => 1,
135             '\deleted' => 1,
136             '\draft' => 1,
137             '\recent' => 1,
138             );
139              
140             =head2 new $host, %options
141              
142             Creates a new C object, connects to C<$host> on port 143,
143             performs some preliminary setup of the session, and returns a
144             reference to the object.
145              
146             Once connected, it processes the connection banner sent by the server.
147             If the considers the session to be preauthenticated, C notes the
148             fact, allowing commands to be issued without logging in.
149              
150             The method also issues a C command, and notes the result.
151             If the server does support IMAP4rev1, the method closes the connection
152             and returns C.
153              
154             The client will use non-synchronizing literals if the server supports
155             the C extension (RFC2088) and the C options is
156             set to C<1>.
157              
158             The following C options are relevant to C:
159              
160             =over 4
161              
162             =item C 1>
163              
164             =item C 0>
165              
166             =item C 0>
167              
168             =item C 0>
169              
170             =back
171              
172             C also understands the following options, specific to the module:
173              
174             =over 4
175              
176             =item C 'lf'>
177              
178             Controls what style of end-of-line processing to presented to the
179             end-programmer. The default, C<'lf'>, assumes that the programemr
180             wants to fling messages terminated with bare LFs when invoking append,
181             and when fetching messages. In this case, the module will map to/from
182             CRLF accordingly.
183              
184             If C is set to C<'crlf'>, the assumption is that the programmer
185             wants messages, or portions of messages, to be terminated with CRLF.
186             It also assumes the programmer is providing messages terminated with
187             the string when invoking the C method, and will not provide an
188             EOL mapping.
189              
190             =back
191              
192             =cut
193              
194             sub new {
195             my $class = shift;
196             my $type = ref($class) || $class;
197             my $host = shift if @_ % 2;
198             my %options = @_;
199              
200             my $self = Net::xAP->new($host, 'imap2(143)', Timeout => 10, %options)
201             or return undef;
202              
203             bless $self, $class;
204              
205             $self->{Options}{EOL} ||= 'lf';
206             $self->{Options}{EOL} = lc($self->{Options}{EOL}); # force lower-case
207              
208             $self->{PreAuth} = 0;
209             $self->{Banner} = undef;
210             $self->{Capabilities} = ();
211             $self->_init_mailbox;
212             $self->{Disconnect} = 0;
213             $self->{State} = IMAP_STATE_NOT_AUTH;
214              
215             $self->{ResponseCallback} = $self->imap_response_callback;
216              
217             STDERR->autoflush(1);
218              
219             $self->_get_banner or return undef;
220              
221             # the little back-flip here with the Synchronous option ensures that
222             # the capability command is issued in Synchronous mode
223              
224             my $mode = $self->{Options}{Synchronous}; # save current sync mode
225             $self->{Options}{Synchronous}++; # force sync mode on
226             my $resp = $self->capability;
227             $self->{Options}{Synchronous} = $mode; # restore previous sync mode
228              
229             if ($resp->status ne 'ok') {
230             carp "capability command failed on initial connection";
231             $self->close_connection or carp "error closing connection: $!";
232             $! = 5; # *sigh* error reporting needs to be improved
233             return undef;
234             }
235              
236             return $self;
237             }
238              
239             sub _init_mailbox {
240             my $self = shift;
241             $self->{Mailbox} = '';
242             $self->{MailboxStatus} = ();
243             $self->{MailboxStatus}{'recent'} = 0;
244             $self->{MailboxStatus}{'unseen'} = 0;
245             $self->{MailboxStatus}{'exists'} = 0;
246             $self->{MailboxStatus}{'uidvalidity'} = 0;
247             $self->{MailboxStatus}{'uidnext'} = 0;
248             $self->{MailboxStatus}{'flags'} = ();
249             }
250              
251             sub debug_text { $_[2] =~ /^(\d+ LOGIN [^\s]+)/i ? "$1 ..." : $_[2] }
252              
253             sub _get_banner {
254             my $self = shift;
255             my $str = $self->getline;
256              
257             my $list = $self->parse_fields($str);
258             return undef unless defined($list);
259              
260             if (($list->[0] eq '*') && ($list->[1] =~ /^preauth$/i)) {
261             $self->{PreAuth}++;
262             $self->{State} = IMAP_STATE_AUTH;
263             } elsif (($list->[0] ne '*') || ($list->[1] !~ /^ok$/i)) {
264             return undef;
265             }
266             my $supports_imap4rev1 = 0;
267             for my $item (@{$list}) {
268             $supports_imap4rev1++ if ($item =~ /^imap4rev1$/i);
269             }
270             unless ($supports_imap4rev1) {
271             $self->close_connection;
272             return undef;
273             }
274              
275             $self->{Banner} = $list;
276              
277             return 1;
278             }
279              
280             sub DESTROY {
281             my $self = shift;
282             }
283              
284             sub AUTOLOAD {
285             my $self = shift;
286             my $cmd = $AUTOLOAD;
287             $cmd =~ s/^.*:://;
288             carp("unknown command: $cmd");
289             return undef;
290             }
291              
292             ###############################################################################
293              
294             =head1 IMAP COMMAND METHODS
295              
296             There are numerous commands in the IMAP protocol. Each of these are
297             mapped to a corresponding method in the C module.
298              
299             Some commands can only be issued in certain protocol states. Some
300             commands alter the state of the session. These facts are indicated in
301             the documentation for the individual command methods.
302              
303             The following list enumerates the protocol states:
304              
305             =over 4
306              
307             =item Non-authenticated
308              
309             The client has not authenticated with the server. Most commands are
310             unavailable in this state.
311              
312             =item Authenticated
313              
314             The client has authenticated with the server.
315              
316             =item Selected
317              
318             The client has opened a mailbox on the server.
319              
320             =back
321              
322             =head2 noop
323              
324             Sends a C command to the server. It is valid in any protocol state.
325              
326             This method is useful for placating the auto-logout god, or for
327             triggering pending unsolicited responses from the server.
328              
329             =cut
330              
331             sub noop { $_[0]->imap_command('noop') }
332              
333             =head2 capability
334              
335             The C method retrieves the capabilities the IMAP server
336             supports. This method is valid in any protocol state.
337              
338             The server sends a C response back to the client.
339              
340             If the response does not indicate support for the C
341             extension, the C option is forced off.
342              
343             =cut
344              
345             sub capability { $_[0]->imap_command('capability') }
346              
347             =head2 logout
348              
349             Logs off of the server. This method is valid in any protocol state.
350              
351             =cut
352              
353             sub logout {
354             $_[0]->{Disconnect}++;
355             $_[0]->imap_command('logout');
356             }
357              
358             =head2 login $user, $password
359              
360             Logs into the server using a simple plaintext password. This method
361             is only valid when the protocol is in the non-authenticated state.
362              
363             If the server supports RFC2221 (IMAP4 Login Referrals), the completion
364             response could include a referral. See RFC2221 for further
365             information about login referrals.
366              
367             If successful, the session state is changed to I.
368              
369             =cut
370              
371             sub login { $_[0]->imap_command('login', ASTRING, $_[1], ASTRING, $_[2]) }
372              
373             =head2 authenticate $authtype, @authinfo
374              
375             Logs into the server using the authentication mechanism specified in
376             C<$authtype>. This method is only valid when the protocol is in the
377             non-authenticated state.
378              
379             The IMAP C command is the same as that documented in
380             RFC2222 (Simple Authentication and Security Layer (SASL)), despite the
381             fact that IMAP predates SASL.
382              
383             If successful, the session state is changed to I.
384              
385             The following authentication mechanisms are currently supported:
386              
387             =over 4
388              
389             =item C<'login'>
390              
391             This is a variation on the simple login technique, except that the
392             information is transmitted in Base64. This does not provide any
393             additional security, but does allow clients to use C.
394              
395             =item C<'cram-md5'>
396              
397             This implements the authentication mechanism defined in RFC2195
398             (IMAP/POP AUTHorize Extension for Simple Challenge/Response). It uses
399             keyed MD5 to avoid sending the password over the wire.
400              
401             =item C<'anonymous'>
402              
403             This implements the authentication mechanism defined in RFC2245
404             (Anonymous SASL Mechanism). Anonymous IMAP access is intended to
405             provide access to public mailboxes or newsgroups.
406              
407             =back
408              
409             The method returns C is C<$authtype> specifies an unsupported
410             mechanism or if the server does not advertise support for the
411             mechanism. The C method can be used to see whether the
412             server supports a particular authentication mechanism.
413              
414             In general, if the server supports a mechanism supported by
415             C, the C command should be used instead of
416             the C method.
417              
418             =cut
419              
420             my %auth_funcs = (
421             'LOGIN' => \&authenticate_login,
422             'CRAM-MD5' => \&authenticate_cram,
423             'ANONYMOUS' => \&authenticate_anonymous,
424             );
425              
426             my @auth_strings;
427              
428             sub authenticate {
429             my $authtype = uc($_[1]);
430             return undef unless defined($auth_funcs{$authtype});
431             return undef unless defined($_[0]->has_authtype($authtype));
432             my $func = $auth_funcs{$authtype};
433             @auth_strings = @_[2..$#_];
434             $_[0]->imap_command('authenticate',
435             ATOM, $authtype,
436             SASLRESP, $func);
437             }
438              
439             sub authenticate_login {
440             my $i = shift;
441              
442             return undef unless defined($auth_strings[$i]);
443             return encode_base64($auth_strings[$i], '');
444             }
445              
446             sub authenticate_cram {
447             my $i = shift;
448             my $challenge = shift;
449              
450             if ($i == 0) {
451             $challenge = decode_base64($challenge);
452             $challenge = hmac_md5_hex($challenge, $auth_strings[1]);
453             $auth_strings[1] = undef;
454             return(encode_base64("$auth_strings[0] $challenge", ''));
455             }
456             return undef;
457             }
458              
459             sub authenticate_anonymous {
460             my $i = shift;
461             return(encode_base64(join(' ', @auth_strings), '')) if ($i == 0);
462             return undef;
463             }
464              
465             =head2 select $mailbox
466              
467             Opens the specified mailbox with the intention of performing reading
468             and writing. This method is valid only when the session is in the
469             authenticated or selected states.
470              
471             If successful, the server sends several responses: C,
472             C, C, as well as C responses containing a
473             C, C, C, and C codes.
474             If also changes the session state to I.
475              
476             If server returns a C response containing a C response
477             code, this means C<$mailbox> does not exist but the server thinks this
478             is because the folder was renamed. In this case, try specifiying the
479             new folder name provided with the C response code.
480              
481             =cut
482              
483             sub select {
484             $_[0]->{Mailbox} = $_[1];
485             my $ret = $_[0]->imap_command('select', ASTRING, _encode_mailbox($_[1]));
486             $_[0]->{Mailbox} = '' unless defined($ret);
487             return $ret;
488             }
489              
490             =head2 examine $mailbox
491              
492             Opens the specified mailbox in read-only mode. This method is valid
493             only when the session is in the authenticated or selected states.
494              
495             =cut
496              
497             sub examine { $_[0]->imap_command('examine', ASTRING, _encode_mailbox($_[1])) }
498              
499             =head2 create $mailbox [, $partition]
500              
501             Creates the specified mailbox. This method is valid only when the
502             session is in the authenticated or selected states.
503              
504             The optional C<$partition> argument is only valid with the Cyrus IMAP
505             daemon. Refer to the section 'Specifying Partitions with "create"'
506             the C file for that package for further information.
507             This feature can only be used by administrators creating new
508             mailboxes. Other servers will probably reject the command if this
509             argument is used. The results are undefined if another server accepts
510             a second argument.
511              
512             =cut
513              
514             sub create {
515             my @args = (ASTRING, _encode_mailbox($_[1]));
516             push @args, ATOM, $_[2] if (defined($_[2]));
517             $_[0]->imap_command('create', @args);
518             }
519              
520             =head2 delete $mailbox
521              
522             Deletes the specified mailbox. Returns C if C<$mailbox> is the
523             currently open mailbox. This method is valid only when the session is
524             in the authenticated or selected states.
525              
526             =cut
527              
528             sub delete {
529             return undef if ($_[0]->{Mailbox} eq $_[1]);
530             $_[0]->imap_command('delete', ASTRING, _encode_mailbox($_[1]));
531             }
532              
533             =head2 rename $oldmailboxname, $newmailboxname [, $partition]
534              
535             Renames the mailbox specified in C<$oldmailbox> to the name specified
536             in C<$newmailbox>. This method is valid only when the session is in
537             the authenticated or selected states.
538              
539             The optional C<$partition> argument is only valid with the Cyrus IMAP
540             daemon. Refer to the section 'Specifying Partitions with "rename"'
541             the C file for that package for further information.
542             This feature can only be used by administrators. Other servers will
543             probably reject the command if this argument is used. The results are
544             undefined if another server accepts a third argument.
545              
546             =cut
547              
548             sub rename {
549             my @args = (ASTRING, _encode_mailbox($_[1]), ASTRING, _encode_mailbox($_[2]));
550             push @args, ATOM, $_[3] if defined($_[3]);
551             $_[0]->imap_command('rename', @args);
552             }
553              
554             =head2 subscribe $mailbox
555              
556             Subscribe to the specified C<$mailbox>. Subscribing in IMAP is
557             subscribing in Usenet News, except that the server maintains the
558             subscription list. This method is valid only when the session is in
559             the authenticated or selected states.
560              
561             =cut
562              
563             sub subscribe { $_[0]->imap_command('subscribe',
564             ASTRING, _encode_mailbox($_[1])) }
565              
566             =head2 unsubscribe $mailbox
567              
568             Unsubscribe from the specified C<$mailbox>. This method is valid only
569             when the session is in the authenticated or selected states.
570              
571             =cut
572              
573             sub unsubscribe { $_[0]->imap_command('unsubscribe',
574             ASTRING, _encode_mailbox($_[1])) }
575              
576             =head2 list $referencename, $mailbox_pattern
577              
578             Send an IMAP C command to the server. This method is valid only
579             when the session is in the authenticated or selected states.
580              
581             Although IMAP folders do not need to be implemented as directories,
582             think of an IMAP reference name as a parameter given to a C or
583             C command, prior to checking for folders matching
584             C<$mailbox_pattern>.
585              
586             The C<$mailbox_pattern> parameter allows a couple wildcard characters
587             to list subsets of the mailboxes on the server.
588              
589             =over 4
590              
591             =item *
592              
593             Matches zero or more characters at the specified location.
594              
595             =item %
596              
597             Like C<*>, matches zero or more characters at the specified location,
598             but does not match hierarchy delimiter characters.
599              
600             If the last character in C<$mailbox_pattern> is a C<%>, matching
601             levels of hierarchy are also returned. In other words: subfolders.
602              
603             =back
604              
605             This method will fail, returning C, if C<$mailbox_pattern> is
606             C<*>. This behavior is not built into the IMAP protocol; it is wired
607             into C. Doing otherwise could be rude to both the client
608             and server machines. If you want to know why, imagine doing
609             C on a machine with a full news feed. The C<%>
610             character should be used to build up a folder tree incrementally.
611              
612             If successful, the server sends a series of C responses.
613              
614             Please note that the C<$referencename> is an IMAPism, not a Perl
615             reference. Also note that the wildcards usable in C<$mailbox_pattern>
616             are specific to IMAP. Perl regexps are not usable here.
617              
618             =cut
619              
620             sub list {
621             return undef if ($_[2] eq '*');
622             $_[0]->imap_command('list',
623             ASTRING, _encode_mailbox($_[1]),
624             ASTRING, _encode_mailbox($_[2]));
625             }
626              
627             =head2 lsub $referencename, $mailbox_pattern
628              
629             Sends an IMAP C command to the server. The C command is
630             similar to the C command, except that the server only returns
631             subscribed mailboxes. This method is valid only when the session is
632             in the authenticated or selected states.
633              
634             The parameters are the same as those for the C method.
635              
636             If successful, the server sends a series of C responses.
637              
638             =cut
639              
640             sub lsub { $_[0]->imap_command('lsub',
641             ASTRING, _encode_mailbox($_[1]),
642             ASTRING, _encode_mailbox($_[2])) }
643              
644             =head2 status $mailbox, @statusattrs
645              
646             Retrieves status information for the specified C<$mailbox>. This
647             method is valid only when the session is in the authenticated or
648             selected states.
649              
650             Per RFC2060, the C<@statusattrs> can contain any of the following
651             strings:
652              
653             =over 4
654              
655             =item * messages
656              
657             The number of messages in the mailbox.
658              
659             =item * recent
660              
661             The number of messages with the C<\recent> flag set.
662              
663             =item * uidnext
664              
665             The UID expected to be assigned to the next mailbox appended to the
666             mailbox. This requires some explanation. Rather than using this
667             value for prefetching the next UID, it should be used to detect
668             whether messages have been added to the mailbox. The value will not
669             change until messages are appended to the mailbox.
670              
671             =item * uidvalidity
672              
673             The unique identifier validity value of the mailbox.
674              
675             =item * unseen
676              
677             The number of messages without the C<\seen> flag set.
678              
679             =back
680              
681             This method will fail, returning C if C<$mailbox> is the
682             currently open mailbox.
683              
684             If successful, the server sends one or more C responses.
685              
686             The status operation can be rather expensive on some folder
687             implementations, so clients should use this method sparingly.
688              
689             =cut
690              
691             sub status {
692             my $self = shift;
693             my $mailbox = shift;
694             return undef if ($self->{Mailbox} eq $mailbox);
695             $self->imap_command('status',
696             ASTRING, _encode_mailbox($mailbox), PARENS, [@_]);
697             }
698              
699             =head2 append $mailbox, $message [, Flags => $flaglistref] [, Date => $date]
700              
701             Appends the email message specified in C<$message> to the mailbox
702             specified in C<$mailbox>. This method is valid only when the session
703             is in the authenticated or selected states.
704              
705             In general, the email message should be a real RFC822 message,
706             although exceptions such as draft messages are reasonable in some
707             situations. Also note that the line terminators in C<$message> need
708             to be CRLF.
709              
710             The C option allows a set of flags to be specified for the
711             message when it is appended. Servers are not required to honor this,
712             but most, if not all, do so.
713              
714             The C option forces the internaldate to the specified value. If
715             C<$date> is a string, the format of the string is C
716             hh:mm:ss [-+]zzzz>, where C
is the day of the month (starting from
717             1), C is the three-character abbreviation for the month name,
718             C is the 4-digit year, C is the hour, C is the minutes,
719             C is the seconds, and C<[-+]zzzz> is the numeric timezone offset.
720             This happens to be the same format returned by the C
721             item from the C command. If C<$date> is a list reference, it is
722             expected to contain two elements: a time integer and a timezone offset
723             string. The timezone string is expected to be formatted as
724             C<[-+]zzzz>. These two values will be used to synthesize a string in
725             the format expected by the IMAP server. As with the C options,
726             servers are not required to honor the C option, but most, if not
727             all, do so.
728              
729             Note that the options are specified at the end of the list of method
730             arguments. This is due to the fact that it is possible to have a
731             C<$mailbox> named C or C. Processing the options at the
732             end of the argument list simplifies argument processing. The order of
733             the arguments will be changed if enough people complain.
734              
735             If server returns a C response containing a C response
736             code, this means C<$mailbox> does not exist but the server thinks the
737             command would have succeeded if the an appropriate C command
738             was issued. On the other hand, failure with no C response
739             code generally means that a C should not be attempted.
740              
741             =cut
742              
743             sub append {
744             my $self = shift;
745             my $mailbox = shift;
746             my $lit = shift;
747             my %options = @_;
748             my @args;
749              
750             push @args, ASTRING, _encode_mailbox($mailbox);
751              
752             if (defined($options{Flags})) {
753             for my $flag (@{$options{Flags}}) {
754             unless ($self->_valid_flag($flag)) {
755             carp "$flag is not a system flag";
756             return undef;
757             }
758             }
759             push @args, PARENS, [@{$options{Flags}}];
760             }
761             if (defined($options{Date})) {
762             my $date;
763             if ((ref($options{Date}) eq 'ARRAY')
764             && defined($options{Date}->[1])){
765             my @months = qw(Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec);
766             my @gmtime = gmtime($options{Date}->[0]);
767             $date = sprintf("%02d-%2s-%4d %02d:%02d:%02d %s",
768             $gmtime[3], $months[$gmtime[4]], $gmtime[5] + 1900,
769             $gmtime[2], $gmtime[1], $gmtime[0],
770             $options{Date}->[1]);
771             } else {
772             $date = $options{Date};
773             }
774             if ($date !~ /^[ \d][\d]-[a-zA-Z]{3}-\d{4} \d\d:\d\d:\d\d [\+\-]\d{4}$/) {
775             carp "invalid date value for append command";
776             return undef;
777             }
778             push @args, ATOM, "\"$date\"";
779             }
780             $lit =~ s/\n/\r\n/mg if ($self->{Options}{EOL} eq 'lf');
781             push @args, ASTRING, $lit;
782              
783             $self->imap_command('append', @args);
784             }
785              
786             =head2 check
787              
788             Ask the server to perform a checkpoint of its data. This method is
789             valid only when the session is in the selected state.
790              
791             While not always needed, this should be called if the client issues a
792             large quantity of updates to a folder in an extended session.
793              
794             =cut
795              
796             sub check { $_[0]->imap_command('check') }
797              
798             =head2 close
799              
800             Close the current mailbox. This method is valid only when the session
801             is in the selected state.
802              
803             If successful, the session state is changed to I.
804              
805             =cut
806              
807             sub close { $_[0]->imap_command('close') }
808              
809             =head2 expunge
810              
811             Delete messages marked for deletion. This method is valid only when
812             the session is in the selected state.
813              
814             If successful, the server sends a series of C responses.
815              
816             It will return C is the mailbox is marked read-only.
817              
818             =cut
819              
820             sub expunge {
821             return undef if $_[0]->is_readonly;
822             $_[0]->imap_command('expunge');
823             }
824              
825             =head2 search [Charset => $charset,] @searchkeys
826              
827             Searches the mailbox for messages matching the criteria contained in
828             C<@searchkeys>. This method is valid only when the session is in the
829             selected state.
830              
831             The C<@searchkeys> list contains strings matching the format described
832             in Section 6.4.4 of RFC2060.
833              
834             If successful, the server send zero or more C responses. Lack
835             of a C response means the server found no matches. Note that
836             the server can send the results of one search in multiple responses.
837              
838             =cut
839              
840             sub search {
841             my $self = shift;
842             my @args;
843             if ($_[0] =~ /^charset$/i) {
844             shift;
845             my $charset = shift;
846             push @args, ATOM, 'charset', ASTRING, $charset;
847             }
848             push @args, map { (ATOM, $_) } @_;
849             $self->imap_command('search', @args);
850             }
851              
852             =head2 fetch $msgset, 'all'|'full'|'fast'|$fetchattr|@fetchattrs
853              
854             Retrieves data about a set of messages. This method is valid only
855             when the session is in the selected state.
856              
857             The C<$msgset> parameter identifies the set of messages from which to
858             retrieve the items of interest. The notation accepted is similar to
859             that found in C<.newsrc> files, except that C<:> is used to specify
860             ranges, instead of C<->. Thus, to specify messages 1, 2, 3, 5, 7, 8,
861             9, the following string could be used: C<'1:3,5,7:9'>. The character
862             C<*> can be used to indicate the highest message number in the
863             mailbox. Thus, to specify the last 4 messages in an 8-message
864             mailbox, you can use C<'5-*'>.
865              
866             The following list enumerates the items that can be retrieved with
867             C. Refer to Section 6.4.5 of RFC2060 for a description of each
868             of these items.
869              
870             =over 4
871              
872             =item * body[$section]E$partialE
873              
874             =item * body.peek[$section]E$partialE
875              
876             Important: the response item returned for a C is C.
877              
878             =item * bodystructure
879              
880             =item * body
881              
882             =item * envelope
883              
884             =item * flags
885              
886             =item * internaldate
887              
888             =item * rfc822
889              
890             =item * rfc822.header
891              
892             =item * rfc822.size
893              
894             =item * rfc822.text
895              
896             =item * uid
897              
898             =back
899              
900             Please note that the items returning messages, or portion of messages,
901             return strings terminated with CRLF.
902              
903             RFC2060 also defines several items that are actually macros for other
904             sets of items:
905              
906             =over 4
907              
908             =item * all
909              
910             A macro equivalent to C<('flags', 'internaldate', 'rfc822.size', 'envelope')>.
911              
912             =item * full
913              
914             A macro equivalent to C<('flags', 'rfc822.size', 'envelope', 'body')>.
915              
916             =item * fast
917              
918             A macro equivalent to C<('flags', 'internaldate', 'rfc822.size')>.
919              
920             =back
921              
922             The C, C, and C items are not intended to be used
923             with other items.
924              
925             If successful, the server responses with one or more C
926             responses.
927              
928             If the completion response from a C command is C, the
929             client should send a C command, to force any pending expunge
930             responses from the server, and retry the C command with
931             C<$msgset> adjusted accordingly.
932              
933             =cut
934              
935             sub fetch {
936             my $self = shift;
937             my $msgset = shift;
938             my @args;
939             if (scalar(@_) == 1) {
940             push @args, ATOM, shift;
941             } else {
942             push @args, PARENS, [@_];
943             }
944             $self->imap_command('fetch', ATOM, $msgset, @args);
945             }
946              
947             =head2 store $msgset, $itemname, @storeattrflags
948              
949             Sets various attributes for the messages identified in C<$msgset>.
950             This method is valid only when the session is in the selected state.
951              
952             The C<$msgset> parameter is described in the section describing C.
953              
954             The C<$itemname> can be one of the following:
955              
956             =over 4
957              
958             =item * flags
959              
960             Replaces the current flags with the flags specified in C<@storeattrflags>.
961              
962             =item * +flags
963              
964             Adds the flags specified in C<@storeattrflags> to the current flags.
965              
966             =item * -flags
967              
968             Removes the flags specified in C<@storeattrflags> from the current
969             flags.
970              
971             =back
972              
973             The C<$itemname> can also have C<.silent> appended, which causes the
974             server to not send back update responses for the messages.
975              
976             If successful, and C<.silent> is used used in C<$itemname>, the server
977             response with a series of C responses reflecting the updates to
978             the specified messages.
979              
980             If the completion response from a C command is C, the
981             client should send a C command, to force any pending expunge
982             responses from the server, and retry the C command with
983             C<$msgset> adjusted accordingly.
984              
985             The C<@storeattrflags> is a list of flag strings.
986              
987             =cut
988              
989             sub store {
990             my $self = shift;
991             my $msgset = shift;
992             my $itemname = shift;
993             for my $flag (@_) {
994             unless ($self->_valid_flag($flag)) {
995             carp "$flag is not a system flag";
996             return undef;
997             }
998             }
999             $self->imap_command('store', ATOM, $msgset, ATOM, $itemname, PARENS, [@_]);
1000             }
1001              
1002             =head2 copy $msgset, $mailbox
1003              
1004             Copy the messages C<$msgset> to the specified mailbox. This method is
1005             valid only when the session is in the selected state.
1006              
1007             The C<$msgset> parameter is described in the section describing C.
1008              
1009             If server returns a C response containing a C response
1010             code, this means C<$mailbox> does not exist but the server thinks the
1011             command would have succeeded if the an appropriate C command
1012             was issued. On the other hand, failure with no C response
1013             code generally means that a C should not be attempted.
1014              
1015             =cut
1016              
1017             sub copy { $_[0]->imap_command('copy',
1018             ATOM, $_[1], ASTRING, _encode_mailbox($_[2])) }
1019              
1020             =head2 uid_copy $msgset, $mailbox
1021              
1022             A variant of C that uses UIDs in C<$msgset>, instead of message
1023             numbers. This method is valid only when the session is in the
1024             selected state.
1025              
1026             =cut
1027              
1028             sub uid_copy { $_[0]->imap_command('uid copy',
1029             ATOM, $_[1],
1030             ASTRING, _encode_mailbox($_[2])) }
1031              
1032             =head2 uid_fetch $msgset, 'all'|'full'|'fast'|$fetchattr|@fetchattrs
1033              
1034             A variant of C that uses UIDs, instead of message numbers, in
1035             C<$msgset> and C responses. This method is valid only when the
1036             session is in the selected state.
1037              
1038             =cut
1039              
1040             sub uid_fetch {
1041             my $self = shift;
1042             my $msgset = shift;
1043             my @args;
1044             if (scalar(@_) == 1) {
1045             push @args, ATOM, shift;
1046             } else {
1047             push @args, PARENS, [@_];
1048             }
1049             $self->imap_command('uid fetch', ATOM, $msgset, @args);
1050             }
1051              
1052             =head2 uid_search [Charset => $charset,] @searchkeys
1053              
1054             A variant of C that uses UIDs, instead of message numbers, in
1055             C<$msgset> and C responses. This method is valid only when
1056             the session is in the selected state.
1057              
1058             =cut
1059              
1060             sub uid_search {
1061             my $self = shift;
1062             my @args;
1063             if ($_[0] =~ /^charset$/i) {
1064             shift;
1065             my $charset = shift;
1066             push @args, ATOM, 'charset', ASTRING, $charset;
1067             }
1068             push @args, map { (ATOM, $_) } @_;
1069             $self->imap_command('uid search', @args);
1070             }
1071              
1072             =head2 uid_store $msgset, $itemname, @storeattrflags
1073              
1074             A variant of C that uses UIDs, instead of message numbers, in
1075             C<$msgset> and C responses. This method is valid only when the
1076             session is in the selected state.
1077              
1078             =cut
1079              
1080             sub uid_store {
1081             my $self = shift;
1082             my $msgset = shift;
1083             my $itemname = shift;
1084             for my $flag (@_) {
1085             unless ($self->_valid_flag($flag)) {
1086             carp "$flag is not a system flag";
1087             return undef;
1088             }
1089             }
1090             $self->imap_command('uid store',
1091             ATOM, $msgset, ATOM, $itemname, PARENS, [@_]);
1092             }
1093             ###############################################################################
1094              
1095             =head1 CONVENIENCE ROUTINES
1096              
1097             In addition to the core protocol methods, C provides
1098             several methods for accessing various pieces of information.
1099              
1100             =head2 is_preauth
1101              
1102             Returns a boolean valud indicating whether the IMAP session is
1103             preauthenticated.
1104              
1105             =cut
1106              
1107             sub is_preauth { $_[0]->{PreAuth} }
1108              
1109             =head2 banner
1110              
1111             Returns the banner string issued by the server at connect time.
1112              
1113             =cut
1114              
1115             sub banner { $_[0]->{Banner} }
1116              
1117             =head2 capabilities
1118              
1119             Returns the list of capabilities supported by the server, minus the
1120             authentication capabilities. The list is not guaranteed to be in any
1121             specific order.
1122              
1123             =cut
1124              
1125             sub capabilities { keys %{$_[0]->{Capabilities}} }
1126              
1127             =head2 has_capability $capname
1128              
1129             Returns a boolean value indicating whether the server supports the
1130             specified capability.
1131              
1132             =cut
1133              
1134             sub has_capability { defined($_[0]->{Capabilities}{uc($_[1])}) }
1135              
1136             =head2 authtypes
1137              
1138             Returns a list of authentication types supported by the server.
1139              
1140             =cut
1141              
1142             sub authtypes { keys %{$_[0]->{AuthTypes}} }
1143              
1144             =head2 has_authtype $authname
1145              
1146             Returns a boolean value indicating whether the server supports the
1147             specified authentication type.
1148              
1149             =cut
1150              
1151             sub has_authtype { defined($_[0]->{AuthTypes}{uc($_[1])}) }
1152              
1153             =head2 qty_messages
1154              
1155             Returns the quantity of messages in the currently selected folder.
1156              
1157             =cut
1158              
1159             sub qty_messages { $_[0]->{MailboxStatus}{'exists'} }
1160              
1161             =head2 qty_recent
1162              
1163             Returns the quantity of recent messages in the currently selected folder.
1164              
1165             =cut
1166              
1167             sub qty_recent { $_[0]->{MailboxStatus}{'recent'} }
1168              
1169             =head2 first_unseen
1170              
1171             Returns the message number of the first unseen messages in the
1172             currently selected folder.
1173              
1174             =cut
1175              
1176             sub first_unseen { $_[0]->{MailboxStatus}{'unseen'} }
1177              
1178             =head2 uidvalidity
1179              
1180             Returns the C value for the currently selected folder.
1181             This is useful for IMAP clients that cache data in persistent storage.
1182             Cache data for a mailbox should only be considered valid if the
1183             C is the same for both cached data and the remote
1184             mailbox. See Section 2.3.1.1 of RFC2060 for further details.
1185              
1186             =cut
1187              
1188             sub uidvalidity { $_[0]->{MailboxStatus}{'uidvalidity'} }
1189              
1190             =head2 uidnext
1191              
1192             Returns the C value for the currently selected folder.
1193              
1194             =cut
1195              
1196             sub uidnext { $_[0]->{MailboxStatus}{'uidnext'} }
1197              
1198             =head2 permanentflags
1199              
1200             Returns the list of permanent flags the server has identified for the
1201             currently open mailbox.
1202              
1203             If a C<\*> flag is present, the server allows new persistent keywords
1204             to be created.
1205              
1206             =cut
1207              
1208             sub permanentflags { keys %{$_[0]->{MailboxStatus}{'permanentflags'}} }
1209              
1210             =head2 is_permanentflag $flag
1211              
1212             Returns a boolean value indicating whether the server considers
1213             C<$flag> to be a permanent flag.
1214              
1215             =cut
1216              
1217             sub is_permanentflag {
1218             defined($_[0]->{MailboxStatus}{'permanentflags'}{lc($_[1])});
1219             }
1220              
1221             =head2 flags
1222              
1223             Returns a list of the flags associated with the mailbox.
1224              
1225             =cut
1226              
1227             sub flags { keys %{$_[0]->{MailboxStatus}{'flags'}} }
1228              
1229             =head2 has_flag $flag
1230              
1231             Returns a boolean value indicating whether the given $flag is defined
1232             for the mailbox.
1233              
1234             =cut
1235              
1236             sub has_flag { defined($_[0]->{MailboxStatus}{'flags'}{lc($_[1])}) }
1237              
1238             =head2 mailbox
1239              
1240             Returns the name of the currently open mailbox. Returns C if
1241             no mailbox is currently open.
1242              
1243             =cut
1244              
1245             sub mailbox { $_[0]->{Mailbox} }
1246              
1247             =head2 is_readonly
1248              
1249             Returns a boolean value indicating whether the currently open mailbox
1250             is read-only.
1251              
1252             =cut
1253              
1254             sub is_readonly { $_[0]->{ReadOnly} }
1255              
1256             #------------------------------------------------------------------------------
1257              
1258             sub _encode_mailbox {
1259             my $str = $_[0];
1260             $str =~ s/&/&-/g;
1261             return $str;
1262             }
1263              
1264             sub _decode_mailbox {
1265             my $str = $_[0];
1266             $str =~ s/&-/&/g;
1267             return $str;
1268             }
1269              
1270             ###############################################################################
1271              
1272             =head1 NAMESPACE EXTENSION
1273              
1274             The following methods are available if the server advertises support
1275             for RFC2342 (IMAP4 Namespace). Refer to that RFC for additional
1276             information.
1277              
1278             =head2 namespace
1279              
1280             Sends a C command to the server, if the server advertises
1281             support for the extension extension.
1282              
1283             =cut
1284              
1285             sub namespace {
1286             my $self = shift;
1287             return undef unless $self->has_capability('NAMESPACE');
1288             $self->imap_command('namespace');
1289             }
1290              
1291             ###############################################################################
1292              
1293             =head1 ACCESS CONTROL EXTENSION
1294              
1295             The following methods are available if the server advertises support
1296             for RFC2086 (IMAP4 ACL Extension). Refer to that RFC for additional
1297             information.
1298              
1299             =head2 setacl $mailbox, $identifier, $modrights
1300              
1301             Sets the access control list for C<$identifier> on C<$mailbox>
1302             according to the rights contained in C<$modrights>.
1303              
1304             The C<$identifier> typically identifies an account name, but can also
1305             specify abstract entities, such as groups.
1306              
1307             The format for C<$modrights> is documented in RFC2086.
1308              
1309             =cut
1310              
1311             sub setacl {
1312             my $self = shift;
1313             return undef unless $self->has_capability('ACL');
1314             $self->imap_command('setacl',
1315             ASTRING, _encode_mailbox($_[0]),
1316             ASTRING, $_[1],
1317             ASTRING, $_[2]);
1318             }
1319              
1320             =head2 getacl $mailbox
1321              
1322             Retrieves the access control list for C<$mailbox>.
1323              
1324             =cut
1325              
1326             sub getacl {
1327             my $self = shift;
1328             return undef unless $self->has_capability('ACL');
1329             $self->imap_command('getacl', ASTRING, _encode_mailbox($_[0]));
1330             }
1331              
1332             =head2 deleteacl $mailbox, $identifier
1333              
1334             Deletes all access control list entries for C<$identifier> from
1335             C<$mailbox>.
1336              
1337             =cut
1338              
1339             sub deleteacl {
1340             my $self = shift;
1341             return undef unless $self->has_capability('ACL');
1342             $self->imap_command('deleteacl',
1343             ASTRING, _encode_mailbox($_[0]), ASTRING, $_[1]);
1344             }
1345              
1346             =head2 listrights $mailbox, $identifier
1347              
1348             List the rights available to C<$identifier> for C<$mailbox>.
1349              
1350             =cut
1351              
1352             sub listrights {
1353             my $self = shift;
1354             return undef unless $self->has_capability('ACL');
1355             $self->imap_command('listrights',
1356             ASTRING, _encode_mailbox($_[0]), ASTRING, $_[1]);
1357             }
1358              
1359             =head2 myrights $mailbox
1360              
1361             List the rights the current user has for C<$mailbox>.
1362              
1363             =cut
1364              
1365             sub myrights {
1366             my $self = shift;
1367             return undef unless $self->has_capability('ACL');
1368             $self->imap_command('myrights', ASTRING, _encode_mailbox($_[0]));
1369             }
1370              
1371             ###############################################################################
1372              
1373             =head1 QUOTA EXTENSION
1374              
1375             The following methods are available if the server advertises support
1376             for RFC2087 (IMAP4 Quota Extension). Refer to that RFC for additional
1377             information.
1378              
1379             =head2 getquota $quotaroot
1380              
1381             Lists the resource usage and limits for C<$quotaroot>.
1382              
1383             =cut
1384              
1385             sub getquota {
1386             my $self = shift;
1387             return undef unless $self->has_capability('QUOTA');
1388             $self->imap_command('getquota', ASTRING, $_[0]);
1389             }
1390              
1391             =head2 setquota $quotaroot, @setquotalist
1392              
1393             Sets the resource limits for C<$quotaroot> to C<@setquotalist>.
1394              
1395             Valid values for C<@setquotalist> are server-dependant.
1396              
1397             =cut
1398              
1399             sub setquota {
1400             my $self = shift;
1401             my $quotaroot = shift;
1402             return undef unless $self->has_capability('QUOTA');
1403             $self->imap_command('setquota', ASTRING, $quotaroot, PARENS, [@_]);
1404             }
1405              
1406             =head2 getquotaroot $mailbox
1407              
1408             Lists the quota roots for C<$mailbox>.
1409              
1410             =cut
1411              
1412             sub getquotaroot {
1413             return undef unless $_[0]->has_capability('QUOTA');
1414             $_[0]->imap_command('getquotaroot', ASTRING, _encode_mailbox($_[1]));
1415             }
1416              
1417             ###############################################################################
1418              
1419             =head1 UIDPLUS EXTENSION
1420              
1421             The following method is available if the server advertises support for
1422             RFC2359 (IMAP4 UIDPLUS Extension). Refer to that RFC for additional
1423             information.
1424              
1425             =head2 uid_expunge $msgset
1426              
1427             A variant of C that allows the operation to be narrowed to
1428             the messages with UIDs specified in C<$msgset>.
1429              
1430             The C<$msgset> parameter is described in the section describing C.
1431              
1432             =cut
1433              
1434             sub uid_expunge {
1435             return undef unless $_[0]->has_capability('UIDPLUS');
1436             $_[0]->imap_command('uid expunge', ATOM, $_[1]);
1437             }
1438              
1439             ###############################################################################
1440              
1441             sub imap_command {
1442             my $self = shift;
1443             if (!defined($cmd_callbacks{$_[0]})) {
1444             carp("unknown imap command: $_[0]");
1445             return undef;
1446             }
1447             unless ($cmd_callbacks{$_[0]}->[1] & $self->{State}) {
1448             carp("invalid state for issuing $_[0] command");
1449             return undef
1450             }
1451             $self->command($self->imap_cmd_callback($_[0]), @_);
1452             }
1453              
1454             ###############################################################################
1455              
1456             =head1 CALLBACKS
1457              
1458             Many of the command methods result in the server sending back response
1459             data. C processes each response by parsing the data,
1460             packages it in an appropriate object, and optionally calls a
1461             programmer-defined callback for the response. This callback mechanism
1462             is how programmers get access to the data retrieved from the server.
1463              
1464             =head2 set_untagged_callback $item, $coderef
1465              
1466             Assigns a programmer-defined code reference to the associated untagged
1467             response. When an untagged response matching C<$item> is received,
1468             C<$coderef> is called, with the IMAP object and the associated
1469             response object passed as parameters.
1470              
1471             The default callback for the C, C, C, and C untagged
1472             responses includes code to output the text from C responses to
1473             stderr, using C. If you set your own callback for these
1474             responses, be sure to code handle C codes. Per Section 7.1 of
1475             RFC2060, clients are required to clearly display C messages to
1476             users.
1477              
1478             =cut
1479              
1480             sub set_untagged_callback {
1481             my $self = shift;
1482             my $item = shift;
1483             my $funcref = shift;
1484              
1485             return undef unless defined($untagged_callbacks{$item});
1486             $untagged_callbacks{$item}->[0] = $funcref;
1487             }
1488              
1489             #------------------------------------------------------------------------------
1490              
1491             sub imap_cmd_callback {
1492             my $self = shift;
1493             my $cmd = shift;
1494             return sub {
1495             my $resp = shift;
1496             return unless (defined($cmd_callbacks{$cmd})
1497             && defined($cmd_callbacks{$cmd}->[0]));
1498             my $func = $cmd_callbacks{$cmd}->[0];
1499             return $self->$func($resp);
1500             }
1501             }
1502              
1503             sub imap_response_callback {
1504             my $self = shift;
1505             # my $seq = $self->next_sequence;
1506             return sub {
1507             my $response = shift;
1508             my ($tag, $rest) = split(/\s/, $response, 2);
1509             if ($tag eq '*') {
1510             return $self->_imap_process_untagged_response($rest);
1511             } elsif ($tag =~ /^\d+$/) {
1512             return $self->_imap_process_tagged_response($tag, $rest);
1513             } else {
1514             croak("gack! server returned bogus tag: [$tag]");
1515             }
1516             }
1517             }
1518              
1519             sub _imap_process_untagged_response {
1520             my $self = shift;
1521             my $str = shift;
1522             my @args;
1523             my $num;
1524              
1525             my ($cmd, $rest) = split(/\s/, $str, 2);
1526             if ($cmd =~ /^\d+$/) {
1527             push @args, $cmd;
1528             ($cmd, $rest) = split(/\s/, $rest, 2);
1529             }
1530             push @args, $rest if defined($rest);
1531             $cmd = lc($cmd);
1532             if (defined($untagged_callbacks{$cmd})) {
1533             my $class = "Net::IMAP::" . ucfirst(lc($cmd));
1534             my $ret = $class->new($self, @args);
1535              
1536             # trigger a user callback, maybe - user callback is passed $self
1537             # and the object created by the internal callback
1538              
1539             if (defined($ret)) {
1540             if (defined($untagged_callbacks{$cmd}->[0])) {
1541             &{$untagged_callbacks{$cmd}->[0]}($self, $ret);
1542             }
1543             $self->debug_print(0, "untagged resp callback returned $ret")
1544             if $self->debug;
1545             } else {
1546             carp("untagged resp callback returned undef");
1547             }
1548             return undef;
1549             } else {
1550             carp("received unknown response from server: [$cmd]\n");
1551             }
1552             }
1553              
1554             sub _imap_process_tagged_response {
1555             my $self = shift;
1556             my $tag = shift;
1557             my $str = shift;
1558              
1559             my $resp = Net::IMAP::Response->new;
1560              
1561             my ($cond, $text) = split(/\s/, $str, 2);
1562             my $resp_code = undef;
1563             if (substr($text, 0, 1) eq '[') {
1564             ($resp_code, $text) = _extract_resp_code($text);
1565             }
1566             $resp->{Sequence} = $tag;
1567             $resp->{Status} = lc($cond);
1568             $resp->{StatusCode} = $resp_code;
1569             $resp->{Text} = $text;
1570              
1571             if ($self->{Disconnect}) {
1572             $self->close_connection or carp "error closing connection: $!";
1573             }
1574             return $resp;
1575             }
1576             ###############################################################################
1577             sub _select_cmd_callback {
1578             my $self = shift;
1579             my $resp = shift;
1580              
1581             if ($resp->status eq 'ok') {
1582             $self->{State} = IMAP_STATE_SELECT;
1583             my $status = $resp->status_code;
1584             $self->{ReadOnly} = (defined($status) && ($status->[0] eq 'read-only'));
1585             } else {
1586             $self->{State} = IMAP_STATE_AUTH;
1587             $self->{Mailbox} = '';
1588             }
1589             }
1590              
1591             sub _login_cmd_callback {
1592             $_[0]->{State} = IMAP_STATE_AUTH if ($_[1]->status eq 'ok');
1593             }
1594              
1595             sub _close_cmd_callback {
1596             if ($_[1]->status eq 'ok') {
1597             $_[0]->_init_mailbox;
1598             $_[0]->{State} = IMAP_STATE_AUTH;
1599             }
1600             }
1601             #------------------------------------------------------------------------------
1602              
1603             sub _default_aux_callback {
1604             my $self = shift;
1605             my $resp = shift;
1606              
1607             my $code = $resp->code;
1608             if (defined($code) && ($code->[0] eq 'alert')) {
1609             carp "Alert: ", $resp->text, "\n";
1610             }
1611             }
1612              
1613             ###############################################################################
1614             sub _valid_flag { ((substr($_[1], 0, 1) ne "\\")
1615             || defined($_system_flags{lc($_[1])})) }
1616             ###############################################################################
1617             sub _extract_resp_code {
1618             my $line = shift;
1619             $line =~ m{
1620             \[
1621             ([^\]]+) # response code
1622             \]
1623             (?:
1624             \s
1625             (.*) # remainder of response line
1626             )?
1627             $
1628             }x;
1629             my $resp_code = $1;
1630             my $rest = $2;
1631             my $resp_code_list = Net::xAP->parse_fields($resp_code);
1632             $resp_code_list->[0] = lc($resp_code_list->[0]);
1633             return($resp_code_list, $rest);
1634             }
1635             ###############################################################################
1636             # use Data::Dumper;
1637             # sub _dump_internals { print STDERR "----\n", Dumper($_[0]), "----\n" }
1638             ###############################################################################
1639              
1640             =head1 RESPONSE OBJECTS
1641              
1642             As mention in the previous section, responses are parsed and packaged
1643             into response objects, which are then passed to callbacks. Each type
1644             of response has a corresponding object class. This section describes
1645             the various response objects provided.
1646              
1647             All of the class names itemized below are prefixed with C.
1648              
1649             As a general rule, IMAP C items are set to C in the parsed
1650             data, and IMAP parenthetical lists are converted to list references
1651             (of one form or another). In addition, atoms, quoted strings, and
1652             literals are presented as Perl strings.
1653              
1654             The condition responses (C, C, C, C, and C)
1655             can include a response code. Refer to Section 7.1 in RFC2060 for a
1656             description of each of the standard response codes.
1657              
1658             =head1 Response
1659              
1660             This is the object class for completion responses.
1661              
1662             =head2 is_tagged
1663              
1664             Returns a boolean value indicating whether the response is tagged. In
1665             the case of tagged completion responses, this value is always C<1>.
1666              
1667             =cut
1668              
1669             package Net::IMAP::Response;
1670             use vars qw(@ISA);
1671             @ISA = qw(Net::xAP::Response);
1672              
1673             sub is_tagged { 1 }
1674              
1675             =head2 has_trycreate
1676              
1677             Returns a boolean value indicating whether the C response
1678             code is present in the response. This can be used after a failed
1679             C or C command to determine whether the server thinks
1680             the operation would succeed if a C was issued for the
1681             associated mailbox.
1682              
1683             =cut
1684              
1685             sub has_trycreate {
1686             my $status_code = $_[0]->status_code;
1687             return (defined($status_code) && (lc($status_code->[0]) eq 'trycreate'));
1688             }
1689              
1690             ###############################################################################
1691              
1692             =head1 UntaggedResponse
1693              
1694             This class is common to all untagged server responses.
1695              
1696             =head2 tag
1697              
1698             Returns a string containing the tag associated with the response. In
1699             the case of untagged responses, this is always C<*>.
1700              
1701             =head2 is_tagged
1702              
1703             Returns a boolean value indicating whether the response is tagged.
1704             Obviously, in the case of untagged responses, this value is always
1705             C<0>.
1706              
1707             =head2 parent
1708              
1709             Returns a reference to the parent IMAP object.
1710              
1711             =cut
1712              
1713             package Net::IMAP::UntaggedResponse;
1714              
1715             sub tag { '*' }
1716             sub is_tagged { 0 }
1717             sub parent { $_[0]->{Parent} }
1718             #------------------------------------------------------------------------------
1719             package Net::IMAP::Cond;
1720             use vars qw(@ISA);
1721             @ISA = qw(Net::IMAP::UntaggedResponse);
1722             use Carp;
1723              
1724             sub new {
1725             my $class = shift;
1726             my $type = ref($class) || $class;
1727             my $parent = shift;
1728             my $str = shift;
1729              
1730             my $self = {};
1731              
1732             bless $self, $class;
1733              
1734             $self->{Parent} = $parent;
1735              
1736             my $resp_code = undef;
1737              
1738             if (substr($str, 0, 1) eq '[') {
1739             ($resp_code, $str) = Net::IMAP::_extract_resp_code($str);
1740             }
1741             $self->{RespCode} = $resp_code;
1742             $self->{Text} = $str;
1743              
1744             carp "Alert: $str\n" if (defined($resp_code) && $resp_code->[0] eq 'alert');
1745              
1746             if (($self->name eq 'bye') && !$self->parent->{Disconnect}) {
1747             # a logout command wasn't issued, so it's probably the result of
1748             # an autologout timer expiring
1749             $self->parent->close_connection or carp "error closing connection: $!";
1750             }
1751              
1752             return $self;
1753             }
1754              
1755             sub code { $_[0]->{RespCode} }
1756              
1757             sub name { undef }
1758             #------------------------------------------------------------------------------
1759              
1760             =head1 Ok
1761              
1762             This is a container for untagged C responses from the server.
1763              
1764             =head2 code
1765              
1766             Returns a list reference containing response code elements in the
1767             response. Returns C if no response code is present.
1768              
1769             =head2 name
1770              
1771             Returns the name of the response. In the case of C, this returns
1772             'ok'. This method is provided as a convenience for end-programmers
1773             wanting to write one common subroutine for one or more of the
1774             responses C, C, C, and C.
1775              
1776             =cut
1777              
1778             package Net::IMAP::Ok;
1779             use vars qw(@ISA);
1780             @ISA = qw(Net::IMAP::Cond);
1781             sub name { 'ok' };
1782             #------------------------------------------------------------------------------
1783              
1784             =head1 No
1785              
1786             This is a container for untagged C responses from the server.
1787              
1788             =cut
1789              
1790             package Net::IMAP::No;
1791             use vars qw(@ISA);
1792             @ISA = qw(Net::IMAP::Cond);
1793             sub name { 'no' };
1794             #------------------------------------------------------------------------------
1795              
1796             =head1 Bad
1797              
1798             This is a container for untagged C responses from the server.
1799              
1800             =cut
1801              
1802             package Net::IMAP::Bad;
1803             use vars qw(@ISA);
1804             @ISA = qw(Net::IMAP::Cond);
1805             sub name { 'bad' };
1806             #------------------------------------------------------------------------------
1807              
1808             =head1 Bye
1809              
1810             This is a container for untagged C responses from the server.
1811              
1812             =cut
1813              
1814             package Net::IMAP::Bye;
1815             use vars qw(@ISA);
1816             @ISA = qw(Net::IMAP::Cond);
1817             sub name { 'bye' };
1818             ###############################################################################
1819              
1820             =head1 Expunge
1821              
1822             This is a container for C responses from the server.
1823              
1824             The information returned by C is automatically updated
1825             when C responses are received.
1826              
1827             =head2 msgnum
1828              
1829             Returns the message number specified in the C response.
1830              
1831             =cut
1832              
1833             package Net::IMAP::Expunge;
1834             use vars qw(@ISA);
1835             @ISA = qw(Net::IMAP::UntaggedResponse);
1836              
1837             sub name { 'expunge' }
1838              
1839             sub new {
1840             my $class = shift;
1841             my $type = ref($class) || $class;
1842             my $parent = shift;
1843             my $str = shift;
1844              
1845             my $self = {};
1846              
1847             bless $self, $class;
1848              
1849             $self->{Parent} = $parent;
1850              
1851             $self->{Msgnum} = $str;
1852              
1853             return $self;
1854             }
1855              
1856             sub msgnum { $_->{Msgnum} }
1857              
1858             ###############################################################################
1859              
1860             =head1 Capability
1861              
1862             This is a container for C responses.
1863              
1864             =head2 capabilities
1865              
1866             Returns the list of capabilities supported by the server, minus the
1867             authentication capabilities. The list is not guaranteed to be in any
1868             specific order.
1869              
1870             =head2 has_capability $capname
1871              
1872             Returns a boolean value indicating whether the server supports the
1873             specified capability.
1874              
1875             =head2 authtypes
1876              
1877             Returns a list of authentication types supported by the server.
1878              
1879             =head2 has_authtype $authname
1880              
1881             Returns a boolean value indicating whether the server supports the
1882             specified authentication type.
1883              
1884             =cut
1885              
1886             package Net::IMAP::Capability;
1887             use vars qw(@ISA);
1888             @ISA = qw(Net::IMAP::UntaggedResponse);
1889              
1890             sub name { 'capability' }
1891              
1892             sub new {
1893             my $class = shift;
1894             my $type = ref($class) || $class;
1895             my $parent = shift;
1896             my $str = shift;
1897              
1898             my $self = {};
1899              
1900             bless $self, $class;
1901              
1902             $self->{Parent} = $parent;
1903              
1904             undef $self->{Parent}{Capabilities}; # needs to be repopulated each time
1905             undef $self->{Parent}{AuthTypes}; # needs to be repopulated each time
1906              
1907             for my $cap (split(/\s/, $str)) {
1908             $cap = uc($cap);
1909             $self->{Parent}{Capabilities}{$cap}++;
1910             $self->{Parent}{AuthTypes}{$1}++ if $cap =~ /^AUTH=(.*)$/;
1911             $self->{Capabilities}{$cap}++;
1912             $self->{AuthTypes}{$1}++ if $cap =~ /^AUTH=(.*)$/;
1913             }
1914              
1915             # force the non-synchronous literals option off if the server
1916             # doesn't support it
1917             $self->{Parent}{Options}{NonSyncLits} = 0
1918             unless defined($self->{Parent}{Capabilities}{'LITERAL+'});
1919              
1920             return $self;
1921             }
1922              
1923             sub capabilities { keys %{$_[0]->{Capabilities}} }
1924              
1925             sub has_capability { defined($_[0]->{Capabilities}{uc($_[1])}) }
1926              
1927             sub authtypes { keys %{$_[0]->{AuthTypes}} }
1928              
1929             sub has_authtype { defined($_[0]->{AuthTypes}{uc($_[1])}) }
1930              
1931             ###############################################################################
1932              
1933             =head1 List
1934              
1935             This is a container for C responses.
1936              
1937             =head2 mailbox
1938              
1939             Returns the name of the mailbox contained in the object.
1940              
1941             =head2 delimiter
1942              
1943             Returns the hierarchy delimiter associated with the mailbox.
1944              
1945             =head2 flags
1946              
1947             Returns a list of the flags associated with the mailbox.
1948              
1949             =head2 has_flag $flag
1950              
1951             Returns a boolean value indicating whether the given $flag is defined
1952             for the mailbox.
1953              
1954             =cut
1955              
1956             package Net::IMAP::List;
1957             use vars qw(@ISA);
1958             @ISA = qw(Net::IMAP::UntaggedResponse);
1959              
1960             sub name { 'list' }
1961              
1962             sub new {
1963             my $class = shift;
1964             my $type = ref($class) || $class;
1965             my $parent = shift;
1966             my $str = shift;
1967              
1968             my $self = {};
1969              
1970             bless $self, $class;
1971              
1972             $self->{Parent} = $parent;
1973              
1974             my $fields = Net::xAP->parse_fields($str);
1975             for my $flag (@{$fields->[0]}) {
1976             $self->{Flags}{lc($flag)}++;
1977             }
1978             $self->{Delim} = $fields->[1];
1979             $self->{Mailbox} = Net::IMAP::_decode_mailbox($fields->[2]);
1980              
1981             return $self;
1982             }
1983              
1984             sub mailbox { $_[0]->{Mailbox} }
1985             sub delimiter { $_[0]->{Delim} }
1986             sub flags { keys %{$_[0]->{Flags}} }
1987             sub has_flag { defined($_[0]->{Flags}{lc($_[1])}) }
1988              
1989             #------------------------------------------------------------------------------
1990              
1991             =head1 List
1992              
1993             This is a container for C responses. It provides the same
1994             interface as the C class.
1995              
1996             =cut
1997              
1998             package Net::IMAP::Lsub;
1999             use vars qw(@ISA);
2000             @ISA = qw(Net::IMAP::List);
2001              
2002             sub name { 'lsub' }
2003              
2004             ###############################################################################
2005              
2006             =head1 Fetch
2007              
2008             This is a container for C responses.
2009              
2010             Responses for partial fetches bear special mention. While both the
2011             starting byte and quantity of bytes are specified when doing partial
2012             fetches with the C command, the corresponding response will
2013             only show the starting byte. In other words, the command
2014             C<$imap-Efetch(1, 'body[]E0.1024E'> will, if successful,
2015             result in a fetch response item of C0E> containing a
2016             1024 octet value. To match a given response for a partial fetch, you
2017             might need to use C to match it up with the corresponding item
2018             specified in the C command.
2019              
2020             =head2 msgnum
2021              
2022             Returns the message number identified in the response.
2023              
2024             =head2 items
2025              
2026             Returns the list of data item names contained in the response. The
2027             list is not guaranteed to be in any specific order.
2028              
2029             =head2 item $item
2030              
2031             Returns the data associated with the specified data item.
2032              
2033             The following list enumerates the data types associated with each
2034             fetch item:
2035              
2036             =over 14
2037              
2038             =item envelope
2039              
2040             Net::IMAP::Envelope
2041              
2042             =item bodystructure
2043              
2044             Net::IMAP::BodyStructure
2045              
2046             =item body
2047              
2048             Net::IMAP::BodyStructure
2049              
2050             =item flags
2051              
2052             Net::IMAP::Flags
2053              
2054             =item UID
2055              
2056             Integer
2057              
2058             =item rfc822.size
2059              
2060             Integer
2061              
2062             =item I
2063              
2064             String
2065              
2066             =back
2067              
2068             =cut
2069              
2070             package Net::IMAP::Fetch;
2071             use vars qw(@ISA);
2072             @ISA = qw(Net::IMAP::UntaggedResponse);
2073              
2074             sub name { 'fetch' }
2075              
2076             sub new {
2077             my $class = shift;
2078             my $type = ref($class) || $class;
2079             my $parent = shift;
2080             my $msgnum = shift;
2081             my $str = shift;
2082              
2083             my $self = {};
2084              
2085             bless $self, $class;
2086              
2087             $self->{Parent} = $parent;
2088              
2089             $self->{Msgnum} = $msgnum;
2090              
2091             my %hash = @{Net::xAP->parse_fields($str)->[0]};
2092             for my $key (keys %hash) {
2093             my $lckey = lc($key);
2094             print "$lckey $hash{$key}\n";
2095             if ($lckey eq 'envelope') {
2096             $self->{Items}{$lckey} = Net::IMAP::Envelope->new($hash{$key});
2097             } elsif (($lckey eq 'bodystructure') || ($lckey eq 'body')) {
2098             $self->{Items}{$lckey} = Net::IMAP::BodyStructure->new($hash{$key});
2099             } elsif ($lckey eq 'flags') {
2100             $self->{Items}{$lckey} = Net::IMAP::Flags->new($parent);
2101             for my $flag (@{$hash{$key}}) {
2102             $self->{Items}{$lckey}{Flags}{lc($flag)}++;
2103             }
2104             } else {
2105             if ($self->{Parent}{Options}{EOL} eq 'lf') {
2106             if ((substr($lckey, 0, 5) eq 'body[')
2107             || ($lckey eq 'rfc822')
2108             || ($lckey eq 'rfc822.header')
2109             || ($lckey eq 'rfc822.text')) {
2110             $hash{$key} =~ s/\r\n/\n/mg;
2111             }
2112             }
2113             $self->{Items}{$lckey} = $hash{$key};
2114             }
2115             }
2116              
2117             return $self;
2118             }
2119              
2120             sub msgnum { $_[0]->{Msgnum} }
2121             sub items { keys %{$_[0]->{Items}} }
2122             sub item { $_[0]->{Items}{lc($_[1])} }
2123              
2124             ###############################################################################
2125              
2126             =head1 Status
2127              
2128             This is a container for C responses.
2129              
2130             =head2 mailbox
2131              
2132             Returns a string containing the mailbox the status information is
2133             associated with.
2134              
2135             =head2 items
2136              
2137             Returns the list of status items contains in the status response.
2138              
2139             =head2 item $item
2140              
2141             Returns the value of the C<$item> status item.
2142              
2143             =cut
2144              
2145             package Net::IMAP::Status;
2146             use vars qw(@ISA);
2147             @ISA = qw(Net::IMAP::UntaggedResponse);
2148              
2149             sub name { 'status' }
2150              
2151             sub new {
2152             my $class = shift;
2153             my $type = ref($class) || $class;
2154             my $parent = shift;
2155             my $str = shift;
2156              
2157             my $self = {};
2158              
2159             bless $self, $class;
2160              
2161             $self->{Parent} = $parent;
2162              
2163             my $fields = Net::xAP->parse_fields($str);
2164             $self->{Mailbox} = Net::IMAP::_decode_mailbox($fields->[0]);
2165             my %hash = @{$fields->[1]};
2166             for my $key (keys %hash) {
2167             $self->{Items}{lc($key)} = $hash{$key};
2168             }
2169              
2170             return $self;
2171             }
2172              
2173             sub mailbox { $_[0]->{Mailbox} }
2174             sub items { keys %{$_[0]->{Items}} }
2175             sub item { $_[0]->{Items}{lc($_[1])} }
2176              
2177             ###############################################################################
2178              
2179             =head1 Search
2180              
2181             This is a container for C responses.
2182              
2183             =head2 msgnums
2184              
2185             Returns the list of message numbers contained in the response.
2186              
2187             =cut
2188              
2189             package Net::IMAP::Search;
2190             use vars qw(@ISA);
2191             @ISA = qw(Net::IMAP::UntaggedResponse);
2192              
2193             sub name { 'search' }
2194              
2195             sub new {
2196             my $class = shift;
2197             my $type = ref($class) || $class;
2198             my $parent = shift;
2199             my $str = shift;
2200              
2201             my $self = {};
2202              
2203             bless $self, $class;
2204              
2205             $self->{Parent} = $parent;
2206              
2207             for my $item (split(/\s/, $str)) {
2208             $self->{Msgnums}{$item}++;
2209             }
2210              
2211             return $self;
2212             }
2213              
2214             sub msgnums { keys %{$_[0]->{Msgnums}} }
2215              
2216             ###############################################################################
2217              
2218             =head1 Flags
2219              
2220             This is a container for C responses.
2221              
2222             =head2 flags
2223              
2224             Returns the list of flags contained in the response.
2225              
2226             =head2 has_flag $flag
2227              
2228             Returns a boolean value indicating whether the specified flag is
2229             contained in the response.
2230              
2231             As a convenience, the information from the C response is also
2232             stored in the parent C object, and is available via
2233             C versions of the C and C methods.
2234              
2235             =cut
2236              
2237             package Net::IMAP::Flags;
2238             use vars qw(@ISA);
2239             @ISA = qw(Net::IMAP::UntaggedResponse);
2240              
2241             sub name { 'flags' }
2242              
2243             sub new {
2244             my $class = shift;
2245             my $type = ref($class) || $class;
2246             my $parent = shift;
2247             my $str = shift;
2248              
2249             my $self = {};
2250              
2251             bless $self, $class;
2252              
2253             $self->{Parent} = $parent;
2254              
2255             if (defined($str)) {
2256             for my $flag (@{Net::xAP->parse_fields($str)->[0]}) {
2257             $self->{Flags}{lc($flag)}++;
2258             $self->{Parent}{MailboxStatus}{'flags'}{lc($flag)}++;
2259             }
2260             }
2261              
2262             return $self;
2263             }
2264              
2265             sub flags { keys %{$_[0]->{Flags}} }
2266             sub has_flag { defined($_[0]->{Flags}{lc($_[1])}) }
2267              
2268             ###############################################################################
2269              
2270             =head1 Exists
2271              
2272             This is a container for C responses.
2273              
2274             =head2 exists
2275              
2276             Returns the quantity of messages in the currently selected mailbox.
2277              
2278             This is information is also available in the C method in
2279             the C class.
2280              
2281             =cut
2282              
2283             package Net::IMAP::Exists;
2284             use vars qw(@ISA);
2285             @ISA = qw(Net::IMAP::UntaggedResponse);
2286              
2287             sub name { 'exists' }
2288              
2289             sub new {
2290             my $class = shift;
2291             my $type = ref($class) || $class;
2292             my $parent = shift;
2293             my $str = shift;
2294              
2295             my $self = {};
2296              
2297             bless $self, $class;
2298              
2299             $self->{Parent} = $parent;
2300              
2301             $self->{Parent}{MailboxStatus}{'exists'} = $str;
2302             $self->{Value} = $str;
2303              
2304             return $self;
2305             }
2306              
2307             sub exists { $_[0]->{Value} }
2308              
2309             ###############################################################################
2310              
2311             =head1 Recent
2312              
2313             This is a container for C responses.
2314              
2315             =head2 recent
2316              
2317             Returns the number of messages with the C<\recent> flag set.
2318              
2319             This information is also available in the C method in the
2320             C class.
2321              
2322             =cut
2323              
2324             package Net::IMAP::Recent;
2325             use vars qw(@ISA);
2326             @ISA = qw(Net::IMAP::UntaggedResponse);
2327              
2328             sub name { 'recent' }
2329              
2330             sub new {
2331             my $class = shift;
2332             my $type = ref($class) || $class;
2333             my $parent = shift;
2334             my $str = shift;
2335              
2336             my $self = {};
2337              
2338             bless $self, $class;
2339              
2340             $self->{Parent} = $parent;
2341              
2342             $self->{Parent}{MailboxStatus}{'recent'} = $str;
2343             $self->{Value} = $str;
2344              
2345             return $self;
2346             }
2347              
2348             sub recent { $_[0]->{Value} }
2349              
2350             ###############################################################################
2351              
2352             =head1 Namespace
2353              
2354             This is a container for C responses.
2355              
2356             =head2 personal [$namespace]
2357              
2358             With no argument specified, returns a list of personal namespaces. If
2359             C<$namespace> is specified, returns the delimiter character for the
2360             specific personal namespace.
2361              
2362             =head2 other_users [$namespace]
2363              
2364             With no argument specified, returns a list of other users' namespaces.
2365             If C<$namespace> is specified, returns the delimiter character for the
2366             specific other users' namespace.
2367              
2368             =head2 shared [$namespace]
2369              
2370             With no argument specified, returns a list of shared namespaces. If
2371             C<$namespace> is specified, returns the delimiter character for the
2372             specific shared namespace.
2373              
2374             =cut
2375              
2376             package Net::IMAP::Namespace;
2377             use vars qw(@ISA);
2378             @ISA = qw(Net::IMAP::UntaggedResponse);
2379              
2380             sub name { 'namespace' }
2381              
2382             my @namespace_types = qw(personal other_users shared);
2383              
2384             sub new {
2385             my $class = shift;
2386             my $type = ref($class) || $class;
2387             my $parent = shift;
2388             my $str = shift;
2389              
2390             my $self = {};
2391              
2392             bless $self, $class;
2393              
2394             $self->{Parent} = $parent;
2395              
2396             my $fields = Net::xAP->parse_fields($str);
2397             for my $n (0 .. 2) {
2398             my $field = $fields->[$n];
2399             for my $item (@{$field}) {
2400             $item->[1] = '' if (lc($item->[1]) eq 'nil');
2401             $self->{Namespaces}{$namespace_types[$n]}{$item->[0]} = $item->[1];
2402             }
2403             }
2404              
2405             return $self;
2406             }
2407              
2408             sub personal {
2409             return $_[0]->{Namespaces}{'personal'}{lc($_[1])} if (defined($_[1]));
2410             keys %{$_[0]->{Namespaces}{'personal'}};
2411             }
2412              
2413             sub other_users {
2414             return $_[0]->{Namespaces}{'other_users'}{lc($_[1])} if (defined($_[1]));
2415             keys %{$_[0]->{Namespaces}{'other_users'}};
2416             }
2417              
2418             sub shared {
2419             return $_[0]->{Namespaces}{'shared'}{lc($_[1])} if (defined($_[1]));
2420             keys %{$_[0]->{Namespaces}{'shared'}};
2421             }
2422              
2423             ###############################################################################
2424              
2425             =head1 ACL
2426              
2427             This is a container for C responses>
2428              
2429             =head2 mailbox
2430              
2431             Returns the name of the mailbox associated with the given ACL data.
2432              
2433             =head2 identifiers
2434              
2435             Returns a list of identifiers contained in the ACL data.
2436              
2437             =head2 identifier $identifier
2438              
2439             =cut
2440              
2441             package Net::IMAP::Acl;
2442             use vars qw(@ISA);
2443             @ISA = qw(Net::IMAP::UntaggedResponse);
2444              
2445             sub name { 'acl' }
2446              
2447             sub new {
2448             my $class = shift;
2449             my $type = ref($class) || $class;
2450             my $parent = shift;
2451             my $str = shift;
2452              
2453             my $self = {};
2454              
2455             bless $self, $class;
2456              
2457             $self->{Parent} = $parent;
2458              
2459             my @fields = @{Net::xAP->parse_fields($str)};
2460             $self->{Mailbox} = shift(@fields);
2461             my %hash = @fields;
2462             for my $key (keys %hash) {
2463             $self->{Identifiers}{lc{$key}} = $hash{$key};
2464             }
2465              
2466             return $self;
2467             }
2468              
2469             sub mailbox { $_[0]->{Mailbox} }
2470             sub identifiers { keys %{$_[0]->{Identifiers}} }
2471             sub identifier { $_[0]->{Identifiers}{lc($_[1])} }
2472              
2473             ###############################################################################
2474              
2475             =head1 Listrights
2476              
2477             This is a container for C responses.
2478              
2479             =head2 mailbox
2480              
2481             Returns the name of the mailbox associated with the given rights.
2482              
2483             =head2 identifier
2484              
2485             Returns a string containing the identifier associated with the rights.
2486              
2487             =head2 rights
2488              
2489             Returns a string containing the rights contained in the response.
2490              
2491             =cut
2492              
2493             package Net::IMAP::Listrights;
2494             use vars qw(@ISA);
2495             @ISA = qw(Net::IMAP::UntaggedResponse);
2496              
2497             sub name { 'listrights' }
2498              
2499             sub new {
2500             my $class = shift;
2501             my $type = ref($class) || $class;
2502             my $parent = shift;
2503             my $str = shift;
2504              
2505             my $self = {};
2506              
2507             bless $self, $class;
2508              
2509             $self->{Parent} = $parent;
2510              
2511             my @fields = @{Net::xAP->parse_fields($str)};
2512             $self->{Mailbox} = shift(@fields);
2513             $self->{Identifier} = shift(@fields);
2514             $self->{Rights} = [@fields];
2515              
2516             return $self;
2517             }
2518              
2519             sub mailbox { $_[0]->{Mailbox} }
2520             sub identifier { $_[0]->{Identifier} }
2521             sub rights { (wantarray) ? @{$_[0]->{Rights}} : $_[0]->{Rights} }
2522              
2523             ###############################################################################
2524              
2525             =head1 Myrights
2526              
2527             This is a container for C responses>
2528              
2529             =head2 mailbox
2530              
2531             Returns the name of the mailbox associated with the given rights.
2532              
2533             =head2 rights
2534              
2535             Returns a string containing the rights contained in the response.
2536              
2537             =cut
2538              
2539             package Net::IMAP::Myrights;
2540             use vars qw(@ISA);
2541             @ISA = qw(Net::IMAP::UntaggedResponse);
2542              
2543             sub name { 'myrights' }
2544              
2545             sub new {
2546             my $class = shift;
2547             my $type = ref($class) || $class;
2548             my $parent = shift;
2549             my $str = shift;
2550              
2551             my $self = {};
2552              
2553             bless $self, $class;
2554              
2555             $self->{Parent} = $parent;
2556              
2557             my $fields = Net::xAP->parse_fields($str);
2558             $self->{Mailbox} = $fields->[0];
2559             $self->{Rights} = $fields->[1];
2560              
2561             return $self;
2562             }
2563              
2564             sub mailbox { $_[0]->{Mailbox} }
2565             sub rights { $_[0]->{Rights} }
2566              
2567             ###############################################################################
2568              
2569             =head1 Quota
2570              
2571             This is a container for C responses.
2572              
2573             =head2 quotaroot
2574              
2575             Returns a string containing the name of the quota root in the response.
2576              
2577             =head2 quotas
2578              
2579             Returns a list of the quotas contained in the response.
2580              
2581             =head2 usage $quota
2582              
2583             Returns the usage value associated with the given C<$quota>. Returns
2584             C is the given C<$quota> is not present in the response.
2585              
2586             =head2 limit $quota
2587              
2588             Returns the usage limit associated with the given C<$quota>. Returns
2589             C is the given C<$quota> is not present in the response.
2590              
2591             =cut
2592              
2593             package Net::IMAP::Quota;
2594             use vars qw(@ISA);
2595             @ISA = qw(Net::IMAP::UntaggedResponse);
2596              
2597             sub name { 'quota' }
2598              
2599             sub new {
2600             my $class = shift;
2601             my $type = ref($class) || $class;
2602             my $parent = shift;
2603             my $str = shift;
2604              
2605             my $self = {};
2606              
2607             bless $self, $class;
2608              
2609             $self->{Parent} = $parent;
2610              
2611             my @fields = @{Net::xAP->parse_fields($str)};
2612             $self->{QuotaRoot} = shift(@fields);
2613             while (@fields) {
2614             my ($resource, $usage, $limit) = splice(@fields, 0, 3);
2615             $self->{Quota}{lc($resource)} = [$usage, $limit];
2616             }
2617              
2618             return $self;
2619             }
2620              
2621             sub quotaroot { $_[0]->{QuotaRoot} }
2622             sub quotas { keys %{$_[0]->{Quotas}} }
2623             sub usage { $_[0]->{Quotas}{lc($_[1])}->[0] }
2624             sub limit { $_[0]->{Quotas}{lc($_[1])}->[1] }
2625              
2626             ###############################################################################
2627              
2628             =head1 Quotaroot
2629              
2630             This is a container for C responses.
2631              
2632             =head2 mailbox
2633              
2634             Returns the name of the mailbox associated with the quotaroot data.
2635              
2636             =head2 quotaroots
2637              
2638             If called in an array context, returns the list of quotaroots
2639             associated with the mailbox. If called in a scalar context, returns a
2640             list reference.
2641              
2642             =cut
2643              
2644             package Net::IMAP::Quotaroot;
2645             use vars qw(@ISA);
2646             @ISA = qw(Net::IMAP::UntaggedResponse);
2647              
2648             sub name { 'quotaroot' }
2649              
2650             sub new {
2651             my $class = shift;
2652             my $type = ref($class) || $class;
2653             my $parent = shift;
2654             my $str = shift;
2655              
2656             my $self = {};
2657              
2658             bless $self, $class;
2659              
2660             $self->{Parent} = $parent;
2661              
2662             my @fields = @{Net::xAP->parse_fields($str)};
2663             $self->{Mailbox} = shift(@fields);
2664             $self->{Quotaroots} = [@fields];
2665              
2666             return $self;
2667             }
2668              
2669             sub mailbox { $_[0]->{Mailbox} }
2670             sub quotaroots { (wantarray) ? @{$_[0]->{Quotaroots}} : $_[0]->{Quotaroots} }
2671              
2672             ###############################################################################
2673              
2674             =head1 MISC FETCH OBJECTS
2675              
2676             A C response can be relatively complicated. This section
2677             documents various classes and methods associated with the various
2678             pieces of information available in C responses.
2679              
2680             =cut
2681              
2682             package Net::IMAP::FetchData;
2683              
2684             sub new {
2685             my $class = shift;
2686             my $type = ref($class) || $class;
2687             my $self = [];
2688             if (defined($_[0])) {
2689             push(@{$self},
2690             map {
2691             (lc($_) eq 'nil') ? undef : Net::xAP->dequote($_)
2692             } @{$_[0]});
2693             }
2694             bless $self, $class;
2695             }
2696              
2697             ###############################################################################
2698              
2699             =head1 BodyStructure
2700              
2701             This is a container for C items in C responses.
2702              
2703             =head2 type
2704              
2705             Returns a string containing the MIME type of the message. This is the
2706             left-hand portion of a MIME media type. For example, the type of
2707             C is C.
2708              
2709             =head2 subtype
2710              
2711             Returns a string containing the MIME subtype of the message. This is
2712             the right-hand portion of a MIME media type. For example, the subtype
2713             of C is C.
2714              
2715             =head2 parameters
2716              
2717             Returns a reference to a hash containing the key/value attribute pairs
2718             in the C field.
2719              
2720             If, for example, the C field was:
2721              
2722             Content-Type: text/plain; charset=us-ascii
2723              
2724             The hash would contain one entry the a key of C, and a value
2725             of C. The key is always forced to be lowercase, but the
2726             case of the value is retained from the server.
2727              
2728             =head2 disposition
2729              
2730             Returns the disposition type in the C field.
2731             Returns C if no such field exists.
2732              
2733             =head2 disp_parameters
2734              
2735             Returns a reference to a hash containing the key/value attributer
2736             pairs in the C field. A reference to an empty
2737             hash is returned if no such field exists, or if there are no
2738             parameters in the field.
2739              
2740             =head2 language
2741              
2742             Returns a reference to a list of the language tags present in the
2743             C field. Returns a reference to an empty hash if no
2744             such field is present.
2745              
2746             =cut
2747              
2748             package Net::IMAP::BodyStructure;
2749              
2750             sub new {
2751             my $class = shift;
2752             my $type = ref($class) || $class;
2753             my $data = shift;
2754              
2755             return Net::IMAP::Multipart->new($data) if (ref($data->[0]) eq 'ARRAY');
2756             return Net::IMAP::Bodypart->new($data);
2757             }
2758              
2759             sub subtype { $_[0]->{Subtype} }
2760             sub parameters { $_[0]->{Parms} }
2761             sub disposition { $_[0]->{Disp} }
2762             sub disp_parameters { $_[0]->{DispParms} }
2763             sub language { $_[0]->{Lang} }
2764              
2765             sub _parse_parms {
2766             my $self = shift;
2767             my $data = shift;
2768             if (ref($data) eq 'ARRAY') {
2769             my @parms = @{$data};
2770             while (@parms) {
2771             my ($key, $value) = splice(@parms, 0, 2);
2772             $self->{Parms}{lc($key)} = $value;
2773             }
2774             }
2775             }
2776              
2777             sub _parse_disp {
2778             my $self = shift;
2779             my $data = shift;
2780              
2781             $self->{Disp} = lc($data);
2782             if (ref($data) eq 'ARRAY') {
2783             if (lc($data->[1]) ne 'nil') {
2784             my @parms = @{$data->[1]};
2785             while (@parms) {
2786             my ($key, $value) = splice(@parms, 0, 2);
2787             $self->{DispParms}{lc($key)} = $value;
2788             }
2789             }
2790             }
2791             }
2792              
2793             sub _parse_lang {
2794             my $self = shift;
2795             my $data = shift;
2796              
2797             $data = lc($data);
2798             if ($data ne 'nil') {
2799             if (ref($data) eq 'ARRAY') {
2800             $self->{Lang} = [map { lc($_) } @{$data}];
2801             } else {
2802             $self->{Lang} = [lc($data)];
2803             }
2804             }
2805             }
2806              
2807             #------------------------------------------------------------------------------
2808              
2809             =head1 Multipart
2810              
2811             This is a container for C
2812              
2813             =head2 parts
2814              
2815             Returns a list reference of the body parts contained in the multipart
2816             entity.
2817              
2818             =cut
2819              
2820             package Net::IMAP::Multipart;
2821             use vars qw(@ISA);
2822             @ISA = qw(Net::IMAP::BodyStructure);
2823              
2824             sub new {
2825             my $class = shift;
2826             my $type = ref($class) || $class;
2827             my $data = shift;
2828              
2829             my $self = {};
2830              
2831             bless $self, $class;
2832              
2833             $self->{Parts} = [];
2834              
2835             my $i = 0;
2836             for my $item (@{$data}) {
2837             last if (ref($item) ne 'ARRAY');
2838             if (ref($item->[0]) eq 'ARRAY') {
2839             push @{$self->{Parts}}, Net::IMAP::Multipart->new($item);
2840             } else {
2841             push @{$self->{Parts}}, Net::IMAP::Bodypart->new($item);
2842             }
2843             $i++;
2844             }
2845              
2846             $self->{Subtype} = lc(Net::xAP->dequote($data->[$i++]));
2847              
2848             $self->{Parms} = {};
2849             $self->{Disp} = undef;
2850             $self->{DispParms} = {};
2851             $self->{Lang} = undef;
2852              
2853             if (defined($data->[$i])) {
2854             $self->_parse_parms($data->[$i++]);
2855             if (defined($data->[$i])) {
2856             $self->_parse_disp($data->[$i++]);
2857             if (defined($data->[$i])) {
2858             $self->_parse_lang($data->[$i++]);
2859             if (defined($data->[$i])) {
2860             carp("Note: bodystructure contains unknown extension fields\n");
2861             }
2862             }
2863             }
2864             }
2865              
2866             return $self;
2867             }
2868              
2869             sub type { 'multipart' }
2870             sub parts { $_[0]->{Parts} }
2871              
2872             #------------------------------------------------------------------------------
2873              
2874             =head1 Bodypart
2875              
2876             This is a container for singlepart entities in C and
2877             C objects.
2878              
2879             =head2 id
2880              
2881             Return a string containing the contents of the C field, if
2882             one is present, otherwise returns undef.
2883              
2884             =head2 description
2885              
2886             Return a string containing the contents of the C
2887             field, if one is present, otherwise returns undef.
2888              
2889             =head2 encoding
2890              
2891             Returns a string containing the contents of the
2892             C field. Returns C if no such field
2893             is in the entity.
2894              
2895             =head2 size
2896              
2897             Returns the number of octets in the entity.
2898              
2899             =head2 lines
2900              
2901             If the MIME content type is C or the major type is
2902             C, returns the number of lines in the entity, else returns C.
2903              
2904             =head2 envelope
2905              
2906             If the MIME content type is C
2907             C object, otherwise returns undef.
2908              
2909             =head2 bodystructure
2910              
2911             If the MIME content type is C
2912             C object, otherwise returns undef.
2913              
2914             =head2 md5
2915              
2916             Returns a string containing the contents of the C field.
2917             Returns C if no such field is in the entity.
2918              
2919             =cut
2920              
2921             package Net::IMAP::Bodypart;
2922             use vars qw(@ISA);
2923             @ISA = qw(Net::IMAP::BodyStructure);
2924             use Carp;
2925              
2926             sub new {
2927             my $class = shift;
2928             my $type = ref($class) || $class;
2929             my $data = shift;
2930              
2931             my $self = {};
2932              
2933             bless $self, $class;
2934              
2935             my $i = 0;
2936              
2937             $self->{Type} = lc(Net::xAP->dequote($data->[$i++]));
2938             $self->{Subtype} = lc(Net::xAP->dequote($data->[$i++]));
2939             $self->{Parms} = {};
2940             $self->_parse_parms($data->[$i++]);
2941             $self->{Id} = Net::xAP->dequote($data->[$i++]);
2942             $self->{Description} = Net::xAP->dequote($data->[$i++]);
2943             $self->{Encoding} = lc(Net::xAP->dequote($data->[$i++]));
2944             $self->{Size} = $data->[$i++];
2945              
2946             if (($self->{Type} eq 'message') && ($self->{Subtype} eq 'rfc822')) {
2947             $self->{Envelope} = Net::IMAP::Envelope->new($data->[$i++]);
2948             $self->{Bodystructure} = Net::IMAP::BodyStructure->new($data->[$i++]);
2949             $self->{Lines} = $data->[$i++];
2950             } elsif ($self->{Type} eq 'text') {
2951             $self->{Lines} = $data->[$i++];
2952             }
2953              
2954             $self->{Envelope} ||= undef;
2955             $self->{BodyStructure} ||= undef;
2956             $self->{Lines} ||= undef;
2957              
2958             if (defined($data->[$i])) {
2959             $self->{MD5} = Net::xAP->dequote($data->[$i++]);
2960             if (defined($data->[$i])) {
2961             $self->_parse_disp($data->[$i++]);
2962             if (defined($data->[$i])) {
2963             $self->_parse_lang($data->[$i++]);
2964             if (defined($data->[$i])) {
2965             carp("Note: bodystructure contains unknown extension fields\n");
2966             }
2967             }
2968             }
2969             }
2970              
2971             $self->{MD5} ||= undef;
2972             $self->{Disp} ||= undef;
2973             $self->{DispParms} ||= {};
2974             $self->{Lang} ||= undef;
2975              
2976             return $self;
2977             }
2978              
2979             sub type { $_[0]->{Type} }
2980             sub id { $_[0]->{Id} }
2981             sub description { $_[0]->{Description} }
2982             sub encoding { $_[0]->{Encoding} }
2983             sub size { $_[0]->{Size} }
2984             sub lines { $_[0]->{Lines} } # message/rfc822 and text/*
2985             sub envelope { $_[0]->{Envelope} } # message/rfc822
2986             sub bodystructure { $_[0]->{Bodystructure} } # message/rfc822
2987             sub md5 { $_[0]->{MD5} }
2988              
2989             ###############################################################################
2990              
2991             =head1 Envelope
2992              
2993             This is a container for envelope data in C responses.
2994              
2995             For those familiar with SMTP, this is not the same type envelope.
2996             Rather, it is a composite structure containing key source,
2997             destination, and reference information in the message. When retrieved
2998             from the server, it is populated into a C object.
2999             The following methods are available.
3000              
3001             =head2 date
3002              
3003             Returns a string with the contents of the C field.
3004              
3005             =head2 subject
3006              
3007             Returns a string with the contents of the C field.
3008              
3009             =head2 from
3010              
3011             Returns a list reference of C objects with the
3012             contents of the C field.
3013              
3014             =head2 sender
3015              
3016             Returns a list reference of C objects with the
3017             contents of the C field. If no C field is present in
3018             the message, the server will default it to the contents of the C
3019             field.
3020              
3021             =head2 reply_to
3022              
3023             Returns a list reference of C objects with the
3024             contents of the C field. If no C field is present
3025             in the message, the server will default it to the contents of the
3026             C field.
3027              
3028             =head2 to
3029              
3030             Returns a list reference of C objects with the
3031             contents of the Cfield. Will return C if no C field
3032             exists in the message.
3033              
3034             =head2 cc
3035              
3036             Returns a list reference of C objects with the
3037             contents of the C field. Will return C if no C field
3038             exists in the message.
3039              
3040             =head2 bcc
3041              
3042             Returns a list reference of C objects with the
3043             contents of the C field. Will return C if no C field
3044             exists in the message.
3045              
3046             =head2 in_reply_to
3047              
3048             Returns a string with the contents of the C field.
3049             Returns C if no such field is present in the message.
3050              
3051             =head2 message_id
3052              
3053             Returns a string with the contents of the C field. Returns
3054             C if no such field is present in the message.
3055              
3056             =cut
3057              
3058             package Net::IMAP::Envelope;
3059             use vars qw(@ISA);
3060             @ISA = qw(Net::IMAP::FetchData);
3061              
3062             sub new {
3063             my $class = shift;
3064             my $type = ref($class) || $class;
3065             my $data = shift;
3066              
3067             my $self = Net::IMAP::FetchData->new
3068             or return undef;
3069              
3070             bless $self, $class;
3071              
3072             $self->[0] = Net::xAP->dequote($data->[0]);
3073             $self->[1] = Net::xAP->dequote($data->[1]);
3074             for my $i (2 .. 7) {
3075             if (lc($data->[$i]) eq 'nil') {
3076             $self->[$i] = undef;
3077             next;
3078             }
3079             push @{$self->[$i]}, map { Net::IMAP::Addr->new($_) } @{$data->[$i]};
3080             }
3081             $self->[8] = Net::xAP->dequote($data->[8]);
3082             $self->[9] = Net::xAP->dequote($data->[9]);
3083              
3084             return $self;
3085             }
3086              
3087             sub date { $_[0]->[0] }
3088             sub subject { $_[0]->[1] }
3089             sub from { $_[0]->[2] }
3090             sub sender { $_[0]->[3] }
3091             sub reply_to { $_[0]->[4] }
3092             sub to { $_[0]->[5] }
3093             sub cc { $_[0]->[6] }
3094             sub bcc { $_[0]->[7] }
3095             sub in_reply_to { $_[0]->[8] }
3096             sub message_id { $_[0]->[9] }
3097              
3098             #------------------------------------------------------------------------------
3099              
3100             =head1 Addr
3101              
3102             This is a container for address structures in C objects.
3103              
3104             =head2 phrase
3105              
3106             Returns a string containing the phrase portion of the address, or
3107             C if no phrase is present.
3108              
3109             =head2 route
3110              
3111             Returns a string containing the route portion of the address, or
3112             C if no route information is present.
3113              
3114             =head2 localpart
3115              
3116             Returns a string containing the localpart portion of the address, or
3117             C if no localpart is present.
3118              
3119             =head2 domain
3120              
3121             Returns a string containing the domain portion of the address, or
3122             C if no domain is present.
3123              
3124             =head2 as_string
3125              
3126             Returns a string representation of the contents of the object.
3127              
3128             =cut
3129              
3130             package Net::IMAP::Addr;
3131             use vars qw(@ISA);
3132             @ISA = qw(Net::IMAP::FetchData);
3133              
3134             sub phrase { $_[0]->[0] }
3135             sub route { $_[0]->[1] }
3136             sub localpart { $_[0]->[2] }
3137             sub domain { $_[0]->[3] }
3138              
3139             sub as_string {
3140             my $self = shift;
3141             my $str;
3142             my $domain = $self->domain;
3143             my $localpart = $self->localpart;
3144             my $route = $self->route;
3145             my $phrase = $self->phrase;
3146              
3147             return undef if (!defined($domain)); # part of a group list
3148             return undef if (!defined($localpart));
3149              
3150             $str = "$localpart\@$domain";
3151             if (defined($route) || defined($phrase)) {
3152             $str = "$route:$str" if defined($route);
3153             $str = "<$str>"; # route-addrs and phrases need <>
3154             $str = "$phrase $str" if defined($phrase);
3155             }
3156             return $str;
3157             }
3158              
3159             ###############################################################################
3160              
3161             =head1 CAVEATS
3162              
3163             Minimal testing has been done against the various IMAP server
3164             implementations. Refer to C for known bugs/malfeatures.
3165              
3166             =head1 AUTHOR
3167              
3168             Kevin Johnson EFE
3169              
3170             =head1 COPYRIGHT
3171              
3172             Copyright (c) 1997-1999 Kevin Johnson .
3173              
3174             All rights reserved. This program is free software; you can
3175             redistribute it and/or modify it under the same terms as Perl itself.
3176              
3177             =cut
3178              
3179             1;