1
0
mirror of https://github.com/imapsync/imapsync.git synced 2024-11-16 15:52:47 +01:00
This commit is contained in:
Nick Bebout 2011-03-12 02:44:47 +00:00
parent 36bfe4238a
commit 9ca0e338a4
170 changed files with 48049 additions and 33315 deletions

View File

@ -6,8 +6,16 @@ BUGS found with Mail-IMAPClient-3.05/
30 timeout.
2) --expunge2 does not expunge anything.
Fixed in Mail-IMAPClient-3.10/
3) Mail-IMAPClient-3.13/
30 timeout on connection.
4) Mail-IMAPClient-3.14/
Wrong. Lacks isUnconnected() method.

132
CREDITS
View File

@ -1,5 +1,5 @@
#!/bin/cat
# $Id: CREDITS,v 1.115 2008/08/27 11:56:52 gilles Exp gilles $
# $Id: CREDITS,v 1.122 2009/05/04 01:08:32 gilles Exp gilles $
If you want to make a donation to the author, Gilles LAMIRAL:
@ -12,7 +12,7 @@ b) If you can read french, please use the following wishlist :
http://amazon.fr/gp/registry/wishlist/37RZF7PPCD7YL
(books will be send with free postal cost)
c) its paypal account gilles.lamiral@laposte.net
c) its paypal account : gilles.lamiral@laposte.net
Here are the persons who helped me to develop imapsync.
Feel free to tell me if a name is missing or if you want
@ -20,6 +20,104 @@ to remove one.
I thank very much all of these people.
Edward Blackburne
Contributed by giving the book
26.95 "Mathematics and Plausible Reasoning (vol 1)"
Xavier Gattuso
Contributed by giving the book
21.86 "Wicked Cool Perl Scripts: Useful Perl Scripts That Solve Difficult Problems"
Richard Madison
Contributed by giving the books
69.95 "Topologie générale: Chapitres 1-4 (French Edition)"
69.95 "Topologie générale: Chapitres 5-10 (French Edition)"
Bill Raines
Contributed by giving the book
31.49 "Designing Web Navigation: Optimizing the User Experience"
Bataille Vincent
Contributed by giving the books
"Les techniques narratives du cinéma"
"Entretien avec Fabienne Verdier"
Sann GmbH
Contributed by giving the book
12.21 "Uncommon Therapy (Haley, Jay)"
Frank Justin Woodman
Contributed by giving the book
75.60 "The Art of Electronics"
Yohann Lucas
Sent a bug report about "+FLAGS" behavior.
Reuben Thomas
Corrected my bad english in the README imapsync(1).
Michal Kubski
Wrote TLS support patches/imapsync-1.217_tls_support.patch
Jari Salmela
Had success with Sun Java(tm) System Messaging Server 6.2-7.05
Gave patches/imapsync_1.267_jari
Not applied, this patch is too server specific but
can be useful to specific users.
Alexander Skwar
From Google Apps domain to Googlemail account.
Had a problem "NO Invalid folder: Sent (Failure)" with
another folder. Solved by --folder (see FAQ)
Cassio Brodbeck Caporal
Had Microsoft Exchange 2000 6.0.6487.0 success.
Tomasz Kaczmarski
Found the nice trick
--skipheader '^(?!Message-ID)'
for buggy servers sending the whole header instead of
just one line when --useheader 'Message-ID' is used.
Benjamin Shapiro
Contributed by giving $5,00 USD (finally 3,38 EUR )
Gustavo Lozano
Contributed by giving the book
19.77 "Wicked Cool Shell Scripts"
Stefan Schmidt
Wrote "speed problem for large mails" FAQ entry.
Fixed INBOX/INBOX bug.
Janina Banach
Contributed by giving the books
19.77 "Hardware Hacking Projects for Geeks"
23.09 "The Best of MAKE"
Ricardo David Consolo
Contributed by giving the book
16.49 "More Joel on Software: Further Thoughts on Diverse and ..."
Quirin Scheitle and Florian Kessler
Contributed by giving the books
32.97 "Designing interfaces: Patterns for Effective Interaction Design"
26.39 "Learning Perl, 5th edition"
Robert Sanders
Contributed by giving the book
40.00 "Processing : A Programming Handbook for Visual Designers and Artists"
Patrick C.F. Ernzer
Contributed by giving the book
19.77 "Funkifying the Clave: Bass and Drums, Goines Ameen"
Daniel Skinner
Made me write the FAQ entry about offlineimap and
read its documentation.
@ -37,20 +135,20 @@ the authuser method with uw-imap. FAQ entry.
Scott Pedigo
Contributed by giving the book
"Smart and Gets Things Done"
11.55 "Smart and Gets Things Done"
Don Jackson
Contributed by giving the book
"The Back of the Napkin"
15.64 "The Back of the Napkin"
Joschua Penix
Contributed by giving the book
"Programming Collective Intelligence"
26.39 "Programming Collective Intelligence"
Bertram N Shure
Contributed by giving the book
"Hackers and Painters".
15.61 "Hackers and Painters".
Simon Heimlicher
Gave a patch to avoid non-selectable folders.
@ -61,7 +159,7 @@ to Cyrus IMAP4 v2.3.7 server ready
Drew McLellan
Contributed by giving the book
"Peopleware: Productive Projects and Teams"
30.55 "Peopleware: Productive Projects and Teams"
Nirdosh Shah
Contributed by giving the books
@ -603,6 +701,23 @@ Eric Yung
Total amount of book prices :
c \
26.95+\
21.86+\
\
69.95+\
69.95+\
31.49+\
12.21+\
\
75.60+\
19.77+\
\
19.77+\
23.09+\
16.49+\
32.97+\
26.39+\
\
16.47+\
26.39+\
29.95+\
@ -632,7 +747,6 @@ c \
40.00+\
18.21+\
24.95+\
31.49+\
64.50+\
32.70+\
50.40+\
@ -650,4 +764,4 @@ c \
31.20+\
40.00
=1253.02
=1668.02

View File

@ -1,15 +1,102 @@
RCS file: RCS/imapsync,v
Working file: imapsync
head: 1.267
head: 1.284
branch:
locks: strict
gilles: 1.284
access list:
symbolic names:
keyword substitution: kv
total revisions: 267; selected revisions: 267
total revisions: 284; selected revisions: 284
description:
----------------------------
revision 1.284 locked by: gilles;
date: 2009/06/30 03:14:24; author: gilles; state: Exp; lines: +15 -19
allow Mail::IMAPClient 3.0.xx by default
Removed Mail::IMAPClient::Ssl since 3.0.19 has it now.
----------------------------
revision 1.283
date: 2009/06/30 02:54:57; author: gilles; state: Exp; lines: +123 -94
Applied Phil Lobbes patch as is : ./patches/imapsync.1.282.patch
----------------------------
revision 1.282
date: 2009/05/11 00:05:39; author: gilles; state: Exp; lines: +15 -10
Added option --justlogin
----------------------------
revision 1.281
date: 2009/04/24 13:58:15; author: gilles; state: Exp; lines: +29 -6
Added tests_flags_regex() regression tests.
----------------------------
revision 1.280
date: 2009/04/02 11:32:10; author: gilles; state: Exp; lines: +103 -47
Applied Phil patch with many IsUnconnected() calls.
----------------------------
revision 1.279
date: 2009/03/22 00:12:15; author: gilles; state: Exp; lines: +9 -7
isUnconnected BAD IsUnconnected GOOD!
----------------------------
revision 1.278
date: 2009/02/23 00:40:25; author: gilles; state: Exp; lines: +14 -12
Less imap output with +FLAGS.SILENT
Changed unsubscribe subscribe order in documentation.
Typos.
----------------------------
revision 1.277
date: 2009/02/21 12:10:50; author: gilles; state: Exp; lines: +8 -6
Better example explanation.
----------------------------
revision 1.276
date: 2009/02/21 04:04:08; author: gilles; state: Exp; lines: +15 -22
Removed mailto: in MAILING-LIST section.
----------------------------
revision 1.275
date: 2009/02/21 02:04:26; author: gilles; state: Exp; lines: +25 -14
Change real password to "MASKED" in command line output.
----------------------------
revision 1.274
date: 2009/02/21 01:10:02; author: gilles; state: Exp; lines: +14 -8
--delete 2 is now a fatal error.
----------------------------
revision 1.273
date: 2009/02/21 00:48:40; author: gilles; state: Exp; lines: +36 -37
Print a warning and return error code each time a disconnection occurs.
----------------------------
revision 1.272
date: 2009/02/20 23:41:09; author: gilles; state: Exp; lines: +78 -78
Fixed many English errors (thanks to Reuben Thomas)
----------------------------
revision 1.271
date: 2009/02/19 23:38:32; author: gilles; state: Exp; lines: +28 -35
Bug fix about $t_prefix and INBOX '.' was hardcoded.
Small change on documentation.
----------------------------
revision 1.270
date: 2009/02/14 22:21:35; author: gilles; state: Exp; lines: +16 -11
Another Phil Lobbes patch.
Exit with error code and warning when a server disconnect
during the folder loop.
----------------------------
revision 1.269
date: 2009/02/14 22:08:18; author: gilles; state: Exp; lines: +65 -38
Applied Phil Lobbes patches.
- catch (what should be) fatal eval errors for regextrans2,
$regexflag, $regexmess, instead of silently ignoring them
and letting the user think they are working/OK
- fix login_imap() Died at .../imapsync line 780 when IsUnconnected()
and log some more useful into to stderr than just 'Died at...'
- check_lib_version() contains a bad use of unset match/capture variables
- added and now use new function myconnect() and myconnect_v2()
does not require hack/override of Mail::IMAPClient::connect
and is backwards compatible with Mail::IMAPClient v2.x
- redo $Mail::IMAPClient::Authuser hack since only
Mail::IMAPClient v2 does not have Authuser()
Many thanks to Phil.
----------------------------
revision 1.268
date: 2009/02/14 03:27:51; author: gilles; state: Exp; lines: +22 -21
Fixed bad VERSION_IMAPClient output
----------------------------
revision 1.267
date: 2008/10/07 11:36:02; author: gilles; state: Exp; lines: +14 -10
Better test to check non existing folders on destination

145
FAQ
View File

@ -1,3 +1,5 @@
#!/bin/cat
# $Id: FAQ,v 1.59 2009/04/30 02:09:09 gilles Exp gilles $
+------------------+
| FAQ for imapsync |
@ -18,10 +20,35 @@ Q. Can you give some configuration examples ?
R. http://www.linux-france.org/prj/imapsync/FAQ
=======================================================================
Q. How can I have support ?
R. Use the mailing-list
To write on the mailing-list, the address is:
<imapsync@linux-france.org>
To subscribe, send a message to:
<imapsync-subscribe@listes.linux-france.org>
To unsubscribe, send a message to:
<imapsync-unsubscribe@listes.linux-france.org>
To contact the person in charge for the list:
<imapsync-request@listes.linux-france.org>
The list archives may be available at:
http://www.linux-france.org/prj/imapsync_list/
So consider that the list is public, anyone
can see your post. Use a pseudonym or do not
post to this list if you want to stay private.
Thank you for your participation.
=======================================================================
Q. Where I can read IMAP RFCs ?
R.
R. Here:
RFC 3501 - INTERNET MESSAGE ACCESS PROTOCOL - VERSION 4rev1
http://www.faqs.org/rfcs/rfc3501.html
@ -45,7 +72,22 @@ Q. Where I can find old imapsync releases ?
R. ftp://www.linux-france.org/pub/prj/imapsync/
=======================================================================
Q. imapsync does not work with Mail::IMAPClient 3.0.x
Q. How can I try imapsync with Mail::IMAPClient 3.xx perl library?
R. - Download latest Mail::IMAPClient 3.xx at
http://search.cpan.org/dist/Mail-IMAPClient/
- untar it anywhere:
tar xzvf Mail-IMAPClient-3.xx.tar.gz
- Download latest imapsync at
http://lamiral.info/~gilles/imapsync/imapsync
- run imapsync with perl and -I option tailing to use Mail-IMAPClient-3.xx
and add also option --allow3xx:
perl -I./Mail-IMAPClient-3.16/lib imapsync ... --allow3xx
=======================================================================
Q. imapsync does not work with Mail::IMAPClient 3.xx
How can I downgrade to 2.2.9 release?
R. - Download Mail::IMAPClient 2.2.9 at
@ -278,14 +320,33 @@ To skip several headers you can use --skipheader one time
imapsync ... --skipheader '^X-|^Status|^Bcc'
or several times (same result)
imapsync ... --skipheader '^X-' --skipheader '^Status' --skipheader '^Bcc'
If you think you have too many header to avoid just use
imapsync ... --useheader 'Message-ID' --skipsize
Remark. (Trick found by Tomasz Kaczmarski)
Option --useheader 'Message-ID' asks the server
to send only header lines begining with 'Message-ID'.
Some (buggy) servers send the whole header (all lines)
instead of the 'Message-ID' line. In that case, a trick
to keep the --useheader filtering behavior is to use
--skipheader with a negative lookahead pattern :
imapsync ... --skipheader '^(?!Message-ID)' --skipsize
Read it as "skip every header except Message-ID".
======================================================================
Q. I am transferring mails from one IMAP server to another. I am using
an SSL connection. Transferring huge mails (>10MB) takes ages.
R. try to transfer the mails without SSL connection. SSL code outside
imapsync uses a memory buffer, which gets increased upon reading of
mails by 4096 bytes. This creates a huge load on the host imapsync
runs on by copying the memory buffers for every 4096 byte step.
This does not occur without SSL.
(Written by Stefan Schmidt)
======================================================================
Q. I want to exclude a folder hierarchy like "public"
@ -471,6 +532,31 @@ Also, you must take imapsync 1.159 at least since I tested
what I just wrote above and found 2 bugs about --mindate
--maxdate options behavior.
=======================================================================
Q. I want to play with headers line and --regexmess but I want to leave
the body as is
R. The header/body separation is a blank line so an example:
--regexmess 's{\A(.*?(?! ^$))^Date:(.*?)$}{$1Date:$2\nX-Date:$2}gxms'
Will replace
HeaderBegin
Message-ID: <499EF800.4030002@blabla.fr>
Date: Fri, 20 Feb 2009 19:35:44 +0100
From: Gilles LAMIRAL <lamiral@linux-france.org>
HeaderEnd
by
HeaderBegin
Message-ID: <499EF800.4030002@blabla.fr>
Date: Fri, 20 Feb 2009 19:35:44 +0100
X-Date: Fri, 20 Feb 2009 19:35:44 +0100
From: Gilles LAMIRAL <lamiral@linux-france.org>
HeaderEnd
This example just add an header line "X-Date:" based on "Date:" line.
=======================================================================
Q. My imap server does not accept a message and warns
@ -531,6 +617,7 @@ imapsync --syncinternaldates \
--host2 imap.gmail.com --port2 993 --ssl2 \
--user2 my_email@gmail.com \
--password2 password \
--useheader 'Message-Id' --skipsize \
--prefix2 '[Gmail]/' \
--folder 'INBOX.Sent' \
--regextrans2 's/Sent/Sent Mail/'
@ -556,6 +643,41 @@ option:
--regextrans2 's/\[Gmail\]/Gmail/'
=======================================================================
Q. migrate email from gmail to google apps
R. Take a look at:
http://biasecurities.com/2009/migrate-email-from-gmail-to-google-apps/
http://www.thamtech.com/blog/2008/03/29/gmail-to-google-apps-email-migration/
=======================================================================
Q. from Microsoft's Exchange 2007 to Google Apps for your Domain
(GAFYD)
R. Take a look at:
http://mark.ossdl.de/2009/02/migrating-from-exchange-2007-to-google-apps-mail/
=======================================================================
Q. Syncing from Google Apps domain to Googlemail account
A known bug encountered with this output (Alexander is a folder name):
++++ Verifying [Alexander] -> [Alexander] ++++
+ NO msg #16 [A96Dh4AwlLVphOAW5MS/eQ:779824] in Alexander
+ Copying msg #16:779824 to folder Alexander
flags from : [\Seen]["04-Jul-2007 14:32:22 +0100"]
Couldn't append msg #16 (Subject:[Rieter-Event (please accept with
comments)]) to folder Alexander: 46 NO Invalid folder: Sent (Failure)
In fact folder "Sent" is just the last folder listed previously
as a:
...
To Folder [Sent] does not exist yet
To Folder [Sonja] Size: 1024546 Messages: 96
...
R. Just run imapsync a time like this :
imapsync ... --folder Alexander
=======================================================================
Q. I'm migrating from WU to Cyrus, and the mail folders are
under /home/user/mail but the tool copies everything in
@ -729,6 +851,11 @@ R. http://www.archiveopteryx.org/migration/imapsync
Use:
--useheader Message-Id --skipsize
======================================================================
Q. To Sun Java(tm) System Messaging Server 6.2-7.05
Q. To Communigate Pro - Solaris version
R. See and run patches/imapsync_1.267_jari
======================================================================
Q. From any to Exchange2007
@ -749,6 +876,12 @@ R2. Other solution
Two users succeded by using "MS Transporter Suite" (which is closed
expensive nonfree software).
======================================================================
Q. From Microsoft Exchange 2000 IMAP4rev1 server version 6.0.6487.0.
R. imapsync ... \
--prefix1 INBOX. --prefix2 INBOX. --syncinternaldates --subscribe \
--maxsize 10485760
======================================================================
Q: How can I write an .rpm with imapsync

14
INSTALL
View File

@ -1,4 +1,4 @@
# $Id: INSTALL,v 1.14 2008/08/16 17:18:58 gilles Exp gilles $
# $Id: INSTALL,v 1.15 2009/06/30 03:21:17 gilles Exp gilles $
#
# INSTALL file for imapsync
# imapsync : IMAP sync or copy tool.
@ -58,12 +58,13 @@ Here is some individual module help:
http://search.cpan.org/~djkernen/
http://search.cpan.org/~djkernen/Mail-IMAPClient-2.2.9/
In fact I use Mail-IMAPClient-2.2.9 (debian package)
In fact I use Mail-IMAPClient-2.2.9
To know the version you have on your system try :
perl -mMail::IMAPClient -e 'print $Mail::IMAPClient::VERSION, "\n"'
New Mail-IMAPClient-3.xx doesn't work with imapsync for the moment.
New Mail-IMAPClient-3.xx works now with imapsync,
at least with Mail-IMAPClient-3.19 (previous may bug)
- Perl Digest::MD5 module.
http://search.cpan.org/
@ -111,9 +112,10 @@ TESTING
-------
The test will break as they are home specific.
You need a running imap server on localhost with two accounts
toto@est.belle with a password located in the file /var/tmp/secret1
titi@est.belle with a password located in the file /var/tmp/secret2
You need a running imap server on localhost with several accounts
toto with a password located in the file $HOME/var/pass/secret.toto
titi with a password located in the file $HOME/var/pass/secret.titi
tata with a password located in the file $HOME/var/pass/secret.tata
Of course, you can change the file tests.sh and run the tests with :

View File

@ -0,0 +1,131 @@
The "Artistic License"
Preamble
The intent of this document is to state the conditions under which a
Package may be copied, such that the Copyright Holder maintains some
semblance of artistic control over the development of the package,
while giving the users of the package the right to use and distribute
the Package in a more-or-less customary fashion, plus the right to make
reasonable modifications.
Definitions:
"Package" refers to the collection of files distributed by the
Copyright Holder, and derivatives of that collection of files
created through textual modification.
"Standard Version" refers to such a Package if it has not been
modified, or has been modified in accordance with the wishes
of the Copyright Holder as specified below.
"Copyright Holder" is whoever is named in the copyright or
copyrights for the package.
"You" is you, if you're thinking about copying or distributing
this Package.
"Reasonable copying fee" is whatever you can justify on the
basis of media cost, duplication charges, time of people involved,
and so on. (You will not be required to justify it to the
Copyright Holder, but only to the computing community at large
as a market that must bear the fee.)
"Freely Available" means that no fee is charged for the item
itself, though there may be fees involved in handling the item.
It also means that recipients of the item may redistribute it
under the same conditions they received it.
1. You may make and give away verbatim copies of the source form of the
Standard Version of this Package without restriction, provided that you
duplicate all of the original copyright notices and associated disclaimers.
2. You may apply bug fixes, portability fixes and other modifications
derived from the Public Domain or from the Copyright Holder. A Package
modified in such a way shall still be considered the Standard Version.
3. You may otherwise modify your copy of this Package in any way, provided
that you insert a prominent notice in each changed file stating how and
when you changed that file, and provided that you do at least ONE of the
following:
a) place your modifications in the Public Domain or otherwise make them
Freely Available, such as by posting said modifications to Usenet or
an equivalent medium, or placing the modifications on a major archive
site such as uunet.uu.net, or by allowing the Copyright Holder to include
your modifications in the Standard Version of the Package.
b) use the modified Package only within your corporation or organization.
c) rename any non-standard executables so the names do not conflict
with standard executables, which must also be provided, and provide
a separate manual page for each non-standard executable that clearly
documents how it differs from the Standard Version.
d) make other distribution arrangements with the Copyright Holder.
4. You may distribute the programs of this Package in object code or
executable form, provided that you do at least ONE of the following:
a) distribute a Standard Version of the executables and library files,
together with instructions (in the manual page or equivalent) on where
to get the Standard Version.
b) accompany the distribution with the machine-readable source of
the Package with your modifications.
c) give non-standard executables non-standard names, and clearly
document the differences in manual pages (or equivalent), together
with instructions on where to get the Standard Version.
d) make other distribution arrangements with the Copyright Holder.
5. You may charge a reasonable copying fee for any distribution of this
Package. You may charge any fee you choose for support of this
Package. You may not charge a fee for this Package itself. However,
you may distribute this Package in aggregate with other (possibly
commercial) programs as part of a larger (possibly commercial) software
distribution provided that you do not advertise this Package as a
product of your own. You may embed this Package's interpreter within
an executable of yours (by linking); this shall be construed as a mere
form of aggregation, provided that the complete Standard Version of the
interpreter is so embedded.
6. The scripts and library files supplied as input to or produced as
output from the programs of this Package do not automatically fall
under the copyright of this Package, but belong to whoever generated
them, and may be sold commercially, and may be aggregated with this
Package. If such scripts or library files are aggregated with this
Package via the so-called "undump" or "unexec" methods of producing a
binary executable image, then distribution of such an image shall
neither be construed as a distribution of this Package nor shall it
fall under the restrictions of Paragraphs 3 and 4, provided that you do
not represent such an executable image as a Standard Version of this
Package.
7. C subroutines (or comparably compiled subroutines in other
languages) supplied by you and linked into this Package in order to
emulate subroutines and variables of the language defined by this
Package shall not be considered part of this Package, but are the
equivalent of input as in Paragraph 6, provided these subroutines do
not change the language in any way that would cause it to fail the
regression tests for the language.
8. Aggregation of this Package with a commercial distribution is always
permitted provided that the use of this Package is embedded; that is,
when no overt attempt is made to make this Package's interfaces visible
to the end user of the commercial distribution. Such use shall not be
construed as a distribution of this Package.
9. The name of the Copyright Holder may not be used to endorse or promote
products derived from this software without specific prior written permission.
10. THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
The End

View File

@ -0,0 +1,9 @@
REPORING BUGS
See the section on "REPORTING BUGS" in the module's documentation if you are
having problems.
YOU MUST FOLLOW THE INSTRUCTIONS IN THE DOCUMENTATION AND PROVIDE ALL OF THE NECESSARY
INFORMATION if you expect a response from your bug report. You should also look at
the data you gather before you send it, since doing so will often solve your problem.

View File

@ -0,0 +1,725 @@
package Mail::IMAPClient::BodyStructure;
#$Id: BodyStructure.pm,v 1.3 2003/06/12 21:41:37 dkernen Exp $
#use Parse::RecDescent;
use Mail::IMAPClient;
use Mail::IMAPClient::BodyStructure::Parse;
use vars qw/$parser/;
use Exporter;
push @ISA, "Exporter";
push @EXPORT_OK , '$parser';
$Mail::IMAPClient::BodyStructure::VERSION = '0.0.2';
# Do it once more to show we mean it!
$Mail::IMAPClient::BodyStructure::VERSION = '0.0.2';
$parser = Mail::IMAPClient::BodyStructure::Parse->new()
or die "Cannot parse rules: $@\n" .
"Try remaking Mail::IMAPClient::BodyStructure::Parse.\n"
and return undef;
sub new {
my $class = shift;
my $bodystructure = shift;
my $self = $parser->start($bodystructure) or return undef;
$self->{_prefix} = "";
if ( exists $self->{bodystructure} ) {
$self->{_id} = 'HEAD' ;
} else {
$self->{_id} = 1;
}
$self->{_top} = 1;
return bless($self ,ref($class)||$class);
}
sub _get_thingy {
my $thingy = shift;
my $object = shift||(ref($thingy)?$thingy:undef);
unless ( defined($object) and ref($object) ) {
$@ = "No argument passed to $thingy method." ;
$^W and print STDERR "$@\n" ;
return undef;
}
unless ( "$object" =~ /HASH/
and exists($object->{$thingy})
) {
$@ = ref($object) .
" $object does not have " .
( $thingy =~ /^[aeiou]/i ? "an " : "a " ) .
"${thingy}. " .
( ref($object) =~ /HASH/ ? "It has " . join(", ",keys(%$object)) : "") ;
$^W and print STDERR "$@\n" ;
return undef;
}
return Unwrapped($object->{$thingy});
}
BEGIN {
foreach my $datum (qw/ bodytype bodysubtype bodyparms bodydisp bodyid
bodydesc bodyenc bodysize bodylang
envelopestruct textlines
/
) {
no strict 'refs';
*$datum = sub { _get_thingy($datum, @_); };
}
}
sub parts {
my $self = shift;
if ( exists $self->{PartsList} ) {
return wantarray ? @{$self->{PartsList}} : $self->{PartsList} ;
}
my @parts = ();
$self->{PartsList} = \@parts;
unless ( exists($self->{bodystructure}) ) {
$self->{PartsIndex}{1} = $self ;
@parts = ("HEAD",1);
return wantarray ? @parts : \@parts;
}
#@parts = ( 1 );
#} else {
foreach my $p ($self->bodystructure()) {
push @parts, $p->id();
$self->{PartsIndex}{$p->id()} = $p ;
if ( uc($p->bodytype()||"") eq "MESSAGE" ) {
#print "Part $parts[-1] is a ",$p->bodytype,"\n";
push @parts,$parts[-1] . ".HEAD";
#} else {
# print "Part $parts[-1] is a ",$p->bodytype,"\n";
}
}
#}
return wantarray ? @parts : \@parts;
}
sub oldbodystructure {
my $self = shift;
if ( exists $self->{_bodyparts} ) {
return wantarray ? @{$self->{_bodyparts}} : $self->{_bodyparts} ;
}
my @bodyparts = ( $self );
$self->{_id} ||= "HEAD"; # aka "0"
my $count = 0;
#print STDERR "Analyzing a ",$self->bodytype, " part which I think is part number ",
# $self->{_id},"\n";
my $dump = Data::Dumper->new( [ $self ] , [ 'bodystructure' ] );
$dump->Indent(1);
foreach my $struct (@{$self->{bodystructure}}) {
$struct->{_prefix} ||= $self->{_prefix} . +$count . "." unless $struct->{_top};
$struct->{_id} ||= $self->{_prefix} . $count unless $struct->{_top};
#if (
# uc($struct->bodytype) eq 'MULTIPART' or
# uc($struct->bodytype) eq 'MESSAGE'
#) {
#} else {
#}
push @bodyparts, $struct,
ref($struct->{bodystructure}) ? $struct->bodystructure : () ;
}
$self->{_bodyparts} = \@bodyparts ;
return wantarray ? @bodyparts : $self->bodyparts ;
}
sub bodystructure {
my $self = shift;
my @parts = ();
my $partno = 0;
my $prefix = $self->{_prefix} || "";
#print STDERR "Analyzing a ",($self->bodytype||"unknown ") ,
# " part which I think is part number ",
# $self->{_id},"\n";
my $bs = $self;
$prefix = "$prefix." if ( $prefix and $prefix !~ /\.$/);
if ( $self->{_top} ) {
$self->{_id} ||= "HEAD";
$self->{_prefix} ||= "HEAD";
$partno = 0;
for (my $x = 0; $x < scalar(@{$self->{bodystructure}}) ; $x++) {
$self->{bodystructure}[$x]{_id} = ++$partno ;
$self->{bodystructure}[$x]{_prefix} = $partno ;
push @parts, $self->{bodystructure}[$x] ,
$self->{bodystructure}[$x]->bodystructure;
}
} else {
$partno = 0;
foreach my $p ( @{$self->{bodystructure}} ) {
$partno++;
if (
! exists $p->{_prefix}
) {
$p->{_prefix} = "$prefix$partno";
}
$p->{_prefix} = "$prefix$partno";
$p->{_id} ||= "$prefix$partno";
#my $bt = $p->bodytype;
#if ($bt eq 'MESSAGE') {
#$p->{_id} = $prefix .
#$partno = 0;
#}
push @parts, $p, $p->{bodystructure} ? $p->bodystructure : ();
}
}
return wantarray ? @parts : \@parts;
}
sub id {
my $self = shift;
return $self->{_id} if exists $self->{_id};
return "HEAD" if $self->{_top};
#if ($self->bodytype eq 'MESSAGE') {
# return
#}
if ($self->{bodytype} eq 'MULTIPART') {
my $p = $self->{_id}||$self->{_prefix} ;
$p =~ s/\.$//;
return $p;
} else {
return $self->{_id} ||= 1;
}
}
sub Unwrapped {
my $unescape = Mail::IMAPClient::Unescape(@_);
$unescape =~ s/^"(.*)"$/$1/ if defined($unescape);
return $unescape;
}
package Mail::IMAPClient::BodyStructure::Part;
@ISA = qw/Mail::IMAPClient::BodyStructure/;
package Mail::IMAPClient::BodyStructure::Envelope;
@ISA = qw/Mail::IMAPClient::BodyStructure/;
sub new {
my $class = shift;
my $envelope = shift;
my $self = $Mail::IMAPClient::BodyStructure::parser->envelope($envelope);
return $self;
}
sub _do_accessor {
my $datum = shift;
if (scalar(@_) > 1) {
return $_[0]->{$datum} = $_[1] ;
} else {
return $_[0]->{$datum};
}
}
# the following for loop sets up accessor methods for
# the object's address attributes:
sub _mk_address_method {
my $datum = shift;
my $method1 = $datum . "_addresses" ;
no strict 'refs';
*$method1 = sub {
my $self = shift;
return undef unless ref($self->{$datum}) eq 'ARRAY';
my @list = map {
my $pn = $_->personalname ;
$pn = "" if $pn eq 'NIL' ;
( $pn ? "$pn " : "" ) .
"<" .
$_->mailboxname .
'@' .
$_->hostname .
">"
} @{$self->{$datum}} ;
if ( $senderFields{$datum} ) {
return wantarray ? @list : $list[0] ;
} else {
return wantarray ? @list : \@list ;
}
};
}
BEGIN {
for my $datum (
qw( subject inreplyto from messageid bcc date replyto to sender cc )
) {
no strict 'refs';
*$datum = sub { _do_accessor($datum, @_); };
}
my %senderFields = map { ($_ => 1) } qw/from sender replyto/ ;
for my $datum (
qw( from bcc replyto to sender cc )
) {
_mk_address_method($datum);
}
}
package Mail::IMAPClient::BodyStructure::Address;
@ISA = qw/Mail::IMAPClient::BodyStructure/;
for my $datum (
qw( personalname mailboxname hostname sourcename )
) {
no strict 'refs';
*$datum = sub { return $_[0]->{$datum}; };
}
1;
__END__
=head1 NAME
Mail::IMAPClient::BodyStructure - Perl extension to Mail::IMAPClient to facilitate
the parsing of server responses to the FETCH BODYSTRUCTURE and FETCH ENVELOPE
IMAP client commands.
=head1 SYNOPSIS
use Mail::IMAPClient::BodyStructure;
use Mail::IMAPClient;
my $imap = Mail::IMAPClient->new(Server=>$serv,User=>$usr,Password=>$pwd);
$imap->select("INBOX") or die "cannot select the inbox for $usr: $@\n";
my @recent = $imap->search("recent");
foreach my $new (@recent) {
my $struct = Mail::IMAPClient::BodyStructure->new(
$imap->fetch($new,"bodystructure")
);
print "Msg $new (Content-type: ",$struct->bodytype,"/",$struct->bodysubtype,
") contains these parts:\n\t",join("\n\t",$struct->parts),"\n\n";
}
=head1 DESCRIPTION
This extension will parse the result of an IMAP FETCH BODYSTRUCTURE command into a perl
data structure. It also provides helper methods that will help you pull information out
of the data structure.
Use of this extension requires Parse::RecDescent. If you don't have Parse::RecDescent
then you must either get it or refrain from using this module.
=head2 EXPORT
Nothing is exported by default. C<$parser> is exported upon request. C<$parser>
is the BodyStucture object's Parse::RecDescent object, which you'll probably
only need for debugging purposes.
=head1 Class Methods
The following class method is available:
=head2 new
This class method is the constructor method for instantiating new
Mail::IMAPClient::BodyStructure objects. The B<new> method accepts one argument,
a string containing a server response to a FETCH BODYSTRUCTURE directive.
Only one message's body structure should be described in this
string, although that message may contain an arbitrary number of parts.
If you know the messages sequence number or unique ID (UID) but haven't got its
body structure, and you want to get the body structure and parse it into a
B<Mail::IMAPClient::BodyStructure> object, then you might as well save yourself
some work and use B<Mail::IMAPClient>'s B<get_bodystructure> method, which
accepts a message sequence number (or UID if I<Uid> is true) and returns a
B<Mail::IMAPClient::BodyStructure> object. It's functionally equivalent to issuing the
FETCH BODYSTRUCTURE IMAP client command and then passing the results to
B<Mail::IMAPClient::BodyStructure>'s B<new> method but it does those things in one
simple method call.
=head1 Object Methods
The following object methods are available:
=head2 bodytype
The B<bodytype> object method requires no arguments.
It returns the bodytype for the message whose structure is described by the calling
B<Mail::IMAPClient::Bodystructure> object.
=cut
=head2 bodysubtype
The B<bodysubtype> object method requires no arguments.
It returns the bodysubtype for the message whose structure is described by the calling
B<Mail::IMAPClient::Bodystructure> object.
=cut
=head2 bodyparms
The B<bodyparms> object method requires no arguments.
It returns the bodyparms for the message whose structure is described by the calling
B<Mail::IMAPClient::Bodystructure> object.
=cut
=head2 bodydisp
The B<bodydisp> object method requires no arguments.
It returns the bodydisp for the message whose structure is described by the calling
B<Mail::IMAPClient::Bodystructure> object.
=cut
=head2 bodyid
The B<bodyid> object method requires no arguments.
It returns the bodyid for the message whose structure is described by the calling
B<Mail::IMAPClient::Bodystructure> object.
=cut
=head2 bodydesc
The B<bodydesc> object method requires no arguments.
It returns the bodydesc for the message whose structure is described by the calling
B<Mail::IMAPClient::Bodystructure> object.
=cut
=head2 bodyenc
The B<bodyenc> object method requires no arguments.
It returns the bodyenc for the message whose structure is described by the calling
B<Mail::IMAPClient::Bodystructure> object.
=cut
=head2 bodysize
The B<bodysize> object method requires no arguments.
It returns the bodysize for the message whose structure is described by the calling
B<Mail::IMAPClient::Bodystructure> object.
=cut
=head2 bodylang
The B<bodylang> object method requires no arguments.
It returns the bodylang for the message whose structure is described by the calling
B<Mail::IMAPClient::Bodystructure> object.
=cut
=head2 bodystructure
The B<bodystructure> object method requires no arguments.
It returns the bodystructure for the message whose structure is described by the calling
B<Mail::IMAPClient::Bodystructure> object.
=cut
=head2 envelopestruct
The B<envelopestruct> object method requires no arguments.
It returns the envelopestruct for the message whose structure is described by the
calling B<Mail::IMAPClient::Bodystructure> object. This envelope structure is blessed
into the B<Mail::IMAPClient::BodyStructure::Envelope> subclass, which is explained more
fully below.
=cut
=head2 textlines
The B<textlines> object method requires no arguments.
It returns the textlines for the message whose structure is described by the calling
B<Mail::IMAPClient::Bodystructure> object.
=cut
=head1 Envelopes and the Mail::IMAPClient::BodyStructure::Envelope Subclass
The IMAP standard specifies that output from the IMAP B<FETCH ENVELOPE> command
will be an RFC2060 envelope structure. It further specifies that output from the
B<FETCH BODYSTRUCTURE> command may also contain embedded envelope structures (if,
for example, a message's subparts contain one or more included messages). Objects
belonging to B<Mail::IMAPClient::BodyStructure::Envelope> are Perl representations
of these envelope structures, which is to say the nested parenthetical lists of
RFC2060 translated into a Perl datastructure.
Note that all of the fields relate to the specific part to which they belong. In other
words, output from a FETCH nnnn ENVELOPE command (or, in B<Mail::IMAPClient>,
C<$imap->fetch($msgid,"ENVELOPE")> or C<my $env = $imap->get_envelope($msgid)>) are for
the message, but fields from within a bodystructure relate to the message subpart and
not the parent message.
An envelope structure's B<Mail::IMAPClient::BodyStructure::Envelope> representation
is a hash of thingies that looks like this:
{
subject => "subject",
inreplyto => "reference_message_id",
from => [ addressStruct1 ],
messageid => "message_id",
bcc => [ addressStruct1, addressStruct2 ],
date => "Tue, 09 Jul 2002 14:15:53 -0400",
replyto => [ adressStruct1, addressStruct2 ],
to => [ adressStruct1, addressStruct2 ],
sender => [ adressStruct1 ],
cc => [ adressStruct1, addressStruct2 ],
}
The B<...::Envelope> object also has methods for accessing data in the structure. They
are:
=over 4
=item date
Returns the date of the message.
=item inreplyto
Returns the message id of the message to which this message is a reply.
=item subject
Returns the subject of the message.
=item messageid
Returns the message id of the message.
=back
You can also use the following methods to get addressing information. Each of these methods
returns an array of B<Mail::IMAPClient::BodyStructure::Address> objects, which are perl
data structures representing RFC2060 address structures. Some of these arrays would naturally
contain one element (such as B<from>, which normally contains a single "From:" address); others
will often contain more than one address. However, because RFC2060 defines all of these as "lists
of address structures", they are all translated into arrays of B<...::Address> objects.
See the section on B<Mail::IMAPClient::BodyStructure::Address>", below, for alternate (and
preferred) ways of accessing these data.
The methods available are:
=over 4
=item bcc
Returns an array of blind cc'ed recipients' address structures. (Don't expect much in here
unless the message was sent from the mailbox you're poking around in, by the way.)
=item cc
Returns an array of cc'ed recipients' address structures.
=item from
Returns an array of "From:" address structures--usually just one.
=item replyto
Returns an array of "Reply-to:" address structures. Once again there is usually
just one address in the list.
=item sender
Returns an array of senders' address structures--usually just one and usually the same
as B<from>.
=item to
Returns an array of recipients' address structures.
=back
Each of the methods that returns a list of address structures (i.e. a list of
B<Mail::IMAPClient::BodyStructure::Address> arrays) also has an analagous method
that will return a list of E-Mail addresses instead. The addresses are in the
format C<personalname E<lt>mailboxname@hostnameE<gt>> (see the section on
B<Mail::IMAPClient::BodyStructure::Address>, below) However, if the personal name
is 'NIL' then it is omitted from the address.
These methods are:
=over 4
=item bcc_addresses
Returns a list (or an array reference if called in scalar context) of blind cc'ed
recipients' email addresses. (Don't expect much in here unless the message was sent
from the mailbox you're poking around in, by the way.)
=item cc_addresses
Returns a list of cc'ed recipients' email addresses. If called in a scalar
context it returns a reference to an array of email addresses.
=item from_addresses
Returns a list of "From:" email addresses. If called in a scalar context
it returns the first email address in the list. (It's usually a list of just
one anyway.)
=item replyto_addresses
Returns a list of "Reply-to:" email addresses. If called in a scalar context
it returns the first email address in the list.
=item sender_addresses
Returns a list of senders' email addresses. If called in a scalar context
it returns the first email address in the list.
=item to_addresses
Returns a list of recipients' email addresses. If called in a scalar context
it returns a reference to an array of email addresses.
=back
Note that context affects the behavior of all of the above methods.
Those fields that will commonly contain multiple entries (i.e. they are
recipients) will return an array reference when called in scalar context.
You can use this behavior to optimize performance.
Those fields that will commonly contain just one address (the sender's) will
return the first (and usually only) address. You can use this behavior to
optimize your development time.
=head1 Addresses and the Mail::IMAPClient::BodyStructure::Address
Several components of an envelope structure are address structures. They are each
parsed into their own object, B<Mail::IMAPClient::BodyStructure::Address>, which
looks like this:
{
mailboxname => 'somebody.special',
hostname => 'somplace.weird.com',
personalname => 'Somebody Special
sourceroute => 'NIL'
}
RFC2060 specifies that each address component of a bodystructure is a list of
address structures, so B<Mail::IMAPClient::BodyStructure> parses each of these into
an array of B<Mail::IMAPClient::BodyStructure::Address> objects.
Each of these objects has the following methods available to it:
=over 4
=item mailboxname
Returns the "mailboxname" portion of the address, which is the part to the left
of the '@' sign.
=item hostname
Returns the "hostname" portion of the address, which is the part to the right of the
'@' sign.
=item personalname
Returns the "personalname" portion of the address, which is the part of
the address that's treated like a comment.
=item sourceroute
Returns the "sourceroute" portion of the address, which is typically "NIL".
=back
Taken together, the parts of an address structure form an address that will
look something like this:
C<personalname E<lt>mailboxname@hostnameE<gt>>
Note that because the B<Mail::IMAPClient::BodyStructure::Address> objects come in
arrays, it's generally easier to use the methods available to
B<Mail::IMAPClient::BodyStructure::Envelope> to obtain all of the addresses in a
particular array in one operation. These methods are provided, however, in case
you'd rather do things the hard way. (And also because the aforementioned methods
from B<Mail::IMAPClient::BodyStructure::Envelope> need them anyway.)
=cut
=head1 AUTHOR
David J. Kernen
=head1 SEE ALSO
perl(1), Mail::IMAPClient, and RFC2060. See also Parse::RecDescent if you want
to understand the internals of this module.
=cut
# History:
# $Log: BodyStructure.pm,v $
# Revision 1.3 2003/06/12 21:41:37 dkernen
# Cleaning up cvs repository
#
# Revision 1.1 2003/06/12 21:37:03 dkernen
#
# Preparing 2.2.8
# Added Files: COPYRIGHT
# Modified Files: Parse.grammar
# Added Files: Makefile.old
# Makefile.PL Todo sample.perldb
# BodyStructure.pm
#
# Revision 1.2 2002/09/26 17:56:14 dkernen
#
# Modified Files:
# BUG_REPORTS Changes IMAPClient.pm INSTALL_perl5.80 MANIFEST
# Makefile.PL for version 2.2.3. See the Changes file for details.
# Modified Files: BodyStructure.pm -- cosmetic changes to pod doc
#
# Revision 1.1 2002/08/30 20:58:51 dkernen
#
# In Mail::IMAPClient/IMAPClient, added files: BUG_REPORTS getGrammer runtest sample.perldb
# In Mail::IMAPClient/IMAPClient/BodyStructure, added files: BodyStructure.pm Makefile.PL debug.ksh runtest
#

View File

@ -0,0 +1,21 @@
COPYRIGHT
Copyright 1999, 2000, 2001, 2002 , 2003 The Kernen Group, Inc.
All rights reserved.
This program is free software; you can redistribute it and/or modify it
under the terms of either:
a) the "Artistic License" which comes with this Kit, or
b) the GNU General Public License as published by the Free Software
Foundation; either version 1, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See either the GNU
General Public License or the Artistic License for more details. All your
base are belong to us.

View File

@ -0,0 +1,12 @@
use ExtUtils::MakeMaker;
# See lib/ExtUtils/MakeMaker.pm for details of how to influence
# the contents of the Makefile that is written.
WriteMakefile(
'DIR' => [ 'Parse' ] ,
'NAME' => 'Mail::IMAPClient::BodyStructure',
'VERSION_FROM' => '../IMAPClient.pm', # finds $VERSION
'PREREQ_PM' => {
"Parse::RecDescent" => '1.94',
"Exporter" => 0,
},
);

View File

@ -0,0 +1,46 @@
use ExtUtils::MakeMaker;
use Parse::RecDescent;
unlink "./Parse.pm" if -f "./Parse.pm";
sub MY::top_targets {
package MY;
my $inherit = shift->SUPER::top_targets(@_);
my @inherit = split("\n",$inherit);
for (@inherit) {
if ( /^\s*all\s*:{1,2}/ ) {
s/(all\s*:{1,2}\s*)/$1Parse\.pm /;
}
}
return join("\n",@inherit);
}
sub MY::clean {
package MY;
my $inherit = shift->SUPER::clean(@_);
return join("\n",$inherit," rm Parse.pm") ;
}
sub MY::postamble {
my $string =
'@$(PERL) "-MParse::RecDescent" "-" ' .
'"Parse.grammar" '.
'"Mail::IMAPClient::BodyStructure::Parse"' ;
return "Parse.pm: Parse.grammar\n\t$string\n\n";
}
# See lib/ExtUtils/MakeMaker.pm for details of how to influence
# the contents of the Makefile that is written.
#print "",MY->top_target;
WriteMakefile(
'NAME' => 'Mail::IMAPClient::Parse',
'VERSION_FROM' => '../../IMAPClient.pm',
'PREREQ_PM' => {"Parse::RecDescent" => 0 },
'PM' => {
'Parse.pm' =>
'$(INST_LIBDIR)/BodyStructure/Parse.pm'
},
);

View File

@ -0,0 +1,288 @@
# Directives
# ( none)
# Start-up Actions
{
my $subpartCount = 0;
my $partCount = 0;
}
#
# Atoms
TEXT: /^"TEXT"|^TEXT/i { $return = "TEXT" }
PLAIN: /^"PLAIN"|^PLAIN/i { $return = "PLAIN" }
HTML: /"HTML"|HTML/i { $return = "HTML" }
MESSAGE: /^"MESSAGE"|^MESSAGE/i { $return = "MESSAGE" }
RFC822: /^"RFC822"|^RFC822/i { $return = "RFC822" }
NIL: /^NIL/i { $return = "NIL" }
NUMBER: /^(\d+)/ { $return = $item[1]; $return||defined($return);}
# Strings:
SINGLE_QUOTED_STRING: "'" /(?:\\'|[^'])*/ "'" {
$return = $item{__PATTERN1__} ;
$return||defined($return);
}
DOUBLE_QUOTED_STRING: '"' /(?:\\"|[^"])*/ '"' {
$return = $item{__PATTERN1__} ;
$return||defined($return);
}
QUOTED_STRING: DOUBLE_QUOTED_STRING | SINGLE_QUOTED_STRING {
$return = $item{DOUBLE_QUOTED_STRING}||$item{SINGLE_QUOTED_STRING} ;
$return||defined($return);
}
BARESTRING: ...!/^[)('"]/ /^(?!\(|\))(?:\\ |\S)+/ {
$return = $item{__PATTERN1__} ; $return||defined($return);
}
STRING: QUOTED_STRING | BARESTRING {
$return = $item{QUOTED_STRING}||$item{BARESTRING} ;
$return||defined($return);
}
OLDSTRING: /^"((?:[^"\\]|\\.)*)"/ | /^([^ \(\)]+)/
{ $item{__PATTERN1__} =~ s/^"(.*)"$/$1/;
$return = $item{__PATTERN1__} || $item{__PATTERN2__} ;
$return||defined($return);
}
#BARESTRING: /^[^(]+\s+(?=\()/
# { $return = $item[1] ; $return||defined($return);}
textlines: NIL | NUMBER { $return = $item[1] || $item[2]; $return||defined($return); }
rfc822message: MESSAGE RFC822 { $return = "MESSAGE RFC822" }
key: STRING { $return = $item{STRING} ; $return||defined($return);}
value: NIL | '(' <commit> kvpair(s) ')'| NUMBER | STRING
{ $return = $item{NIL} ||
$item{NUMBER} ||
$item{STRING} ||
{ map { (%$_) } @{$item{'kvpair(s)'}} } ;
$return||defined($return);
}
kvpair: ...!")" key value
{ $return = { $item{key} => $item{value} }; $return||defined($return);}
bodytype: STRING
{ $return = $item{STRING} ; $return||defined($return);}
bodysubtype: PLAIN | HTML | NIL | STRING
{ $return = $item{PLAIN}||$item{HTML}||$item{NIL}||$item{STRING} ;
$return||defined($return);
}
bodyparms: NIL | '(' kvpair(s) ')'
{
$return = $item{NIL} ||
{ map { (%$_) } @{$item{'kvpair(s)'}} };
$return || defined($return);
}
bodydisp: NIL | '(' kvpair(s) ')'
{
$return = $item{NIL} ||
{ map { (%$_) } @{$item{'kvpair(s)'}} };
$return || defined($return);
}
bodyid: ...!/[()]/ NIL | STRING
{ $return = $item{NIL} || $item{STRING} ; $return||defined($return);}
bodydesc: ...!/[()]/ NIL | STRING
{ $return = $item{NIL} || $item{STRING} ; $return||defined($return);}
bodyenc: NIL | STRING | '(' kvpair(s) ')'
{
$return = $item{NIL} ||
$item{STRING} ||
{ map { (%$_) } @{$item{'kvpair(s)'}} };
$return||defined($return);
}
bodysize: ...!/[()]/ NIL | NUMBER
{ $return = $item{NIL} || $item{NUMBER} ;$return||defined($return);}
bodyMD5: NIL | STRING
{ $return = $item{NIL} || $item{STRING} ;$return||defined($return);}
bodylang: NIL | STRING | "(" STRING(s) ")"
{ $return = $item{NIL} || $item{'STRING(s)'} ;$return||defined($return);}
personalname: NIL | STRING
{ $return = $item{NIL} || $item{STRING} ;$return||defined($return);}
sourceroute: NIL | STRING
{ $return = $item{NIL} || $item{STRING} ;$return||defined($return);}
mailboxname: NIL | STRING
{ $return = $item{NIL} || $item{STRING} ;$return||defined($return);}
hostname: NIL | STRING
{ $return = $item{NIL} || $item{STRING} ;$return||defined($return);}
addressstruct: "(" personalname sourceroute mailboxname hostname ")"
{ $return = {
personalname => $item{personalname} ,
sourceroute => $item{sourceroute} ,
mailboxname => $item{mailboxname} ,
hostname => $item{hostname} ,
} ;
bless($return, "Mail::IMAPClient::BodyStructure::Address");
}
subject: NIL | STRING
{
$return = $item{NIL} || $item{STRING} ;
$return||defined($return);
}
inreplyto: NIL | STRING
{ $return = $item{NIL} || $item{STRING} ;$return||defined($return);}
messageid: NIL | STRING
{ $return = $item{NIL} || $item{STRING} ;$return||defined($return);}
date: NIL | STRING
{ $return = $item{NIL} || $item{STRING} ;$return||defined($return);}
cc: NIL | "(" addressstruct(s) ")"
{ $return = $item{NIL} || $item{'addressstruct(s)'} }
bcc: NIL | "(" addressstruct(s) ")"
{ $return = $item{NIL} || $item{'addressstruct(s)'} }
from: NIL | "(" addressstruct(s) ")"
{ $return = $item{NIL} || $item{'addressstruct(s)'} }
replyto: NIL | "(" addressstruct(s) ")"
{ $return = $item{NIL} || $item{'addressstruct(s)'} }
sender: NIL | "(" addressstruct(s) ")"
{ $return = $item{NIL} || $item{'addressstruct(s)'} }
to: NIL | "(" addressstruct(s) ")"
{ $return = $item{NIL} || $item{'addressstruct(s)'} }
envelopestruct: "(" date subject from sender replyto to cc bcc inreplyto messageid ")"
{ $return = {};
foreach my $what (qw/date subject from sender replyto to cc bcc inreplyto messageid/) {
$return->{$what} = $item{$what};
}
bless $return, "Mail::IMAPClient::BodyStructure::Envelope";
$return||defined($return);
}
basicfields: bodysubtype bodyparms bodyid(?)
bodydesc(?) bodyenc(?)
bodysize(?) {
$return = {
bodysubtype => $item{bodysubtype} ,
bodyparms => $item{bodyparms} ,
bodyid => (ref $item{'bodyid(?)'} ?
$item{'bodyid(?)'}[0] :
$item{'bodyid(?)'} ),
'bodydesc' => (ref $item{'bodydesc(?)'} ?
$item{'bodydesc(?)'}[0] :
$item{'bodydesc(?)'} ),
'bodyenc' => (ref $item{'bodyenc(?)'} ?
$item{'bodyenc(?)'}[0] :
$item{'bodyenc(?)'} ),
'bodysize' => (ref $item{'bodysize(?)'} ?
$item{'bodysize(?)'}[0] :
$item{'bodysize(?)'} ),
};
$return;
}
textmessage: TEXT <commit> basicfields textlines(?) bodyMD5(?) bodydisp(?) bodylang(?)
{
$return = $item{basicfields}||{};
$return->{bodytype} = 'TEXT';
foreach my $what (qw/textlines(?) bodyMD5(?) bodydisp(?) bodylang(?)/) {
my $k = $what; $k =~ s/\(\?\)$//;
ref($item{$what}) and $return->{$k} = $item{$what}[0];
}
$return||defined($return);
}
othertypemessage: bodytype basicfields bodyparms(?) bodydisp(?) bodylang(?)
{ $return = {};
foreach my $what (qw/bodytype bodyparms(?) bodydisp(?) bodylang(?)/) {
my $k = $what; $k =~ s/\(\?\)$//;
$return->{$k} = ref($item{$what})? $item{$what}[0] : $item{$what} ;
}
while ( my($k,$v) = each %{$item{basicfields}} ) { $return->{$k} = $v }
$return||defined($return);
}
messagerfc822message:
rfc822message <commit> bodyparms bodyid bodydesc bodyenc bodysize
envelopestruct bodystructure textlines
bodyMD5(?) bodydisp(?) bodylang(?)
{
$return = {};
foreach my $what (qw/ bodyparms bodyid bodydesc bodyenc bodysize
envelopestruct bodystructure textlines
bodyMD5(?) bodydisp(?) bodylang(?)
/
) {
my $k = $what; $k =~ s/\(\?\)$//;
$return->{$k} = ref $item{$what} =~ 'ARRAY'?
$item{$what}[0] : $item{$what};
}
while ( my($k,$v) = each %{$item{bodystructure}[0]} ) { $return->{$k} = $v }
while ( my($k,$v) = each %{$item{basicfields}} ) { $return->{$k} = $v }
$return->{bodytype} = "MESSAGE" ;
$return->{bodysubtype}= "RFC822" ;
$return||defined($return);
}
subpart: "(" part ")"
{
$return = $item{part} ;
$return||defined($return);
} <defer: ++$subpartCount;>
part: subpart(s) <commit> basicfields
bodyparms(?) bodydisp(?) bodylang(?)
<defer: $subpartCount = 0>
{
$return = bless($item{basicfields},
"Mail::IMAPClient::BodyStructure");
$return->{bodytype} = "MULTIPART";
$return->{bodystructure} = $item{'subpart(s)'};
foreach my $b (qw/bodyparms(?) bodydisp(?) bodylang(?)/) {
my $k = $b; $k =~ s/\(\?\)$//;
$return->{$k} = ref($item{$b}) ? $item{$b}[0] : $item{$b};
}
$return||defined($return) ;
}
| textmessage
{
$return = bless $item{textmessage}, "Mail::IMAPClient::BodyStructure";
$return||defined($return);
}
| messagerfc822message
{
$return = bless $item{messagerfc822message}, "Mail::IMAPClient::BodyStructure";
$return||defined($return);
}
| othertypemessage
{
$return = bless $item{othertypemessage}, "Mail::IMAPClient::BodyStructure";
$return||defined($return);
}
bodystructure: "(" part(s) ")"
{
$return = $item{'part(s)'} ;
$return||defined($return);
}
start: /.*\(.*BODYSTRUCTURE \(/i part(1) /\).*\)\r?\n?/
{
#print STDERR "item = ",Data::Dumper->Dump([\%item],['$item']);
$return = $item{'part(1)'}[0];
$return||defined($return);
}
envelope: /.*\(.*ENVELOPE/ envelopestruct /.*\)/ {
$return = $item{envelopestruct} ;
$return||defined($return) ;
}

View File

@ -0,0 +1,281 @@
# Directives
# ( none)
# Start-up Actions
{
my $subpartCount = 0;
my $partCount = 0;
}
#
# Atoms
TEXT: /^"TEXT"|^TEXT/i { $return = "TEXT" }
PLAIN: /^"PLAIN"|^PLAIN/i { $return = "PLAIN" }
HTML: /"HTML"|HTML/i { $return = "HTML" }
MESSAGE: /^"MESSAGE"|^MESSAGE/i { $return = "MESSAGE" }
RFC822: /^"RFC822"|^RFC822/i { $return = "RFC822" }
NIL: /^NIL/i { $return = "NIL" }
NUMBER: /^(\d+)/ { $return = $item[1]; $return||defined($return);}
# Strings:
SINGLE_QUOTED_STRING: "'" /(?:\\'|[^'])*/ "'" {
$return = $item{__PATTERN1__} ;
$return||defined($return);
}
DOUBLE_QUOTED_STRING: '"' /(?:\\"|[^"])*/ '"' {
$return = $item{__PATTERN1__} ;
$return||defined($return);
}
QUOTED_STRING: DOUBLE_QUOTED_STRING | SINGLE_QUOTED_STRING {
$return = $item{DOUBLE_QUOTED_STRING}||$item{SINGLE_QUOTED_STRING} ;
$return||defined($return);
}
BARESTRING: ...!/^[)('"]/ /^(?!\(|\))(?:\\ |\S)+/ {
$return = $item{__PATTERN1__} ; $return||defined($return);
}
STRING: QUOTED_STRING | BARESTRING {
$return = $item{QUOTED_STRING}||$item{BARESTRING} ;
$return||defined($return);
}
OLDSTRING: /^"((?:[^"\\]|\\.)*)"/ | /^([^ \(\)]+)/
{ $item{__PATTERN1__} =~ s/^"(.*)"$/$1/;
$return = $item{__PATTERN1__} || $item{__PATTERN2__} ;
$return||defined($return);
}
#BARESTRING: /^[^(]+\s+(?=\()/
# { $return = $item[1] ; $return||defined($return);}
textlines: NIL | NUMBER { $return = $item[1] || $item[2]; $return||defined($return); }
rfc822message: MESSAGE RFC822 { $return = "MESSAGE RFC822" }
key: STRING { $return = $item{STRING} ; $return||defined($return);}
value: NIL | '(' <commit> kvpair(s) ')'| NUMBER | STRING
{ $return = $item{NIL} ||
$item{NUMBER} ||
$item{STRING} ||
{ map { (%$_) } @{$item{kvpair}} } ;
$return||defined($return);
}
kvpair: ...!")" key value
{ $return = { $item{key} => $item{value} }; $return||defined($return);}
bodytype: STRING
{ $return = $item{STRING} ; $return||defined($return);}
bodysubtype: PLAIN | HTML | NIL | STRING
{ $return = $item{PLAIN}||$item{HTML}||$item{NIL}||$item{STRING} ;
$return||defined($return);
}
bodyparms: NIL | '(' kvpair(s) ')'
{
$return = $item{NIL} ||
{ map { (%$_) } @{$item{kvpair}} };
$return || defined($return);
}
bodydisp: NIL | '(' kvpair(s) ')'
{
$return = $item{NIL} ||
{ map { (%$_) } @{$item{kvpair}} };
$return || defined($return);
}
bodyid: ...!/[()]/ NIL | STRING
{ $return = $item{NIL} || $item{STRING} ; $return||defined($return);}
bodydesc: ...!/[()]/ NIL | STRING
{ $return = $item{NIL} || $item{STRING} ; $return||defined($return);}
bodyenc: NIL | STRING | '(' kvpair(s) ')'
{
$return = $item{NIL} ||
$item{STRING} ||
{ map { (%$_) } @{$item{kvpair}} };
$return||defined($return);
}
bodysize: ...!/[()]/ NIL | NUMBER
{ $return = $item{NIL} || $item{NUMBER} ;$return||defined($return);}
bodyMD5: NIL | STRING
{ $return = $item{NIL} || $item{STRING} ;$return||defined($return);}
bodylang: NIL | STRING | "(" STRING(s) ")"
{ $return = $item{NIL} || $item{STRING} ;$return||defined($return);}
personalname: NIL | STRING
{ $return = $item{NIL} || $item{STRING} ;$return||defined($return);}
sourceroute: NIL | STRING
{ $return = $item{NIL} || $item{STRING} ;$return||defined($return);}
mailboxname: NIL | STRING
{ $return = $item{NIL} || $item{STRING} ;$return||defined($return);}
hostname: NIL | STRING
{ $return = $item{NIL} || $item{STRING} ;$return||defined($return);}
addressstruct: "(" personalname sourceroute mailboxname hostname ")"
{ $return = {
personalname => $item{personalname} ,
sourceroute => $item{sourceroute} ,
mailboxname => $item{mailboxname} ,
hostname => $item{hostname} ,
} ;
bless($return, "Mail::IMAPClient::BodyStructure::Address");
}
subject: NIL | STRING
{
$return = $item{NIL} || $item{STRING} ;
$return||defined($return);
}
inreplyto: NIL | STRING
{ $return = $item{NIL} || $item{STRING} ;$return||defined($return);}
messageid: NIL | STRING
{ $return = $item{NIL} || $item{STRING} ;$return||defined($return);}
date: NIL | STRING
{ $return = $item{NIL} || $item{STRING} ;$return||defined($return);}
cc: NIL | "(" addressstruct(s) ")"
{ $return = $item{NIL} || $item{addressstruct} }
bcc: NIL | "(" addressstruct(s) ")"
{ $return = $item{NIL} || $item{addressstruct} }
from: NIL | "(" addressstruct(s) ")"
{ $return = $item{NIL} || $item{addressstruct} }
replyto: NIL | "(" addressstruct(s) ")"
{ $return = $item{NIL} || $item{addressstruct} }
sender: NIL | "(" addressstruct(s) ")"
{ $return = $item{NIL} || $item{addressstruct} }
to: NIL | "(" addressstruct(s) ")"
{ $return = $item{NIL} || $item{addressstruct} }
envelopestruct: "(" date subject from sender replyto to cc bcc inreplyto messageid ")"
{ $return = {};
foreach my $what (qw/date subject from sender replyto to cc bcc inreplyto messageid/) {
$return->{$what} = $item{$what};
}
bless $return, "Mail::IMAPClient::BodyStructure::Envelope";
$return||defined($return);
}
basicfields: bodysubtype bodyparms bodyid(?)
bodydesc(?) bodyenc(?)
bodysize(?) {
$return = {
bodysubtype => $item{bodysubtype} ,
bodyparms => $item{bodyparms} ,
bodyid => (ref $item{bodyid} ?
$item{bodyid}[0] :
$item{bodyid} ),
bodydesc => (ref $item{bodydesc} ?
$item{bodydesc}[0] :
$item{bodydesc} ),
bodyenc => (ref $item{bodyenc} ?
$item{bodyenc}[0] :
$item{bodyenc} ),
bodysize => (ref $item{bodysize} ?
$item{bodysize}[0] :
$item{bodysize} ),
};
$return;
}
textmessage: TEXT <commit> basicfields textlines(?) bodyMD5(?) bodydisp(?) bodylang(?)
{
$return = $item{basicfields}||{};
$return->{bodytype} = 'TEXT';
foreach my $what (qw/textlines bodyMD5 bodydisp bodylang/) {
ref($item{$what}) and $return->{$what} = $item{$what}[0];
}
$return||defined($return);
}
othertypemessage: bodytype basicfields bodyparms(?) bodydisp(?) bodylang(?)
{ $return = {};
foreach my $what (qw/bodytype bodyparms bodydisp bodylang/) {
$return->{$what} = ref($item{$what})? $item{$what}[0] : $item{$what} ;
}
while ( my($k,$v) = each %{$item{basicfields}} ) { $return->{$k} = $v }
$return||defined($return);
}
messagerfc822message:
rfc822message <commit> bodyparms bodyid bodydesc bodyenc bodysize
envelopestruct bodystructure textlines
bodyMD5(?) bodydisp(?) bodylang(?)
{
$return = {};
foreach my $what (qw/ bodyparms bodyid bodydesc bodyenc bodysize
envelopestruct bodystructure textlines
bodyMD5 bodydisp bodylang
/
) {
$return->{$what} = ref $item{$what} =~ 'ARRAY'?
$item{$what}[0] : $item{$what};
}
while ( my($k,$v) = each %{$item{bodystructure}[0]} ) { $return->{$k} = $v }
while ( my($k,$v) = each %{$item{basicfields}} ) { $return->{$k} = $v }
$return->{bodytype} = "MESSAGE" ;
$return->{bodysubtype}= "RFC822" ;
$return||defined($return);
}
subpart: "(" part ")"
{
$return = $item{part} ;
$return||defined($return);
} <defer: ++$subpartCount;>
part: subpart(s) <commit> basicfields
bodyparms(?) bodydisp(?) bodylang(?)
<defer: $subpartCount = 0>
{
$return = bless($item{basicfields}, "Mail::IMAPClient::BodyStructure");
$return->{bodytype} = "MULTIPART";
$return->{bodystructure} = $item{subpart};
foreach my $b (qw/bodyparms bodydisp bodylang/) {
$return->{$b} = ref($item{$b}) ? $item{$b}[0] : $item{$b};
}
$return||defined($return) ;
}
| textmessage
{
$return = bless $item{textmessage}, "Mail::IMAPClient::BodyStructure";
$return||defined($return);
}
| messagerfc822message
{
$return = bless $item{messagerfc822message}, "Mail::IMAPClient::BodyStructure";
$return||defined($return);
}
| othertypemessage
{
$return = bless $item{othertypemessage}, "Mail::IMAPClient::BodyStructure";
$return||defined($return);
}
bodystructure: "(" part(s) ")"
{
$return = $item{part} ;
$return||defined($return);
}
start: /.*\(.*BODYSTRUCTURE \(/i part(1) /\).*\)\r?\n?/
{
$return = $item{part}[0] ;
$return||defined($return);
}
envelope: /.*\(.*ENVELOPE/ envelopestruct /.*\)/ {
$return = $item{envelopestruct} ;
$return||defined($return) ;
}

View File

@ -0,0 +1,21 @@
package Mail::IMAPClient::BodyStructure::Parse;
$Mail::IMAPClient::BodyStructure::Parse::VERSION = "0.0.1";
$Mail::IMAPClient::BodyStructure::Parse::VERSION = "0.0.1";
=head1 NAME
Mail::IMAPClient::BodyStructure::Parse -- used internally by Mail::IMAPClient::BodyStructure
=head1 DESCRIPTION
This module is used internally by L<Mail::IMAPClient::BodyStructure> and is
generated using L<Parse::RecDescent>. It is not meant to be used directly by
other scripts nor is there much point in debugging it.
=head1 SYNOPSIS
This module is used internally by L<Mail::IMAPClient::BodyStructure> and is not meant to
be used or called directly from applications. So don't do that.
=cut

View File

@ -0,0 +1,39 @@
# Before `make install' is performed this script should be runnable with
# `make test'. After `make install' it should work as `perl test.pl'
# $Id: parse.t,v 1.2 2002/08/30 20:48:34 dkernen Exp $
######################### We start with some black magic to print on failure.
# Change 1..1 below to 1..last_test_to_print .
use Mail::IMAPClient::BodyStructure::Parse;
BEGIN {
print "1..1\n";
$main::loaded = 1;
$| = 1;
print "ok 1\n";
}
END {print "not ok 1\n" unless $main::loaded;}
# History:
# $Log: parse.t,v $
# Revision 1.2 2002/08/30 20:48:34 dkernen
#
# #
# Modified Files:
# Changes IMAPClient.pm MANIFEST Makefile Makefile.PL README
# Todo test.txt
# BodyStructure/Parse/Makefile
# BodyStructure/Parse/Parse.pm
# BodyStructure/Parse/Parse.pod
# BodyStructure/Parse/t/parse.t
# for version 2.2.1
# #
#
# Revision 1.1 2002/08/23 14:34:29 dkernen
#
# Modified Files: Changes IMAPClient.pm Makefile Makefile.PL test.txt for version 2.2.0
# Added Files: Makefile Makefile.PL Parse.grammar Parse.pm Parse.pod version 2.2.0
# Added Files: parse.t for version 2.2.0
#

View File

@ -0,0 +1,55 @@
# Before `make install' is performed this script should be runnable with
# `make test'. After `make install' it should work as `perl test.pl'
# $Id: bodystructure.t,v 1.1 2002/08/23 14:34:40 dkernen Exp $
######################### We start with some black magic to print on failure.
# Change 1..1 below to 1..last_test_to_print .
use Mail::IMAPClient::BodyStructure;
use warnings;
BEGIN {
print "1..8\n";
$main::loaded = 1;
$| = 1;
print "ok 1\n";
}
my $bs=<<"END_OF_BS";
(BODYSTRUCTURE ("TEXT" "PLAIN" ("CHARSET" "us-ascii") NIL NIL "7BIT" 511 20 NIL NIL NIL))^M
END_OF_BS
my $bsobj = Mail::IMAPClient::BodyStructure->new($bs) ;
if ($bsobj) { print "ok 2\n" } else {
print "not ok 2\n";
exit;
}
if ($bsobj->bodytype eq 'TEXT') { print "ok 3\n" }
else {print "not ok 3 (expected 'TEXT' ; got '" . $bsobj->bodytype . "')\n"}
if ($bsobj->bodysubtype eq 'PLAIN') { print "ok 4\n" }
else {print "not ok 4 (expected 'PLAIN' ; got '" . $bsobj->bodytype . "')\n"}
my $bs2 = <<'END_OF_BS2';
(BODYSTRUCTURE (("TEXT" "PLAIN" ("CHARSET" "us-ascii") NIL NIL "7BIT" 2 1 NIL NIL NIL)("MESSAGE" "RFC822" NIL NIL NIL "7BIT" 3930 ("Tue, 16 Jul 2002 15:29:17 -0400" "Re: [Fwd: Here is the the list of uids]" (("Michael Etcetera" NIL "michael.etcetera" "generic.com")) (("Michael Etcetera" NIL "michael.etcetera" "generic.com")) (("Michael Etcetera" NIL "michael.etcetera" "generic.com")) (("Michael Etcetera" NIL "michael.etcetera" "generic.com")) (("David J Kavid" NIL "david.kavid" "generic.com")) NIL NIL "<72f9a217.a21772f9@generic.com>") (("TEXT" "PLAIN" ("CHARSET" "us-ascii") NIL NIL "7BIT" 369 11 NIL NIL NIL)("MESSAGE" "RFC822" NIL NIL NIL "7BIT" 2599 ("Tue, 9 Jul 2002 13:42:04 -0400" "Here is the the list of uids" (("Nicholas Kringle" NIL "nicholas.kringle" "generic.com")) (("Nicholas Kringle" NIL "nicholas.kringle" "generic.com")) (("Nicholas Kringle" NIL "nicholas.kringle" "generic.com")) (("Michael Etcetera" NIL "michael.etcetera" "generic.com")) (("Richard W Continued" NIL "richard.continued" "generic.com")) NIL NIL "<015401c2276f$f09b7c10$59cab08c@one.two.generic.com>") ((("TEXT" "PLAIN" ("CHARSET" "iso-8859-1") NIL NIL "QUOTED-PRINTABLE" 256 10 NIL NIL NIL)("TEXT" "HTML" ("CHARSET" "iso-8859-1") NIL NIL "QUOTED-PRINTABLE" 791 22 NIL NIL NIL) "ALTERNATIVE" ("BOUNDARY" "----=_NextPart_001_0151_01C2274E.6969D0F0") NIL NIL) "MIXED" ("BOUNDARY" "----=_NextPart_000_0150_01C2274E.6969D0F0") NIL NIL) 75 NIL NIL NIL) "MIXED" ("BOUNDARY" "--1f34eac2082b02") NIL ("EN")) 118 NIL NIL NIL) "MIXED" ("BOUNDARY" "------------F600BD8FDDD648ABA72A09E0") NIL NIL))
END_OF_BS2
$bsobj = Mail::IMAPClient::BodyStructure->new($bs2) ;
if ($bsobj) { print "ok 5\n" } else {print "not ok 5\n"}
if ($bsobj->bodytype eq 'MULTIPART') { print "ok 6\n" }
else {print "not ok 6 (expected 'MULTIPART' ; got '" . $bsobj->bodytype . "')\n"}
if ($bsobj->bodysubtype eq 'MIXED') { print "ok 7\n" }
else {print "not ok 7 (expected 'MIXED' ; got '" . $bsobj->bodytype . "')\n"}
if (join("#",$bsobj->parts) eq "1#2#2.HEAD#2.1#2.2#2.2.HEAD#2.2.1#2.2.1.1#2.2.1.2") {
print "ok 8\n";
} else {print "not ok 8\n"}
END {print "not ok 1\n" unless $main::loaded;}
# History:
# $Log: bodystructure.t,v $
# Revision 1.1 2002/08/23 14:34:40 dkernen
#
# Modified Files: Changes IMAPClient.pm Makefile Makefile.PL test.txt for version 2.2.0
# Added Files: Makefile Makefile.PL Parse.grammar Parse.pm Parse.pod version 2.2.0
# Added Files: parse.t for version 2.2.0
# Added Files: bodystructure.t for 2.2.0
#

View File

@ -0,0 +1,21 @@
COPYRIGHT
Copyright 1999, 2000, 2001, 2002 , 2003 The Kernen Group, Inc.
All rights reserved.
This program is free software; you can redistribute it and/or modify it
under the terms of either:
a) the "Artistic License" which comes with this Kit, or
b) the GNU General Public License as published by the Free Software
Foundation; either version 1, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See either the GNU
General Public License or the Artistic License for more details. All your
base are belong to us.

View File

@ -1,366 +1,45 @@
== Revision History for Mail::IMAPClient
All changes from 2.99_01 upward are made by Mark Overmeer. The changes
before that are applied by David Kernen
version 3.05: Wed Feb 20 08:59:37 CET 2008
Fixes:
- match ENVELOPE and BODYSTRUCTURE more strict in the
grammar, to avoid confusion. [Zach Levow]
- get_envelope and get_bodystructure failed for servers which
did not return the whole answer in one piece. [Zach Levow]
- do not produce parser errors when get_envelope does not
return an envelope. [Zach Levow]
- PLAIN login response possibly solely a '+' [Zach] and [Nick]
version 3.04: Fri Jan 25 09:25:51 CET 2008
Fixes:
- read_header fix for UID on Windows Server 2003.
rt.cpan.org#32398 [Michiel Stelman]
Improvements:
- doc update on authentication, by [Thomas Jarosch]
version 3.03: Wed Jan 9 22:11:36 CET 2008
Fixes:
- LIST (f.i. used by folders()) did not return anything when the
passed argument had a trailing separator. [Gunther Heintze]
- Rfc2060_datetime() must include a zone.
rt.cpan.org#31971 [David Golden]
- folders() uses LIST, and then calls a STATUS on each of the
names found. This is superfluous, and will cause problems when
the STATUS fails... for instance because of ACL limitations
on the sub-folder.
rt.cpan.org#31962 [Thomas Jarosch]
- fixed a zillion of problems in the BodyStructure parser. The
original author did not understand parsing, nor Perl.
- part numbering wrong when nested messages contained multiparts
Improvements:
- implementation of DIGEST-MD5 authentication [Thomas Jarosch]
- removed call for status() in Massage(), which hopefully speeds-up
things without destroying anything. It removed a possible deep
recursion, which no-one reported (so should be ok to remove it)
- simplified folders() algorithm.
- merged folder commands, like subscribe into one.
- added unsubscribe()
rt.cpan.org#31268 [G Miller]
- lazy-load Digest::HMAC_MD5
version 3.02: Wed Dec 5 21:33:17 CET 2007
Fixes:
- Another attempt to get get FETCH UID right. Patch by [David Golden]
version 3.01: Wed Dec 5 09:55:43 CET 2007
Changes:
- removed version number from ::BodyStructure
Fixes:
- quote password at login.
rt.cpan.org#31035 [Andy Harriston]
- empty return of flags command should be empty list, not undef.
rt.cpan.org#31195 [David Golden]
- UID command does not work with folder management commands
rt.cpan.org#31182 [Robbert Norris]
- _read_line simplifications avoids timeouts.
rt.cpan.org#31221 [Robbert Norris]
- FETCH did not detect the UID of a message anymore.
[David Golden]
Improvements:
- proxyauth for SUN/iPlanet/NetScape IMAP servers.
patch by rt.cpan.org#31152 [Robbert Norris]
- use grep in stead of map in one occasion in MessageSet.pm
[Yves Orton]
version 3.00: Wed Nov 28 09:56:54 CET 2007
Fixes:
- "${peek}[]" should be "$peek\[]" for perl 5.6.1
rt.cpan.org#30900 [Gerald Richter]
version 2.99_07: Wed Nov 14 09:54:46 CET 2007
Fixes:
- forgot to update the translate grammar.
version 2.99_06: Mon Nov 12 23:21:58 CET 2007
Fixes:
- body structure can have any number of optional parameters.
Patch by [Gerald Richter].
- get_bodystructure did not take the output correctly [Gerald Richter]
- parser of body-structure did not handle optional body parameters
Patch by [Gerald Richter], rt.cpan.org#4479 [Geoffrey D. Bennet]
version 2.99_05: Mon Nov 12 00:17:42 CET 2007
Fixes:
- pod error in MessageSet.pm
- folders() without argument failed. [Gerald Richter]
Improvements:
- better use of format syntax in date formatting.
- Rfc2060_datetime also contains the time.
- append_file() now has options to pass flags and time of file
in one go. [Thomas Jarosch]
version 2.99_04: Sat Nov 10 20:55:18 CET 2007
Changes:
- Simplified initiation of IMAP object with own Socket with a new
option: RawSocket [Flavio Poletti]
Fixes:
- fixed read_line [Flavio Poletti]
- fixed test-run in t/basic.t [Flavio Poletti]
version 2.99_03: Thu Nov 1 12:36:44 CET 2007
Fixes:
- Remove note about optional Parse::RecDescent by Makefile.PL;
it is not optional anymore
Improvements:
- When syswrite() returns 0, that might be caused by an error
as well. Take the timeout/maxtemperrors track.
rt.cpan.org#4701 [C Meyer]
- add NTLM support for logging-in, cleanly intergrated. Requires
the user to install Authen::NTLM.
version 2.99_02: Fri Oct 26 11:47:35 CEST 2007
The whole Mail::IMAPClient was rewritten, hopefully without
breaking the interface. Nearly no line was untouched.
The following things happened:
- use warnings, use strict everywhere
- removed many lines which were commented out, over the years
- $self->_debug if $self->Debug checked debug flag twice
- $self->LogError calls where quite inconsequent wrt $@ and carp
- consequent layout, changed sporadic tabs in blanks
- consequent calling convensions
- \0x0d\0x0a is always \r\n
- zillions of minor syntactical improvements
- a few major algorithmic rewrites to simplify the code, still
many oppotunities for improvements.
- expanded "smart" accessor methods, search abbreviations,
and autoloaded methods into separate subs. In total much
shorter, and certainly better understandable!
- fixed many potential bugs.
- labeled some weird things with #????
Over 1000 lines (30%!) and 25kB smaller in size
Needs to be tested!!!! Volunteers?
Fixes:
- Exchange 2007 only works with new parameter: IgnoreSizeErrors
rt.cpan.org#28933 [Dregan], #5297 [Kevin P. Fleming]
- Passed socket did not get selected.
debian bug #401144, rt.cpan.org# [Alexander Zanger],
#8480 [Karl Gaissmaier], #8481 [Karl Gaissmaier],
#7298 [Herbert Engelmann]
http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=401144
- Seperator not correctly extracted from list command.
rt.cpan.org#9236 [Eugene Koontz], #4662 [Rasjid]
- migrate() Massage'd foldername twice
rt.cpan.org#20703 [Peter J. Holzer]
- migrate() could loop because error in regexp.
rt.cpan.org#20703 [Peter J. Holzer]
- migrate() append_string result not tested.
rt.cpan.org#8577 [guest]
- Failing fetch() returned undef, not empty list.
rt.cpan.org#18361 [Robert Terzi]
- Fix "use of uninitialised" warning when expunge is called
rt.cpan.org#15002 [Matt Jackson]
- Fix count subfolders in is_parent, regexp did not take care
of regex special characters in foldername and seperator.
rt.cpan.org#12883 [Mike Porter]
- In fetch_hash(), the capturing of UID was too complicated
(and simply wrong)
rt.cpan.org#9341 [Gilles Lamiral]
- overload in MessageSet treated the 3rd arg (reverse) as
message-set.
- do not send the password on a different line as the username
in LOGIN. Suggested by many people, amongst them
rt.cpan.org#4449 [Lars Uffmann]
- select() with $timeout==0 (no timeout) returns immediately.
Should be 'undef' as 4th select parameter.
rt.cpan.org#5962 [Colin Robertson] and [Jules Agee]
- examine() remembers Massage()d folder name, not the unescaped
version. rt.cpan.org#7859 [guest]
Improvements:
- PREAUTH support by rt.cpan.org#17693 [Danny Siu]
- Option "SupportedFlags", useful when the source supports
different flags than the peer in migrate().
Requested by rt.cpan.org#12961 [Don Christensen]
- Fast_io did not clear $@ on unimportant errors.
rt.cpan.org#9835 [guest] and #11220 [Brian Helterline]
- Digest::HMAC_MD5 and MIME::Base64 are now prerequisits.
rt.cpan.org#6391 [David Greaves]
- PLAIN (SASL) authentication added, option Proxy
rt.cpan.org#5706 [Carl Provencher]
- removed Bodystructure.grammar and IMAPClient.cleanup from dist.
- reworked Bodystructure and MessageSet as well.
- EnableServerResponseInLiteral now autodetect (hence ignored)
version 2.99_01:
After 4 years of silence, Mark Overmeer took maintenance. David
Kernen could not be reached. Please let him contact the new
maintainer.
A considerable clean-up took place, fixing bug and adapting the
distribution to current best practices.
- use "prompt" in Makefile.PL, to please CPAN-testers
- removed old Parse::RecDescent grammars
- include Artistic and Copying (GPL) into COPYRIGHT file
- remove INSTALL_perl5.80
- removed all the seperate Makefile.PLs and test directories
- removed the hard-copy of all involved RFCs: there are better
sources for those.
- converted tests to use "Test::More"
- Authmechanism eq 'LOGIN' understood.
- test for CRAM-MD5 removed, because conflicts with test params
from Makefile.PL
- test for fast-io removed, it is Perl core functionality
- require IO::Socket::INET 1.26 to avoid Port number work-around.
- Parse::RecDescent is required, and the grammars are pre-parsed
in the distribution. This makes the whole installation process
a lot easier.
- Update Todo, and many other texts.
- added pod tester in t/pod.t
- cleaned-up the rt.cpan.org bug-list from spam. The next
release will contain fixes for the real reports.
Revision History for Perl extension Mail::IMAPClient.
Changes in version 2.2.9
------------------------
Fixed problem in migrate that caused problems in versions of perl earlier
than 5.6. Thanks go to Steven Roberts for reporting the problem and
identifying its cause.
Fixed problem in migrate that caused problems in versions of perl earlier than
5.6. Thanks go to Steven Roberts for reporting the problem and identifying its
cause.
Fixed problem in the make process that caused tests for BodyStructure
subclass to fail if the grammer had been compiled under a different
version of Parse::RecDescent. This problem was detected by the dedicated
people at testers@cpan.org.
Fixed problem in the make process that caused tests for BodyStructure subclass
to fail if the grammer had been compiled under a different version of
Parse::RecDescent. This problem was detected by the dedicated people at
testers@cpan.org.
Fixed a compatibility problem using Parse::RecDescent version 1.94.
This caused BodyStructure and Thread to fail for 5.8.x users. A number of
people reported this bug to CPAN but it took me a while to realize what
was going on. Really it took me a while to realize my Parse::RecDescent
was out of date. ;-) Now this module is delivered with two versions of
each of the affected grammars and Makefile.PL determines which version
to use. Upgrading to Parse::RecDescent 1.94 will require you to re-run
Makefile.PL and reinstall Mail::IMAPClient.
This caused BodyStructure and Thread to fail for 5.8.x users. A number
of people reported this bug to CPAN but it took me a while to realize what
was going on. Really it took me a while to realize my Parse::RecDescent was
out of date. ;-) Now this module is delivered with two versions of each of
the affected grammars and Makefile.PL determines which version to use.
Upgrading to Parse::RecDescent 1.94 will require you to re-run Makefile.PL
and reinstall Mail::IMAPClient.
Changes in version 2.2.8
------------------------
Change the login method so that it always send password as a literal
to get around problem 2544 reported by Phil Tracy which caused
passwords containing asterisks to fail on some systems (but not any of
mine...). Good catch, Phil.
Change the login method so that it always send password as a literal to get around
problem 2544 reported by Phil Tracy which caused passwords containing asterisks to
fail on some systems (but not any of mine...). Good catch, Phil.
Added a new example that demonstrates the use of imtest (a utility
that comes with Cyrus IMAP) and Mail::IMAPClient together. The
example uses imtest to do secure authentication and then "passes" the
connection over to Mail::IMAPClient (but imtest is still brokering
the encryption/decryption). This example comes from an idea of
Tara L. Andrews', whose brainstorm it was to use imtest to broker
secure connections. (But I still want to get encryption working with
Mail::IMAPClient some day!)
Added a new example that demonstrates the use of imtest (a utility that comes with
Cyrus IMAP) and Mail::IMAPClient together. The example uses imtest to do secure
authentication and then "passes" the connection over to Mail::IMAPClient (but
imtest is still brokering the encryption/decryption). This example comes from
an idea of Tara L. Andrews', whose brainstorm it was to use imtest to broker secure
connections. (But I still want to get encryption working with Mail::IMAPClient some
day!)
Fixed an error in which a "+" was used as a conncatenation error instead
of a ".". Thanks to Andrew Bramble for reporting this, even though he
mistakenly identified it as a "typo". It is not a typo; a plus sign is the
correct concatenation operator, as any decent Java book will tell you ;-)
Fixed an error in which a "+" was used as a conncatenation error instead of a ".".
Thanks to Andrew Bramble for reporting this, even though he mistakenly identified
it as a "typo". It is not a typo; a plus sign is the correct concatenation operator,
as any decent Java book will tell you ;-)
Fixed an error in the login method when the password contains a special
character (such as an asterisk.) Thanks to Phil Tracey for reporting
this bug.
Fixed an error in the login method when the password contains a special character
(such as an asterisk.) Thanks to Phil Tracey for reporting this bug.
Fixed some bugs in _send_line (the "O" side of the I/O engine) that were
reported by Danny Smith.
@ -582,109 +261,94 @@ module will allow you to use NTML authentication with Mail::IMAPClient connectio
Also changed the authenticate method so that it will work with Authen::NTML without
the update mentioned in NTLM::Authen's README.
Added a second example on using the new migrate method,
migrate_mail2.pl. This example demonstrates more advanced techniques
then the first, such as using the separator method to massage folder
names and stuff like that.
Added a second example on using the new migrate method, migrate_mail2.pl. This example
demonstrates more advanced techniques then the first, such as using the separator method
to massage folder names and stuff like that.
Added support for the IMAP THREAD extension. Added
Mail::IMAPClient::Thread.pm to support this. (This pm file is generated
during make from Thread/Thread.grammar.) This new function should be
considered experimental. Note also that this extension has nothing to do
with threaded perl or anything like that. This is still on the TODO list.
Added support for the IMAP THREAD extension. Added Mail::IMAPClient::Thread.pm to support
this. (This pm file is generated during make from Thread/Thread.grammar.) This new
function should be considered experimental. Note also that this extension has nothing
to do with threaded perl or anything like that. This is still on the TODO list.
Updated the search, sort, and thread methods to set $@ to "" before
attempting their respective operations so that text in $@ won't be left
over from some other error and therefore always indicative of an error
in search, sort, or thread, respectively.
Updated the search, sort, and thread methods to set $@ to "" before attempting their
respective operations so that text in $@ won't be left over from some other error and
therefore always indicative of an error in search, sort, or thread, respectively.
Made many many tweaks to the documentation, including adding more examples
(albeit simple ones) and fixing some errors.
Made many many tweaks to the documentation, including adding more examples (albeit
simple ones) and fixing some errors.
Changes in version 2.2.0
------------------------
Fixed some tests so that they are less likely to give false negatives. For
example, test 41 would fail if the test account happened to have an
empty inbox.
Fixed some tests so that they are less likely to give false negatives. For example, test
41 would fail if the test account happened to have an empty inbox.
Made improvements to Mail::IMAPClient::BodyStructure and renamed
Mail::IMAPClient::Parse to Mail::IMAPClient::BodyStructure::Parse. (This
should be transparent to apps since the ...Parse helper module is
used by BodyStructure.pm only.) I also resumed my earlier practice of
using ...Parse.pm from within BodyStructure.pm to avoid the overhead of
compiling the grammar every time you use BodyStructure.pm. (Parse.pm is
just the output from saving the compiled Parse::RecDescent grammar.) In a
related change, I've moved the grammar into its own file (Parse.grammar)
and taught Makefile.PL how to write a Makefile that converts the .grammar
file into a .pm file. This work includes a number of fixes to how a body
structure gets parsed and the parts list returned by the parts method,
among other things. I was able to successfully parse every bodystructure
I could get my hands on, and that's a lot.
Made improvements to Mail::IMAPClient::BodyStructure and renamed Mail::IMAPClient::Parse
to Mail::IMAPClient::BodyStructure::Parse. (This should be transparent to apps since the
...Parse helper module is used by BodyStructure.pm only.) I also resumed my earlier practice
of using ...Parse.pm from within BodyStructure.pm to avoid the overhead of compiling the
grammar every time you use BodyStructure.pm. (Parse.pm is just the output from saving
the compiled Parse::RecDescent grammar.) In a related change, I've moved the grammar into
its own file (Parse.grammar) and taught Makefile.PL how to write a Makefile that converts
the .grammar file into a .pm file. This work includes a number of fixes to how a body structure
gets parsed and the parts list returned by the parts method, among other things. I was able
to successfully parse every bodystructure I could get my hands on, and that's a lot.
Also added a bunch of new methods to Mail::IMAPClient::BodyStructure
and its child classes. The child classes don't even have files of their
own yet; they still live with their parent class! Notable amoung these
changes is support for the FETCH ENVELOPE IMAP command (which was easy
to build in once the BODYSTRUCTURE stuff was working) and some helper
modules to get at the envelope info (as well as envelope information
for MESSAGE/RFC822 attachments from the BODYSTRUCTURE output). Have a
look at the documentation for Mail::IMAPClient::BodyStructure for more
information.
Also added a bunch of new methods to Mail::IMAPClient::BodyStructure and its child classes.
The child classes don't even have files of their own yet; they still live with
their parent class! Notable amoung these changes is support for the FETCH ENVELOPE IMAP
command (which was easy to build in once the BODYSTRUCTURE stuff was working) and some
helper modules to get at the envelope info (as well as envelope information for
MESSAGE/RFC822 attachments from the BODYSTRUCTURE output). Have a look at the
documentation for Mail::IMAPClient::BodyStructure for more information.
Fixed a bug in the folders method regarding quotes and folders with
spaces in the names. The bug must have been around for a while but
rarely manifested itself because of the way methods that take folder
name arguments always try to get the quoting right anyway but it was
still there. Noticing it was the hard part (none of you guys reported
it to me!).
Fixed a bug in the folders method regarding quotes and folders with spaces in the names. The
bug must have been around for a while but rarely manifested itself because of the way
methods that take folder name arguments always try to get the quoting right anyway but
it was still there. Noticing it was the hard part (none of you guys reported it to me!).
Fixed a bug reported by Jeremy Hinton regarding how the search method
handles dates. It was screwing it all up but it should be much better now.
Fixed a bug reported by Jeremy Hinton regarding how the search method handles dates. It was
screwing it all up but it should be much better now.
Added the get_envelope method which is like the get_bodystructure method
except for in ways in which it's different.
Added the get_envelope method which is like the get_bodystructure method except for in ways
in which it's different.
Added the messages method (a suggestion from Danny Carroll), which is
functionally equivalent to $imap->search("ALL") but easier to type.
Added the messages method (a suggestion from Danny Carroll), which is functionally
equivalent to $imap->search("ALL") but easier to type.
Added new arguments to the bodypart_string method so that you can get
just a part of a part (or a part of a subpart for that matter...) I did
this so I could verify BodyStructure's parts method by fetching the first
few bytes of a part (just to prove that the part has a valid part number).
Added new arguments to the bodypart_string method so that you can get just a part of a part
(or a part of a subpart for that matter...) I did this so I could verify BodyStructure's
parts method by fetching the first few bytes of a part (just to prove that the part has a
valid part number).
Added new tests to test the migrate function and to do more thorough
testing of the BodyStructure stuff. Also added a test to make sure that
searches that come up empty handed return an undef instead of an empty
array (reference), regardless of context. Which reminds me...
Added new tests to test the migrate function and to do more thorough testing of the
BodyStructure stuff. Also added a test to make sure that searches that come up empty handed
return an undef instead of an empty array (reference), regardless of context. Which reminds
me...
Fixed a bug in which searches that don't find any hits would return a
reference to an empty array instead of undef when called in a scalar
context. This bug sounds awfully familiar, which is why I added the test
mentioned above...
Fixed a bug in which searches that don't find any hits would return a reference to an empty
array instead of undef when called in a scalar context. This bug sounds awfully familiar,
which is why I added the test mentioned above...
Changes in version 2.1.5
------------------------
Fixed the migrate method so now it not only works, but also works
as originally planned (i.e. without requiring source messages to
be read entirely into memory). If the message is smaller than
the value in the Buffer parameter (default is 4096) then a normal
$imap2->append($folder,$imap1->message_string) is done. However, if
the message is over the buffer size then it is retrieved and written a
bufferful at a time until the whole message has been read and sent. (The
receiving server still expects the entire message at once, but it
will have to wait because the message is being read from the source in
smaller chunks and then written to the destination a chunk at a time.)
This needs extensive testing before I'd be willing to trust it (or at
least extensive logging so you know when something has gone terribly
wrong) and I consider this method to be in BETA in this release. (Numerous
people wrote complaining that migrate didn't work, and some even included
patches to make it work, but the real bug in the last release wasn't
that migrate was broken but that I had inadvertently included the pod for
the method which I knew perfectly well was not ready to be released. My
apologies to anyone who was affected by this.) The migrate method does
seem to work okay on iPlanet (i.e. Netscape) Messenger Server 4.x. Please
let me know if you have any issues on this or any other platform.
Fixed the migrate method so now it not only works, but also works as originally
planned (i.e. without requiring source messages to be read entirely into memory).
If the message is smaller than the value in the Buffer parameter (default is 4096) then
a normal $imap2->append($folder,$imap1->message_string) is done. However, if the message
is over the buffer size then it is retrieved and written a bufferful at a time until the
whole message has been read and sent. (The receiving server still expects the entire
message at once, but it will have to wait because the message is being read from the
source in smaller chunks and then written to the destination a chunk at a time.)
This needs extensive testing before I'd be willing to trust it (or at least extensive
logging so you know when something has gone terribly wrong) and I consider this method
to be in BETA in this release. (Numerous people wrote complaining that migrate didn't
work, and some even included patches to make it work, but the real bug in the last
release wasn't that migrate was broken but that I had inadvertently included the pod
for the method which I knew perfectly well was not ready to be released. My apologies
to anyone who was affected by this.) The migrate method does seem to work okay on
iPlanet (i.e. Netscape) Messenger Server 4.x. Please let me know if you have any
issues on this or any other platform.
Added a new example, migrate_mbox.pl, which will demonstrate the migrate method.

View File

@ -1,156 +1,3 @@
COPYRIGHT
Copyright 1999, 2000, 2001, 2002 , 2003 The Kernen Group, Inc.
All rights reserved.
This program is free software; you can redistribute it and/or modify it
under the terms of either:
a) the "Artistic License" which comes with this Kit, or
b) the GNU General Public License as published by the Free Software
Foundation; either version 1, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See either the GNU
General Public License or the Artistic License for more details. All your
base are belong to us.
=============
The "Artistic License"
Preamble
The intent of this document is to state the conditions under which a
Package may be copied, such that the Copyright Holder maintains some
semblance of artistic control over the development of the package,
while giving the users of the package the right to use and distribute
the Package in a more-or-less customary fashion, plus the right to make
reasonable modifications.
Definitions:
"Package" refers to the collection of files distributed by the
Copyright Holder, and derivatives of that collection of files
created through textual modification.
"Standard Version" refers to such a Package if it has not been
modified, or has been modified in accordance with the wishes
of the Copyright Holder as specified below.
"Copyright Holder" is whoever is named in the copyright or
copyrights for the package.
"You" is you, if you're thinking about copying or distributing
this Package.
"Reasonable copying fee" is whatever you can justify on the
basis of media cost, duplication charges, time of people involved,
and so on. (You will not be required to justify it to the
Copyright Holder, but only to the computing community at large
as a market that must bear the fee.)
"Freely Available" means that no fee is charged for the item
itself, though there may be fees involved in handling the item.
It also means that recipients of the item may redistribute it
under the same conditions they received it.
1. You may make and give away verbatim copies of the source form of the
Standard Version of this Package without restriction, provided that you
duplicate all of the original copyright notices and associated disclaimers.
2. You may apply bug fixes, portability fixes and other modifications
derived from the Public Domain or from the Copyright Holder. A Package
modified in such a way shall still be considered the Standard Version.
3. You may otherwise modify your copy of this Package in any way, provided
that you insert a prominent notice in each changed file stating how and
when you changed that file, and provided that you do at least ONE of the
following:
a) place your modifications in the Public Domain or otherwise make them
Freely Available, such as by posting said modifications to Usenet or
an equivalent medium, or placing the modifications on a major archive
site such as uunet.uu.net, or by allowing the Copyright Holder to include
your modifications in the Standard Version of the Package.
b) use the modified Package only within your corporation or organization.
c) rename any non-standard executables so the names do not conflict
with standard executables, which must also be provided, and provide
a separate manual page for each non-standard executable that clearly
documents how it differs from the Standard Version.
d) make other distribution arrangements with the Copyright Holder.
4. You may distribute the programs of this Package in object code or
executable form, provided that you do at least ONE of the following:
a) distribute a Standard Version of the executables and library files,
together with instructions (in the manual page or equivalent) on where
to get the Standard Version.
b) accompany the distribution with the machine-readable source of
the Package with your modifications.
c) give non-standard executables non-standard names, and clearly
document the differences in manual pages (or equivalent), together
with instructions on where to get the Standard Version.
d) make other distribution arrangements with the Copyright Holder.
5. You may charge a reasonable copying fee for any distribution of this
Package. You may charge any fee you choose for support of this
Package. You may not charge a fee for this Package itself. However,
you may distribute this Package in aggregate with other (possibly
commercial) programs as part of a larger (possibly commercial) software
distribution provided that you do not advertise this Package as a
product of your own. You may embed this Package's interpreter within
an executable of yours (by linking); this shall be construed as a mere
form of aggregation, provided that the complete Standard Version of the
interpreter is so embedded.
6. The scripts and library files supplied as input to or produced as
output from the programs of this Package do not automatically fall
under the copyright of this Package, but belong to whoever generated
them, and may be sold commercially, and may be aggregated with this
Package. If such scripts or library files are aggregated with this
Package via the so-called "undump" or "unexec" methods of producing a
binary executable image, then distribution of such an image shall
neither be construed as a distribution of this Package nor shall it
fall under the restrictions of Paragraphs 3 and 4, provided that you do
not represent such an executable image as a Standard Version of this
Package.
7. C subroutines (or comparably compiled subroutines in other
languages) supplied by you and linked into this Package in order to
emulate subroutines and variables of the language defined by this
Package shall not be considered part of this Package, but are the
equivalent of input as in Paragraph 6, provided these subroutines do
not change the language in any way that would cause it to fail the
regression tests for the language.
8. Aggregation of this Package with a commercial distribution is always
permitted provided that the use of this Package is embedded; that is,
when no overt attempt is made to make this Package's interfaces visible
to the end user of the commercial distribution. Such use shall not be
construed as a distribution of this Package.
9. The name of the Copyright Holder may not be used to endorse or promote
products derived from this software without specific prior written permission.
10. THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
The End
=============
GNU GENERAL PUBLIC LICENSE
Version 1, February 1989

View File

@ -0,0 +1 @@
.

File diff suppressed because it is too large Load Diff

View File

@ -1,3 +1,10 @@
package Mail::IMAPClient;
# $Id: IMAPClient.pod,v 20001010.1 2003/06/12 21:35:53 dkernen Exp $
$Mail::IMAPClient::VERSION = '2.2.7';
$Mail::IMAPClient::VERSION = '2.2.7'; # do it twice to make sure it takes
=head1 NAME
Mail::IMAPClient - An IMAP Client API
@ -38,176 +45,126 @@ object's status, see the section labeled L<"Status Methods">, below.
=head2 Advanced Authentication Mechanisms
RFC2060 defines two commands for authenticating to an IMAP server:
LOGIN for plain text authentication and AUTHENTICATE for more secure
authentication mechanisms. Currently Mail::IMAPClient supports
DIGEST-MD5, CRAM-MD5, LOGIN, PLAIN (SASL), and NTLM authentication.
RFC2060 defines two commands for authenticating to an IMAP server: LOGIN for
plain text authentication and AUTHENTICATE for more secure authentication
mechanisms. Currently Mail::IMAPClient supports CRAM-MD5 and plain text
authentication. There are also a number of methods and parameters that you
can use to build your own authentication mechanism. Since this topic is a source
of many questions, I will provide a quick overview here. All of the methods and
parameters discussed here are described in more detail elsewhere in this document;
this section is meant to help you get started.
There are also a number of methods and parameters that you can use to
build your own authentication mechanism. Since this topic is a source of
many questions, I will provide a quick overview here. All of the methods
and parameters discussed here are described in more detail elsewhere in
this document; this section is meant to help you get started.
First of all, if you just want to do plain text authentication and your server is
okay with that idea then you don't even need to read this section.
First of all, if you just want to do plain text authentication and
your server is okay with that idea then you don't even need to read
this section.
Second of all, the intent of this section is to help you implement the authentication
mechanism of your choice, but you will have to understand how that mechanism works.
There are I<lots> of authentication mechanisms and most of them are not available to
me to test with for one reason or another. Even if this section does not answer
all of your authentication questions it I<does> contain all the answers that I have,
which I admit are scant.
Second of all, the intent of this section is to help you implement the
authentication mechanism of your choice, but you will have to understand
how that mechanism works. There are I<lots> of authentication mechanisms
and most of them are not available to me to test with for one reason or
another. Even if this section does not answer all of your authentication
questions it I<does> contain all the answers that I have, which I admit
are scant.
Third of all, if you manage to get any advanced authentication mechanisms to work then
please consider donating them to this module. I don't quite have a framework visualized
for how different authentication mechanisms could "plug in" to this module but I would
like to eventually see this module distributed with a number of helper modules to
implement various authentication schemes.
Third of all, if you manage to get any advanced authentication mechanisms
to work then please consider donating them to this module. I don't quite
have a framework visualized for how different authentication mechanisms
could "plug in" to this module but I would like to eventually see this
module distributed with a number of helper modules to implement various
authentication schemes.
The B<Mail::IMAPClient>'s support for add-on authentication mechanisms is pretty straight
forward and is built upon several assumptions. Basically you create a callback to be used to
provide the response to the server's challenge. The I<Authcallback> parameter contains a
reference to the callback, which can be an anonymous subroutine or a named subroutine.
Then, you identify your authentication mechanism, either via the I<Authmechanism> parameter
or as an argument to L<authenticate>.
The B<Mail::IMAPClient>'s support for add-on authentication mechanisms is
pretty straight forward and is built upon several assumptions. Basically
you create a callback to be used to provide the response to the server's
challenge. The I<Authcallback> parameter contains a reference to the
callback, which can be an anonymous subroutine or a named subroutine.
Then, you identify your authentication mechanism, either via the
I<Authmechanism> parameter or as an argument to L<authenticate>.
You may also need to provide a subroutine to encrypt (or whatever) data before it is sent
to the server. The I<Prewritemethod> parameter must contain a reference to this subroutine.
And, you will need to decrypt data from the server; a reference to the subroutine that
does this must be stored in the I<Readmethod> parameter.
You may also need to provide a subroutine to encrypt (or whatever) data
before it is sent to the server. The I<Prewritemethod> parameter must
contain a reference to this subroutine. And, you will need to decrypt
data from the server; a reference to the subroutine that does this must
be stored in the I<Readmethod> parameter.
This framework is based on the assumptions that a) the mechanism you are using requires
a challenge-response exchange, and b) the mechanism does not fundamentally alter the
exchange between client and server but merely wraps the exchange in a layer of
encryption. It particularly assumes that the line-oriented nature of the IMAP conversation
is preserved; authentication mechanisms that break up messages into blocks of a
predetermined size may still be possible but will certainly be more difficult to implement.
This framework is based on the assumptions that a) the mechanism you are
using requires a challenge-response exchange, and b) the mechanism does
not fundamentally alter the exchange between client and server but merely
wraps the exchange in a layer of encryption. It particularly assumes
that the line-oriented nature of the IMAP conversation is preserved;
authentication mechanisms that break up messages into blocks of a
predetermined size may still be possible but will certainly be more
difficult to implement.
Alternatively, if you have access to B<imtest>, a utility included in the Cyrus IMAP
distribution, you can use that utility to broker your communications with the IMAP server.
This is quite easy to implement. An example, L<examples/imtestExample.pl>, can be found in
the C<examples> subdirectory of the source distribution.
Alternatively, if you have access to B<imtest>, a utility included in
the Cyrus IMAP distribution, you can use that utility to broker your
communications with the IMAP server. This is quite easy to implement. An
example, L<examples/imtestExample.pl>, can be found in the C<examples>
subdirectory of the source distribution.
The following list summarizes the methods and parameters that you may
find useful in implementing advanced autentication:
The following list summarizes the methods and parameters that you may find useful in
implementing advanced autentication:
=over 4
=item authenticate method
This method implements the AUTHENTICATE IMAP client command as documented
in RFC2060. If you have set the I<Authmechanism> parameter then the
L<login> method will call L<authenticate> instead of doing a clear text
login, which is its normal behavior. If you don't want B<login> to call
B<authenticate> on your behalf then you can call it yourself. Instead
of setting an I<Authmechanism> you can just pass the authmechanism as
the first argument to AUTHENTICATE.
This method implements the AUTHENTICATE IMAP client command as documented in RFC2060.
If you have set the I<Authmechanism> parameter then the L<login> method will call
L<authenticate> instead of doing a clear text login, which is its normal behavior.
If you don't want B<login> to call B<authenticate> on your behalf then you can call
it yourself. Instead of setting an I<Authmechanism> you can just pass the authmechanism
as the first argument to AUTHENTICATE.
=item Socket and RawSocket Parameters
=item Socket Parameter
Both parameters hold a reference to the socket connection. Normally this
is set for you by the L<connect> method, but if you are implementing
an advanced authentication technique you may choose to set up your own
socket connection and then set this parameter manually, bypassing the
B<connect> method completely. This is also useful if you want to use
L<IO::Socket::INET> alternatives, like L<IO::Socket::SSL>.
The I<Socket> parameter holds a reference to the socket connection. Normally this
is set for you by the L<connect> method, but if you are implementing an advanced
authentication technique you may choose to set up your own socket connection and then
set this parameter manually, bypassing the B<connect> method completely.
The I<RawSocket> parameter simply records the socket to use for future
operations, without attempting any interaction on it. In this case, you
have to be sure to handle all the preliminar operations and to manually
set the B<Mail::IMAPClient> object in sync with its actual status with
respect to this socket (see below for additional parameters regarding
this, especially the I<State> parameter).
=item State, Server, Password, and User Parameters
The I<Socket> parameter, instead, also attempts to carry on preliminar
phases if the conditions apply. If both parameters are present, this
takes the precedence over I<RawSocket>. It is primarily used to
provide an alternative socket for communications, e.g. to use
L<IO::Socket::SSL> instead of L<IO::Socket::INET> used by L<connect>
by default.
B<PLEASE NOTE>
As of version 2.99_04 of this module, the I<Socket> parameter has
changed semantics to make it more "DWIM". The I<RawSocket> parameter was
introduced as a replacement for the I<Socket> parameter in older version.
=item State, Server, Proxy, Password, and User Parameters
If you need to make your own connection to the server and perform your
authentication manually, then you can set these parameters to keep your
B<Mail::IMAPClient> object in sync with its actual status. Of these,
only the I<State> parameter is always necessary. The others need to be
set only if you think your program will need them later.
I<Proxy> is required for PLAIN (SASL) authentication.
If you need to make your own connection to the server and perform your authentication
manually, then you can set these parameters to keep your B<Mail::IMAPClient> object
in sync with its actual status. Of these, only the I<State> parameter is always necessary.
The others need to be set only if you think your program will need them later.
=item Authmechanism
Set this to the value that AUTHENTICATE should send to the server as the
authentication mechanism. If you are brokering your own authentication
then this parameter may be less useful. It is also not needed by the
L<authenticate> method. It exists solely so that you can set it when
you call L<new> to instantiate your object. The B<new> method will
call L<connect>, who will call L<login>. If B<login> sees that you've
set an I<Authmechanism> then it will call B<authenticate>, using your
I<Authmechanism> and I<Authcallback> parameters as arguments.
=item Authuser
Normally you authenticate and log in with the username specified in
the User parameter. When you are using DIGEST-MD5 as I<Authmechanism>,
you can optionally specify a different username for the final log in.
This can be useful to mark messages as seen for the I<Authuser>
if you don't know the password of the user as the seen state
is often a per-user state.
Set this to the value that AUTHENTICATE should send to the server as the authentication
mechanism. If you are brokering your own authentication then this parameter may be less
useful. It is also not needed by the L<authenticate> method. It exists solely so that you
can set it when you call L<new> to instantiate your object. The B<new> method will call
L<connect>, who will call L<login>. If B<login> sees that you've set an I<Authmechanism>
then it will call B<authenticate>, using your I<Authmechanism> and I<Authcallback>
parameters as arguments.
=item Authcallback
The I<Authcallback> parameter, if set, should contain a pointer
to a subroutine. The L<login> method will use this as the callback
argument to the B<authenticate> method if the I<Authmechanism> and
I<Authcallback> parameters are both set. If you set I<Authmechanism>
but not I<Authcallback> then the default callback for your mechanism will
be used. All supported authentication mechanisms have a default callback;
in every other case not supplying the callback results in an error.
The I<Authcallback> parameter, if set, should contain a pointer to a subroutine. The
L<login> method will use this as the callback argument to the B<authenticate> method
if the I<Authmechanism> and I<Authcallback> parameters are both set. If you set
I<Authmechanism> but not I<Authcallback> then the default callback for your mechanism
will be used. Unfortunately only the CRAM-MD5 authentication mechanism has a default
callback; in every other case not supplying the callback results in an error.
Most advanced authentication mechanisms require a challenge-response
exchange. After the L<authenticate> method sends "<tag> AUTHENTICATE
<Authmechanism>\r\n" to the IMAP server, the server replies with
a challenge. The B<authenticate> method then invokes the code whose
reference is stored in the I<Authcallback> parameter as follows:
Most advanced authentication mechanisms require a challenge-response exchange. After the
L<authenticate> method sends "<tag> AUTHENTICATE <Authmechanism>\r\n" to the IMAP
server, the server replies with a challenge. The B<authenticate> method then invokes
the code whose reference is stored in the I<Authcallback> parameter as follows:
$Authcallback->($challenge,$imap)
where C<$Authcallback> is the code reference stored in the I<Authcallback>
parameter, C<$challenge> is the challenge received from the IMAP server,
and C<$imap> is a pointer to the B<Mail::IMAPClient> object. The return
value from the I<Authcallback> routine should be the response to the
challenge, and that return value will be sent by the L<authenticate>
method to the server.
where C<$Authcallback> is the code reference stored in the I<Authcallback> parameter,
C<$challenge> is the challenge received from the IMAP server, and C<$imap> is a pointer
to the B<Mail::IMAPClient> object. The return value from the I<Authcallback> routine
should be the response to the challenge, and that return value will be sent by the
L<authenticate> method to the server.
=item Readmethod
The I<Readmethod> parameter points to a routine that will read data from
the socket connection. This read method will replace the B<sysread> that
would otherwise be performed by B<Mail::IMAPClient>. The replacement
method is called with five arguments. The first is a pointer to the
B<Mail::IMAPClient> object; the rest are the four arguments required by
the B<sysread> function. Note the third argument (which corresponds to
the second argument to B<sysread>) is a buffer to read into; this will
be a pointer to a scalar. So for example if your I<Readmethod> were
just going to replace B<sysread> without any intervening processing
(which would be silly but this is just an example after all) then you
would set your I<Readmethod> like this:
The I<Readmethod> parameter points to a routine that will read data from the socket
connection. This read method will replace the B<sysread> that would otherwise be
performed by B<Mail::IMAPClient>. The replacement method is called with five
arguments. The first is a pointer to the B<Mail::IMAPClient> object; the rest
are the four arguments required by the B<sysread> function. Note the third argument
(which corresponds to the second argument to B<sysread>) is a buffer to read into;
this will be a pointer to a scalar. So for example if your I<Readmethod> were just
going to replace B<sysread> without any intervening processing (which would be silly
but this is just an example after all) then you would set your I<Readmethod> like this:
$imap->Readmethod(
sub {
@ -217,39 +174,18 @@ would set your I<Readmethod> like this:
}
);
Note particularly the double dollar signs in C<$$buffer> in the B<sysread>
call; this is not a typo!
Note particularly the double dollar signs in C<$$buffer> in the B<sysread> call; this
is not a typo!
=item Prewritemethod
The I<Prewritemethod>, if defined, should contain a pointer to a
subroutine. It is called immediately prior to writing to the socket
connection. It is called by B<Mail::IMAPClient> with two arguments:
a reference to the B<Mail::IMAPClient> object and the ASCII text
string to be written. It should return another string that will be
the actual string sent to the IMAP server. The idea here is that your
I<Prewritemethod> will do whatever encryption is necessary and then
return the result to the caller so it in turn can be sent to the server.
=item Ignoresizeerrors
Certain (caching) servers, like Exchange 2007, often report the wrong
message size. Instead of chopping the message into a size that it
fits the specified size, the reported size will be simply ignored
when this parameter is set to C<1>.
=item Supportedflags
Especially when C<migrate()> is used, the receiving peer may need to
be configured explicitly with the list of supported flags; that may
be different from the source IMAP server.
The names are to be specified as an ARRAY. Black-slashes and casing
will be ignored.
You may also specify a CODE reference, which will be called for each of
the flags seperately. In this case, the flags are not (yet) normalized.
The returned lists of the CODE calls are shape the resulting flag list.
The I<Prewritemethod>, if defined, should contain a pointer to a subroutine.
It is called immediately prior to writing to the
socket connection. It is called by B<Mail::IMAPClient> with two arguments:
a reference to the B<Mail::IMAPClient> object and the ASCII text string to be written.
It should return another string that will be the actual string sent to the IMAP server.
The idea here is that your I<Prewritemethod> will do whatever encryption is necessary
and then return the result to the caller so it in turn can be sent to the server.
=back
@ -526,21 +462,6 @@ seconds since the epoch date. It returns an RFC2060 compliant date
string for that date (as required in date-related arguments to SEARCH,
such as "since", "before", etc.).
=head2 Rfc2060_datetime
Example:
$date = $imap->Rfc2060_datetime($seconds);
# or:
$date = Mail::IMAPClient->Rfc2060_datetime($seconds);
The B<Rfc2060_datetime> method accepts one or two arguments: a obligatory
timestamp and an optional zone. The zone shall be formatted as
C<< [+-]\d{4} >>, and defaults to C<< +0000 >>. The timestamp follows the
definition of the output of the platforms specific C<time>, usually in
seconds since Jan 1st 1970. However, you have to correct the number
yourself for the zone.
=head2 Rfc822_date
Example:
@ -702,8 +623,8 @@ Example:
my $new_msg_uid = $imap->append_file(
$folder,
$filename,
[$input_record_separator, flags, date] # optional
$filename
[ , $input_record_separator ] # optional (not arrayref)
) or die "Could not append_file: $@\n";
The B<append_file> method adds a message to the specified folder. It
@ -738,9 +659,10 @@ depending on whether you supplied that optional third argument).
Example:
# brackets indicate optional arguments (not array refs):
my $uid = $imap->append_string( $folder, $text [,$flags [,$date ] ])
or die "Could not append_string: $@\n";
# brackets indicate optional arguments (not array refs):
my $uid = $imap->append_string( $folder, $text [ , $flags [ , $date ] ])
or die "Could not append_string: $@\n";
The B<append_string> method adds a message to the specified folder. It
requires two arguments, the name of the folder to append the message
@ -801,8 +723,9 @@ override parameter settings.
If you do not specify a second argument and you have not set the
I<Authcallback> parameter, then the first argument must be
one of the authentication mechanisms for which B<Mail::IMAPClient>
has built in support.
one of the authentication mechanisms for which B<Mail::IMAPClient> has
built in support. Currently there is only built in support for CRAM-MD5,
but I hope to add more in future releases.
If you are interested in doing NTLM authentication then please see Mark
Bush's L<Authen::NTLM>, which can work with B<Mail::IMAPClient> to
@ -1421,7 +1344,7 @@ B<has_capability>.
Example:
my $idle = $imap->idle or warn "Couldn't idle: $@\n";
goDoOtherThings();
&goDoOtherThings;
$imap->done($idle) or warn "Error from done: $@\n";
The B<idle> method places the IMAP connection in an IDLE state. Your
@ -1616,13 +1539,7 @@ B<login> is sometimes called automatically by L<connect>, which in turn
is sometimes called automatically by L<new>. You can predict this
behavior once you've read the section on the L<new> method.
Then Sun/iPlanet/Netscape IMAP servers to allow an administrative user to
masquerade as another user. The B<proxyauth> method uses the IMAP
PROXYAUTH client command provided like this:
$imap->login("admin", "password");
$imap->proxyauth("someuser");
=cut
=head2 logout
@ -1870,8 +1787,6 @@ consumption. If you have older scripts that used L<message_to_file> and
L<append_file> to move large messages between IMAP mailboxes then you
may want to try this method as a possible replacement.
See also C<Supportedflags>.
=head2 move
Example:
@ -2403,7 +2318,7 @@ will B<Mail::IMAPClient>.
If you'd like, you can use the L<Rfc2060_date> method to convert from
epoch time (as returned by L<time|perlfunc/time>) into an RFC2060 date
specification.
specification.
=cut
@ -3097,7 +3012,28 @@ to a true value.
=head2 EnableServerResponseInLiteral
Removed in 2.99_01 (now autodetect)
Example:
$EnableServerResponseInLiteral = $imap->EnableServerResponseInLiteral();
# or:
$imap->EnableServerResponseInLiteral($new_value);
The I<EnableServerResponseInLiteral> parameter tells
B<Mail::IMAPClient> to expect server responses to be embedded in
literal strings. Usually literal strings contain only message data, not
server responses. I have seen at least one IMAP server implementation
though that includes the final <tag> OK response in the literal data.
If your server does this then your script will hang whenever you try to
read literal data, such as message text, or even output from the
L<folders> method if some of your folders have special characters such
as double quotes or sometimes spaces in the name.
I am pretty sure this behavior is not RFC2060 compliant so I am
dropping it by default. In fact, I encountered the problem a long time
ago when still new to IMAP and may have imagined the whole thing.
However, if your scripts hang running certain methods you may want to
at least try enabling this parameter by passing the eponymous method a
true value.
=head2 Fast_io
@ -3260,82 +3196,45 @@ Example:
}
If set to a true value, then the L<search> method will return a
If set to a true value, then the L<search> method will return a
L<Mail::IMAPClient::MessageSet> object if called in a scalar context,
instead of the array reference that B<fetch> normally returns when called
in a scalar context. If set to zero or if undefined, then B<search>
instead of the array reference that B<fetch> normally returns when
called in a scalar context. If set to zero or if undefined, then B<search>
will continue to return an array reference when called in scalar context.
This parameter has no affect on the B<search> method when B<search>
is called in a list context.
This parameter has no affect on the B<search> method when B<search> is called
in a list context.
=head2 RawSocket
=head2 Readmethod
Example:
$socket = $imap->RawSocket;
# or:
$imap->RawSocket($socketh);
The I<RawSocket> method can be used to obtain the socket handle of the
current connection (say, to do I/O on the connection that is not
otherwise supported by B<Mail::IMAPClient>) or to replace the current
socket with a new handle (for instance an SSL handle, see
L<IO::Socket::SSL>, but be sure to see the L<Socket> method as well).
This parameter, if supplied, should contain a reference to a subroutine that will
replace sysreads. The subroutine will be passed the following arguments:
=over 4
If you supply a socket handle yourself, either by doing something like:
1. imap_object_ref - a reference to the current imap object
$imap=Mail::IMAPClient->new(RawSocket => $sock, User => ... );
2. scalar_ref - a reference to a scalar variable into which data is read. The data
place in here should be "finished data", so if you are decrypting or removing signatures
then be sure to do that before you place data into this buffer.
or by doing something like:
3. read_length - the number of bytes requested to be read
$imap = Mail::IMAPClient->new(User => $user,
Password => $pass, Server => $host);
# blah blah blah
$imap->RawSocket($ssl);
4. offset - the offset into C<scalar_ref> into which data should be read. If not supplied it
should default to zero.
then it will be up to you to establish the connection AND to
authenticate, either via the L<login> method, or the fancier
L<authenticate>, or, since you know so much anyway, by just doing raw
I/O against the socket until you're logged in. If you do any of this
then you should also set the L<State> parameter yourself to reflect the
current state of the object (i.e. Connected, Authenticated, etc).
=back
Note that no operation will be attempted on the socket when this method
is called. In particular, after the TCP connections towards the IMAP
server is established, the protocol mandates the server to send an
initial greeting message, and you will have to explicitly cope with
this message before doing any other operation, e.g. trying to call
L<login>. Caveat emptor.
Note that this method completely replaces reads from the connection to the server, so if
you define one of these then your subroutine will have to actually do the read. It is for
things like this that we have the L<Socket> parameter and eponymous accessor method.
For a more DWIM approach to setting the socket see L<Socket>.
Your I<Readmethod> will probably need to know more than this to do whatever it does.
It is recommended that you tuck all other pertinent information into a hash, and store
a reference to this hash somewhere where your method can get to it, possibly in the
I<Mail::IMAPClient> object itself.
=head2 Readmethod IMAP, BUFFER, LENGTH, OFFSET
This parameter, if supplied, should contain a reference to a subroutine
that will replace sysreads. The subroutine will be passed the following
arguments: first the used Mail::IMAPClient object. As second,
a reference to a scalar variable into which data is readl the BUFFER. The
data place in here should be "finished data", so if you are decrypting
or removing signatures then be sure to do that before you place data
into this buffer.
As third, the number of bytes requested to be read; the LENGTH of the
request. Finally, the OFFSET into the BUFFER where the data should be
read. If not supplied it should default to zero.
Note that this method completely replaces reads from the connection
to the server, so if you define one of these then your subroutine will
have to actually do the read. It is for things like this that we have
the L<Socket> parameter and eponymous accessor method.
Your I<Readmethod> will probably need to know more than this to do
whatever it does. It is recommended that you tuck all other pertinent
information into a hash, and store a reference to this hash somewhere
where your method can get to it, possibly in the I<Mail::IMAPClient>
object itself.
If you need a I<Readmethod> then you probably need a L<Prewritemethod>
as well.
If you need a I<Readmethod> then you probably need a L<Prewritemethod> as well.
=head2 Server
@ -3356,12 +3255,11 @@ method.
=head2 Showcredentials
Normally debugging output will mask the login credentials when the plain
text login mechanism is used. Setting I<Showcredentials> to a true value
will suppress this, so that you can see the string being passed back
and forth during plain text login. Only set this to true when you are
debugging problems with the IMAP LOGIN command, and then turn it off
right away when you're finished working on that problem.
Normally debugging output will mask the login credentials when the plain text
login mechanism is used. Setting I<Showcredentials> to a true value will suppress
this, so that you can see the string being passed back and forth during plain text
login. Only set this to true when you are debugging problems with the IMAP LOGIN
command, and then turn it off right away when you're finished working on that problem.
Example:
@ -3372,10 +3270,6 @@ Example:
=head2 Socket
B<PLEASE NOTE>
The semantics of this method has changed as of version 2.99_04 of this module.
If you need the old semantics, you now have to use L<RawSocket>.
Example:
$Socket = $imap->Socket();
@ -3385,61 +3279,24 @@ Example:
The I<Socket> method can be used to obtain the socket handle of the
current connection (say, to do I/O on the connection that is not
otherwise supported by B<Mail::IMAPClient>) or to replace the current
socket with a new handle (for instance an SSL handle, see
IO::Socket::SSL).
socket with a new handle (perhaps an SSL handle, for example).
If you supply a socket handle yourself, either by doing something like:
$imap = Mail::IMAPClient->new(Socket => $sock, User => ... );
$imap=Mail::IMAPClient->new(Socket=>$sock, User => ... );
or by doing something like:
$imap = Mail::IMAPClient->new(User => $user,
Password => $pass, Server => $host);
$imap=Mail::IMAPClient->new(User => $user, Password => $pass, Server => $host);
# blah blah blah
$imap->Socket($ssl);
then it will be up to you to establish the connection, i.e. make sure
that C<$ssl> in the example is a valid and connected socket.
This method is primarily used to provide a drop-in replacement for
L<IO::Socket::INET>, used by L<connect> by default. In fact, this method
is called by L<connect> itself after having established a suitable
L<IO::Socket::INET> socket connection towards the target server; for
this reason, this method also carries the normal operations associated
with L<connect>, namely:
=over
=item *
read the initial greeting message from the server;
=item *
call L<login> if the conditions apply (see L<connect> for details);
=item *
leave the I<Mail::IMAPClient> object in a suitable state.
=back
For these reasons, the following example will work "out of the box":
use IO::Socket::SSL;
my $imap = Mail::IMAPClient->new
( User => 'your-username',
Password => 'your-password',
Socket => IO::Socket::SSL->new
( Proto => 'tcp',
PeerAddr => 'some.imap.server',
PeerPort => 993, # IMAP over SSL standard port
),
);
If you need more control over the socket, e.g. you have to implement a fancier
authentication method, see L<RawSocket>.
then it will be up to you to establish the connection AND to
authenticate, either via the L<login> method, or the fancier
L<authenticate>, or, since you know so much anyway, by just doing raw
I/O against the socket until you're logged in. If you do any of this
then you should also set the L<State> parameter yourself to reflect the
current state of the object (i.e. Connected, Authenticated, etc).
=cut

View File

@ -0,0 +1,73 @@
Mail::IMAPClient Installation
The Mail::IMAPClient is written entirely in Perl, so it should install on any reasonably
recent version of Perl. See the README file for a perl one-liner that you can run to verify
that your perl has what it takes to run Mail::IMAPClient.
The installation is standard:
0) cd to installation directory
1) perl Makefile.PL (and reply to the prompt(s))
2) make (optional)
3) make test (optional)
4) make install
The 'make install' and 'make test' will both do step 2 ('make') if you haven't done it
already. Currently the test script is lame (although not as lame as in the last release!)
but I hope to incorporate more thorough testing in a future version. You should at least
try it and let me know if your tests fail.
Version 1.0 changed the installation script so that it reuses the parameter file for
the tests if it finds one. Installation can be run in the background if the test.txt file
exists. Touching it is good enough to prevent prompts; having a correctly formatted
version (as shown in test_template.txt) is even better, as it will allow you to do a
thorough 'make test'. Invalid data in test.txt (either from precreating it or from
responding inaccurately to prompts) will cause 'make test' to report 'not ok' results
but won't break anything important (like the IMAPClient.pm file, or your car).
If you have tests that fail it may be more illuminating to run the tests by hand. IE:
perl -I./blib/lib t/basic.t from the installation dir will pinpoint the failing test.
Better yet, supply an argument to basic/t (any 'true' argument will do; I use '1') to
turn on debugging, which will be placed in your installation directory in 'imap1.debug'
and 'imap2.debug'. E-mail me the results.
If you don't have a test.txt file in your installation directory then you will have to
answer at least one prompt. If you do have a test.txt file, and you run 'make clean',
then you won't have a test.txt file anymore, so take precautions.
If you do have a test.txt file and you don't run 'make clean' then a text file will
be sitting around containing logon credentials, so, again, take precautions. (It's just
a test account anyway, right?)
If, when replying to the "perl Makefile.PL" prompts, you supply server, id, and
password credentials for an id that has a ridiculously huge number of folders and
subfolders then the 'make test' may run approximately forever. Next time try an id
with less stuff.
For examples on using Mail::IMAPClient, check out the examples subdirectory. If you have
better examples, then why haven't you e-mailed them to me? Also, I totally recommend
that you have a copy of RFC2060 handy when using this module, since the documentation
for this module is meant to compliment, not replace, RFC2060. In fact, I am so convinced
that you'll need the RFC that I've included a copy of it in the distribution, under
the "docs/" subdirectory. It's a smashing good read so have at it. Other IMAP related
rfcs are there as well.
One of the examples in the examples/ subdirectory is called cleanTest.pl. If you find
your 'make test' has had trouble and left some folders named "IMAPClient_*" in your
test account, you can run this example to clean up the account. But probably only after
you've fixed any problems encountered with 'make test'!
This module uses Damian Conway's excellent Parse::RecDescent module for some advanced
features. If you don't have that module installed then you can still install
Mail::IMAPClient but you won't have the full functionality. If you have
Parse::RecDescent installed and then upgrade it, you may find that some features in
Mail::IMAPClient suddenly start throwing compile-time errors. Just 'make clean' and
then 'make', 'make test', and 'make install'. This happens because grammers compiled
under older releases of Parse::RecDescent are sometimes incompatible with newer
Parse::RecDescent runtime engines. This would never be a problem if Mail::IMAPClient
recompiled grammers at run time, but for performance reasons it precompiles them at
install time. TANSTAAFL.
Now go and write IMAP clients.
Dave Kernen

View File

@ -0,0 +1,25 @@
Please let me know if you have any problems under perl 5.8.x.
I do know of one issue under perl 5.8.0. If you are installing from
a work directory that contains a double colon in one of the
component subdirectory names then some of the tests may fail.
For example, I do my development work from a subdirectory that
has "Mail::IMAPClient" in the path, and 'make test' fails for
the subcomponents of Mail::IMAPClient from that path; the test
harness is unable to locate the ../lib/blib subdirectory and so
cannot load the .pm file. If I install from a different directory
without "::"'s then everything tests okay. I do not see this with
earlier versions of perl.
A work around is to not install from a subdirectory with "::".
An alternative work around is to do 'make install' before 'make test'.
This gets around the problem by placing a copy of the necessary files
in your installation directories, so that even though 'make test'
cannot find ../blib/lib, it can find the necessary .pm files in your
(production!) installation libraries so the tests will still succeed.
However, you have to remember to do 'make install' first every time
you install a new version of this module, or you will be testing the
old version instead of the new one.

View File

@ -0,0 +1,81 @@
Changes
COPYRIGHT
Todo
IMAPClient.pm
IMAPClient.pod
BodyStructure/BodyStructure.pm
BodyStructure/Parse/Parse.pod
INSTALL
BUG_REPORTS
INSTALL_perl5.80
MANIFEST
README
Makefile.PL
t/basic.t
t/fast_io.t
t/uidplus.t
t/uidfast.t
t/cram-md5.t
t/ranges.t
Copying
Artistic
examples/build_dist.pl
examples/build_ldif.pl
examples/cleanTest.pl
examples/copy_folder.pl
examples/cyrus_expunge.pl
examples/cyrus_expire.pl
examples/find_dup_msgs.pl
examples/imap_to_mbox.pl
examples/migrate_mbox.pl
examples/migrate_mail2.pl
examples/populate_mailbox.pl
examples/sharedFolder.pl
examples/imtestExample.pl
test_template.txt
sample.perldb
docs/rfc1731.txt
docs/rfc1732.txt
docs/rfc1733.txt
docs/rfc2060.txt
docs/rfc2061.txt
docs/rfc2062.txt
docs/rfc2086.txt
docs/rfc2087.txt
docs/rfc2088.txt
docs/rfc2177.txt
docs/rfc2180.txt
docs/rfc2192.txt
docs/rfc2193.txt
docs/rfc2195.txt
docs/rfc2221.txt
docs/rfc2222.txt
docs/rfc2234.txt
docs/rfc2245.txt
docs/rfc2342.txt
docs/rfc2359.txt
docs/rfc2683.txt
docs/rfc2831.txt
docs/draft-ietf-imapext-sort-06.txt
BodyStructure/Parse/Makefile.PL
BodyStructure/Parse/Parse.grammar_old
BodyStructure/Parse/Parse.grammar_new
BodyStructure/Parse/t/parse.t
BodyStructure/Makefile.PL
BodyStructure/t/bodystructure.t
docs/draft-crispin-imapv-17.txt
docs/draft-ietf-imapext-annotate-04.txt
docs/draft-ietf-imapext-thread-11.txt
Thread/Thread.pod
Thread/Thread.grammar_old
Thread/Thread.grammar_new
Thread/Makefile.PL
Thread/t/thread.t
MessageSet/Makefile.PL
MessageSet/MessageSet.pm
MessageSet/t/range.t
BodyStructure/COPYRIGHT
Thread/COPYRIGHT
docs/COPYRIGHT
examples/COPYRIGHT
MessageSet/COPYRIGHT

1
Mail-IMAPClient-2.2.9/Mail Symbolic link
View File

@ -0,0 +1 @@
.

View File

@ -0,0 +1,148 @@
use ExtUtils::MakeMaker;
use File::Copy;
use Cwd;
# See lib/ExtUtils/MakeMaker.pm for details of how to influence
# the contents of the Makefile that is written.
$DO_BODYSTRUCTURE = eval "require 'Parse/RecDescent.pm'" ;
unless ($DO_BODYSTRUCTURE) {
print
"*** NOTE ***\n\n",
"Unable to find and load Parse::RecDescent.\n",
"Mail::IMAPClient will be installed without support for\n",
"the get_bodystructure method and without the \n",
"Mail::IMAPClient::BodyStructure subclasses. \n\n",
"If you need these subclasses, install Parse::RecDescent \nand ",
"re-run Makefile.PL. \n\n";
}
&set_PRD_type if $DO_BODYSTRUCTURE;
WriteMakefile(
'DIR' => [ 'MessageSet', $DO_BODYSTRUCTURE ? ( 'BodyStructure' , 'Thread' ) : () ],
'NAME' => 'Mail::IMAPClient',
'VERSION_FROM' => 'IMAPClient.pm', # finds $VERSION
'clean' => { FILES => 'test.txt' },
'PREREQ_PM' => {
'Errno' => 0,
'IO::Socket' => 0,
'Fcntl' => 0,
'IO::Select' => 0,
'IO::File' => 0,
'Data::Dumper' => 0,
'Carp' => 0,
},
);
=begin prereqs
The Mail::IMAPClient module uses the IO::Socket module to make a socket
connection to an IMAP server and the Socket module to get some constants.
It also uses Errno, Fcntl (for faster I/O) and IO::Select, IO::File,
Data::Dumper, and Carp.
=end prereqs
=cut
&set_test_data;
sub set_test_data {
unless (-f "./IMAPClient.pm") { warn "ERROR: not in installation directory\n"; return }
return if -f "./test.txt";
print "You have the option of running an extended suite of tests during\n",
"'make test'. This requires an IMAP server name, user account, and ",
"password to test with.","\n","\n",
"Do you want to run the extended tests? (n/y) ==> ";
my $yes = <STDIN>;
return unless $yes =~ /^[Yy](?:[Ee]:[Ss]?)?$/ ;
unless (open TST,">./test.txt") { warn "ERROR: couldn't open ./test.txt: $!\n"; return }
my $server = "";
until ($server ) {
print "\nPlease provide the hostname or IP address of a host running an IMAP server \n",
"(or QUIT to skip the extended tests) ==> ";
$server = <STDIN>;
chomp $server;
return if $server =~ /^\s*quit\s*$/i ;
}
print TST "server=$server\n";
my $user = "";
until ($user) {
print "\nPlease provide the username of an account\non $server (or QUIT) ==> ";
$user = <STDIN>;
chomp $user;
return if $user =~ /^\s*quit\s*$/i ;
}
print TST "user=$user\n";
my $passe = "";
until ($passed) {
print "\nPlease provide the password for $user\n(or QUIT) ==> ";
$passed = <STDIN>;
chomp $passed;
return if $passed =~ /^\s+$|^quit$/i ;
}
print TST "passed=$passed\n";
print "\nPlease provide the port to connect to on $server to run the test \n",
"(default is 143) ==> ";
my $port = <STDIN>;
chomp $port;
$port ||= 143;
print TST "port=$port\n";
print "\nPlease provide the authentication mechanism to use on $server to run the test \n",
"(default is 'LOGIN', which uses the plain text LOGIN command) ==> ";
my $authmech = <STDIN>;
chomp $authmech;
$authmech ||= 'LOGIN';
print TST "authmechanism=$authmech\n";
close TST;
print "\nGracias! The information you provided (including the \n",
" password!) has been stored in ",cwd,"/test.txt and should be\n",
" removed (either by hand or by 'make clean') after testing.\n";
}
sub set_PRD_type {
my $g = <<' EOG';
start: thing(s)
{ $return = \%item; }
thing: /YES/
{ $return = \%item; }
EOG
my $p = Parse::RecDescent->new($g);
my $i = $p->start("YES YES");
if ( exists($i->{'thing(s)'}) ) {
print "Using new-style Parse::RecDescent grammars\n";
copy("./Thread/Thread.grammar_new","./Thread/Thread.grammar");
copy( "./BodyStructure/Parse/Parse.grammar_new",
"./BodyStructure/Parse/Parse.grammar"
);
} elsif ($i->{'thing'}) {
print "Using old-style Parse::RecDescent grammars\n";
print "If you upgrade Parse::RecDescent then you will ",
"have to re-run Makefile.PL and re-make and re-'make install'",
"Mail::IMAPClient.\n";
copy("./Thread/Thread.grammar_old","./Thread/Thread.grammar");
copy( "./BodyStructure/Parse/Parse.grammar_old",
"./BodyStructure/Parse/Parse.grammar"
);
} else {
print "Unable to parse simple Parse::RecDescent code. ",
"Skipping installation of advanced features.";
$DO_BODYSTRUCTURE = 0;
}
}

View File

@ -0,0 +1 @@
MessageSet/MessageSet.pm

View File

@ -0,0 +1,21 @@
COPYRIGHT
Copyright 1999, 2000, 2001, 2002 , 2003 The Kernen Group, Inc.
All rights reserved.
This program is free software; you can redistribute it and/or modify it
under the terms of either:
a) the "Artistic License" which comes with this Kit, or
b) the GNU General Public License as published by the Free Software
Foundation; either version 1, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See either the GNU
General Public License or the Artistic License for more details. All your
base are belong to us.

View File

@ -0,0 +1,20 @@
#$Id: Makefile.PL,v 1.1 2002/10/23 20:45:54 dkernen Exp $
use ExtUtils::MakeMaker;
use Cwd;
# See lib/ExtUtils/MakeMaker.pm for details of how to influence
# the contents of the Makefile that is written.
WriteMakefile(
'NAME' => 'Mail::IMAPClient::MessageSet',
'VERSION_FROM' => '../IMAPClient.pm', # finds $VERSION
);
#History:
#$Log: Makefile.PL,v $
#Revision 1.1 2002/10/23 20:45:54 dkernen
#
#Modified Files: Changes IMAPClient.pm MANIFEST Makefile.PL
#Added Files: Makefile.PL MessageSet.pm
#
#

View File

@ -0,0 +1,416 @@
package Mail::IMAPClient::MessageSet;
#$Id: MessageSet.pm,v 1.3 2002/12/13 18:08:49 dkernen Exp $
=head1 NAME
Mail::IMAPClient::MessageSet -- an extension to Mail::IMAPClient that
expresses lists of message sequence numbers or message UID's in the shortest
way permissable by RFC2060.
=cut
sub str {
# print "Overloaded ", overload::StrVal(${$_[0]}),"\n";
return overload::StrVal(${$_[0]});
}
sub rem {
my $self = shift;
my $minus = ref($self)->new(@_);
my %deleted = map { $_ => 1 } @{$minus->unfold} ;
${$self} = $self->range(
map { exists $deleted{$_} ? () : $_ } @{$self->unfold}
);
return $self;
}
sub cat {
my $self = shift;
my @a = ("$self",@_);
${$self} = $self->range(@a);
return $self;
}
use overload qq/""/ => "str" ,
qq/.=/=>"cat",
qq/+=/=>"cat",
qq/-=/=>"rem",
q/@{}/=>"unfold",
fallback => "TRUE";
sub new {
my $class = shift;
my $range = $class->range(@_);
my $object = \$range;
bless $object, $class;
return $object ;
}
sub range {
my $class = shift;
if ( scalar(@_) == 1 and
ref($_[0]) =~ /Mail::IMAPClient::MessageSet/
) {
return $_[0] ;
}
my @msgs = ();
for my $m (@_) {
next if !defined($m) or $m eq "";
if ( ref($m) ) {
foreach my $mm (@$m) {
foreach my $c ( split(/,/,$mm) ) {
if ( $c =~ /:/ ) {
my($l,$h) = split(/:/,$c) ;
push @msgs,$l .. $h ;
} else {
push @msgs,$c;
}
}
}
} else {
#print STDERR "m=$m\n";
foreach my $c ( split(/,/,$m) ) {
if ( $c =~ /:/ ) {
my($l,$h) = split(/:/,$c) ;
push @msgs,$l .. $h ;
} else {
push @msgs,$c;
}
}
}
}
return undef unless @msgs;
my @range = ();
my $high = $low = "";
for my $m (sort {$a<=>$b} @msgs) {
$low = $m if $low eq "";
next if $high ne "" and $high == $m ; # been here, done this
if ( $high eq "" ) {
$high = $m ;
} elsif ( $m == $high + 1 ) {
$high = $m ;
} else {
push @range, $low == $high ? "$low," : "$low:$high," ;
$low = $m ;
$high = $m ;
}
}
push @range, $low == $high ? "$low" : "$low:$high" ;
my $range = join("",@range);
return $range;
}
sub unfold {
my $self = $_[0];
return wantarray ?
( map { my($l,$h)= split(/:/,$_) ; $h?($l..$h):$l }
split(/,/,$$self)
) :
[ map { my($l,$h)= split(/:/,$_) ; $h?($l..$h):$l }
split(/,/,$$self)
]
;
}
=head2 DESCRIPTION
The B<Mail::IMAPClient::MessageSet> module is designed to make life easier
for programmers who need to manipulate potentially large sets of IMAP
message UID's or sequence numbers.
This module presents an object-oriented interface into handling your message
sets. The object reference returned by the L<new> method is an overloaded
reference to a scalar variable that contains the message set's compact
RFC2060 representation. The object is overloaded so that using it like a string
returns this compact message set representation. You can also add messages to
the set (using either a '.=' operator or a '+=' operator) or remove messages
(with the '-=' operator). And if you use it as an array reference, it will
humor you and act like one by calling L<unfold> for you. (But you need perl 5.6
or above to do this.)
RFC2060 specifies that multiple messages can be provided to certain IMAP
commands by separating them with commas. For example, "1,2,3,4,5" would
specify messages 1, 2, 3, 4, and (you guessed it!) 5. However, if you are
performing an operation on lots of messages, this string can get quite long.
So long that it may slow down your transaction, and perhaps even cause the
server to reject it. So RFC2060 also permits you to specifiy a range of
messages, so that messages 1, 2, 3, 4 and 5 can also be specified as
"1:5".
This is where B<Mail::IMAPClient::MessageSet> comes in. It will convert your
message set into the shortest correct syntax. This could potentially save you
tons of network I/O, as in the case where you want to fetch the flags for
all messages in a 10000 message folder, where the messages are all numbered
sequentially. Delimited as commas, and making the best-case assumption that
the first message is message "1", it would take 48893 bytes to specify the
whole message set using the comma-delimited method. To specify it as a range,
it takes just seven bytes (1:10000).
=head2 SYNOPSIS
To illustrate, let's take the trivial example of a search that returns these
message uids: 1,3,4,5,6,9,10, as follows:
@msgs = $imap->search("SUBJECT","Virus"); # returns 1,3,4,5,6,9,10
my $msgset = Mail::IMAPClient::MessageSet->new(@msgs);
print "$msgset\n"; # prints "1,3:6,9:10\n"
# add message 14 to the set:
$msgset += 14;
print "$msgset\n"; # prints "1,3:6,9:10,14\n"
# add messages 16,17,18,19, and 20 to the set:
$msgset .= "16,17,18:20";
print "$msgset\n"; # prints "1,3:6,9:10,14,16:20\n"
# Hey, I didn't really want message 17 in there; let's take it out:
$msgset -= 17;
print "$msgset\n"; # prints "1,3:6,9:10,14,16,18:20\n"
# Now let's iterate over each message:
for my $msg (@$msgset) {
print "$msg\n";
} # Prints: "1\n3\n4\n5\n6\n9\n10\n14\n16\n18\n19\n20"
(Note that the L<Mail::IMAPClient> B<Range> method can be used as
a short-cut to specifying C<Mail::IMAPClient::MessageSet-E<gt>new(@etc)>.)
=cut
=head1 CLASS METHODS
The only class method you need to worry about is B<new>. And if you create
your B<Mail::IMAPClient::MessageSet> objects via L<Mail::IMAPClient>'s
B<Range> method then you don't even need to worry about B<new>.
=head2 new
Example:
my $msgset = Mail::IMAPClient::MessageSet->new(@msgs);
The B<new> method requires at least one argument. That argument can be
either a message, a comma-separated list of messages, a colon-separated
range of messages, or a combination of comma-separated messages and
colon-separated ranges. It can also be a reference to an array of messages,
comma-separated message lists, and colon separated ranges.
If more then one argument is supplied to B<new>, then those arguments should
be more message numbers, lists, and ranges (or references to arrays of them)
just as in the first argument.
The message numbers passed to B<new> can really be any kind of number at
all but to be useful in a L<Mail::IMAPClient> session they should be either
message UID's (if your I<Uid> parameter is true) or message sequence numbers.
The B<new> method will return a reference to a B<Mail::IMAPClient::MessageSet>
object. That object, when double quoted, will act just like a string whose
value is the message set expressed in the shortest possible way, with the
message numbers sorted in ascending order and with duplicates removed.
=head1 OBJECT METHODS
The only object method currently available to a B<Mail::IMAPClient::MessageSet>
object is the L<unfold> method.
=head2 unfold
Example:
my $msgset = $imap->Range( $imap->messages ) ;
my @all_messages = $msgset->unfold;
The B<unfold> method returns an array of messages that belong to the
message set. If called in a scalar context it returns a reference to the
array instead.
=head1 OVERRIDDEN OPERATIONS
B<Mail::IMAPClient::MessageSet> overrides a number of operators in order
to make manipulating your message sets easier. The overridden operations are:
=head2 stringify
Attempts to stringify a B<Mail::IMAPClient::MessageSet> object will result in
the compact message specification being returned, which is almost certainly
what you will want.
=head2 Auto-increment
Attempts to autoincrement a B<Mail::IMAPClient::MessageSet> object will
result in a message (or messages) being added to the object's message set.
Example:
$msgset += 34;
# Message #34 is now in the message set
=head2 Concatenate
Attempts to concatenate to a B<Mail::IMAPClient::MessageSet> object will
result in a message (or messages) being added to the object's message set.
Example:
$msgset .= "34,35,36,40:45";
# Messages 34,35,36,40,41,42,43,44,and 45 are now in the message set
The C<.=> operator and the C<+=> operator can be used interchangeably, but
as you can see by looking at the examples there are times when use of one
has an aesthetic advantage over use of the other.
=head2 Autodecrement
Attempts to autodecrement a B<Mail::IMAPClient::MessageSet> object will
result in a message being removed from the object's message set.
Examples:
$msgset -= 34;
# Message #34 is no longer in the message set
$msgset -= "1:10";
# Messages 1 through 10 are no longer in the message set
If you attempt to remove a message that was not in the original message set
then your resulting message set will be the same as the original, only more
expensive. However, if you attempt to remove several messages from the message
set and some of those messages were in the message set and some were not,
the additional overhead of checking for the messages that were not there
is negligable. In either case you get back the message set you want regardless
of whether it was already like that or not.
=cut
=head1 REPORTING BUGS
Please feel free to e-mail the author at C<bug-Mail-IMAPClient@rt.cpan.org>
if you encounter any strange behaviors. Don't worry about hurting my
feelings or sounding like a whiner or anything like that;
if there's a problem with this module you'll be doing me a favor by
reporting it. However, I probably won't be able to do much about it if
you don't include enough information, so please read and follow these
instructions carefully.
When reporting a bug, please be sure to include the following:
- As much information about your environment as possible. I especially
need to know B<which version of Mail::IMAPClient you are running> and the
B<type/version of IMAP server> to which you are connecting. Your OS and
perl verions would be helpful too.
- As detailed a description of the problem as possible. (What are you
doing? What happens? Have you found a work-around?)
- An example script that demonstrates the problem (preferably with as
few lines of code as possible!) and which calls the Mail::IMAPClient's
L<new> method with the L<Debug> parameter set to "1". (If this generates
a ridiculous amount of output and you're sure you know where the problem
is, you can create your object with debugging turned off and then
turn it on later, just before you issue the commands that recreate the
problem. On the other hand, if you can do this you can probably also
reduce the program rather than reducing the output, and this would be
the best way to go under most circumstances.)
- Output from the example script when it's running with the Debug
parameter turned on. You can edit the output to remove (or preferably
to "X" out) sensitive data, such as hostnames, user names, and
passwords, but PLEASE do not remove the text that identifies the TYPE
of IMAP server to which you are connecting. Note that in most versions
of B<Mail::IMAPClient>, debugging does not print out the user or
password from the login command line. However, if you use some other
means of authenticating then you may need to edit the debugging output
with an eye to security.
- If something worked in a previous release and doesn't work now,
please tell me which release did work. You don't have to test every
intervening release; just let me know it worked in version x but
doesn't work in version (x+n) or whatever.
- Don't be surprised if I come back asking for a trace of the problem.
To provide this, you should create a file called I<.perldb> in your
current working directory and include the following line of text in
that file:
C<&parse_options("NonStop=1 LineInfo=mail_imapclient_db.out");>
For your debugging convenience, a sample .perldb file, which was
randomly assigned the name F<sample.perldb>, is provided in the
distribution.
Next, without changing your working directory, debug the example script
like this: C<perl -d example_script.pl [ args ]>
Note that in these examples, the script that demonstrates your problem
is named "example_script.pl" and the trace output will be saved in
"mail_imapclient_db.out". You should either change these values to suit
your needs, or change your needs to suit these values.
Bug reports should be mailed to:
bug-Mail-IMAPClient@rt.cpan.org
Please remember to place a SHORT description of the problem in the subject
of the message. Please try to be a bit specific; things like "Bug
in Mail::IMAPClient" or "Computer Problem" won't exactly expedite things
on my end.
=head1 REPORTING THINGS THAT ARE NOT BUGS
If you have suggestions for extending this functionality of this module, or
if you have a question and you can't find an answer in any of the
documentation (including the RFC's, which are included in this distribution
for a reason), then you can e-mail me at the following address:
comment-Mail-IMAPClient@rt.cpan.org
Please note that this address is for questions, suggestions, and other comments
about B<Mail::IMAPClient>. It's not for reporting bugs, it's not for general
correspondence, and it's especially not for selling porn, mortgages, Viagra,
or anything else.
=head1 AUTHOR
David J. Kernen
The Kernen Consulting Group, Inc
DJKERNEN@cpan.org
=cut
=head1 COPYRIGHT
Copyright 1999, 2000, 2001, 2002 The Kernen Group, Inc.
All rights reserved.
This program is free software; you can redistribute it and/or modify it
under the terms of either:
=over 4
=item a) the "Artistic License" which comes with this Kit, or
=item b) the GNU General Public License as published by the Free Software
Foundation; either version 1, or (at your option) any later version.
=back
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See either the GNU
General Public License or the Artistic License for more details. All your
base are belong to us.
=cut
my $not_void = 11; # This module goes all the way up to 11!
# History:
# $Log: MessageSet.pm,v $
# Revision 1.3 2002/12/13 18:08:49 dkernen
# Made changes for version 2.2.6 (see Changes file for more info)
#
# Revision 1.2 2002/11/08 15:48:42 dkernen
#
# Modified Files: Changes
# IMAPClient.pm
# Modified Files: MessageSet.pm
#
# Revision 1.1 2002/10/23 20:45:55 dkernen
#
# Modified Files: Changes IMAPClient.pm MANIFEST Makefile.PL
# Added Files: Makefile.PL MessageSet.pm
#
#

View File

@ -0,0 +1,84 @@
#!/usr/local/bin/perl
#$Id: range.t,v 1.2 2003/06/12 21:42:17 dkernen Exp $
END {print "not ok 1\n" unless $main::loaded;}
use Mail::IMAPClient::MessageSet;
BEGIN {
$| = 1;
print "1..7\n";
$main::loaded = 1;
print "ok 1\n";
}
my $one = q/1:4,3:6,10:15,20:25,2:8/;
my $range = Mail::IMAPClient::MessageSet->new($one);
if ( "$range" eq "1:8,10:15,20:25" ) {
print "ok 2\n";
} else {
print "not ok 2 ($range)\n";
}
if ( join(",",$range->unfold) eq
"1,2,3,4,5,6,7,8,10,11,12,13,14,15,20,21,22,23,24,25"
) {
print "ok 3\n";
} else {
print "not ok 3 (",join("",$range->unfold),")\n";
}
$range .= "30,31,32,31:34,40:44";
if ( "$range" eq "1:8,10:15,20:25,30:34,40:44" ) {
print "ok 4\n";
} else {
print "not ok 4 ($range)\n";
}
if ( join(",",$range->unfold) eq
"1,2,3,4,5,6,7,8,10,11,12,13,14,15,20,21,22,23,24,25," .
"30,31,32,33,34,40,41,42,43,44"
) {
print "ok 5\n";
} else {
print "not ok 5 (",join("",$range->unfold),")\n";
}
$range -= "1:2";
if ( "$range" eq "3:8,10:15,20:25,30:34,40:44" ) {
print "ok 6\n";
} else {
print "not ok 6 ($range)\n";
}
if ( join(",",$range->unfold) eq
"3,4,5,6,7,8,10,11,12,13,14,15,20,21,22,23,24,25," .
"30,31,32,33,34,40,41,42,43,44"
) {
print "ok 7\n";
} else {
print "not ok 7 (",join("",$range->unfold),")\n";
}
exit;
# History:
# $Log: range.t,v $
# Revision 1.2 2003/06/12 21:42:17 dkernen
# Cleaning up cvs repository
#
# Revision 1.1 2003/06/12 21:37:24 dkernen
#
# Preparing 2.2.8
# Added Files: COPYRIGHT
# Modified Files: Parse.grammar
# Added Files: Makefile.old
# Makefile.PL Todo sample.perldb
# BodyStructure.pm
# Parse.grammar Parse.pod
# range.t
#
# Revision 1.1 2002/10/23 20:46:00 dkernen
#
# Modified Files: Changes IMAPClient.pm MANIFEST Makefile.PL
# Added Files: Makefile.PL MessageSet.pm
# Added Files: range.t
#
#

View File

@ -0,0 +1,150 @@
Mail::IMAPClient
COPYRIGHT
Copyright 1999, 2000 The Kernen Group, Inc.
All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of either:
a) the "Artistic License" which comes with this Kit, or
b) the GNU General Public License as published by the Free Software
Foundation; either versio n 1, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See either
the GNU General Public License or the Artistic License for more details.
DESCRIPTION
This module provides perl routines that simplify a sockets connection
to and an IMAP conversation with an IMAP server.
COMPATIBILITY
This module was developed on Solaris 2.5.1 and 2.6 against Netscape IMAP
servers versions 3.6 and 4.1. However, since it is written in perl and
designed for flexibility, it should run on any OS with a TCP/IP stack and
a version of perl that includes the Socket and IO::Socket modules. It also
should be able to talk to any IMAP server, even those that have, um,
proprietary features (assuming that the programmer knows what those features
are).
To date, I know that the test suite runs successfully with the following IMAP
servers:
-Netscape Messenging Server v4.x
-Netscape Messenging Server v3.x
-UW-IMAP (I think it was 4.5)
-Cyrus IMAP4 v1.5.19
-Mirapoint Message Server Appliances (OS versions 1.6.1, 1.7.1, and 2.0.2)
I also know that it has some problems running against the InterMail server vM.4.001.02.00
(and probably other versions of InterMail as well).
Version 2.0.3 has been tested with the mdaemon server with mixed results. It seems that mdaemon
does not comply strictly with RFC2060 and so you may have problems using this module
with mdaemon, especially with folder names with embedded spaces or embedded double quotes. You may
be able to get some simple tasks to work but you won't be able to run the test suite successfully.
Use with caution.
If your server requires the use of the AUTHENTICATE IMAP client command (say,
for strong authentication) then you can still use this module, provided you can come
up with the appropriate responses to any challenges offered by your server. Mark Bush's
Authen::NTLM module can assist with this if you specifically are interested in NTLM
authentication.
DEPENDENCIES
The Mail::IMAPClient module uses the IO::Socket module to make a socket
connection to an IMAP server and the Socket module to get some constants.
It also uses Errno, Fcntl (for faster I/O) and IO::Select, IO::File,
Data::Dumper, and Carp.
You can verify that your system has a sufficient perl installation by
entering on the command line:
perl -e "use constant; use Socket; use IO::Socket; use IO::File; use IO::Select; use Fcntl; \
use Errno; use Carp; use Data::Dumper;"
If you get compile errors then you'll have trouble using Mail::IMAPClient.
If you need to use the bodystructure helper module Mail::IMAPClient::BodyStructure then you also need
Parse::RecDescent. Try this on the command line:
perl -e "use Parse::RecDescent;"
If you get compile errors then you will not be able to use the
Mail::IMAPClient::BodyStructure module (or the get_bodystructure
method in Mail::IMAPClient). You will also get errors when you run
'make test' in t/bodystructure and/or t/parse. If these tests fail
you can still use Mail::IMAPClient safely (assuming the other tests passed!) but
you will not be able to use Mail::IMAPClient::BodyStructure or the
get_bodystructure method in Mail::IMAPClient.
(Note that as of version 2.2.0 the above is somewhat obsolete, since Makefile.PL
will detect whether or not you have Parse::RecDescent and will either choose to
or decline to install the ::BodyStructure stuff accordingly.)
REPORING BUGS
See the section on "REPORTING BUGS" in the module's documentation if you are having
problems.
YOU MUST FOLLOW THE INSTRUCTIONS IN THE DOCUMENTATION AND PROVIDE ALL OF THE NECESSARY
INFORMATION if you expect a response from your bug report. You should also look at
the data you gather before you send it, since doing so will often solve your problem.
INSTALLATION
Generally, gunzipping and untarring the source file, running 'perl Makefile.PL'
and 'make install' are all it takes to install this module. And if that's too
much work you can always use the CPAN module! ;-)
OVERVIEW OF FUNCTIONALITY
Mail::IMAPClient.pm provides methods to simplify the connection to and the
conversation between a perl script and an IMAP server. Virtually all IMAP Client
commands (as defined in rfc2060) are supported, either through IMAPClient object
methods or the 'default method', which is an AUTOLOAD hack that assumes a
default syntax for IMAP Client commands of:
tagvalue COMMAND [Arg1 [Arg2 [... Arg3]]]"
By remarkable coincidence, AUTOLOAD's default syntax mimics the general syntax
of IMAP Client commands. This means that if a script tries to use any undefined
method then that method will be interpreted as an unimplemented IMAP command,
and the default syntax will be used to create the command string. I did this
as a short cut to writing a bunch of methods that were practically the same.
There are inheritance implications because of this approach but as far as I
can tell this is not a serious limitation. However, if you decide to write
modules that inherit from this class that require AUTOLOAD logic of their
own then you will have to take the Mail::IMAPClient's AUTOLOAD strategy into
account.
Where methods are defined, they usually exist to add functionality, perhaps by
massaging output or by supplying default arguments. An example is the search
method, which accepts the same arguments as the SEARCH IMAP Client command (as
documented in RFC2060) but which massages the results so that the return value
is an array of message sequence numbers matching the search criteria, rather
than a line of text listing the sequence numbers.
Some methods exists solely to add functionality, such as the folders method,
which invokes the list method but then massages the results to produce an array
containing all folder names. The message_count and delete_messsage methods are
similarly examples of methods that add function to "raw" IMAP Client commands.
Further information is provided in the module's documentation, which you are
encouraged to read and enjoy.
Good Luck!
Dave Kernen
The Kernen Group, Inc.
DJKERNEN@cpan.org

View File

@ -0,0 +1,21 @@
COPYRIGHT
Copyright 1999, 2000, 2001, 2002 , 2003 The Kernen Group, Inc.
All rights reserved.
This program is free software; you can redistribute it and/or modify it
under the terms of either:
a) the "Artistic License" which comes with this Kit, or
b) the GNU General Public License as published by the Free Software
Foundation; either version 1, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See either the GNU
General Public License or the Artistic License for more details. All your
base are belong to us.

View File

@ -0,0 +1,45 @@
use ExtUtils::MakeMaker;
use Parse::RecDescent;
unlink './Thread.pm' if -f './Thread.pm';
sub MY::top_targets {
package MY;
my $inherit = shift->SUPER::top_targets(@_);
my @inherit = split("\n",$inherit);
for (@inherit) {
if ( /^\s*all\s*:{1,2}/ ) {
s/(all\s*:{1,2}\s*)/$1Thread\.pm /;
}
}
return join("\n",@inherit);
}
sub MY::clean {
package MY;
my $inherit = shift->SUPER::clean(@_);
return join("\n",$inherit," rm Thread.pm") ;
}
sub MY::postamble {
my $string =
'@$(PERL) "-MParse::RecDescent" "-" ' .
'"Thread.grammar" '.
'"Mail::IMAPClient::Thread"' ;
return "Thread.pm: Thread.grammar\n\t$string\n\n";
}
# See lib/ExtUtils/MakeMaker.pm for details of how to influence
# the contents of the Makefile that is written.
#print "",MY->top_target;
WriteMakefile(
'NAME' => 'Mail::IMAPClient::Thread',
'VERSION_FROM' => '../IMAPClient.pm',
'PREREQ_PM' => {"Parse::RecDescent" => 0 },
'PM' => {
'Thread.pm' =>
'$(INST_LIBDIR)/Thread.pm'
},
);

View File

@ -16,3 +16,4 @@ thread: "(" threadmember(s) ")"
start: /^\* THREAD /i thread(s?) {
$return=$item{'thread(s?)'}||undef;
}

View File

@ -0,0 +1,19 @@
# Atoms:
NUMBER: /\d+/
# Rules:
threadmember: NUMBER { $return = $item{NUMBER} ; } |
thread { $return = $item{thread} ; }
thread: "(" threadmember(s) ")"
{
$return = $item{threadmember}||undef;
}
# Start:
start: /^\* THREAD /i thread(s?) {
$return=$item{thread}||undef;
}

View File

@ -0,0 +1,70 @@
# Before `make install' is performed this script should be runnable with
# `make test'. After `make install' it should work as `perl test.pl'
# $Id: thread.t,v 1.1 2002/08/30 20:50:43 dkernen Exp $
######################### We start with some black magic to print on failure.
# Change 1..1 below to 1..last_test_to_print .
use Mail::IMAPClient::Thread;
BEGIN {
print "1..6\n";
$main::loaded = 1;
$| = 1;
print "ok 1\n";
}
$t1 = <<'e1';
* THREAD (166)(167)(168)(169)(172)(170)(171)(173)(174 175 176 178 181 180)(179)(177 183 182 188 184 185 186 187 189)(190)(191)(192)(193)(194 195)(196 197 198)(199)(200 202)(201)(203)(204)(205)(206 207)(208)
e1
$t2 = <<'e2';
* THREAD (166)(167)(168)(169)(172)((170)(179))(171)(173)((174)(175)(176)(178)(181)(180))((177)(183)(182)(188 (184)(189))(185 186)(187))(190)(191)(192)(193)((194)(195 196))(197 198)(199)(200 202)(201)(203)(204)(205 206 207)(208)
e2
my $parser = Mail::IMAPClient::Thread->new;
if ( $parser ) {
print "ok 2\n";
} else {
print "not ok 2\n";
}
my $thr1 = $parser->start($t1) ;
if ( $thr1 ) {
print "ok 3\n";
} else {
print "not ok 3\n";
}
if ( scalar(@$thr1) == 25 ) {
print "ok 4\n";
} else {
print "not ok 4\n";
}
my $thr2 = $parser->start($t2) ;
if ( $thr2 ) {
print "ok 5\n";
} else {
print "not ok 5\n";
}
if ( scalar(@$thr2) == 23 ) {
print "ok 6\n";
} else {
print "not ok 6\n";
}
END {print "not ok 1\n" unless $main::loaded;}
# History:
# $Log: thread.t,v $
# Revision 1.1 2002/08/30 20:50:43 dkernen
#
# Added Files: Thread/Makefile.PL Thread/Thread.grammar Thread/Thread.pod
# Added Files: Thread/t/thread.t
#
#

View File

@ -0,0 +1,44 @@
The following is a list of some items that I hope to include in a future
release:
- Support for threaded perl programs (still pending as of version 2.2.0.).
-Support for imaps (Imap via SSL). I don't have any way to test this right now
but if you get this to work or know someone who has I'd be really interested in
hearing from you.
- Support for more authentication mechanisms. Currently plain authentication and
cram-md5 authentication are supported. I have DIGEST-MD5 working at the AUTH
qop, but haven't incorporated it into a released version because I'm still trying
to get at least the integrity qop working, and maybe even privacy, but considering
how much trouble I'm having with just the integrity level I wouldn't hold my breath
if I were you ;-).
- Currently a number of IMAP Client commands are implemented using the
'default method', which is an AUTOLOAD hack. I'd like to reduce that if
possible to a bare minimum. (Some are still pending as of version 2.2.7.)
- I'd like to see this module certified for more OS's and more IMAP servers.
This is (hopefully) just a matter of testing; the code should already be
compatible with the IMAP servers that are out there and with any OS that
allows the IO::Socket module to work. ** A number of platforms have been added
to the list of tested platforms since this was first written. Please contact
DJKernen@cpan.org if you have any to add.
- Support for newer/older/other versions of IMAP. Currently only RFC2060 is
explicitly supported, although thanks to the 'default method' (implemented
via an AUTOLOAD hack) virtually any IMAP command is supported, even
proprietary commands, X- extensions, and so forth. But not necessarily other
authentication mechanisms... :-( (NOTE: the AUTHENTICATE method
partially addresses this issue.)
- Support for piping output from (some?) imap commands directly to a
thingy of some sort (perhaps a coderef, a filehandle, or both).
- Your thingy here!!! Send me your request, and I'll do it in the order of
( $popularity/$difficulty ).
- Support for perl version 6. This will probably involve a rewrite that will make
portions of the Mail::IMAPClient module look more like the Mail::IMAPClient::BodyStructure
module. (Perl 6 will have built-in support for semantics that look remarkably like
Damian Conway's Parse::RecDescent module, which will solve a lot of problems for me.)

View File

@ -0,0 +1,21 @@
COPYRIGHT
Copyright 1999, 2000, 2001, 2002 , 2003 The Kernen Group, Inc.
All rights reserved.
This program is free software; you can redistribute it and/or modify it
under the terms of either:
a) the "Artistic License" which comes with this Kit, or
b) the GNU General Public License as published by the Free Software
Foundation; either version 1, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See either the GNU
General Public License or the Artistic License for more details. All your
base are belong to us.

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,564 @@
IMAP Extensions Working Group M. Crispin
INTERNET-DRAFT: IMAP SORT K. Murchison
Document: internet-drafts/draft-ietf-imapext-sort-06.txt December 2000
INTERNET MESSAGE ACCESS PROTOCOL - SORT EXTENSION
Status of this Memo
This document is an Internet-Draft and is in full conformance with
all provisions of Section 10 of RFC 2026.
Internet-Drafts are working documents of the Internet Engineering
Task Force (IETF), its areas, and its working groups. Note that
other groups may also distribute working documents as
Internet-Drafts.
Internet-Drafts are draft documents valid for a maximum of six months
and may be updated, replaced, or obsoleted by other documents at any
time. It is inappropriate to use Internet-Drafts as reference
material or to cite them other than as "work in progress."
The list of current Internet-Drafts can be accessed at
http://www.ietf.org/ietf/1id-abstracts.txt
To view the list Internet-Draft Shadow Directories, see
http://www.ietf.org/shadow.html.
A revised version of this document will be submitted to the RFC
editor as an Informational Document for the Internet Community.
A revised version of this draft document, describing an expanded
version of this protocol extension, will be submitted to the RFC
editor as a Proposed Standard for the Internet Community.
Discussion and suggestions for improvement are requested, and should
be sent to ietf-imapext@IMC.ORG. This document will expire before 29
June 2001. Distribution of this memo is unlimited.
Abstract
This document describes an experimental server-based sorting
extension to the IMAP4rev1 protocol, as implemented by the University
of Washington's IMAP toolkit. This extension provides substantial
performance improvements for IMAP clients which offer sorted views.
A server which supports this extension indicates this with a
Crispin [Page 1]
INTERNET DRAFT IMAP SORT EXPIRES 29 June 2000
capability name of "SORT". Client implementations SHOULD accept any
capability name which begins with "SORT" as indicating support for
the extension described in this document. This provides for future
upwards-compatible extensions.
At the time of this document was written, the IMAP Extensions Working
Group (IETF-IMAPEXT) was considering upwards-compatible additions to
the SORT extension described in this document, tentatively called the
SORT2 extension.
Crispin [Page 2]
INTERNET DRAFT IMAP SORT EXPIRES 29 June 2000
Extracted Subject Text
The "SUBJECT" SORT criteria uses a version of the subject which has
specific subject artifacts of deployed Internet mail software
removed. Due to the complexity of these artifacts, the formal syntax
for the subject extraction rules is ambiguous. The following
procedure is followed to determine the actual "base subject" which is
used to sort by subject:
(1) Convert any RFC 2047 encoded-words in the subject to
UTF-8. Convert all tabs and continuations to space.
Convert all multiple spaces to a single space.
(2) Remove all trailing text of the subject that matches
the subj-trailer ABNF, repeat until no more matches are
possible.
(3) Remove all prefix text of the subject that matches the
subj-leader ABNF.
(4) If there is prefix text of the subject that matches the
subj-blob ABNF, and removing that prefix leaves a non-empty
subj-base, then remove the prefix text.
(5) Repeat (3) and (4) until no matches remain.
Note: it is possible to defer step (2) until step (6), but this
requires checking for subj-trailer in step (4).
(6) If the resulting text begins with the subj-fwd-hdr ABNF
and ends with the subj-fwd-trl ABNF, remove the
subj-fwd-hdr and subj-fwd-trl and repeat from step (2).
(7) The resulting text is the "base subject" used in the
SORT.
All servers and disconnected clients MUST use exactly this algorithm
when sorting by subject. Otherwise there is potential for a user to
get inconsistent results based on whether they are running in
connected or disconnected IMAP mode.
Crispin [Page 3]
INTERNET DRAFT IMAP SORT EXPIRES 29 June 2000
Additional Commands
This command is an extension to the IMAP4rev1 base protocol.
The section header is intended to correspond with where it would be
located in the main document if it was part of the base
specification.
6.3.SORT. SORT Command
Arguments: sort program
charset specification
searching criteria (one or more)
Data: untagged responses: SORT
Result: OK - sort completed
NO - sort error: can't sort that charset or
criteria
BAD - command unknown or arguments invalid
The SORT command is a variant of SEARCH with sorting semantics for
the results. Sort has two arguments before the searching criteria
argument; a parenthesized list of sort criteria, and the searching
charset.
Note that unlike SEARCH, the searching charset argument is
mandatory. The US-ASCII and UTF-8 charsets MUST be implemented.
All other charsets are optional.
There is also a UID SORT command which corresponds to SORT the way
that UID SEARCH corresponds to SEARCH.
The SORT command first searches the mailbox for messages that
match the given searching criteria using the charset argument for
the interpretation of strings in the searching criteria. It then
returns the matching messages in an untagged SORT response, sorted
according to one or more sort criteria.
If two or more messages exactly match according to the sorting
criteria, these messages are sorted according to the order in
which they appear in the mailbox. In other words, there is an
implicit sort criterion of "sequence number".
When multiple sort criteria are specified, the result is sorted in
the priority order that the criteria appear. For example,
(SUBJECT DATE) will sort messages in order by their subject text;
Crispin [Page 4]
INTERNET DRAFT IMAP SORT EXPIRES 29 June 2000
and for messages with the same subject text will sort by their
sent date.
Untagged EXPUNGE responses are not permitted while the server is
responding to a SORT command, but are permitted during a UID SORT
command.
The defined sort criteria are as follows. Refer to the Formal
Syntax section for the precise syntactic definitions of the
arguments. If the associated RFC-822 header for a particular
criterion is absent, it is treated as the empty string. The empty
string always collates before non-empty strings.
ARRIVAL
Internal date and time of the message. This differs from the
ON criteria in SEARCH, which uses just the internal date.
CC
RFC-822 local-part of the first "cc" address.
DATE
Sent date and time from the Date: header, adjusted by time
zone. This differs from the SENTON criteria in SEARCH, which
uses just the date and not the time, nor adjusts by time zone.
FROM
RFC-822 local-part of the "From" address.
REVERSE
Followed by another sort criterion, has the effect of that
criterion but in reverse order.
Note: REVERSE only reverses a single criterion, and does not
affect the implicit "sequence number" sort criterion if all
other criteria are identicial. Consequently, a sort of
REVERSE SUBJECT is not the same as a reverse ordering of a
SUBJECT sort.
This can be avoided by use of additional criteria, e.g.
SUBJECT DATE vs. REVERSE SUBJECT REVERSE DATE. In general,
however, it's better (and faster, if the client has a
"reverse current ordering" command) to reverse the results
in the client instead of issuing a new SORT.
SIZE
Size of the message in octets.
SUBJECT
Extracted subject text.
Crispin [Page 5]
INTERNET DRAFT IMAP SORT EXPIRES 29 June 2000
TO
RFC-822 local-part of the first "To" address.
Example: C: A282 SORT (SUBJECT) UTF-8 SINCE 1-Feb-1994
S: * SORT 2 84 882
S: A282 OK SORT completed
C: A283 SORT (SUBJECT REVERSE DATE) UTF-8 ALL
S: * SORT 5 3 4 1 2
S: A283 OK SORT completed
C: A284 SORT (SUBJECT) US-ASCII TEXT "not in mailbox"
S: * SORT
S: A284 OK SORT completed
Crispin [Page 6]
INTERNET DRAFT IMAP SORT EXPIRES 29 June 2000
Additional Responses
This response is an extension to the IMAP4rev1 base protocol.
The section heading of this response is intended to correspond with
where it would be located in the main document.
7.2.SORT. SORT Response
Data: zero or more numbers
The SORT response occurs as a result of a SORT or UID SORT
command. The number(s) refer to those messages that match the
search criteria. For SORT, these are message sequence numbers;
for UID SORT, these are unique identifiers. Each number is
delimited by a space.
Example: S: * SORT 2 3 6
Crispin [Page 7]
INTERNET DRAFT IMAP SORT EXPIRES 29 June 2000
Formal Syntax of SORT commands and Responses
sort-data = "SORT" *(SP nz-number)
sort = ["UID" SP] "SORT" SP
"(" sort-criterion *(SP sort-criterion) ")"
SP search_charset 1*(SP search_key)
sort-criterion = ["REVERSE" SP] sort-key
sort-key = "ARRIVAL" / "CC" / "DATE" / "FROM" / "SIZE" /
"SUBJECT" / "TO"
The following syntax describes subject extraction rules (2)-(6):
subject = *subj-leader [subj-middle] *subj-trailer
subj-refwd = ("re" / ("fw" ["d"])) *WSP [subj-blob] ":"
subj-blob = "[" *BLOBCHAR "]" *WSP
subj-fwd = subj-fwd-hdr subject subj-fwd-trl
subj-fwd-hdr = "[fwd:"
subj-fwd-trl = "]"
subj-leader = (*subj-blob subj-refwd) / WSP
subj-middle = *subj-blob (subj-base / subj-fwd)
; last subj-blob is subj-base if subj-base would
; otherwise be empty
subj-trailer = "(fwd)" / WSP
subj-base = NONWSP *([*WSP] NONWSP)
; can be a subj-blob
BLOBCHAR = %x01-5a / %x5c / %x5e-7f
; any CHAR except '[' and ']'
NONWSP = %x01-08 / %x0a-1f / %x21-7f
; any CHAR other than WSP
Crispin [Page 8]
INTERNET DRAFT IMAP SORT EXPIRES 29 June 2000
Security Considerations
Security issues are not discussed in this memo.
Internationalization Considerations
By default, strings are sorted according to the "minimum sorting
collation algorithm". All implementations of SORT MUST implement the
minimum sorting collation algorithm.
In the minimum sorting collation algorithm, the Basic Latin
alphabetics (U+0041 to U+005A uppercase, U+0061 to U+007A lowercase)
are sorted in a case-insensitive fashion; that is, "A" (U+0041) and
"a" (U+0061) are treated as exact equals. The characters U+005B to
U+0060 are sorted after the Basic Latin alphabetics; for example,
U+005E is sorted after U+005A and U+007A. All other characters are
sorted according to their octet values, as expressed in UTF-8. No
attempt is made to treat composed characters specially, or to do
case-insensitive comparisons of composed characters.
Note: this means, among other things, that the composed
characters in the Latin-1 Supplement are not compared in
what would be considered an ISO 8859-1 "case-insensitive"
fashion. Case comparison rules for characters with
diacriticals differ between languages; the minimum sorting
collation does not attempt to deal with this at all. This
is reserved for other sorting collations, which may be
language-specific.
Other sorting collations, and the ability to change the sorting
collation, will be defined in a separate document dealing with IMAP
internationalization.
It is anticipated that there will be a generic Unicode sorting
collation, which will provide generic case-insensitivity for
alphabetic scripts, specification of composed character handling, and
language-specific sorting collations. A server which implements
non-default sorting collations will modify its sorting behavior
according to the selected sorting collation.
Non-English translations of "Re" or "Fw"/"Fwd" are not specified for
removal in the extracted subject text process. By specifying that
only the English forms of the prefixes are used, it becomes a simple
display time task to localize the prefix language for the user. If,
on the other hand, prefixes in multiple languages are permitted, the
result is a geometrically complex, and ultimately unimplementable,
task. In order to improve the ability to support non-English display
Crispin [Page 9]
INTERNET DRAFT IMAP SORT EXPIRES 29 June 2000
in Internet mail clients, only the English form of these prefixes
should be transmitted in Internet mail messages.
Author's Address
Mark R. Crispin
Networks and Distributed Computing
University of Washington
4545 15th Avenue NE
Seattle, WA 98105-4527
Phone: (206) 543-5762
EMail: MRC@CAC.Washington.EDU
Kenneth Murchison
Oceana Matrix Ltd.
21 Princeton Place
Orchard Park, NY 14127
Phone: (716) 662-8973 x26
EMail: ken@oceana.com
Crispin [Page 10]

View File

@ -0,0 +1,788 @@
IMAP Extensions Working Group M. Crispin
Internet Draft: IMAP THREAD K. Murchison
Document: internet-drafts/draft-ietf-imapext-thread-11.txt June 2002
INTERNET MESSAGE ACCESS PROTOCOL - THREAD EXTENSION
Status of this Memo
This document is an Internet-Draft and is in full conformance with
all provisions of Section 10 of RFC 2026.
Internet-Drafts are working documents of the Internet Engineering
Task Force (IETF), its areas, and its working groups. Note that
other groups may also distribute working documents as Internet-
Drafts.
Internet-Drafts are draft documents valid for a maximum of six months
and may be updated, replaced, or obsoleted by other documents at any
time. It is inappropriate to use Internet-Drafts as reference
material or to cite them other than as "work in progress."
The list of current Internet-Drafts can be accessed at
http://www.ietf.org/ietf/1id-abstracts.txt
To view the list Internet-Draft Shadow Directories, see
http://www.ietf.org/shadow.html.
A revised version of this draft document will be submitted to the RFC
editor as a Proposed Standard for the Internet Community. Discussion
and suggestions for improvement are requested, and should be sent to
ietf-imapext@IMC.ORG. This document will expire before 22 December
2002. Distribution of this memo is unlimited.
Abstract
This document describes the server-based threading extension to the
IMAP4rev1 protocol. This extension provides substantial performance
improvements for IMAP clients which offer threaded views.
A server which supports this extension indicates this with one or
more capability names consisting of "THREAD=" followed by a supported
threading algorithm name as described in this document. This
provides for future upwards-compatible extensions.
Crispin and Murchison [Page 1]
INTERNET DRAFT IMAP THREAD EXPIRES 22 December 2002
Base Subject Text
Threading uses the "base subject," which has specific subject
artifacts of deployed Internet mail software removed. Due to the
complexity of these artifacts, the formal syntax for the subject
extraction rules is ambiguous. The following procedure is followed
to determine the actual "base subject" which is used to thread:
(1) Convert any RFC 2047 encoded-words in the subject to
UTF-8. Convert all tabs and continuations to space.
Convert all multiple spaces to a single space.
(2) Remove all trailing text of the subject that matches
the subj-trailer ABNF, repeat until no more matches are
possible.
(3) Remove all prefix text of the subject that matches the
subj-leader ABNF.
(4) If there is prefix text of the subject that matches the
subj-blob ABNF, and removing that prefix leaves a non-empty
subj-base, then remove the prefix text.
(5) Repeat (3) and (4) until no matches remain.
Note: it is possible to defer step (2) until step (6),
but this requires checking for subj-trailer in step (4).
(6) If the resulting text begins with the subj-fwd-hdr ABNF
and ends with the subj-fwd-trl ABNF, remove the
subj-fwd-hdr and subj-fwd-trl and repeat from step (2).
(7) The resulting text is the "base subject" used in
threading.
All servers and disconnected clients MUST use exactly this algorithm
when threading. Otherwise there is potential for a user to get
inconsistent results based on whether they are running in connected
or disconnected IMAP mode.
Sent Date
As used in this document, the term "sent date" refers to the date and
time from the Date: header, adjusted by time zone. This differs from
date-related criteria in SEARCH, which use just the date and not the
time, nor adjusts by time zone.
Crispin and Murchison [Page 2]
INTERNET DRAFT IMAP THREAD EXPIRES 22 December 2002
Additional Commands
This command is an extension to the IMAP4rev1 base protocol.
The section header is intended to correspond with where it would be
located in the main document if it was part of the base
specification.
6.3.THREAD. THREAD Command
Arguments: threading algorithm
charset specification
searching criteria (one or more)
Data: untagged responses: THREAD
Result: OK - thread completed
NO - thread error: can't thread that charset or
criteria
BAD - command unknown or arguments invalid
The THREAD command is a variant of SEARCH with threading semantics
for the results. Thread has two arguments before the searching
criteria argument; a threading algorithm, and the searching
charset. Note that unlike SEARCH, the searching charset argument
is mandatory.
There is also a UID THREAD command which corresponds to THREAD the
way that UID SEARCH corresponds to SEARCH.
The THREAD command first searches the mailbox for messages that
match the given searching criteria using the charset argument for
the interpretation of strings in the searching criteria. It then
returns the matching messages in an untagged THREAD response,
threaded according to the specified threading algorithm.
Sorting is in ascending order. Earlier dates sort before later
dates; smaller sizes sort before larger sizes; and strings are
sorted according to ascending values established by their
collation algorithm (see under "Internationalization
Considerations").
Crispin and Murchison [Page 3]
INTERNET DRAFT IMAP THREAD EXPIRES 22 December 2002
The defined threading algorithms are as follows:
ORDEREDSUBJECT
The ORDEREDSUBJECT threading algorithm is also referred to as
"poor man's threading." The searched messages are sorted by
base subject and then by the sent date. The messages are then
split into separate threads, with each thread containing
messages with the same base subject text. Finally, the threads
are sorted by the sent date of the first message in the thread.
Note that each message in a thread is a child (as opposed to a
sibling) of the previous message.
REFERENCES
The REFERENCES threading algorithm is based on the algorithm
written by Jamie Zawinski which was used in "Netscape Mail and
News" versions 2.0 through 3.0. For details, see
http://www.jwz.org/doc/threading.html.
This algorithm threads the searched messages by grouping them
together in parent/child relationships based on which messages
are replies to others. The parent/child relationships are
built using two methods: reconstructing a message's ancestry
using the references contained within it; and checking the
original (not base) subject of a message to see if it is a
reply to (or forward of) another message.
Note: "Message ID" in the following description refers to a
normalized form of the msg-id in [RFC 2822]. The actual
text in an RFC 2822 may use quoting, resulting in multiple
ways of expressing the same Message ID. Implementations of
the REFERENCES threading algorithm MUST normalize any msg-id
in order to avoid false non-matches due to differences in
quoting.
For example, the msg-id
<"01KF8JCEOCBS0045PS"@xxx.yyy.com>
and the msg-id
<01KF8JCEOCBS0045PS@xxx.yyy.com>
MUST be interpreted as being the same Message ID.
The references used for reconstructing a message's ancestry are
found using the following rules:
If a message contains a [NEWS]-style References header line,
then use the Message IDs in the References header line as
the references.
Crispin and Murchison [Page 4]
INTERNET DRAFT IMAP THREAD EXPIRES 22 December 2002
If a message does not contain a References header line, or
the References header line does not contain any valid
Message IDs, then use the first (if any) valid Message ID
found in the In-Reply-To header line as the only reference
(parent) for this message.
Note: Although [RFC 2822] permits multiple Message IDs in
the In-Reply-To header, in actual practice this
discipline has not been followed. For example,
In-Reply-To headers have been observed with email
addresses after the Message ID, and there are no good
heuristics for software to determine the difference.
This is not a problem with the References header however.
If a message does not contain an In-Reply-To header line, or
the In-Reply-To header line does not contain a valid Message
ID, then the message does not have any references (NIL).
A message is considered to be a reply or forward if the base
subject extraction rules, applied to the original subject,
remove any of the following: a subj-refwd, a "(fwd)"
subj-trailer, or a subj-fwd-hdr and subj-fwd-trl.
The REFERENCES algorithm is significantly more complex than
ORDEREDSUBJECT and consists of six main steps. These steps are
outlined in detail below.
(1) For each searched message:
(A) Using the Message IDs in the message's references, link
the corresponding messages (those whose Message-ID header
line contains the given reference Message ID) together as
parent/child. Make the first reference the parent of the
second (and the second a child of the first), the second the
parent of the third (and the third a child of the second),
etc. The following rules govern the creation of these
links:
If a message does not contain a Message-ID header line,
or the Message-ID header line does not contain a valid
Message ID, then assign a unique Message ID to this
message.
If two or more messages have the same Message ID, assign
a unique Message ID to each of the duplicates.
If no message can be found with a given Message ID,
create a dummy message with this ID. Use this dummy
Crispin and Murchison [Page 5]
INTERNET DRAFT IMAP THREAD EXPIRES 22 December 2002
message for all subsequent references to this ID.
If a message already has a parent, don't change the
existing link. This is done because the References
header line may have been truncated by a MUA. As a
result, there is no guarantee that the messages
corresponding to adjacent Message IDs in the References
header line are parent and child.
Do not create a parent/child link if creating that link
would introduce a loop. For example, before making
message A the parent of B, make sure that A is not a
descendent of B.
Note: Message ID comparisons are case-sensitive.
(B) Create a parent/child link between the last reference
(or NIL if there are no references) and the current message.
If the current message already has a parent, it is probably
the result of a truncated References header line, so break
the current parent/child link before creating the new
correct one. As in step 1.A, do not create the parent/child
link if creating that link would introduce a loop. Note
that if this message has no references, that it will now
have no parent.
Note: The parent/child links created in steps 1.A and 1.B
MUST be kept consistent with one another at ALL times.
(2) Gather together all of the messages that have no parents
and make them all children (siblings of one another) of a dummy
parent (the "root"). These messages constitute the first
(head) message of the threads created thus far.
(3) Prune dummy messages from the thread tree. Traverse each
thread under the root, and for each message:
If it is a dummy message with NO children, delete it.
If it is a dummy message with children, delete it, but
promote its children to the current level. In other words,
splice them in with the dummy's siblings.
Do not promote the children if doing so would make them
children of the root, unless there is only one child.
(4) Sort the messages under the root (top-level siblings only)
by sent date. In the case of an exact match on sent date or if
Crispin and Murchison [Page 6]
INTERNET DRAFT IMAP THREAD EXPIRES 22 December 2002
either of the Date: headers used in a comparison can not be
parsed, use the order in which the messages appear in the
mailbox (that is, by sequence number) to determine the order.
In the case of a dummy message, sort its children by sent date
and then use the first child for the top-level sort.
(5) Gather together messages under the root that have the same
base subject text.
(A) Create a table for associating base subjects with
messages, called the subject table.
(B) Populate the subject table with one message per each
base subject. For each child of the root:
(i) Find the subject of this thread, by using the base
subject from either the current message or its first
child if the current message is a dummy. This is the
thread subject.
(ii) If the thread subject is empty, skip this message.
(iii) Look up the message associated with the thread
subject in the subject table.
(iv) If there is no message in the subject table with the
thread subject, add the current message and the thread
subject to the subject table.
Otherwise, if the message in the subject table is not a
dummy, AND either of the following criteria are true:
The current message is a dummy, OR
The message in the subject table is a reply or forward
and the current message is not.
then replace the message in the subject table with the
current message.
(C) Merge threads with the same thread subject. For each
child of the root:
(i) Find the message's thread subject as in step 5.B.i
above.
(ii) If the thread subject is empty, skip this message.
Crispin and Murchison [Page 7]
INTERNET DRAFT IMAP THREAD EXPIRES 22 December 2002
(iii) Lookup the message associated with this thread
subject in the subject table.
(iv) If the message in the subject table is the current
message, skip this message.
Otherwise, merge the current message with the one in the
subject table using the following rules:
If both messages are dummies, append the current
message's children to the children of the message in
the subject table (the children of both messages
become siblings), and then delete the current message.
If the message in the subject table is a dummy and the
current message is not, make the current message a
child of the message in the subject table (a sibling
of its children).
If the current message is a reply or forward and the
message in the subject table is not, make the current
message a child of the message in the subject table (a
sibling of its children).
Otherwise, create a new dummy message and make both
the current message and the message in the subject
table children of the dummy. Then replace the message
in the subject table with the dummy message.
Note: Subject comparisons are case-insensitive, as
described under "Internationalization
Considerations."
(6) Traverse the messages under the root and sort each set of
siblings by sent date. Traverse the messages in such a way
that the "youngest" set of siblings are sorted first, and the
"oldest" set of siblings are sorted last (grandchildren are
sorted before children, etc). In the case of an exact match on
sent date or if either of the Date: headers used in a
comparison can not be parsed, use the order in which the
messages appear in the mailbox (that is, by sequence number) to
determine the order. In the case of a dummy message (which can
only occur with top-level siblings), use its first child for
sorting.
Crispin and Murchison [Page 8]
INTERNET DRAFT IMAP THREAD EXPIRES 22 December 2002
Example: C: A283 THREAD ORDEREDSUBJECT UTF-8 SINCE 5-MAR-2000
S: * THREAD (166)(167)(168)(169)(172)(170)(171)
(173)(174 175 176 178 181 180)(179)(177 183
182 188 184 185 186 187 189)(190)(191)(192)
(193)(194 195)(196 197 198)(199)(200 202)(201)
(203)(204)(205)(206 207)(208)
S: A283 OK THREAD completed
C: A284 THREAD ORDEREDSUBJECT US-ASCII TEXT "gewp"
S: * THREAD
S: A284 OK THREAD completed
C: A285 THREAD REFERENCES UTF-8 SINCE 5-MAR-2000
S: * THREAD (166)(167)(168)(169)(172)((170)(179))
(171)(173)((174)(175)(176)(178)(181)(180))
((177)(183)(182)(188 (184)(189))(185 186)(187))
(190)(191)(192)(193)((194)(195 196))(197 198)
(199)(200 202)(201)(203)(204)(205 206 207)(208)
S: A285 OK THREAD completed
Note: The line breaks in the first and third client
responses are for editorial clarity and do not appear in
real THREAD responses.
Crispin and Murchison [Page 9]
INTERNET DRAFT IMAP THREAD EXPIRES 22 December 2002
Additional Responses
This response is an extension to the IMAP4rev1 base protocol.
The section heading of this response is intended to correspond with
where it would be located in the main document.
7.2.THREAD. THREAD Response
Data: zero or more threads
The THREAD response occurs as a result of a THREAD or UID THREAD
command. It contains zero or more threads. A thread consists of
a parenthesized list of thread members.
Thread members consist of zero or more message numbers, delimited
by spaces, indicating successive parent and child. This continues
until the thread splits into multiple sub-threads, at which point
the thread nests into multiple sub-threads with the first member
of each subthread being siblings at this level. There is no limit
to the nesting of threads.
The messages numbers refer to those messages that match the search
criteria. For THREAD, these are message sequence numbers; for UID
THREAD, these are unique identifiers.
Example: S: * THREAD (2)(3 6 (4 23)(44 7 96))
The first thread consists only of message 2. The second thread
consists of the messages 3 (parent) and 6 (child), after which it
splits into two subthreads; the first of which contains messages 4
(child of 6, sibling of 44) and 23 (child of 4), and the second of
which contains messages 44 (child of 6, sibling of 4), 7 (child of
44), and 96 (child of 7). Since some later messages are parents
of earlier messages, the messages were probably moved from some
other mailbox at different times.
-- 2
-- 3
\-- 6
|-- 4
| \-- 23
|
\-- 44
\-- 7
\-- 96
Crispin and Murchison [Page 10]
INTERNET DRAFT IMAP THREAD EXPIRES 22 December 2002
Example: S: * THREAD ((3)(5))
In this example, 3 and 5 are siblings of a parent which does not
match the search criteria (and/or does not exist in the mailbox);
however they are members of the same thread.
Crispin and Murchison [Page 11]
INTERNET DRAFT IMAP THREAD EXPIRES 22 December 2002
Formal Syntax of THREAD commands and Responses
thread-data = "THREAD" [SP 1*thread-list]
thread-list = "(" thread-members / thread-nested ")"
thread-members = nz-number *(SP nz-number) [SP thread-nested]
thread-nested = 2*thread-list
thread = ["UID" SP] "THREAD" SP thread-algorithm
SP search-charset 1*(SP search-key)
thread-algorithm = "ORDEREDSUBJECT" / "REFERENCES" / atom
The following syntax describes base subject extraction rules (2)-(6):
subject = *subj-leader [subj-middle] *subj-trailer
subj-refwd = ("re" / ("fw" ["d"])) *WSP [subj-blob] ":"
subj-blob = "[" *BLOBCHAR "]" *WSP
subj-fwd = subj-fwd-hdr subject subj-fwd-trl
subj-fwd-hdr = "[fwd:"
subj-fwd-trl = "]"
subj-leader = (*subj-blob subj-refwd) / WSP
subj-middle = *subj-blob (subj-base / subj-fwd)
; last subj-blob is subj-base if subj-base would
; otherwise be empty
subj-trailer = "(fwd)" / WSP
subj-base = NONWSP *([*WSP] NONWSP)
; can be a subj-blob
BLOBCHAR = %x01-5a / %x5c / %x5e-7f
; any CHAR except '[' and ']'
NONWSP = %x01-08 / %x0a-1f / %x21-7f
; any CHAR other than WSP
Crispin and Murchison [Page 12]
INTERNET DRAFT IMAP THREAD EXPIRES 22 December 2002
Security Considerations
Security issues are not discussed in this memo.
Internationalization Considerations
By default, strings are threaded according to the "minimum sorting
collation algorithm". All implementations of THREAD MUST implement
the minimum sorting collation algorithm.
In the minimum sorting collation algorithm, the Basic Latin
alphabetics (U+0041 to U+005A uppercase, U+0061 to U+007A lowercase)
are sorted in a case-insensitive fashion; that is, "A" (U+0041) and
"a" (U+0061) are treated as exact equals. The characters U+005B to
U+0060 are sorted after the Basic Latin alphabetics; for example,
U+005E is sorted after U+005A and U+007A. All other characters are
sorted according to their octet values, as expressed in UTF-8. No
attempt is made to treat composed characters specially, or to do
case-insensitive comparisons of composed characters.
Note: this means, among other things, that the composed
characters in the Latin-1 Supplement are not compared in
what would be considered an ISO 8859-1 "case-insensitive"
fashion. Case comparison rules for characters with
diacriticals differ between languages; the minimum sorting
collation does not attempt to deal with this at all. This
is reserved for other sorting collations, which may be
language-specific.
;;; *** ITEM FOR DISCUSSION ***
;;; THERE IS SOME CONCERN THAT THIS MINIMUM COLLATION IS TOO MINIMAL,
;;; AND THAT THE "GENERIC UNICODE SORTING COLLATION" DISCUSSED BELOW
;;; NEEDS TO BE THE MINIMUM. ONE SUGGESTION IS UNICODE TECHNICAL
;;; STANDARD 10 (TR-10). IF THIS IS THE MINIMUM, THAT REQUIRES THAT
;;; ALL IMPLEMENTATIONS OF SORT AND THREAD BE UNICODE-SAVVY AT LEAST
;;; TO THE POINT OF IMPLEMENTATION TR-10. IS THIS REALISTIC? DOES
;;; THIS RAISE EXCESSIVE IMPLEMENTATION BARRIERS?
Other sorting collations, and the ability to change the sorting
collation, will be defined in a separate document dealing with IMAP
internationalization.
It is anticipated that there will be a generic Unicode sorting
collation, which will provide generic case-insensitivity for
alphabetic scripts, specification of composed character handling, and
language-specific sorting collations. A server which implements
non-default sorting collations will modify its sorting behavior
according to the selected sorting collation.
Crispin and Murchison [Page 13]
INTERNET DRAFT IMAP THREAD EXPIRES 22 December 2002
Non-English translations of "Re" or "Fw"/"Fwd" are not specified for
removal in the base subject extraction process. By specifying that
only the English forms of the prefixes are used, it becomes a simple
display time task to localize the prefix language for the user. If,
on the other hand, prefixes in multiple languages are permitted, the
result is a geometrically complex, and ultimately unimplementable,
task. In order to improve the ability to support non-English display
in Internet mail clients, only the English form of these prefixes
should be transmitted in Internet mail messages.
A. References
[ABNF] Crocker, D., and Overell, P. "Augmented BNF for Syntax
Specifications: ABNF", RFC 2234, November 1997.
[NEWS] Horton, M., and Adams, R., "Standard for interchange of USENET
messages", RFC-1036, AT&T Bell Laboratories and Center for Seismic
Studies, December, 1987.
[RFC-2822] Resnick, P. "Internet Message Format", RFC 2822, April
2001.
Author's Address
Mark R. Crispin
Networks and Distributed Computing
University of Washington
4545 15th Avenue NE
Seattle, WA 98105-4527
Phone: (206) 543-5762
EMail: MRC@CAC.Washington.EDU
Kenneth Murchison
Oceana Matrix Ltd.
21 Princeton Place
Orchard Park, NY 14127
Phone: (716) 662-8973 x26
EMail: ken@oceana.com
Crispin and Murchison [Page 14]

View File

@ -0,0 +1,339 @@
Network Working Group J. Myers
Request for Comments: 1731 Carnegie Mellon
Category: Standards Track December 1994
IMAP4 Authentication Mechanisms
Status of this Memo
This document specifies an Internet standards track protocol for the
Internet community, and requests discussion and suggestions for
improvements. Please refer to the current edition of the "Internet
Official Protocol Standards" (STD 1) for the standardization state
and status of this protocol. Distribution of this memo is unlimited.
1. Introduction
The Internet Message Access Protocol, Version 4 [IMAP4] contains the
AUTHENTICATE command, for identifying and authenticating a user to an
IMAP4 server and for optionally negotiating a protection mechanism
for subsequent protocol interactions. This document describes
several authentication mechanisms for use by the IMAP4 AUTHENTICATE
command.
2. Kerberos version 4 authentication mechanism
The authentication type associated with Kerberos version 4 is
"KERBEROS_V4".
The data encoded in the first ready response contains a random 32-bit
number in network byte order. The client should respond with a
Kerberos ticket and an authenticator for the principal
"imap.hostname@realm", where "hostname" is the first component of the
host name of the server with all letters in lower case and where
"realm" is the Kerberos realm of the server. The encrypted checksum
field included within the Kerberos authenticator should contain the
server provided 32-bit number in network byte order.
Upon decrypting and verifying the ticket and authenticator, the
server should verify that the contained checksum field equals the
original server provided random 32-bit number. Should the
verification be successful, the server must add one to the checksum
and construct 8 octets of data, with the first four octets containing
the incremented checksum in network byte order, the fifth octet
containing a bit-mask specifying the protection mechanisms supported
by the server, and the sixth through eighth octets containing, in
Myers [Page 1]
RFC 1731 IMAP4 Authentication Mechanisms December 1994
network byte order, the maximum cipher-text buffer size the server is
able to receive. The server must encrypt the 8 octets of data in the
session key and issue that encrypted data in a second ready response.
The client should consider the server authenticated if the first four
octets the un-encrypted data is equal to one plus the checksum it
previously sent.
The client must construct data with the first four octets containing
the original server-issued checksum in network byte order, the fifth
octet containing the bit-mask specifying the selected protection
mechanism, the sixth through eighth octets containing in network byte
order the maximum cipher-text buffer size the client is able to
receive, and the following octets containing a user name string. The
client must then append from one to eight octets so that the length
of the data is a multiple of eight octets. The client must then PCBC
encrypt the data with the session key and respond to the second ready
response with the encrypted data. The server decrypts the data and
verifies the contained checksum. The username field identifies the
user for whom subsequent IMAP operations are to be performed; the
server must verify that the principal identified in the Kerberos
ticket is authorized to connect as that user. After these
verifications, the authentication process is complete.
The protection mechanisms and their corresponding bit-masks are as
follows:
1 No protection mechanism
2 Integrity (krb_mk_safe) protection
4 Privacy (krb_mk_priv) protection
EXAMPLE: The following are two Kerberos version 4 login scenarios
(note that the line breaks in the sample authenticators are for
editorial clarity and are not in real authenticators)
S: * OK IMAP4 Server
C: A001 AUTHENTICATE KERBEROS_V4
S: + AmFYig==
C: BAcAQU5EUkVXLkNNVS5FRFUAOCAsho84kLN3/IJmrMG+25a4DT
+nZImJjnTNHJUtxAA+o0KPKfHEcAFs9a3CL5Oebe/ydHJUwYFd
WwuQ1MWiy6IesKvjL5rL9WjXUb9MwT9bpObYLGOKi1Qh
S: + or//EoAADZI=
C: DiAF5A4gA+oOIALuBkAAmw==
S: A001 OK Kerberos V4 authentication successful
Myers [Page 2]
RFC 1731 IMAP4 Authentication Mechanisms December 1994
S: * OK IMAP4 Server
C: A001 AUTHENTICATE KERBEROS_V4
S: + gcfgCA==
C: BAcAQU5EUkVXLkNNVS5FRFUAOCAsho84kLN3/IJmrMG+25a4DT
+nZImJjnTNHJUtxAA+o0KPKfHEcAFs9a3CL5Oebe/ydHJUwYFd
WwuQ1MWiy6IesKvjL5rL9WjXUb9MwT9bpObYLGOKi1Qh
S: A001 NO Kerberos V4 authentication failed
3. GSSAPI authentication mechanism
The authentication type associated with all mechanisms employing the
GSSAPI [RFC1508] is "GSSAPI".
The first ready response issued by the server contains no data. The
client should call GSS_Init_sec_context, passing in 0 for
input_context_handle (initially) and a targ_name equal to output_name
from GSS_Import_Name called with input_name_type of NULL and
input_name_string of "SERVICE:imap@hostname" where "hostname" is the
fully qualified host name of the server with all letters in lower
case. The client must then respond with the resulting output_token.
If GSS_Init_sec_context returns GSS_CONTINUE_NEEDED, then the client
should expect the server to issue a token in a subsequent ready
response. The client must pass the token to another call to
GSS_Init_sec_context.
If GSS_Init_sec_context returns GSS_COMPLETE, then the client should
respond with any resulting output_token. If there is no
output_token, the client should respond with no data. The client
should then expect the server to issue a token in a subsequent ready
response. The client should pass this token to GSS_Unseal and
interpret the first octet of resulting cleartext as a bit-mask
specifying the protection mechanisms supported by the server and the
second through fourth octets as the maximum size output_message to
send to the server. The client should construct data, with the first
octet containing the bit-mask specifying the selected protection
mechanism, the second through fourth octets containing in network
byte order the maximum size output_message the client is able to
receive, and the remaining octets containing a user name string. The
client must pass the data to GSS_Seal with conf_flag set to FALSE,
and respond with the generated output_message. The client can then
consider the server authenticated.
The server must issue a ready response with no data and pass the
resulting client supplied token to GSS_Accept_sec_context as
input_token, setting acceptor_cred_handle to NULL (for "use default
credentials"), and 0 for input_context_handle (initially). If
GSS_Accept_sec_context returns GSS_CONTINUE_NEEDED, the server should
Myers [Page 3]
RFC 1731 IMAP4 Authentication Mechanisms December 1994
return the generated output_token to the client in a ready response
and pass the resulting client supplied token to another call to
GSS_Accept_sec_context.
If GSS_Accept_sec_context returns GSS_COMPLETE, then if an
output_token is returned, the server should return it to the client
in a ready response and expect a reply from the client with no data.
Whether or not an output_token was returned, the server then should
then construct 4 octets of data, with the first octet containing a
bit-mask specifying the protection mechanisms supported by the server
and the second through fourth octets containing in network byte order
the maximum size output_token the server is able to receive. The
server must then pass the plaintext to GSS_Seal with conf_flag set to
FALSE and issue the generated output_message to the client in a ready
response. The server must then pass the resulting client supplied
token to GSS_Unseal and interpret the first octet of resulting
cleartext as the bit-mask for the selected protection mechanism, the
second through fourth octets as the maximum size output_message to
send to the client, and the remaining octets as the user name. Upon
verifying the src_name is authorized to authenticate as the user
name, The server should then consider the client authenticated.
The protection mechanisms and their corresponding bit-masks are as
follows:
1 No protection mechanism
2 Integrity protection.
Sender calls GSS_Seal with conf_flag set to FALSE
4 Privacy protection.
Sender calls GSS_Seal with conf_flag set to TRUE
4. S/Key authentication mechanism
The authentication type associated with S/Key [SKEY] is "SKEY".
The first ready response issued by the server contains no data. The
client responds with the user name string.
The data encoded in the second ready response contains the decimal
sequence number followed by a single space and the seed string for
the indicated user. The client responds with the one-time-password,
as either a 64-bit value in network byte order or encoded in the "six
English words" format.
Upon successful verification of the one-time-password, the server
should consider the client authenticated.
Myers [Page 4]
RFC 1731 IMAP4 Authentication Mechanisms December 1994
S/Key authentication does not provide for any protection mechanisms.
EXAMPLE: The following are two S/Key login scenarios.
S: * OK IMAP4 Server
C: A001 AUTHENTICATE SKEY
S: +
C: bW9yZ2Fu
S: + OTUgUWE1ODMwOA==
C: Rk9VUiBNQU5OIFNPT04gRklSIFZBUlkgTUFTSA==
S: A001 OK S/Key authentication successful
S: * OK IMAP4 Server
C: A001 AUTHENTICATE SKEY
S: +
C: c21pdGg=
S: + OTUgUWE1ODMwOA==
C: BsAY3g4gBNo=
S: A001 NO S/Key authentication failed
5. References
[IMAP4] Crispin, M., "Internet Message Access Protocol - Version 4",
RFC 1730, University of Washington, December 1994.
[RFC1508] Linn, J., "Generic Security Service Application Program
Interface", RFC 1508, Geer Zolot Associates, September 1993.
[SKEY] Haller, Neil M. "The S/Key One-Time Password System",
Bellcore, Morristown, New Jersey, October 1993,
thumper.bellcore.com:pub/nmh/docs/ISOC.symp.ps
Myers [Page 5]
RFC 1731 IMAP4 Authentication Mechanisms December 1994
6. Security Considerations
Security issues are discussed throughout this memo.
7. Author's Address
John G. Myers
Carnegie-Mellon University
5000 Forbes Ave.
Pittsburgh PA, 15213-3890
EMail: jgm+@cmu.edu
Myers [Page 6]

View File

@ -0,0 +1,283 @@
Network Working Group M. Crispin
Request for Comments: 1732 University of Washington
Category: Informational December 1994
IMAP4 COMPATIBILITY WITH IMAP2 AND IMAP2BIS
Status of this Memo
This memo provides information for the Internet community. This memo
does not specify an Internet standard of any kind. Distribution of
this memo is unlimited.
Introduction
This is a summary of hints and recommendations to enable an IMAP4
implementation to interoperate with implementations that conform to
earlier specifications. None of these hints and recommendations are
required by the IMAP4 specification; implementors must decide for
themselves whether they want their implementation to fail if it
encounters old software.
IMAP4 has been designed to be upwards compatible with earlier
specifications. For the most part, IMAP4 facilities that were not in
earlier specifications should be invisible to clients unless the
client asks for the facility.
In some cases, older servers may support some of the capabilities
listed as being "new in IMAP4" as experimental extensions to the
IMAP2 protocol described in RFC 1176.
This information may not be complete; it reflects current knowledge
of server and client implementations as well as "folklore" acquired
in the evolution of the protocol.
Crispin [Page 1]
RFC 1732 IMAP4 - Compatibility December 1994
IMAP4 client interoperability with old servers
In general, a client should be able to discover whether an IMAP2
server supports a facility by trial-and-error; if an attempt to use a
facility generates a BAD response, the client can assume that the
server does not support the facility.
A quick way to check whether a server implementation supports the
IMAP4 specification is to try the CAPABILITY command. An OK response
that includes the IMAP4 capability value indicates a server that
supports IMAP4; a BAD response or one without the IMAP4 capability
value indicates an older server.
The following is a list of facilities that are only in IMAP4, and
suggestions for how new clients might interoperate with old servers:
CAPABILITY command
A BAD response to this command indicates that the server
implements IMAP2 (or IMAP2bis) and not IMAP4.
AUTHENTICATE command.
Use the LOGIN command.
LSUB and LIST commands
Try the RFC 1176 FIND command.
* in a sequence
Use the number of messages in the mailbox from the EXISTS
unsolicited response.
SEARCH extensions (character set, additional criteria)
Reformulate the search request using only the searching
options listed in search_old in the IMAP4 grammar. This may
entail doing multiple searches to achieve the desired
results.
BODYSTRUCTURE fetch data item
Try to fetch the non-extensible BODY data item.
body section number 0
Fetch the entire message and extract the header.
RFC822.HEADER.LINES and RFC822.HEADER.LINES.NOT fetch data items
Use RFC822.HEADER and remove the unwanted information.
BODY.PEEK[section], RFC822.PEEK, and RFC822.TEXT.PEEK fetch data
items Use the corresponding non-PEEK versions and manually
clear the \Seen flag as necessary.
Crispin [Page 2]
RFC 1732 IMAP4 - Compatibility December 1994
UID fetch data item and the UID commands
No equivalent capabilitity exists in older servers.
FLAGS.SILENT, +FLAGS.SILENT, and -FLAGS.SILENT store data items
Use the corresponding non-SILENT versions and ignore the
untagged FETCH responses which com eback.
The following IMAP4 facilities were introduced in the experimental
IMAP2bis revisions to RFC-1176, and may be present in a server that
does not support the CAPABILITY command:
CREATE, DELETE, and RENAME commands
To test whether these commands are present, try a CREATE
INBOX command. If the response is NO, these commands are
supported by the server. If the response is BAD, they are
not. Older servers without the CREATE capability may sup-
port implicit creation of a mailbox by a COPY command with a
non-existant name as the destination.
APPEND command
To test whether this command is present, try to append a
zero-length stream to a mailbox name that is known not to
exist (or at least, highly unlikely to exist) on the remote
system.
SUBSCRIBE and UNSUBSCRIBE commands
Try the form of these commands with the optional MAILBOX
keyword.
EXAMINE command
Use the SELECT command instead.
flags and internal date argument to APPEND command
Try the APPEND without any flag list and internal date argu-
ments.
BODY, BODY[section], and FULL fetch data items
Use RFC822.TEXT and ALL instead. Server does not support
MIME.
PARTIAL command
Use the appropriate FETCH command and ignore the unwanted
data.
IMAP4 client implementations must accept all responses and data for-
mats documented in the IMAP4 specification, including those labeled
Crispin [Page 3]
RFC 1732 IMAP4 - Compatibility December 1994
as obsolete. This includes the COPY and STORE unsolicited responses
and the old format of dates and times. In particular, client imple-
mentations must not treat a date/time as a fixed format string; nor
may they assume that the time begins at a particular octet.
IMAP4 client implementations must not depend upon the presence of any
server extensions that are not in the base IMAP4 specification.
The experimental IMAP2bis version specified that the TRYCREATE spe-
cial information token is sent as a separate unsolicited OK response
instead of inside the NO response.
The FIND BBOARDS, FIND ALL.BBOARDS, and BBOARD commands of RFC 1176
are removed from IMAP4. There is no equivalent to the bboard com-
mands, which provided a separate namespace with implicit restrictions
on what may be done in that namespace.
Older server implementations may automatically create the destination
mailbox on COPY if that mailbox does not already exist. This was how
a new mailbox was created in older specifications. If the server
does not support the CREATE command (see above for how to test for
this), it will probably create a mailbox on COPY.
Older server implementations may not preserve flags or internal dates
on COPY. Some server implementations may not permit the preservation
of certain flags on COPY or their setting with APPEND as site policy.
Crispin [Page 4]
RFC 1732 IMAP4 - Compatibility December 1994
IMAP4 server interoperability with old clients
In general, there should be no interoperation problem between a
server conforming to the IMAP4 specification and a well-written
client that conforms to an earlier specification. Known problems are
noted below:
Poor wording in the description of the CHECK command in earlier
specifications implied that a CHECK command is the way to get the
current number of messages in the mailbox. This is incorrect. A
CHECK command does not necessarily result in an EXISTS response.
Clients must remember the most recent EXISTS value sent from the
server, and should not generate unnecessary CHECK commands.
An incompatibility exists with COPY in IMAP4. COPY in IMAP4
servers does not automatically create the destination mailbox if
that mailbox does not already exist. This may cause problems with
old clients that expect automatic mailbox creation in COPY.
The PREAUTH unsolicited response is new in IMAP4. It is highly
unlikely that an old client would ever see this response.
The format of dates and times has changed due to the impending end
of the century. Clients that fail to accept a four-digit year or
a signed four-digit timezone value will not work properly with
IMAP4.
An incompatibility exists with the use of "\" in quoted strings.
This is best avoided by using literals instead of quoted strings
if "\" or <"> is embedded in the string.
Security Considerations
Security issues are not discussed in this memo.
Author's Address:
Mark R. Crispin
Networks and Distributed Computing, JE-30
University of Washington
Seattle, WA 98195
Phone: (206) 543-5762
EMail: MRC@CAC.Washington.EDU
Crispin [Page 5]

View File

@ -0,0 +1,171 @@
Network Working Group M. Crispin
Request for Comments: 1733 University of Washington
Category: Informational December 1994
DISTRIBUTED ELECTRONIC MAIL MODELS IN IMAP4
Status of this Memo
This memo provides information for the Internet community. This memo
does not specify an Internet standard of any kind. Distribution of
this memo is unlimited.
Distributed Electronic Mail Models
There are three fundamental models of client/server email: offline,
online, and disconnected use. IMAP4 can be used in any one of these
three models.
The offline model is the most familiar form of client/server email
today, and is used by protocols such as POP-3 (RFC 1225) and UUCP.
In this model, a client application periodically connects to a
server. It downloads all the pending messages to the client machine
and deletes these from the server. Thereafter, all mail processing
is local to the client. This model is store-and-forward; it moves
mail on demand from an intermediate server (maildrop) to a single
destination machine.
The online model is most commonly used with remote filesystem
protocols such as NFS. In this model, a client application
manipulates mailbox data on a server machine. A connection to the
server is maintained throughout the session. No mailbox data are
kept on the client; the client retrieves data from the server as is
needed. IMAP4 introduces a form of the online model that requires
considerably less network bandwidth than a remote filesystem
protocol, and provides the opportunity for using the server for CPU
or I/O intensive functions such as parsing and searching.
The disconnected use model is a hybrid of the offline and online
models, and is used by protocols such as PCMAIL (RFC 1056). In this
model, a client user downloads some set of messages from the server,
manipulates them offline, then at some later time uploads the
changes. The server remains the authoritative repository of the
messages. The problems of synchronization (particularly when
multiple clients are involved) are handled through the means of
unique identifiers for each message.
Crispin [Page 1]
RFC 1733 IMAP4 - Model December 1994
Each of these models have their own strengths and weaknesses:
Feature Offline Online Disc
------- ------- ------ ----
Can use multiple clients NO YES YES
Minimum use of server connect time YES NO YES
Minimum use of server resources YES NO NO
Minimum use of client disk resources NO YES NO
Multiple remote mailboxes NO YES YES
Fast startup NO YES NO
Mail processing when not online YES NO YES
Although IMAP4 has its origins as a protocol designed to accommodate
the online model, it can support the other two models as well. This
makes possible the creation of clients that can be used in any of the
three models. For example, a user may wish to switch between the
online and disconnected models on a regular basis (e.g. owing to
travel).
IMAP4 is designed to transmit message data on demand, and to provide
the facilities necessary for a client to decide what data it needs at
any particular time. There is generally no need to do a wholesale
transfer of an entire mailbox or even of the complete text of a
message. This makes a difference in situations where the mailbox is
large, or when the link to the server is slow.
More specifically, IMAP4 supports server-based RFC 822 and MIME
processing. With this information, it is possible for a client to
determine in advance whether it wishes to retrieve a particular
message or part of a message. For example, a user connected to an
IMAP4 server via a dialup link can determine that a message has a
2000 byte text segment and a 40 megabyte video segment, and elect to
fetch only the text segment.
In IMAP4, the client/server relationship lasts only for the duration
of the TCP connection. There is no registration of clients. Except
for any unique identifiers used in disconnected use operation, the
client initially has no knowledge of mailbox state and learns it from
the IMAP4 server when a mailbox is selected. This initial transfer
is minimal; the client requests additional state data as it needs.
As noted above, the choice for the location of mailbox data depends
upon the model chosen. The location of message state (e.g. whether
or not a message has been read or answered) is also determined by the
model, and is not necessarily the same as the location of the mailbox
data. For example, in the online model message state can be co-
located with mailbox data; it can also be located elsewhere (on the
client or on a third agent) using unique identifiers to achieve
Crispin [Page 2]
RFC 1733 IMAP4 - Model December 1994
common reference across sessions. The latter is particularly useful
with a server that exports public data such as netnews and does not
maintain per-user state.
The IMAP4 protocol provides the generality to implement these
different models. This is done by means of server and (especially)
client configuration, and not by requiring changes to the protocol or
the implementation of the protocol.
Security Considerations
Security issues are not discussed in this memo.
Author's Address:
Mark R. Crispin
Networks and Distributed Computing, JE-30
University of Washington
Seattle, WA 98195
Phone: (206) 543-5762
EMail: MRC@CAC.Washington.EDU
Crispin [Page 3]

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,171 @@
Network Working Group M. Crispin
Request for Comments: 2061 University of Washington
Category: Informational December 1996
IMAP4 COMPATIBILITY WITH IMAP2BIS
Status of this Memo
This memo provides information for the Internet community. This memo
does not specify an Internet standard of any kind. Distribution of
this memo is unlimited.
Introduction
The Internet Message Access Protocol (IMAP) has been through several
revisions and variants in its 10-year history. Many of these are
either extinct or extremely rare; in particular, several undocumented
variants and the variants described in RFC 1064, RFC 1176, and RFC
1203 fall into this category.
One variant, IMAP2bis, is at the time of this writing very common and
has been widely distributed with the Pine mailer. Unfortunately,
there is no definite document describing IMAP2bis. This document is
intended to be read along with RFC 1176 and the most recent IMAP4
specification (RFC 2060) to assist implementors in creating an IMAP4
implementation to interoperate with implementations that conform to
earlier specifications. Nothing in this document is required by the
IMAP4 specification; implementors must decide for themselves whether
they want their implementation to fail if it encounters old software.
At the time of this writing, IMAP4 has been updated from the version
described in RFC 1730. An implementor who wishes to interoperate
with both RFC 1730 and RFC 2060 should refer to both documents.
This information is not complete; it reflects current knowledge of
server and client implementations as well as "folklore" acquired in
the evolution of the protocol. It is NOT a description of how to
interoperate with all variants of IMAP, but rather with the old
variant that is most likely to be encountered. For detailed
information on interoperating with other old variants, refer to RFC
1732.
IMAP4 client interoperability with IMAP2bis servers
A quick way to check whether a server implementation supports the
IMAP4 specification is to try the CAPABILITY command. An OK response
will indicate which variant(s) of IMAP4 are supported by the server.
Crispin Informational [Page 1]
RFC 2061 IMAP4 Compatibility December 1996
If the client does not find any of its known variant in the response,
it should treat the server as IMAP2bis. A BAD response indicates an
IMAP2bis or older server.
Most IMAP4 facilities are in IMAP2bis. The following exceptions
exist:
CAPABILITY command
The absense of this command indicates IMAP2bis (or older).
AUTHENTICATE command.
Use the LOGIN command.
LSUB, SUBSCRIBE, and UNSUBSCRIBE commands
No direct functional equivalent. IMAP2bis had a concept
called "bboards" which is not in IMAP4. RFC 1176 supported
these with the BBOARD and FIND BBOARDS commands. IMAP2bis
augmented these with the FIND ALL.BBOARDS, SUBSCRIBE BBOARD,
and UNSUBSCRIBE BBOARD commands. It is recommended that
none of these commands be implemented in new software,
including servers that support old clients.
LIST command
Use the command FIND ALL.MAILBOXES, which has a similar syn-
tax and response to the FIND MAILBOXES command described in
RFC 1176. The FIND MAILBOXES command is unlikely to produce
useful information.
* in a sequence
Use the number of messages in the mailbox from the EXISTS
unsolicited response.
SEARCH extensions (character set, additional criteria)
Reformulate the search request using only the RFC 1176 syn-
tax. This may entail doing multiple searches to achieve the
desired results.
BODYSTRUCTURE fetch data item
Use the non-extensible BODY data item.
body sections HEADER, TEXT, MIME, HEADER.FIELDS, HEADER.FIELDS.NOT
Use body section numbers only.
BODY.PEEK[section]
Use BODY[section] and manually clear the \Seen flag as
necessary.
Crispin Informational [Page 2]
RFC 2061 IMAP4 Compatibility December 1996
FLAGS.SILENT, +FLAGS.SILENT, and -FLAGS.SILENT store data items
Use the corresponding non-SILENT versions and ignore the
untagged FETCH responses which come back.
UID fetch data item and the UID commands
No functional equivalent.
CLOSE command
No functional equivalent.
In IMAP2bis, the TRYCREATE special information token is sent as a
separate unsolicited OK response instead of inside the NO response.
IMAP2bis is ambiguous about whether or not flags or internal dates
are preserved on COPY. It is impossible to know what behavior is
supported by the server.
IMAP4 server interoperability with IMAP2bis clients
The only interoperability problem between an IMAP4 server and a
well-written IMAP2bis client is an incompatibility with the use of
"\" in quoted strings. This is best avoided by using literals
instead of quoted strings if "\" or <"> is embedded in the string.
Security Considerations
Security issues are not discussed in this memo.
Author's Address
Mark R. Crispin
Networks and Distributed Computing
University of Washington
4545 15th Aveneue NE
Seattle, WA 98105-4527
Phone: (206) 543-5762
EMail: MRC@CAC.Washington.EDU
Crispin Informational [Page 3]

View File

@ -0,0 +1,451 @@
Network Working Group M. Crispin
Request for Comments: 2062 University of Washington
Category: Informational December 1996
Internet Message Access Protocol - Obsolete Syntax
Status of this Memo
This memo provides information for the Internet community. This memo
does not specify an Internet standard of any kind. Distribution of
this memo is unlimited.
Abstract
This document describes obsolete syntax which may be encountered by
IMAP4 implementations which deal with older versions of the Internet
Mail Access Protocol. IMAP4 implementations MAY implement this
syntax in order to maximize interoperability with older
implementations.
This document repeats information from earlier documents, most
notably RFC 1176 and RFC 1730.
Obsolete Commands and Fetch Data Items
The following commands are OBSOLETE. It is NOT required to support
any of these commands or fetch data items in new server
implementations. These commands are documented here for the benefit
of implementors who may wish to support them for compatibility with
old client implementations.
The section headings of these commands are intended to correspond
with where they would be located in the main document if they were
not obsoleted.
6.3.OBS.1. FIND ALL.MAILBOXES Command
Arguments: mailbox name with possible wildcards
Data: untagged responses: MAILBOX
Result: OK - find completed
NO - find failure: can't list that name
BAD - command unknown or arguments invalid
Crispin Informational [Page 1]
RFC 2062 IMAP4 Obsolete December 1996
The FIND ALL.MAILBOXES command returns a subset of names from the
complete set of all names available to the user. It returns zero
or more untagged MAILBOX replies. The mailbox argument to FIND
ALL.MAILBOXES is similar to that for LIST with an empty reference,
except that the characters "%" and "?" match a single character.
Example: C: A002 FIND ALL.MAILBOXES *
S: * MAILBOX blurdybloop
S: * MAILBOX INBOX
S: A002 OK FIND ALL.MAILBOXES completed
6.3.OBS.2. FIND MAILBOXES Command
Arguments: mailbox name with possible wildcards
Data: untagged responses: MAILBOX
Result: OK - find completed
NO - find failure: can't list that name
BAD - command unknown or arguments invalid
The FIND MAILBOXES command returns a subset of names from the set
of names that the user has declared as being "active" or
"subscribed". It returns zero or more untagged MAILBOX replies.
The mailbox argument to FIND MAILBOXES is similar to that for LSUB
with an empty reference, except that the characters "%" and "?"
match a single character.
Example: C: A002 FIND MAILBOXES *
S: * MAILBOX blurdybloop
S: * MAILBOX INBOX
S: A002 OK FIND MAILBOXES completed
6.3.OBS.3. SUBSCRIBE MAILBOX Command
Arguments: mailbox name
Data: no specific data for this command
Result: OK - subscribe completed
NO - subscribe failure: can't subscribe to that name
BAD - command unknown or arguments invalid
The SUBSCRIBE MAILBOX command is identical in effect to the
SUBSCRIBE command. A server which implements this command must be
able to distinguish between a SUBSCRIBE MAILBOX command and a
SUBSCRIBE command with a mailbox name argument of "MAILBOX".
Crispin Informational [Page 2]
RFC 2062 IMAP4 Obsolete December 1996
Example: C: A002 SUBSCRIBE MAILBOX #news.comp.mail.mime
S: A002 OK SUBSCRIBE MAILBOX to #news.comp.mail.mime
completed
C: A003 SUBSCRIBE MAILBOX
S: A003 OK SUBSCRIBE to MAILBOX completed
6.3.OBS.4. UNSUBSCRIBE MAILBOX Command
Arguments: mailbox name
Data: no specific data for this command
Result: OK - unsubscribe completed
NO - unsubscribe failure: can't unsubscribe that name
BAD - command unknown or arguments invalid
The UNSUBSCRIBE MAILBOX command is identical in effect to the
UNSUBSCRIBE command. A server which implements this command must
be able to distinguish between a UNSUBSCRIBE MAILBOX command and
an UNSUBSCRIBE command with a mailbox name argument of "MAILBOX".
Example: C: A002 UNSUBSCRIBE MAILBOX #news.comp.mail.mime
S: A002 OK UNSUBSCRIBE MAILBOX from #news.comp.mail.mime
completed
C: A003 UNSUBSCRIBE MAILBOX
S: A003 OK UNSUBSCRIBE from MAILBOX completed
6.4.OBS.1 PARTIAL Command
Arguments: message sequence number
message data item name
position of first octet
number of octets
Data: untagged responses: FETCH
Result: OK - partial completed
NO - partial error: can't fetch that data
BAD - command unknown or arguments invalid
The PARTIAL command is equivalent to the associated FETCH command,
with the added functionality that only the specified number of
octets, beginning at the specified starting octet, are returned.
Only a single message can be fetched at a time. The first octet
of a message, and hence the minimum for the starting octet, is
octet 1.
Crispin Informational [Page 3]
RFC 2062 IMAP4 Obsolete December 1996
The following FETCH items are valid data for PARTIAL: RFC822,
RFC822.HEADER, RFC822.TEXT, BODY[<section>], as well as any .PEEK
forms of these.
Any partial fetch that attempts to read beyond the end of the text
is truncated as appropriate. If the starting octet is beyond the
end of the text, an empty string is returned.
The data are returned with the FETCH response. There is no
indication of the range of the partial data in this response. It
is not possible to stream multiple PARTIAL commands of the same
data item without processing and synchronizing at each step, since
streamed commands may be executed out of order.
There is no requirement that partial fetches follow any sequence.
For example, if a partial fetch of octets 1 through 10000 breaks
in an awkward place for BASE64 decoding, it is permitted to
continue with a partial fetch of 9987 through 19987, etc.
The handling of the \Seen flag is the same as in the associated
FETCH command.
Example: C: A005 PARTIAL 4 RFC822 1 1024
S: * 1 FETCH (RFC822 {1024}
S: Return-Path: <gray@cac.washington.edu>
S: ...
S: ......... FLAGS (\Seen))
S: A005 OK PARTIAL completed
6.4.5.OBS.1 Obsolete FETCH Data Items
The following FETCH data items are obsolete:
BODY[<...>0] A body part number of 0 is the [RFC-822] header of
the message. BODY[0] is functionally equivalent to
BODY[HEADER], differing in the syntax of the
resulting untagged FETCH data (BODY[0] is
returned).
RFC822.HEADER.LINES <header_list>
Functionally equivalent to BODY.PEEK[HEADER.LINES
<header_list>], differing in the syntax of the
resulting untagged FETCH data (RFC822.HEADER is
returned).
Crispin Informational [Page 4]
RFC 2062 IMAP4 Obsolete December 1996
RFC822.HEADER.LINES.NOT <header_list>
Functionally equivalent to
BODY.PEEK[HEADER.LINES.NOT <header_list>],
differing in the syntax of the resulting untagged
FETCH data (RFC822.HEADER is returned).
RFC822.PEEK Functionally equivalent to BODY.PEEK[], except for
the syntax of the resulting untagged FETCH data
(RFC822 is returned).
RFC822.TEXT.PEEK
Functionally equivalent to BODY.PEEK[TEXT], except
for the syntax of the resulting untagged FETCH data
(RFC822.TEXT is returned).
Obsolete Responses
The following responses are OBSOLETE. Except as noted below, these
responses MUST NOT be transmitted by new server implementations.
Client implementations SHOULD accept these responses.
The section headings of these responses are intended to correspond
with where they would be located in the main document if they were
not obsoleted.
7.2.OBS.1. MAILBOX Response
Data: name
The MAILBOX response MUST NOT be transmitted by server
implementations except in response to the obsolete FIND MAILBOXES
and FIND ALL.MAILBOXES commands. Client implementations that do
not use these commands MAY ignore this response. It is documented
here for the benefit of implementors who may wish to support it
for compatibility with old client implementations.
This response occurs as a result of the FIND MAILBOXES and FIND
ALL.MAILBOXES commands. It returns a single name that matches the
FIND specification. There are no attributes or hierarchy
delimiter.
Example: S: * MAILBOX blurdybloop
Crispin Informational [Page 5]
RFC 2062 IMAP4 Obsolete December 1996
7.3.OBS.1. COPY Response
Data: none
The COPY response MUST NOT be transmitted by new server
implementations. Client implementations MUST ignore the COPY
response. It is documented here for the benefit of client
implementors who may encounter this response from old server
implementations.
In some experimental versions of this protocol, this response was
returned in response to a COPY command to indicate on a
per-message basis that the message was copied successfully.
Example: S: * 44 COPY
7.3.OBS.2. STORE Response
Data: message data
The STORE response MUST NOT be transmitted by new server
implementations. Client implementations MUST treat the STORE
response as equivalent to the FETCH response. It is documented
here for the benefit of client implementors who may encounter this
response from old server implementations.
In some experimental versions of this protocol, this response was
returned instead of FETCH in response to a STORE command to report
the new value of the flags.
Example: S: * 69 STORE (FLAGS (\Deleted))
Formal Syntax of Obsolete Commands and Responses
Each obsolete syntax rule that is suffixed with "_old" is added to
the corresponding name in the formal syntax. For example,
command_auth_old adds the FIND command to command_auth.
command_auth_old ::= find
command_select_old
::= partial
date_year_old ::= 2digit
;; (year - 1900)
date_time_old ::= <"> date_day_fixed "-" date_month "-" date_year
SPACE time "-" zone_name <">
Crispin Informational [Page 6]
RFC 2062 IMAP4 Obsolete December 1996
find ::= "FIND" SPACE ["ALL."] "MAILBOXES" SPACE
list_mailbox
fetch_att_old ::= "RFC822.HEADER.LINES" [".NOT"] SPACE header_list /
fetch_text_old
fetch_text_old ::= "BODY" [".PEEK"] section_old /
"RFC822" [".HEADER" / ".TEXT" [".PEEK"]]
msg_data_old ::= "COPY" / ("STORE" SPACE msg_att)
partial ::= "PARTIAL" SPACE nz_number SPACE fetch_text_old SPACE
number SPACE number
section_old ::= "[" (number ["." number]) "]"
subscribe_old ::= "SUBSCRIBE" SPACE "MAILBOX" SPACE mailbox
unsubscribe_old ::= "UNSUBSCRIBE" SPACE "MAILBOX" SPACE mailbox
zone_name ::= "UT" / "GMT" / "Z" / ;; +0000
"AST" / "EDT" / ;; -0400
"EST" / "CDT" / ;; -0500
"CST" / "MDT" / ;; -0600
"MST" / "PDT" / ;; -0700
"PST" / "YDT" / ;; -0800
"YST" / "HDT" / ;; -0900
"HST" / "BDT" / ;; -1000
"BST" / ;; -1100
"A" / "B" / "C" / "D" / "E" / "F" / ;; +1 to +6
"G" / "H" / "I" / "K" / "L" / "M" / ;; +7 to +12
"N" / "O" / "P" / "Q" / "R" / "S" / ;; -1 to -6
"T" / "U" / "V" / "W" / "X" / "Y" ;; -7 to -12
Security Considerations
Security issues are not discussed in this memo.
Crispin Informational [Page 7]
RFC 2062 IMAP4 Obsolete December 1996
Author's Address
Mark R. Crispin
Networks and Distributed Computing
University of Washington
4545 15th Aveneue NE
Seattle, WA 98105-4527
Phone: (206) 543-5762
EMail: MRC@CAC.Washington.EDU
Crispin Informational [Page 8]

View File

@ -0,0 +1,451 @@
Network Working Group J. Myers
Request for Comments: 2086 Carnegie Mellon
Category: Standards Track January 1997
IMAP4 ACL extension
Status of this Memo
This document specifies an Internet standards track protocol for the
Internet community, and requests discussion and suggestions for
improvements. Please refer to the current edition of the "Internet
Official Protocol Standards" (STD 1) for the standardization state
and status of this protocol. Distribution of this memo is unlimited.
1. Abstract
The ACL extension of the Internet Message Access Protocol [IMAP4]
permits access control lists to be manipulated through the IMAP
protocol.
Table of Contents
1. Abstract............................................... 1
2. Conventions Used in this Document...................... 1
3. Introduction and Overview.............................. 2
4. Commands............................................... 3
4.1. SETACL................................................. 3
4.2. DELETEACL.............................................. 4
4.3. GETACL................................................. 4
4.4. LISTRIGHTS............................................. 4
4.5. MYRIGHTS............................................... 5
5. Responses.............................................. 5
5.1. ACL.................................................... 5
5.2. LISTRIGHTS............................................. 6
5.3. MYRIGHTS............................................... 6
6. Formal Syntax.......................................... 6
7. References............................................. 7
8. Security Considerations................................ 7
9. Author's Address....................................... 8
2. Conventions Used in this Document
In examples, "C:" and "S:" indicate lines sent by the client and
server respectively.
Myers Standards Track [Page 1]
RFC 2086 ACL extension January 1997
3. Introduction and Overview
The ACL extension is present in any IMAP4 implementation which
returns "ACL" as one of the supported capabilities to the CAPABILITY
command.
An access control list is a set of <identifier,rights> pairs.
Identifier is a US-ASCII string. The identifier anyone is reserved
to refer to the universal identity (all authentications, including
anonymous). All user name strings accepted by the LOGIN or
AUTHENTICATE commands to authenticate to the IMAP server are reserved
as identifiers for the corresponding user. Identifiers starting with
a dash ("-") are reserved for "negative rights", described below.
All other identifier strings are interpreted in an implementation-
defined manner.
Rights is a string listing a (possibly empty) set of alphanumeric
characters, each character listing a set of operations which is being
controlled. Letters are reserved for ``standard'' rights, listed
below. The set of standard rights may only be extended by a
standards-track document. Digits are reserved for implementation or
site defined rights. The currently defined standard rights are:
l - lookup (mailbox is visible to LIST/LSUB commands)
r - read (SELECT the mailbox, perform CHECK, FETCH, PARTIAL,
SEARCH, COPY from mailbox)
s - keep seen/unseen information across sessions (STORE SEEN flag)
w - write (STORE flags other than SEEN and DELETED)
i - insert (perform APPEND, COPY into mailbox)
p - post (send mail to submission address for mailbox,
not enforced by IMAP4 itself)
c - create (CREATE new sub-mailboxes in any implementation-defined
hierarchy)
d - delete (STORE DELETED flag, perform EXPUNGE)
a - administer (perform SETACL)
An implementation may tie rights together or may force rights to
always or never be granted to particular identifiers. For example,
in an implementation that uses unix mode bits, the rights "wisd" are
tied, the "a" right is always granted to the owner of a mailbox and
is never granted to another user. If rights are tied in an
implementation, the implementation must be conservative in granting
rights in response to SETACL commands--unless all rights in a tied
set are specified, none of that set should be included in the ACL
entry for that identifier. A client may discover the set of rights
which may be granted to a given identifier in the ACL for a given
mailbox by using the LISTRIGHTS command.
Myers Standards Track [Page 2]
RFC 2086 ACL extension January 1997
It is possible for multiple identifiers in an access control list to
apply to a given user (or other authentication identity). For
example, an ACL may include rights to be granted to the identifier
matching the user, one or more implementation-defined identifiers
matching groups which include the user, and/or the identifier
"anyone". How these rights are combined to determine the user's
access is implementation-defined. An implementation may choose, for
example, to use the union of the rights granted to the applicable
identifiers. An implementation may instead choose, for example, to
only use those rights granted to the most specific identifier present
in the ACL. A client may determine the set of rights granted to the
logged-in user for a given mailbox by using the MYRIGHTS command.
When an identifier in an ACL starts with a dash ("-"), that indicates
that associated rights are to be removed from the identifier that is
prefixed by the dash. For example, if the identifier "-fred" is
granted the "w" right, that indicates that the "w" right is to be
removed from users matching the identifier "fred". Implementations
need not support having identifiers which start with a dash in ACLs.
4. Commands
4.1. SETACL
Arguments: mailbox name
authentication identifier
access right modification
Data: no specific data for this command
Result: OK - setacl completed
NO - setacl failure: can't set acl
BAD - command unknown or arguments invalid
The SETACL command changes the access control list on the
specified mailbox so that the specified identifier is granted
permissions as specified in the third argument.
The third argument is a string containing an optional plus ("+")
or minus ("-") prefix, followed by zero or more rights characters.
If the string starts with a plus, the following rights are added
to any existing rights for the identifier. If the string starts
with a minus, the following rights are removed from any existing
rights for the identifier. If the string does not start with a
plus or minus, the rights replace any existing rights for the
identifier.
Myers Standards Track [Page 3]
RFC 2086 ACL extension January 1997
4.2. DELETEACL
Arguments: mailbox name
authentication identifier
Data: no specific data for this command
Result: OK - deleteacl completed
NO - deleteacl failure: can't delete acl
BAD - command unknown or arguments invalid
The DELETEACL command removes any <identifier,rights> pair for the
specified identifier from the access control list for the specified
mailbox.
4.3. GETACL
Arguments: mailbox name
Data: untagged responses: ACL
Result: OK - getacl completed
NO - getacl failure: can't get acl
BAD - command unknown or arguments invalid
The GETACL command returns the access control list for mailbox in
an untagged ACL reply.
Example: C: A002 GETACL INBOX
S: * ACL INBOX Fred rwipslda
S: A002 OK Getacl complete
4.4. LISTRIGHTS
Arguments: mailbox name
authentication identifier
Data: untagged responses: LISTRIGHTS
Result: OK - listrights completed
NO - listrights failure: can't get rights list
BAD - command unknown or arguments invalid
The LISTRIGHTS command takes a mailbox name and an identifier and
returns information about what rights may be granted to the identifier
in the ACL for the mailbox.
Myers Standards Track [Page 4]
RFC 2086 ACL extension January 1997
Example: C: a001 LISTRIGHTS ~/Mail/saved smith
S: * LISTRIGHTS ~/Mail/saved smith la r swicd
S: a001 OK Listrights completed
C: a005 LISTRIGHTS archive.imap anyone
S: * LISTRIGHTS archive.imap anyone "" l r s w i p c d a
0 1 2 3 4 5 6 7 8 9
4.5. MYRIGHTS
Arguments: mailbox name
Data: untagged responses: MYRIGHTS
Result: OK - myrights completed
NO - myrights failure: can't get rights
BAD - command unknown or arguments invalid
The MYRIGHTS command returns the set of rights that the user has
to mailbox in an untagged MYRIGHTS reply.
Example: C: A003 MYRIGHTS INBOX
S: * MYRIGHTS INBOX rwipslda
S: A003 OK Myrights complete
5. Responses
5.1. ACL
Data: mailbox name
zero or more identifier rights pairs
The ACL response occurs as a result of a GETACL command. The first
string is the mailbox name for which this ACL applies. This is
followed by zero or more pairs of strings, each pair contains the
identifier for which the entry applies followed by the set of
rights that the identifier has.
Myers Standards Track [Page 5]
RFC 2086 ACL extension January 1997
5.2. LISTRIGHTS
Data: mailbox name
identifier
required rights
list of optional rights
The LISTRIGHTS response occurs as a result of a LISTRIGHTS
command. The first two strings are the mailbox name and identifier
for which this rights list applies. Following the identifier is a
string containing the (possibly empty) set of rights the
identifier will always be granted in the mailbox.
Following this are zero or more strings each containing a set of
rights the identifier may be granted in the mailbox. Rights
mentioned in the same string are tied together--either all must be
granted to the identifier in the mailbox or none may be granted.
The same right may not be listed more than once in the LISTRIGHTS
command.
5.3. MYRIGHTS
Data: mailbox name
rights
The MYRIGHTS response occurs as a result of a MYRIGHTS command.
The first string is the mailbox name for which these rights apply.
The second string is the set of rights that the client has.
6. Formal Syntax
The following syntax specification uses the augmented Backus-Naur
Form (BNF) notation as specified in [RFC-822] as modified by [IMAP4].
Non-terminals referenced but not defined below are as defined by
[IMAP4].
Except as noted otherwise, all alphabetic characters are case-
insensitive. The use of upper or lower case characters to define
token strings is for editorial clarity only. Implementations MUST
accept these strings in a case-insensitive fashion.
Myers Standards Track [Page 6]
RFC 2086 ACL extension January 1997
acl_data ::= "ACL" SPACE mailbox *(SPACE identifier SPACE
rights)
deleteacl ::= "DELETEACL" SPACE mailbox SPACE identifier
getacl ::= "GETACL" SPACE mailbox
identifier ::= astring
listrights ::= "LISTRIGHTS" SPACE mailbox SPACE identifier
listrights_data ::= "LISTRIGHTS" SPACE mailbox SPACE identifier
SPACE rights *(SPACE rights)
mod_rights ::= astring
;; +rights to add, -rights to remove
;; rights to replace
myrights ::= "MYRIGHTS" SPACE mailbox
myrights_data ::= "MYRIGHTS" SPACE mailbox SPACE rights
rights ::= astring
setacl ::= "SETACL" SPACE mailbox SPACE identifier
SPACE mod_rights
7. References
[IMAP4] Crispin, M., "Internet Message Access Protocol - Version 4",
RFC 1730, University of Washington, December 1994.
[RFC-822] Crocker, D., "Standard for the Format of ARPA Internet Text
Messages", STD 11, RFC 822.
8. Security Considerations
An implementation must make sure the ACL commands themselves do not
give information about mailboxes with appropriately restricted ACL's.
For example, a GETACL command on a mailbox for which the user has
insufficient rights should not admit the mailbox exists, much less
return the mailbox's ACL.
Myers Standards Track [Page 7]
RFC 2086 ACL extension January 1997
9. Author's Address
John G. Myers
Carnegie-Mellon University
5000 Forbes Ave.
Pittsburgh PA, 15213-3890
Email: jgm+@cmu.edu
Myers Standards Track [Page 8]

View File

@ -0,0 +1,283 @@
Network Working Group J. Myers
Request for Comments: 2087 Carnegie Mellon
Category: Standards Track January 1997
IMAP4 QUOTA extension
Status of this Memo
This document specifies an Internet standards track protocol for the
Internet community, and requests discussion and suggestions for
improvements. Please refer to the current edition of the "Internet
Official Protocol Standards" (STD 1) for the standardization state
and status of this protocol. Distribution of this memo is unlimited.
1. Abstract
The QUOTA extension of the Internet Message Access Protocol [IMAP4]
permits administrative limits on resource usage (quotas) to be
manipulated through the IMAP protocol.
Table of Contents
1. Abstract........................................... 1
2. Conventions Used in this Document.................. 1
3. Introduction and Overview.......................... 2
4. Commands........................................... 2
4.1. SETQUOTA Command................................... 2
4.2. GETQUOTA Command................................... 2
4.3. GETQUOTAROOT Command............................... 3
5. Responses.......................................... 3
5.1. QUOTA Response..................................... 3
5.2. QUOTAROOT Response................................. 4
6. Formal syntax...................................... 4
7. References......................................... 5
8. Security Considerations............................ 5
9. Author's Address................................... 5
2. Conventions Used in this Document
In examples, "C:" and "S:" indicate lines sent by the client and
server respectively.
Myers Standards Track [Page 1]
RFC 2087 QUOTA January 1997
3. Introduction and Overview
The QUOTA extension is present in any IMAP4 implementation which
returns "QUOTA" as one of the supported capabilities to the
CAPABILITY command.
An IMAP4 server which supports the QUOTA capability may support
limits on any number of resources. Each resource has an atom name
and an implementation-defined interpretation which evaluates to an
integer. Examples of such resources are:
Name Interpretation
STORAGE Sum of messages' RFC822.SIZE, in units of 1024 octets
MESSAGE Number of messages
Each mailbox has zero or more implementation-defined named "quota
roots". Each quota root has zero or more resource limits. All
mailboxes that share the same named quota root share the resource
limits of the quota root.
Quota root names do not necessarily have to match the names of
existing mailboxes.
4. Commands
4.1. SETQUOTA Command
Arguments: quota root
list of resource limits
Data: untagged responses: QUOTA
Result: OK - setquota completed
NO - setquota error: can't set that data
BAD - command unknown or arguments invalid
The SETQUOTA command takes the name of a mailbox quota root and a
list of resource limits. The resource limits for the named quota root
are changed to be the specified limits. Any previous resource limits
for the named quota root are discarded.
If the named quota root did not previously exist, an implementation
may optionally create it and change the quota roots for any number of
existing mailboxes in an implementation-defined manner.
Myers Standards Track [Page 2]
RFC 2087 QUOTA January 1997
Example: C: A001 SETQUOTA "" (STORAGE 512)
S: * QUOTA "" (STORAGE 10 512)
S: A001 OK Setquota completed
4.2. GETQUOTA Command
Arguments: quota root
Data: untagged responses: QUOTA
Result: OK - getquota completed
NO - getquota error: no such quota root, permission
denied
BAD - command unknown or arguments invalid
The GETQUOTA command takes the name of a quota root and returns the
quota root's resource usage and limits in an untagged QUOTA response.
Example: C: A003 GETQUOTA ""
S: * QUOTA "" (STORAGE 10 512)
S: A003 OK Getquota completed
4.3. GETQUOTAROOT Command
Arguments: mailbox name
Data: untagged responses: QUOTAROOT, QUOTA
Result: OK - getquota completed
NO - getquota error: no such mailbox, permission denied
BAD - command unknown or arguments invalid
The GETQUOTAROOT command takes the name of a mailbox and returns the
list of quota roots for the mailbox in an untagged QUOTAROOT
response. For each listed quota root, it also returns the quota
root's resource usage and limits in an untagged QUOTA response.
Example: C: A003 GETQUOTAROOT INBOX
S: * QUOTAROOT INBOX ""
S: * QUOTA "" (STORAGE 10 512)
S: A003 OK Getquota completed
Myers Standards Track [Page 3]
RFC 2087 QUOTA January 1997
5. Responses
5.1. QUOTA Response
Data: quota root name
list of resource names, usages, and limits
This response occurs as a result of a GETQUOTA or GETQUOTAROOT
command. The first string is the name of the quota root for which
this quota applies.
The name is followed by a S-expression format list of the resource
usage and limits of the quota root. The list contains zero or
more triplets. Each triplet conatins a resource name, the current
usage of the resource, and the resource limit.
Resources not named in the list are not limited in the quota root.
Thus, an empty list means there are no administrative resource
limits in the quota root.
Example: S: * QUOTA "" (STORAGE 10 512)
5.2. QUOTAROOT Response
Data: mailbox name
zero or more quota root names
This response occurs as a result of a GETQUOTAROOT command. The
first string is the mailbox and the remaining strings are the
names of the quota roots for the mailbox.
Example: S: * QUOTAROOT INBOX ""
S: * QUOTAROOT comp.mail.mime
6. Formal syntax
The following syntax specification uses the augmented Backus-Naur
Form (BNF) notation as specified in RFC 822 with one exception; the
delimiter used with the "#" construct is a single space (SP) and not
one or more commas.
Except as noted otherwise, all alphabetic characters are case-
insensitive. The use of upper or lower case characters to define
token strings is for editorial clarity only. Implementations MUST
accept these strings in a case-insensitive fashion.
Myers Standards Track [Page 4]
RFC 2087 QUOTA January 1997
getquota ::= "GETQUOTA" SP astring
getquotaroot ::= "GETQUOTAROOT" SP astring
quota_list ::= "(" #quota_resource ")"
quota_resource ::= atom SP number SP number
quota_response ::= "QUOTA" SP astring SP quota_list
quotaroot_response
::= "QUOTAROOT" SP astring *(SP astring)
setquota ::= "SETQUOTA" SP astring SP setquota_list
setquota_list ::= "(" 0#setquota_resource ")"
setquota_resource ::= atom SP number
7. References
[IMAP4] Crispin, M., "Internet Message Access Protocol - Version 4",
RFC 1730, University of Washington, December 1994.
[RFC-822] Crocker, D., "Standard for the Format of ARPA Internet
Text Messages", STD 11, RFC 822.
8. Security Considerations
Implementors should be careful to make sure the implementation of
these commands does not violate the site's security policy. The
resource usage of other users is likely to be considered confidential
information and should not be divulged to unauthorized persons.
9. Author's Address
John G. Myers
Carnegie-Mellon University
5000 Forbes Ave.
Pittsburgh PA, 15213-3890
EMail: jgm+@cmu.edu
Myers Standards Track [Page 5]

View File

@ -0,0 +1,115 @@
Network Working Group J. Myers
Request for Comments: 2088 Carnegie Mellon
Cateogry: Standards Track January 1997
IMAP4 non-synchronizing literals
Status of this Memo
This document specifies an Internet standards track protocol for the
Internet community, and requests discussion and suggestions for
improvements. Please refer to the current edition of the "Internet
Official Protocol Standards" (STD 1) for the standardization state
and status of this protocol. Distribution of this memo is unlimited.
1. Abstract
The Internet Message Access Protocol [IMAP4] contains the "literal"
syntactic construct for communicating strings. When sending a
literal from client to server, IMAP4 requires the client to wait for
the server to send a command continuation request between sending the
octet count and the string data. This document specifies an
alternate form of literal which does not require this network round
trip.
2. Conventions Used in this Document
In examples, "C:" and "S:" indicate lines sent by the client and
server respectively.
3. Specification
The non-synchronizing literal is added an alternate form of literal,
and may appear in communication from client to server instead of the
IMAP4 form of literal. The IMAP4 form of literal, used in
communication from client to server, is referred to as a
synchronizing literal.
Non-synchronizing literals may be used with any IMAP4 server
implementation which returns "LITERAL+" as one of the supported
capabilities to the CAPABILITY command. If the server does not
advertise the LITERAL+ capability, the client must use synchronizing
literals instead.
The non-synchronizing literal is distinguished from the original
synchronizing literal by having a plus ('+') between the octet count
and the closing brace ('}'). The server does not generate a command
continuation request in response to a non-synchronizing literal, and
Myers Standards Track [Page 1]
RFC 2088 LITERAL January 1997
clients are not required to wait before sending the octets of a non-
synchronizing literal.
The protocol receiver of an IMAP4 server must check the end of every
received line for an open brace ('{') followed by an octet count, a
plus ('+'), and a close brace ('}') immediately preceeding the CRLF.
If it finds this sequence, it is the octet count of a non-
synchronizing literal and the server MUST treat the specified number
of following octets and the following line as part of the same
command. A server MAY still process commands and reject errors on a
line-by-line basis, as long as it checks for non-synchronizing
literals at the end of each line.
Example: C: A001 LOGIN {11+}
C: FRED FOOBAR {7+}
C: fat man
S: A001 OK LOGIN completed
4. Formal Syntax
The following syntax specification uses the augmented Backus-Naur
Form (BNF) notation as specified in [RFC-822] as modified by [IMAP4].
Non-terminals referenced but not defined below are as defined by
[IMAP4].
literal ::= "{" number ["+"] "}" CRLF *CHAR8
;; Number represents the number of CHAR8 octets
6. References
[IMAP4] Crispin, M., "Internet Message Access Protocol - Version 4",
draft-crispin-imap-base-XX.txt, University of Washington, April 1996.
[RFC-822] Crocker, D., "Standard for the Format of ARPA Internet Text
Messages", STD 11, RFC 822.
7. Security Considerations
There are no known security issues with this extension.
8. Author's Address
John G. Myers
Carnegie-Mellon University
5000 Forbes Ave.
Pittsburgh PA, 15213-3890
Email: jgm+@cmu.edu
Myers Standards Track [Page 2]

View File

@ -0,0 +1,227 @@
Network Working Group B. Leiba
Request for Comments: 2177 IBM T.J. Watson Research Center
Category: Standards Track June 1997
IMAP4 IDLE command
Status of this Memo
This document specifies an Internet standards track protocol for the
Internet community, and requests discussion and suggestions for
improvements. Please refer to the current edition of the "Internet
Official Protocol Standards" (STD 1) for the standardization state
and status of this protocol. Distribution of this memo is unlimited.
1. Abstract
The Internet Message Access Protocol [IMAP4] requires a client to
poll the server for changes to the selected mailbox (new mail,
deletions). It's often more desirable to have the server transmit
updates to the client in real time. This allows a user to see new
mail immediately. It also helps some real-time applications based on
IMAP, which might otherwise need to poll extremely often (such as
every few seconds). (While the spec actually does allow a server to
push EXISTS responses aysynchronously, a client can't expect this
behaviour and must poll.)
This document specifies the syntax of an IDLE command, which will
allow a client to tell the server that it's ready to accept such
real-time updates.
2. Conventions Used in this Document
In examples, "C:" and "S:" indicate lines sent by the client and
server respectively.
The key words "MUST", "MUST NOT", "SHOULD", "SHOULD NOT", and "MAY"
in this document are to be interpreted as described in RFC 2060
[IMAP4].
3. Specification
IDLE Command
Arguments: none
Responses: continuation data will be requested; the client sends
the continuation data "DONE" to end the command
Leiba Standards Track [Page 1]
RFC 2177 IMAP4 IDLE command June 1997
Result: OK - IDLE completed after client sent "DONE"
NO - failure: the server will not allow the IDLE
command at this time
BAD - command unknown or arguments invalid
The IDLE command may be used with any IMAP4 server implementation
that returns "IDLE" as one of the supported capabilities to the
CAPABILITY command. If the server does not advertise the IDLE
capability, the client MUST NOT use the IDLE command and must poll
for mailbox updates. In particular, the client MUST continue to be
able to accept unsolicited untagged responses to ANY command, as
specified in the base IMAP specification.
The IDLE command is sent from the client to the server when the
client is ready to accept unsolicited mailbox update messages. The
server requests a response to the IDLE command using the continuation
("+") response. The IDLE command remains active until the client
responds to the continuation, and as long as an IDLE command is
active, the server is now free to send untagged EXISTS, EXPUNGE, and
other messages at any time.
The IDLE command is terminated by the receipt of a "DONE"
continuation from the client; such response satisfies the server's
continuation request. At that point, the server MAY send any
remaining queued untagged responses and then MUST immediately send
the tagged response to the IDLE command and prepare to process other
commands. As in the base specification, the processing of any new
command may cause the sending of unsolicited untagged responses,
subject to the ambiguity limitations. The client MUST NOT send a
command while the server is waiting for the DONE, since the server
will not be able to distinguish a command from a continuation.
The server MAY consider a client inactive if it has an IDLE command
running, and if such a server has an inactivity timeout it MAY log
the client off implicitly at the end of its timeout period. Because
of that, clients using IDLE are advised to terminate the IDLE and
re-issue it at least every 29 minutes to avoid being logged off.
This still allows a client to receive immediate mailbox updates even
though it need only "poll" at half hour intervals.
Leiba Standards Track [Page 2]
RFC 2177 IMAP4 IDLE command June 1997
Example: C: A001 SELECT INBOX
S: * FLAGS (Deleted Seen)
S: * 3 EXISTS
S: * 0 RECENT
S: * OK [UIDVALIDITY 1]
S: A001 OK SELECT completed
C: A002 IDLE
S: + idling
...time passes; new mail arrives...
S: * 4 EXISTS
C: DONE
S: A002 OK IDLE terminated
...another client expunges message 2 now...
C: A003 FETCH 4 ALL
S: * 4 FETCH (...)
S: A003 OK FETCH completed
C: A004 IDLE
S: * 2 EXPUNGE
S: * 3 EXISTS
S: + idling
...time passes; another client expunges message 3...
S: * 3 EXPUNGE
S: * 2 EXISTS
...time passes; new mail arrives...
S: * 3 EXISTS
C: DONE
S: A004 OK IDLE terminated
C: A005 FETCH 3 ALL
S: * 3 FETCH (...)
S: A005 OK FETCH completed
C: A006 IDLE
4. Formal Syntax
The following syntax specification uses the augmented Backus-Naur
Form (BNF) notation as specified in [RFC-822] as modified by [IMAP4].
Non-terminals referenced but not defined below are as defined by
[IMAP4].
command_auth ::= append / create / delete / examine / list / lsub /
rename / select / status / subscribe / unsubscribe
/ idle
;; Valid only in Authenticated or Selected state
idle ::= "IDLE" CRLF "DONE"
Leiba Standards Track [Page 3]
RFC 2177 IMAP4 IDLE command June 1997
5. References
[IMAP4] Crispin, M., "Internet Message Access Protocol - Version
4rev1", RFC 2060, December 1996.
6. Security Considerations
There are no known security issues with this extension.
7. Author's Address
Barry Leiba
IBM T.J. Watson Research Center
30 Saw Mill River Road
Hawthorne, NY 10532
Email: leiba@watson.ibm.com
Leiba Standards Track [Page 4]

View File

@ -0,0 +1,787 @@
Network Working Group M. Gahrns
Request for Comments: 2180 Microsoft
Category: Informational July 1997
IMAP4 Multi-Accessed Mailbox Practice
Status of this Memo
This memo provides information for the Internet community. This memo
does not specify an Internet standard of any kind. Distribution of
this memo is unlimited.
1. Abstract
IMAP4[RFC-2060] is rich client/server protocol that allows a client
to access and manipulate electronic mail messages on a server.
Within the protocol framework, it is possible to have differing
results for particular client/server interactions. If a protocol does
not allow for this, it is often unduly restrictive.
For example, when multiple clients are accessing a mailbox and one
attempts to delete the mailbox, an IMAP4 server may choose to
implement a solution based upon server architectural constraints or
individual preference.
With this flexibility comes greater client responsibility. It is not
sufficient for a client to be written based upon the behavior of a
particular IMAP server. Rather the client must be based upon the
behavior allowed by the protocol.
By documenting common IMAP4 server practice for the case of
simultaneous client access to a mailbox, we hope to ensure the widest
amount of inter-operation between IMAP4 clients and servers.
The behavior described in this document reflects the practice of some
existing servers or behavior that the consensus of the IMAP mailing
list has deemed to be reasonable. The behavior described within this
document is believed to be [RFC-2060] compliant. However, this
document is not meant to define IMAP4 compliance, nor is it an
exhaustive list of valid IMAP4 behavior. [RFC-2060] must always be
consulted to determine IMAP4 compliance, especially for server
behavior not described within this document.
Gahrns Informational [Page 1]
RFC 2180 IMAP4 Multi-Accessed Mailbox Practice July 1997
2. Conventions used in this document
In examples,"C1:", "C2:" and "C3:" indicate lines sent by 3 different
clients (client #1, client #2 and client #3) that are connected to a
server. "S1:", "S2:" and "S3:" indicated lines sent by the server to
client #1, client #2 and client #3 respectively.
A shared mailbox, is a mailbox that can be used by multiple users.
A multi-accessed mailbox, is a mailbox that has multiple clients
simultaneously accessing it.
A client is said to have accessed a mailbox after a successful SELECT
or EXAMINE command.
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
"SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
document are to be interpreted as described in [RFC-2119].
3. Deletion/Renaming of a multi-accessed mailbox
If an external agent or multiple clients are accessing a mailbox,
care must be taken when handling the deletion or renaming of the
mailbox. Following are some strategies an IMAP server may choose to
use when dealing with this situation.
3.1. The server MAY fail the DELETE/RENAME command of a multi-accessed
mailbox
In some cases, this behavior may not be practical. For example, if a
large number of clients are accessing a shared mailbox, the window in
which no clients have the mailbox accessed may be small or non-
existent, effectively rendering the mailbox undeletable or
unrenamable.
Example:
<Client #1 and Client #2 have mailbox FOO accessed. Client #1 tries
to DELETE the mailbox and is refused>
C1: A001 DELETE FOO
S1: A001 NO Mailbox FOO is in use by another user.
Gahrns Informational [Page 2]
RFC 2180 IMAP4 Multi-Accessed Mailbox Practice July 1997
3.2. The server MAY allow the DELETE command of a multi-accessed
mailbox, but keep the information in the mailbox available for
those clients that currently have access to the mailbox.
When all clients have finished accessing the mailbox, it is
permanently removed. For clients that do not already have access to
the mailbox, the 'ghosted' mailbox would not be available. For
example, it would not be returned to these clients in a subsequent
LIST or LSUB command and would not be a valid mailbox argument to any
other IMAP command until the reference count of clients accessing the
mailbox reached 0.
In some cases, this behavior may not be desirable. For example if
someone created a mailbox with offensive or sensitive information,
one might prefer to have the mailbox deleted and all access to the
information contained within removed immediately, rather than
continuing to allow access until the client closes the mailbox.
Furthermore, this behavior, may prevent 'recycling' of the same
mailbox name until all clients have finished accessing the original
mailbox.
Example:
<Client #1 and Client #2 have mailbox FOO selected. Client #1 DELETEs
mailbox FOO>
C1: A001 DELETE FOO
S1: A001 OK Mailbox FOO is deleted.
<Client #2 is still able to operate on the deleted mailbox>
C2: B001 STORE 1 +FLAGS (\Seen)
S2: * 1 FETCH FLAGS (\Seen)
S2: B001 OK STORE completed
<Client #3 which did not have access to the mailbox prior to the
deletion by client #1 does not have access to the mailbox>
C3: C001 STATUS FOO (MESSAGES)
S3: C001 NO Mailbox does not exist
<Nor is client #3 able to create a mailbox with the name FOO, while
the reference count is non zero>
C3: C002 CREATE FOO
S3: C002 NO Mailbox FOO is still in use. Try again later.
Gahrns Informational [Page 3]
RFC 2180 IMAP4 Multi-Accessed Mailbox Practice July 1997
<Client #2 closes its access to the mailbox, no other clients have
access to the mailbox FOO and reference count becomes 0>
C2: B002 CLOSE
S2: B002 OK CLOSE Completed
<Now that the reference count on FOO has reached 0, the mailbox name
can be recycled>
C3: C003 CREATE FOO
S3: C003 OK CREATE Completed
3.3. The server MAY allow the DELETE/RENAME of a multi-accessed
mailbox, but disconnect all other clients who have the mailbox
accessed by sending a untagged BYE response.
A server may often choose to disconnect clients in the DELETE case,
but may choose to implement a "friendlier" method for the RENAME
case.
Example:
<Client #1 and Client #2 have mailbox FOO accessed. Client #1 DELETEs
the mailbox FOO>
C1: A002 DELETE FOO
S1: A002 OK DELETE completed.
<Server disconnects all other users of the mailbox>
S2: * BYE Mailbox FOO has been deleted.
3.4. The server MAY allow the RENAME of a multi-accessed mailbox by
simply changing the name attribute on the mailbox.
Other clients that have access to the mailbox can continue issuing
commands such as FETCH that do not reference the mailbox name.
Clients would discover the renaming the next time they referred to
the old mailbox name. Some servers MAY choose to include the
[NEWNAME] response code in their tagged NO response to a command that
contained the old mailbox name, as a hint to the client that the
operation can succeed if the command is issued with the new mailbox
name.
Gahrns Informational [Page 4]
RFC 2180 IMAP4 Multi-Accessed Mailbox Practice July 1997
Example:
<Client #1 and Client #2 have mailbox FOO accessed. Client #1 RENAMEs
the mailbox.>
C1: A001 RENAME FOO BAR
S1: A001 OK RENAME completed.
<Client #2 is still able to do operations that do not reference the
mailbox name>
C2: B001 FETCH 2:4 (FLAGS)
S2: * 2 FETCH . . .
S2: * 3 FETCH . . .
S2: * 4 FETCH . . .
S2: B001 OK FETCH completed
<Client #2 is not able to do operations that reference the mailbox
name>
C2: B002 APPEND FOO {300} C2: Date: Mon, 7 Feb 1994
21:52:25 0800 (PST) C2: . . . S2: B002 NO [NEWNAME FOO
BAR] Mailbox has been renamed
4. Expunging of messages on a multi-accessed mailbox
If an external agent or multiple clients are accessing a mailbox,
care must be taken when handling the EXPUNGE of messages. Other
clients accessing the mailbox may be in the midst of issuing a
command that depends upon message sequence numbers. Because an
EXPUNGE response can not be sent while responding to a FETCH, STORE
or SEARCH command, it is not possible to immediately notify the
client of the EXPUNGE. This can result in ambiguity if the client
issues a FETCH, STORE or SEARCH operation on a message that has been
EXPUNGED.
4.1. Fetching of expunged messages
Following are some strategies an IMAP server may choose to use when
dealing with a FETCH command on expunged messages.
Gahrns Informational [Page 5]
RFC 2180 IMAP4 Multi-Accessed Mailbox Practice July 1997
Consider the following scenario:
- Client #1 and Client #2 have mailbox FOO selected.
- There are 7 messages in the mailbox.
- Messages 4:7 are marked for deletion.
- Client #1 issues an EXPUNGE, to expunge messages 4:7
4.1.1. The server MAY allow the EXPUNGE of a multi-accessed mailbox but
keep the messages available to satisfy subsequent FETCH commands
until it is able to send an EXPUNGE response to each client.
In some cases, the behavior of keeping "ghosted" messages may not be
desirable. For example if a message contained offensive or sensitive
information, one might prefer to instantaneously remove all access to
the information, regardless of whether another client is in the midst
of accessing it.
Example: (Building upon the scenario outlined in 4.1.)
<Client #2 is still able to access the expunged messages because the
server has kept a 'ghosted' copy of the messages until it is able to
notify client #2 of the EXPUNGE>
C2: B001 FETCH 4:7 RFC822
S2: * 4 FETCH RFC822 . . . (RFC822 info returned)
S2: * 5 FETCH RFC822 . . . (RFC822 info returned)
S2: * 6 FETCH RFC822 . . . (RFC822 info returned)
S2: * 7 FETCH RFC822 . . . (RFC822 info returned)
S2: B001 OK FETCH Completed
<Client #2 issues a command where it can get notified of the EXPUNGE>
C2: B002 NOOP
S2: * 4 EXPUNGE
S2: * 4 EXPUNGE
S2: * 4 EXPUNGE
S2: * 4 EXPUNGE
S2: * 3 EXISTS
S2: B002 OK NOOP Complete
<Client #2 no longer has access to the expunged messages>
C2: B003 FETCH 4:7 RFC822
S2: B003 NO Messages 4:7 are no longer available.
Gahrns Informational [Page 6]
RFC 2180 IMAP4 Multi-Accessed Mailbox Practice July 1997
4.1.2 The server MAY allow the EXPUNGE of a multi-accessed mailbox,
and on subsequent FETCH commands return FETCH responses only for
non-expunged messages and a tagged NO.
After receiving a tagged NO FETCH response, the client SHOULD issue a
NOOP command so that it will be informed of any pending EXPUNGE
responses. The client may then either reissue the failed FETCH
command, or by examining the EXPUNGE response from the NOOP and the
FETCH response from the FETCH, determine that the FETCH failed
because of pending expunges.
Example: (Building upon the scenario outlined in 4.1.)
<Client #2 attempts to FETCH a mix of expunged and non-expunged
messages. A FETCH response is returned only for then non-expunged
messages along with a tagged NO>
C2: B001 FETCH 3:5 ENVELOPE
S2: * 3 FETCH ENVELOPE . . . (ENVELOPE info returned)
S2: B001 NO Some of the requested messages no longer exist
<Upon receiving a tagged NO FETCH response, Client #2 issues a NOOP
to be informed of any pending EXPUNGE responses>
C2: B002 NOOP
S2: * 4 EXPUNGE
S2: * 4 EXPUNGE
S2: * 4 EXPUNGE
S2: * 4 EXPUNGE
S2: * 3 EXISTS
S2: B002 OK NOOP Completed.
<By receiving a FETCH response for message 3, and an EXPUNGE response
that indicates messages 4:7 have been expunged, the client does not
need to re-issue the FETCH>
Gahrns Informational [Page 7]
RFC 2180 IMAP4 Multi-Accessed Mailbox Practice July 1997
4.1.3 The server MAY allow the EXPUNGE of a multi-accessed mailbox, and
on subsequent FETCH commands return the usual FETCH responses for
non-expunged messages, "NIL FETCH Responses" for expunged
messages, and a tagged OK response.
If all of the messages in the subsequent FETCH command have been
expunged, the server SHOULD return only a tagged NO. In this case,
the client SHOULD issue a NOOP command so that it will be informed of
any pending EXPUNGE responses. The client may then either reissue
the failed FETCH command, or by examining the EXPUNGE response from
the NOOP, determine that the FETCH failed because of pending
expunges.
"NIL FETCH responses" are a representation of empty data as
appropriate for the FETCH argument specified.
Example:
* 1 FETCH (ENVELOPE (NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL))
* 1 FETCH (FLAGS ())
* 1 FETCH (INTERNALDATE "00-Jan-0000 00:00:00 +0000")
* 1 FETCH (RFC822 "")
* 1 FETCH (RFC822.HEADER "")
* 1 FETCH (RFC822.TEXT "")
* 1 FETCH (RFC822.SIZE 0)
* 1 FETCH (BODY ("TEXT" "PLAIN" NIL NIL NIL "7BIT" 0 0)
* 1 FETCH (BODYSTRUCTURE ("TEXT" "PLAIN" NIL NIL NIL "7BIT" 0 0)
* 1 FETCH (BODY[<section>] "")
* 1 FETCH (BODY[<section>]<partial> "")
In some cases, a client may not be able to distinguish between "NIL
FETCH responses" received because a message was expunged and those
received because the data actually was NIL. For example, a * 5
FETCH (FLAGS ()) response could be received if no flags were set on
message 5, or because message 5 was expunged. In a case of potential
ambiguity, the client SHOULD issue a command such as NOOP to force
the sending of the EXPUNGE responses to resolve any ambiguity.
Example: (Building upon the scenario outlined in 4.1.)
<Client #2 attempts to access a mix of expunged and non-expunged
messages. Normal data is returned for non-expunged message, "NIL
FETCH responses" are returned for expunged messages>
Gahrns Informational [Page 8]
RFC 2180 IMAP4 Multi-Accessed Mailbox Practice July 1997
C2: B002 FETCH 3:5 ENVELOPE
S2: * 3 FETCH ENVELOPE . . . (ENVELOPE info returned)
S2: * 4 FETCH ENVELOPE (NIL NIL NIL NIL NIL NIL NIL NIL
NIL NIL)
S2: * 5 FETCH ENVELOPE (NIL NIL NIL NIL NIL NIL NIL NIL
NIL NIL)
S2: B002 OK FETCH Completed
<Client #2 attempts to FETCH only expunged messages and receives a
tagged NO response>
C2: B002 FETCH 4:7 ENVELOPE
S2: B002 NO Messages 4:7 have been expunged.
4.1.4 To avoid the situation altogether, the server MAY fail the
EXPUNGE of a multi-accessed mailbox
In some cases, this behavior may not be practical. For example, if a
large number of clients are accessing a shared mailbox, the window in
which no clients have the mailbox accessed may be small or non-
existent, effectively rendering the message unexpungeable.
4.2. Storing of expunged messages
Following are some strategies an IMAP server may choose to use when
dealing with a STORE command on expunged messages.
4.2.1 If the ".SILENT" suffix is used, and the STORE completed
successfully for all the non-expunged messages, the server SHOULD
return a tagged OK.
Example: (Building upon the scenario outlined in 4.1.)
<Client #2 tries to silently STORE flags on expunged and non-
expunged messages. The server sets the flags on the non-expunged
messages and returns OK>
C2: B001 STORE 1:7 +FLAGS.SILENT (\SEEN)
S2: B001 OK
Gahrns Informational [Page 9]
RFC 2180 IMAP4 Multi-Accessed Mailbox Practice July 1997
4.2.2. If the ".SILENT" suffix is not used, and only expunged messages
are referenced, the server SHOULD return only a tagged NO.
Example: (Building upon the scenario outlined in 4.1.)
<Client #2 tries to STORE flags only on expunged messages>
C2: B001 STORE 5:7 +FLAGS (\SEEN)
S2: B001 NO Messages have been expunged
4.2.3. If the ".SILENT" suffix is not used, and a mixture of expunged
and non-expunged messages are referenced, the server MAY set the
flags and return a FETCH response for the non-expunged messages
along with a tagged NO.
After receiving a tagged NO STORE response, the client SHOULD issue a
NOOP command so that it will be informed of any pending EXPUNGE
responses. The client may then either reissue the failed STORE
command, or by examining the EXPUNGE responses from the NOOP and
FETCH responses from the STORE, determine that the STORE failed
because of pending expunges.
Example: (Building upon the scenario outlined in 4.1.)
<Client #2 tries to STORE flags on a mixture of expunged and non-
expunged messages>
C2: B001 STORE 1:7 +FLAGS (\SEEN)
S2: * FETCH 1 FLAGS (\SEEN)
S2: * FETCH 2 FLAGS (\SEEN)
S2: * FETCH 3 FLAGS (\SEEN)
S2: B001 NO Some of the messages no longer exist.
C2: B002 NOOP
S2: * 4 EXPUNGE
S2: * 4 EXPUNGE
S2: * 4 EXPUNGE
S2: * 4 EXPUNGE
S2: * 3 EXISTS
S2: B002 OK NOOP Completed.
<By receiving FETCH responses for messages 1:3, and an EXPUNGE
response that indicates messages 4:7 have been expunged, the client
does not need to re-issue the STORE>
Gahrns Informational [Page 10]
RFC 2180 IMAP4 Multi-Accessed Mailbox Practice July 1997
4.2.4. If the ".SILENT" suffix is not used, and a mixture of expunged
and non-expunged messages are referenced, the server MAY return
an untagged NO and not set any flags.
After receiving a tagged NO STORE response, the client SHOULD issue a
NOOP command so that it will be informed of any pending EXPUNGE
responses. The client would then re-issue the STORE command after
updating its message list per any EXPUNGE response.
If a large number of clients are accessing a shared mailbox, the
window in which there are no pending expunges may be small or non-
existent, effectively disallowing a client from setting the flags on
all messages at once.
Example: (Building upon the scenario outlined in 4.1.)
<Client #2 tries to STORE flags on a mixture of expunged and non-
expunged messages>
C2: B001 STORE 1:7 +FLAGS (\SEEN)
S2: B001 NO Some of the messages no longer exist.
<Client #2 issues a NOOP to be informed of the EXPUNGED messages>
C2: B002 NOOP
S2: * 4 EXPUNGE
S2: * 4 EXPUNGE
S2: * 4 EXPUNGE
S2: * 4 EXPUNGE
S2: * 3 EXISTS
S2: B002 OK NOOP Completed.
<Client #2 updates its message list and re-issues the STORE on only
those messages that have not been expunged>
C2: B003 STORE 1:3 +FLAGS (\SEEN) S2: * FETCH 1 FLAGS
(\SEEN) S2: * FETCH 2 FLAGS (\SEEN) S2: * FETCH 3 FLAGS
(\SEEN) S2: B003 OK STORE Completed
4.3. Searching of expunged messages
A server MAY simply not return a search response for messages that
have been expunged and it has not been able to inform the client
about. If a client was expecting a particular message to be returned
in a search result, and it was not, the client SHOULD issue a NOOP
command to see if the message was expunged by another client.
Gahrns Informational [Page 11]
RFC 2180 IMAP4 Multi-Accessed Mailbox Practice July 1997
4.4 Copying of expunged messages
COPY is the only IMAP4 sequence number command that is safe to allow
an EXPUNGE response on. This is because a client is not permitted to
cascade several COPY commands together. A client is required to wait
and confirm that the copy worked before issuing another one.
4.4.1 The server MAY disallow the COPY of messages in a multi-access
mailbox that contains expunged messages.
Pending EXPUNGE response(s) MUST be returned to the COPY command.
Example:
C: A001 COPY 2,4,6,8 FRED
S: * 4 EXPUNGE
S: A001 NO COPY rejected, because some of the requested
messages were expunged
Note: Non of the above messages are copied because if a COPY command
is unsuccessful, the server MUST restore the destination mailbox to
its state before the COPY attempt.
4.4.2 The server MAY allow the COPY of messages in a multi-access
mailbox that contains expunged messages.
Pending EXPUNGE response(s) MUST be returned to the COPY command.
Messages that are copied are messages corresponding to sequence
numbers before any EXPUNGE response.
Example:
C: A001 COPY 2,4,6,8 FRED
S: * 3 EXPUNGE
S: A001 OK COPY completed
In the above example, the messages that are copied to FRED are
messages 2,4,6,8 at the start of the COPY command. These are
equivalent to messages 2,3,5,7 at the end of the COPY command. The
EXPUNGE response can't take place until after the messages from the
COPY command are identified (because of the "no expunge while no
commands in progress" rule).
Gahrns Informational [Page 12]
RFC 2180 IMAP4 Multi-Accessed Mailbox Practice July 1997
Example:
C: A001 COPY 2,4,6,8 FRED
S: * 4 EXPUNGE
S: A001 OK COPY completed
In the above example, message 4 was copied before it was expunged,
and MUST appear in the destination mailbox FRED.
5. Security Considerations
This document describes behavior of servers that use the IMAP4
protocol, and as such, has the same security considerations as
described in [RFC-2060].
In particular, some described server behavior does not allow for the
immediate deletion of information when a mailbox is accessed by
multiple clients. This may be a consideration when dealing with
sensitive information where immediate deletion would be preferred.
6. References
[RFC-2060], Crispin, M., "Internet Message Access Protocol - Version
4rev1", RFC 2060, University of Washington, December 1996.
[RFC-2119], Bradner, S., "Key words for use in RFCs to Indicate
Requirement Levels", RFC 2119, Harvard University, March 1997.
7. Acknowledgments
This document is the result of discussions on the IMAP4 mailing list
and is meant to reflect consensus of this group. In particular,
Raymond Cheng, Mark Crispin, Jim Evans, Erik Forsberg, Steve Hole,
Mark Keasling, Barry Leiba, Syd Logan, John Mani, Pat Moran, Larry
Osterman, Chris Newman, Bart Schaefer, Vladimir Vulovic, and Jack De
Winter were active participants in this discussion or made
suggestions to this document.
Gahrns Informational [Page 13]
RFC 2180 IMAP4 Multi-Accessed Mailbox Practice July 1997
8. Author's Address
Mike Gahrns
Microsoft
One Microsoft Way
Redmond, WA, 98072
Phone: (206) 936-9833
EMail: mikega@microsoft.com
Gahrns Informational [Page 14]

View File

@ -0,0 +1,899 @@
Network Working Group C. Newman
Request for Comments: 2192 Innosoft
Category: Standards Track September 1997
IMAP URL Scheme
Status of this memo
This document specifies an Internet standards track protocol for
the Internet community, and requests discussion and suggestions for
improvements. Please refer to the current edition of the "Internet
Official Protocol Standards" (STD 1) for the standardization state
and status of this protocol. Distribution of this memo is
unlimited.
Abstract
IMAP [IMAP4] is a rich protocol for accessing remote message
stores. It provides an ideal mechanism for accessing public
mailing list archives as well as private and shared message stores.
This document defines a URL scheme for referencing objects on an
IMAP server.
1. Conventions used in this document
The key words "MUST", "MUST NOT", "SHOULD", "SHOULD NOT", and "MAY"
in this document are to be interpreted as defined in "Key words for
use in RFCs to Indicate Requirement Levels" [KEYWORDS].
2. IMAP scheme
The IMAP URL scheme is used to designate IMAP servers, mailboxes,
messages, MIME bodies [MIME], and search programs on Internet hosts
accessible using the IMAP protocol.
The IMAP URL follows the common Internet scheme syntax as defined
in RFC 1738 [BASIC-URL] except that clear text passwords are not
permitted. If :<port> is omitted, the port defaults to 143.
Newman Standards Track [Page 1]
RFC 2192 IMAP URL Scheme September 1997
An IMAP URL takes one of the following forms:
imap://<iserver>/
imap://<iserver>/<enc_list_mailbox>;TYPE=<list_type>
imap://<iserver>/<enc_mailbox>[uidvalidity][?<enc_search>]
imap://<iserver>/<enc_mailbox>[uidvalidity]<iuid>[isection]
The first form is used to refer to an IMAP server, the second form
refers to a list of mailboxes, the third form refers to the
contents of a mailbox or a set of messages resulting from a search,
and the final form refers to a specific message or message part.
Note that the syntax here is informal. The authoritative formal
syntax for IMAP URLs is defined in section 11.
3. IMAP User Name and Authentication Mechanism
A user name and/or authentication mechanism may be supplied. They
are used in the "LOGIN" or "AUTHENTICATE" commands after making the
connection to the IMAP server. If no user name or authentication
mechanism is supplied, the user name "anonymous" is used with the
"LOGIN" command and the password is supplied as the Internet e-mail
address of the end user accessing the resource. If the URL doesn't
supply a user name, the program interpreting the IMAP URL SHOULD
request one from the user if necessary.
An authentication mechanism can be expressed by adding
";AUTH=<enc_auth_type>" to the end of the user name. When such an
<enc_auth_type> is indicated, the client SHOULD request appropriate
credentials from that mechanism and use the "AUTHENTICATE" command
instead of the "LOGIN" command. If no user name is specified, one
SHOULD be obtained from the mechanism or requested from the user as
appropriate.
The string ";AUTH=*" indicates that the client SHOULD select an
appropriate authentication mechanism. It MAY use any mechanism
listed in the CAPABILITY command or use an out of band security
service resulting in a PREAUTH connection. If no user name is
specified and no appropriate authentication mechanisms are
available, the client SHOULD fall back to anonymous login as
described above. This allows a URL which grants read-write access
to authorized users, and read-only anonymous access to other users.
If a user name is included with no authentication mechanism, then
";AUTH=*" is assumed.
Newman Standards Track [Page 2]
RFC 2192 IMAP URL Scheme September 1997
Since URLs can easily come from untrusted sources, care must be
taken when resolving a URL which requires or requests any sort of
authentication. If authentication credentials are supplied to the
wrong server, it may compromise the security of the user's account.
The program resolving the URL should make sure it meets at least
one of the following criteria in this case:
(1) The URL comes from a trusted source, such as a referral server
which the client has validated and trusts according to site policy.
Note that user entry of the URL may or may not count as a trusted
source, depending on the experience level of the user and site
policy.
(2) Explicit local site policy permits the client to connect to the
server in the URL. For example, if the client knows the site
domain name, site policy may dictate that any hostname ending in
that domain is trusted.
(3) The user confirms that connecting to that domain name with the
specified credentials and/or mechanism is permitted.
(4) A mechanism is used which validates the server before passing
potentially compromising client credentials.
(5) An authentication mechanism is used which will not reveal
information to the server which could be used to compromise future
connections.
URLs which do not include a user name must be treated with extra
care, since they are more likely to compromise the user's primary
account. A URL containing ";AUTH=*" must also be treated with
extra care since it might fall back on a weaker security mechanism.
Finally, clients are discouraged from using a plain text password
as a fallback with ";AUTH=*" unless the connection has strong
encryption (e.g. a key length of greater than 56 bits).
A program interpreting IMAP URLs MAY cache open connections to an
IMAP server for later re-use. If a URL contains a user name, only
connections authenticated as that user may be re-used. If a URL
does not contain a user name or authentication mechanism, then only
an anonymous connection may be re-used. If a URL contains an
authentication mechanism without a user name, then any non-
anonymous connection may be re-used.
Note that if unsafe or reserved characters such as " " or ";" are
present in the user name or authentication mechanism, they MUST be
encoded as described in RFC 1738 [BASIC-URL].
Newman Standards Track [Page 3]
RFC 2192 IMAP URL Scheme September 1997
4. IMAP server
An IMAP URL referring to an IMAP server has the following form:
imap://<iserver>/
A program interpreting this URL would issue the standard set of
commands it uses to present a view of the contents of an IMAP
server. This is likely to be semanticly equivalent to one of the
following URLs:
imap://<iserver>/;TYPE=LIST
imap://<iserver>/;TYPE=LSUB
The program interpreting this URL SHOULD use the LSUB form if it
supports mailbox subscriptions.
5. Lists of mailboxes
An IMAP URL referring to a list of mailboxes has the following
form:
imap://<iserver>/<enc_list_mailbox>;TYPE=<list_type>
The <list_type> may be either "LIST" or "LSUB", and is case
insensitive. The field ";TYPE=<list_type>" MUST be included.
The <enc_list_mailbox> is any argument suitable for the
list_mailbox field of the IMAP [IMAP4] LIST or LSUB commands. The
field <enc_list_mailbox> may be omitted, in which case the program
interpreting the IMAP URL may use "*" or "%" as the
<enc_list_mailbox>. The program SHOULD use "%" if it supports a
hierarchical view, otherwise it SHOULD use "*".
Note that if unsafe or reserved characters such as " " or "%" are
present in <enc_list_mailbox> they MUST be encoded as described in
RFC 1738 [BASIC-URL]. If the character "/" is present in
enc_list_mailbox, it SHOULD NOT be encoded.
6. Lists of messages
An IMAP URL referring to a list of messages has the following form:
imap://<iserver>/<enc_mailbox>[uidvalidity][?<enc_search>]
Newman Standards Track [Page 4]
RFC 2192 IMAP URL Scheme September 1997
The <enc_mailbox> field is used as the argument to the IMAP4
"SELECT" command. Note that if unsafe or reserved characters such
as " ", ";", or "?" are present in <enc_mailbox> they MUST be
encoded as described in RFC 1738 [BASIC-URL]. If the character "/"
is present in enc_mailbox, it SHOULD NOT be encoded.
The [uidvalidity] field is optional. If it is present, it MUST be
the argument to the IMAP4 UIDVALIDITY status response at the time
the URL was created. This SHOULD be used by the program
interpreting the IMAP URL to determine if the URL is stale.
The [?<enc_search>] field is optional. If it is not present, the
contents of the mailbox SHOULD be presented by the program
interpreting the URL. If it is present, it SHOULD be used as the
arguments following an IMAP4 SEARCH command with unsafe characters
such as " " (which are likely to be present in the <enc_search>)
encoded as described in RFC 1738 [BASIC-URL].
7. A specific message or message part
An IMAP URL referring to a specific message or message part has the
following form:
imap://<iserver>/<enc_mailbox>[uidvalidity]<iuid>[isection]
The <enc_mailbox> and [uidvalidity] are as defined above.
If [uidvalidity] is present in this form, it SHOULD be used by the
program interpreting the URL to determine if the URL is stale.
The <iuid> refers to an IMAP4 message UID, and SHOULD be used as
the <set> argument to the IMAP4 "UID FETCH" command.
The [isection] field is optional. If not present, the URL refers
to the entire Internet message as returned by the IMAP command "UID
FETCH <uid> BODY.PEEK[]". If present, the URL refers to the object
returned by a "UID FETCH <uid> BODY.PEEK[<section>]" command. The
type of the object may be determined with a "UID FETCH <uid>
BODYSTRUCTURE" command and locating the appropriate part in the
resulting BODYSTRUCTURE. Note that unsafe characters in [isection]
MUST be encoded as described in [BASIC-URL].
Newman Standards Track [Page 5]
RFC 2192 IMAP URL Scheme September 1997
8. Relative IMAP URLs
Relative IMAP URLs are permitted and are resolved according to the
rules defined in RFC 1808 [REL-URL] with one exception. In IMAP
URLs, parameters are treated as part of the normal path with
respect to relative URL resolution. This is believed to be the
behavior of the installed base and is likely to be documented in a
future revision of the relative URL specification.
The following observations are also important:
The <iauth> grammar element is considered part of the user name for
purposes of resolving relative IMAP URLs. This means that unless a
new login/server specification is included in the relative URL, the
authentication mechanism is inherited from a base IMAP URL.
URLs always use "/" as the hierarchy delimiter for the purpose of
resolving paths in relative URLs. IMAP4 permits the use of any
hierarchy delimiter in mailbox names. For this reason, relative
mailbox paths will only work if the mailbox uses "/" as the
hierarchy delimiter. Relative URLs may be used on mailboxes which
use other delimiters, but in that case, the entire mailbox name
MUST be specified in the relative URL or inherited as a whole from
the base URL.
The base URL for a list of mailboxes or messages which was referred
to by an IMAP URL is always the referring IMAP URL itself. The
base URL for a message or message part which was referred to by an
IMAP URL may be more complicated to determine. The program
interpreting the relative URL will have to check the headers of the
MIME entity and any enclosing MIME entities in order to locate the
"Content-Base" and "Content-Location" headers. These headers are
used to determine the base URL as defined in [HTTP]. For example,
if the referring IMAP URL contains a "/;SECTION=1.2" parameter,
then the MIME headers for section 1.2, for section 1, and for the
enclosing message itself SHOULD be checked in that order for
"Content-Base" or "Content-Location" headers.
9. Multinational Considerations
IMAP4 [IMAP4] section 5.1.3 includes a convention for encoding
non-US-ASCII characters in IMAP mailbox names. Because this
convention is private to IMAP, it is necessary to convert IMAP's
encoding to one that can be more easily interpreted by a URL
display program. For this reason, IMAP's modified UTF-7 encoding
for mailboxes MUST be converted to UTF-8 [UTF8]. Since 8-bit
characters are not permitted in URLs, the UTF-8 characters are
Newman Standards Track [Page 6]
RFC 2192 IMAP URL Scheme September 1997
encoded as required by the URL specification [BASIC-URL]. Sample
code is included in Appendix A to demonstrate this conversion.
10. Examples
The following examples demonstrate how an IMAP4 client program
might translate various IMAP4 URLs into a series of IMAP4 commands.
Commands sent from the client to the server are prefixed with "C:",
and responses sent from the server to the client are prefixed with
"S:".
The URL:
<imap://minbari.org/gray-council;UIDVALIDITY=385759045/;UID=20>
Results in the following client commands:
<connect to minbari.org, port 143>
C: A001 LOGIN ANONYMOUS sheridan@babylon5.org
C: A002 SELECT gray-council
<client verifies the UIDVALIDITY matches>
C: A003 UID FETCH 20 BODY.PEEK[]
The URL:
<imap://michael@minbari.org/users.*;type=list>
Results in the following client commands:
<client requests password from user>
<connect to minbari.org imap server, activate strong encryption>
C: A001 LOGIN MICHAEL zipper
C: A002 LIST "" users.*
The URL:
<imap://psicorp.org/~peter/%E6%97%A5%E6%9C%AC%E8%AA%9E/
%E5%8F%B0%E5%8C%97>
Results in the following client commands:
<connect to psicorp.org, port 143>
C: A001 LOGIN ANONYMOUS bester@psycop.psicorp.org
C: A002 SELECT ~peter/&ZeVnLIqe-/&U,BTFw-
<commands the client uses for viewing the contents of a mailbox>
Newman Standards Track [Page 7]
RFC 2192 IMAP URL Scheme September 1997
The URL:
<imap://;AUTH=KERBEROS_V4@minbari.org/gray-council/;uid=20/
;section=1.2>
Results in the following client commands:
<connect to minbari.org, port 143>
C: A001 AUTHENTICATE KERBEROS_V4
<authentication exchange>
C: A002 SELECT gray-council
C: A003 UID FETCH 20 BODY.PEEK[1.2]
If the following relative URL is located in that body part:
<;section=1.4>
This could result in the following client commands:
C: A004 UID FETCH 20 (BODY.PEEK[1.2.MIME]
BODY.PEEK[1.MIME]
BODY.PEEK[HEADER.FIELDS (Content-Base Content-Location)])
<Client looks for Content-Base or Content-Location headers in
result. If no such headers, then it does the following>
C: A005 UID FETCH 20 BODY.PEEK[1.4]
The URL:
<imap://;AUTH=*@minbari.org/gray%20council?SUBJECT%20shadows>
Could result in the following:
<connect to minbari.org, port 143>
C: A001 CAPABILITY
S: * CAPABILITY IMAP4rev1 AUTH=GSSAPI
S: A001 OK
C: A002 AUTHENTICATE GSSAPI
<authentication exchange>
S: A002 OK user lennier authenticated
C: A003 SELECT "gray council"
...
C: A004 SEARCH SUBJECT shadows
S: * SEARCH 8 10 13 14 15 16
S: A004 OK SEARCH completed
C: A005 FETCH 8,10,13:16 ALL
...
Newman Standards Track [Page 8]
RFC 2192 IMAP URL Scheme September 1997
NOTE: In this final example, the client has implementation
dependent choices. The authentication mechanism could be anything,
including PREAUTH. And the final FETCH command could fetch more or
less information about the messages, depending on what it wishes to
display to the user.
11. Security Considerations
Security considerations discussed in the IMAP specification [IMAP4]
and the URL specification [BASIC-URL] are relevant. Security
considerations related to authenticated URLs are discussed in
section 3 of this document.
Many email clients store the plain text password for later use
after logging into an IMAP server. Such clients MUST NOT use a
stored password in response to an IMAP URL without explicit
permission from the user to supply that password to the specified
host name.
12. ABNF for IMAP URL scheme
This uses ABNF as defined in RFC 822 [IMAIL]. Terminals from the
BNF for IMAP [IMAP4] and URLs [BASIC-URL] are also used. Strings
are not case sensitive and free insertion of linear-white-space is
not permitted.
achar = uchar / "&" / "=" / "~"
; see [BASIC-URL] for "uchar" definition
bchar = achar / ":" / "@" / "/"
enc_auth_type = 1*achar
; encoded version of [IMAP-AUTH] "auth_type"
enc_list_mailbox = 1*bchar
; encoded version of [IMAP4] "list_mailbox"
enc_mailbox = 1*bchar
; encoded version of [IMAP4] "mailbox"
enc_search = 1*bchar
; encoded version of search_program below
enc_section = 1*bchar
; encoded version of section below
Newman Standards Track [Page 9]
RFC 2192 IMAP URL Scheme September 1997
enc_user = 1*achar
; encoded version of [IMAP4] "userid"
imapurl = "imap://" iserver "/" [ icommand ]
iauth = ";AUTH=" ( "*" / enc_auth_type )
icommand = imailboxlist / imessagelist / imessagepart
imailboxlist = [enc_list_mailbox] ";TYPE=" list_type
imessagelist = enc_mailbox [ "?" enc_search ] [uidvalidity]
imessagepart = enc_mailbox [uidvalidity] iuid [isection]
isection = "/;SECTION=" enc_section
iserver = [iuserauth "@"] hostport
; See [BASIC-URL] for "hostport" definition
iuid = "/;UID=" nz_number
; See [IMAP4] for "nz_number" definition
iuserauth = enc_user [iauth] / [enc_user] iauth
list_type = "LIST" / "LSUB"
search_program = ["CHARSET" SPACE astring SPACE]
search_key *(SPACE search_key)
; IMAP4 literals may not be used
; See [IMAP4] for "astring" and "search_key"
section = section_text / (nz_number *["." nz_number]
["." (section_text / "MIME")])
; See [IMAP4] for "section_text" and "nz_number"
uidvalidity = ";UIDVALIDITY=" nz_number
; See [IMAP4] for "nz_number" definition
13. References
[BASIC-URL] Berners-Lee, Masinter, McCahill, "Uniform Resource
Locators (URL)", RFC 1738, CERN, Xerox Corporation, University of
Minnesota, December 1994.
<ftp://ds.internic.net/rfc/rfc1738.txt>
Newman Standards Track [Page 10]
RFC 2192 IMAP URL Scheme September 1997
[IMAP4] Crispin, M., "Internet Message Access Protocol - Version
4rev1", RFC 2060, University of Washington, December 1996.
<ftp://ds.internic.net/rfc/rfc2060.txt>
[IMAP-AUTH] Myers, J., "IMAP4 Authentication Mechanism", RFC 1731,
Carnegie-Mellon University, December 1994.
<ftp://ds.internic.net/rfc/rfc1731.txt>
[HTTP] Fielding, Gettys, Mogul, Frystyk, Berners-Lee, "Hypertext
Transfer Protocol -- HTTP/1.1", RFC 2068, UC Irvine, DEC, MIT/LCS,
January 1997.
<ftp://ds.internic.net/rfc/rfc2068.txt>
[IMAIL] Crocker, "Standard for the Format of ARPA Internet Text
Messages", STD 11, RFC 822, University of Delaware, August 1982.
<ftp://ds.internic.net/rfc/rfc822.txt>
[KEYWORDS] Bradner, "Key words for use in RFCs to Indicate
Requirement Levels", RFC 2119, Harvard University, March 1997.
<ftp://ds.internic.net/rfc/rfc2119.txt>
[MIME] Freed, N., Borenstein, N., "Multipurpose Internet Mail
Extensions", RFC 2045, Innosoft, First Virtual, November 1996.
<ftp://ds.internic.net/rfc/rfc2045.txt>
[REL-URL] Fielding, "Relative Uniform Resource Locators", RFC 1808,
UC Irvine, June 1995.
<ftp://ds.internic.net/rfc/rfc1808.txt>
[UTF8] Yergeau, F. "UTF-8, a transformation format of Unicode and
ISO 10646", RFC 2044, Alis Technologies, October 1996.
<ftp://ds.internic.net/rfc/rfc2044.txt>
14. Author's Address
Chris Newman
Innosoft International, Inc.
1050 Lakes Drive
West Covina, CA 91790 USA
EMail: chris.newman@innosoft.com
Newman Standards Track [Page 11]
RFC 2192 IMAP URL Scheme September 1997
Appendix A. Sample code
Here is sample C source code to convert between URL paths and IMAP
mailbox names, taking into account mapping between IMAP's modified UTF-7
[IMAP4] and hex-encoded UTF-8 which is more appropriate for URLs. This
code has not been rigorously tested nor does it necessarily behave
reasonably with invalid input, but it should serve as a useful example.
This code just converts the mailbox portion of the URL and does not deal
with parameters, query or server components of the URL.
#include <stdio.h>
#include <string.h>
/* hexadecimal lookup table */
static char hex[] = "0123456789ABCDEF";
/* URL unsafe printable characters */
static char urlunsafe[] = " \"#%&+:;<=>?@[\\]^`{|}";
/* UTF7 modified base64 alphabet */
static char base64chars[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+,";
#define UNDEFINED 64
/* UTF16 definitions */
#define UTF16MASK 0x03FFUL
#define UTF16SHIFT 10
#define UTF16BASE 0x10000UL
#define UTF16HIGHSTART 0xD800UL
#define UTF16HIGHEND 0xDBFFUL
#define UTF16LOSTART 0xDC00UL
#define UTF16LOEND 0xDFFFUL
/* Convert an IMAP mailbox to a URL path
* dst needs to have roughly 4 times the storage space of src
* Hex encoding can triple the size of the input
* UTF-7 can be slightly denser than UTF-8
* (worst case: 8 octets UTF-7 becomes 9 octets UTF-8)
*/
void MailboxToURL(char *dst, char *src)
{
unsigned char c, i, bitcount;
unsigned long ucs4, utf16, bitbuf;
unsigned char base64[256], utf8[6];
Newman Standards Track [Page 12]
RFC 2192 IMAP URL Scheme September 1997
/* initialize modified base64 decoding table */
memset(base64, UNDEFINED, sizeof (base64));
for (i = 0; i < sizeof (base64chars); ++i) {
base64[base64chars[i]] = i;
}
/* loop until end of string */
while (*src != '\0') {
c = *src++;
/* deal with literal characters and &- */
if (c != '&' || *src == '-') {
if (c < ' ' || c > '~' || strchr(urlunsafe, c) != NULL) {
/* hex encode if necessary */
dst[0] = '%';
dst[1] = hex[c >> 4];
dst[2] = hex[c & 0x0f];
dst += 3;
} else {
/* encode literally */
*dst++ = c;
}
/* skip over the '-' if this is an &- sequence */
if (c == '&') ++src;
} else {
/* convert modified UTF-7 -> UTF-16 -> UCS-4 -> UTF-8 -> HEX */
bitbuf = 0;
bitcount = 0;
ucs4 = 0;
while ((c = base64[(unsigned char) *src]) != UNDEFINED) {
++src;
bitbuf = (bitbuf << 6) | c;
bitcount += 6;
/* enough bits for a UTF-16 character? */
if (bitcount >= 16) {
bitcount -= 16;
utf16 = (bitcount ? bitbuf >> bitcount
: bitbuf) & 0xffff;
/* convert UTF16 to UCS4 */
if
(utf16 >= UTF16HIGHSTART && utf16 <= UTF16HIGHEND) {
ucs4 = (utf16 - UTF16HIGHSTART) << UTF16SHIFT;
continue;
} else if
(utf16 >= UTF16LOSTART && utf16 <= UTF16LOEND) {
ucs4 += utf16 - UTF16LOSTART + UTF16BASE;
} else {
ucs4 = utf16;
}
Newman Standards Track [Page 13]
RFC 2192 IMAP URL Scheme September 1997
/* convert UTF-16 range of UCS4 to UTF-8 */
if (ucs4 <= 0x7fUL) {
utf8[0] = ucs4;
i = 1;
} else if (ucs4 <= 0x7ffUL) {
utf8[0] = 0xc0 | (ucs4 >> 6);
utf8[1] = 0x80 | (ucs4 & 0x3f);
i = 2;
} else if (ucs4 <= 0xffffUL) {
utf8[0] = 0xe0 | (ucs4 >> 12);
utf8[1] = 0x80 | ((ucs4 >> 6) & 0x3f);
utf8[2] = 0x80 | (ucs4 & 0x3f);
i = 3;
} else {
utf8[0] = 0xf0 | (ucs4 >> 18);
utf8[1] = 0x80 | ((ucs4 >> 12) & 0x3f);
utf8[2] = 0x80 | ((ucs4 >> 6) & 0x3f);
utf8[3] = 0x80 | (ucs4 & 0x3f);
i = 4;
}
/* convert utf8 to hex */
for (c = 0; c < i; ++c) {
dst[0] = '%';
dst[1] = hex[utf8[c] >> 4];
dst[2] = hex[utf8[c] & 0x0f];
dst += 3;
}
}
}
/* skip over trailing '-' in modified UTF-7 encoding */
if (*src == '-') ++src;
}
}
/* terminate destination string */
*dst = '\0';
}
/* Convert hex coded UTF-8 URL path to modified UTF-7 IMAP mailbox
* dst should be about twice the length of src to deal with non-hex
* coded URLs
*/
void URLtoMailbox(char *dst, char *src)
{
unsigned int utf8pos, utf8total, i, c, utf7mode, bitstogo, utf16flag;
unsigned long ucs4, bitbuf;
unsigned char hextab[256];
/* initialize hex lookup table */
Newman Standards Track [Page 14]
RFC 2192 IMAP URL Scheme September 1997
memset(hextab, 0, sizeof (hextab));
for (i = 0; i < sizeof (hex); ++i) {
hextab[hex[i]] = i;
if (isupper(hex[i])) hextab[tolower(hex[i])] = i;
}
utf7mode = 0;
utf8total = 0;
bitstogo = 0;
while ((c = *src) != '\0') {
++src;
/* undo hex-encoding */
if (c == '%' && src[0] != '\0' && src[1] != '\0') {
c = (hextab[src[0]] << 4) | hextab[src[1]];
src += 2;
}
/* normal character? */
if (c >= ' ' && c <= '~') {
/* switch out of UTF-7 mode */
if (utf7mode) {
if (bitstogo) {
*dst++ = base64chars[(bitbuf << (6 - bitstogo)) & 0x3F];
}
*dst++ = '-';
utf7mode = 0;
}
*dst++ = c;
/* encode '&' as '&-' */
if (c == '&') {
*dst++ = '-';
}
continue;
}
/* switch to UTF-7 mode */
if (!utf7mode) {
*dst++ = '&';
utf7mode = 1;
}
/* Encode US-ASCII characters as themselves */
if (c < 0x80) {
ucs4 = c;
utf8total = 1;
} else if (utf8total) {
/* save UTF8 bits into UCS4 */
ucs4 = (ucs4 << 6) | (c & 0x3FUL);
if (++utf8pos < utf8total) {
continue;
}
Newman Standards Track [Page 15]
RFC 2192 IMAP URL Scheme September 1997
} else {
utf8pos = 1;
if (c < 0xE0) {
utf8total = 2;
ucs4 = c & 0x1F;
} else if (c < 0xF0) {
utf8total = 3;
ucs4 = c & 0x0F;
} else {
/* NOTE: can't convert UTF8 sequences longer than 4 */
utf8total = 4;
ucs4 = c & 0x03;
}
continue;
}
/* loop to split ucs4 into two utf16 chars if necessary */
utf8total = 0;
do {
if (ucs4 >= UTF16BASE) {
ucs4 -= UTF16BASE;
bitbuf = (bitbuf << 16) | ((ucs4 >> UTF16SHIFT)
+ UTF16HIGHSTART);
ucs4 = (ucs4 & UTF16MASK) + UTF16LOSTART;
utf16flag = 1;
} else {
bitbuf = (bitbuf << 16) | ucs4;
utf16flag = 0;
}
bitstogo += 16;
/* spew out base64 */
while (bitstogo >= 6) {
bitstogo -= 6;
*dst++ = base64chars[(bitstogo ? (bitbuf >> bitstogo)
: bitbuf)
& 0x3F];
}
} while (utf16flag);
}
/* if in UTF-7 mode, finish in ASCII */
if (utf7mode) {
if (bitstogo) {
*dst++ = base64chars[(bitbuf << (6 - bitstogo)) & 0x3F];
}
*dst++ = '-';
}
/* tie off string */
*dst = '\0';
}
Newman Standards Track [Page 16]

View File

@ -0,0 +1,507 @@
Network Working Group M. Gahrns
Request for Comments: 2193 Microsoft
Category: Standards Track September 1997
IMAP4 Mailbox Referrals
Status of this Memo
This document specifies an Internet standards track protocol for the
Internet community, and requests discussion and suggestions for
improvements. Please refer to the current edition of the "Internet
Official Protocol Standards" (STD 1) for the standardization state
and status of this protocol. Distribution of this memo is unlimited.
1. Abstract
When dealing with large amounts of users, messages and geographically
dispersed IMAP4 [RFC-2060] servers, it is often desirable to
distribute messages amongst different servers within an organization.
For example an administrator may choose to store user's personal
mailboxes on a local IMAP4 server, while storing shared mailboxes
remotely on another server. This type of configuration is common
when it is uneconomical to store all data centrally due to limited
bandwidth or disk resources.
Mailbox referrals allow clients to seamlessly access mailboxes that
are distributed across several IMAP4 servers.
A referral mechanism can provide efficiencies over the alternative
"proxy method", in which the local IMAP4 server contacts the remote
server on behalf of the client, and then transfers the data from the
remote server to itself, and then on to the client. The referral
mechanism's direct client connection to the remote server is often a
more efficient use of bandwidth, and does not require the local
server to impersonate the client when authenticating to the remote
server.
2. Conventions used in this document
In examples, "C:" and "S:" indicate lines sent by the client and
server respectively.
A home server, is an IMAP4 server that contains the user's inbox.
A remote mailbox is a mailbox that is not hosted on the user's home
server.
Gahrns Standards Track [Page 1]
RFC 2193 IMAP4 Mailbox Referrals September 1997
A remote server is a server that contains remote mailboxes.
A shared mailbox, is a mailbox that multiple users have access to.
An IMAP mailbox referral is when the server directs the client to
another IMAP mailbox.
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
"SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
document are to be interpreted as described in [RFC-2119].
3. Introduction and Overview
IMAP4 servers that support this extension MUST list the keyword
MAILBOX-REFERRALS in their CAPABILITY response. No client action is
needed to invoke the MAILBOX-REFERRALS capability in a server.
A MAILBOX-REFERRALS capable IMAP4 server MUST NOT return referrals
that result in a referrals loop.
A referral response consists of a tagged NO response and a REFERRAL
response code. The REFERRAL response code MUST contain as an
argument a one or more valid URLs separated by a space as defined in
[RFC-1738]. If a server replies with multiple URLs for a particular
object, they MUST all be of the same type. In this case, the URL MUST
be an IMAP URL as defined in [RFC-2192]. A client that supports the
REFERRALS extension MUST be prepared for a URL of any type, but it
need only be able to process IMAP URLs.
A server MAY respond with multiple IMAP mailbox referrals if there is
more than one replica of the mailbox. This allows the implementation
of a load balancing or failover scheme. How a server keeps multiple
replicas of a mailbox in sync is not addressed by this document.
If the server has a preferred order in which the client should
attempt to access the URLs, the preferred URL SHOULD be listed in the
first, with the remaining URLs presented in descending order of
preference. If multiple referrals are given for a mailbox, a server
should be aware that there are synchronization issues for a client if
the UIDVALIDITY of the referred mailboxes are different.
An IMAP mailbox referral may be given in response to an IMAP command
that specifies a mailbox as an argument.
Gahrns Standards Track [Page 2]
RFC 2193 IMAP4 Mailbox Referrals September 1997
Example:
A001 NO [REFERRAL IMAP://user;AUTH=*@SERVER2/REMOTE]Remote Mailbox
NOTE: user;AUTH=* is specified as required by [RFC-2192] to avoid a
client falling back to anonymous login.
Remote mailboxes and their inferiors, that are accessible only via
referrals SHOULD NOT appear in LIST and LSUB responses issued against
the user's home server. They MUST appear in RLIST and RLSUB
responses issued against the user's home server. Hierarchy referrals,
in which a client would be required to connect to the remote server
to issue a LIST to discover the inferiors of a mailbox are not
addressed in this document.
For example, if shared mailboxes were only accessible via referrals
on a remote server, a RLIST "" "#SHARED/%" command would return the
same response if issued against the user's home server or the remote
server.
Note: Mailboxes that are available on the user's home server do not
need to be available on the remote server. In addition, there may be
additional mailboxes available on the remote server, but they will
not accessible to the client via referrals unless they appear in the
LIST response to the RLIST command against the user's home server.
A MAILBOX-REFERRALS capable client will issue the RLIST and RLSUB
commands in lieu of LIST and LSUB. The RLIST and RLSUB commands
behave identically to their LIST and LSUB counterparts, except remote
mailboxes are returned in addition to local mailboxes in the LIST and
LSUB responses. This avoids displaying to a non MAILBOX-REFERRALS
enabled client inaccessible remote mailboxes.
4.1. SELECT, EXAMINE, DELETE, SUBSCRIBE, UNSUBSCRIBE, STATUS and APPEND
Referrals
An IMAP4 server MAY respond to the SELECT, EXAMINE, DELETE,
SUBSCRIBE, UNSUBSCRIBE, STATUS or APPEND command with one or more
IMAP mailbox referrals to indicate to the client that the mailbox is
hosted on a remote server.
When a client processes an IMAP mailbox referral, it will open a new
connection or use an existing connection to the remote server so that
it is able to issue the commands necessary to process the remote
mailbox.
Gahrns Standards Track [Page 3]
RFC 2193 IMAP4 Mailbox Referrals September 1997
Example: <IMAP4 connection to home server>
C: A001 DELETE "SHARED/FOO"
S: A001 NO [REFERRAL IMAP://user;AUTH=*@SERVER2/SHARED/FOO]
Remote mailbox. Try SERVER2.
<Client established a second connection to SERVER2 and
issues the DELETE command on the referred mailbox>
S: * OK IMAP4rev1 server ready
C: B001 AUTHENTICATE KERBEROS_V4
<authentication exchange>
S: B001 OK user is authenticated
C: B002 DELETE "SHARED/FOO"
S: B002 OK DELETE completed
Example: <IMAP4 connection to home server>
C: A001 SELECT REMOTE
S: A001 NO [REFERRAL IMAP://user;AUTH=*@SERVER2/REMOTE
IMAP://user;AUTH=*@SERVER3/REMOTE] Remote mailbox.
Try SERVER2 or SERVER3.
<Client opens second connection to remote server, and
issues the commands needed to process the items in the
remote mailbox>
S: * OK IMAP4rev1 server ready
C: B001 AUTHENTICATE KERBEROS_V4
<authentication exchange>
S: B001 OK user is authenticated
C: B002 SELECT REMOTE
S: * 12 EXISTS
S: * 1 RECENT
S: * OK [UNSEEN 10] Message 10 is first unseen
S: * OK [UIDVALIDITY 123456789]
S: * FLAGS (Answered Flagged Deleted Seen Draft)
S: * OK [PERMANENTFLAGS (Answered Deleted Seen ]
S: B002 OK [READ-WRITE] Selected completed
C: B003 FETCH 10:12 RFC822
S: * 10 FETCH . . .
S: * 11 FETCH . . .
S: * 12 FETCH . . .
S: B003 OK FETCH Completed
Gahrns Standards Track [Page 4]
RFC 2193 IMAP4 Mailbox Referrals September 1997
<Client is finished processing the REMOTE mailbox and
wants to process a mailbox on its home server>
C: B004 LOGOUT
S: * BYE IMAP4rev1 server logging out
S: B004 OK LOGOUT Completed
<Client continues with first connection>
C: A002 SELECT INBOX
S: * 16 EXISTS
S: * 2 RECENT
S: * OK [UNSEEN 10] Message 10 is first unseen
S: * OK [UIDVALIDITY 123456789]
S: * FLAGS (Answered Flagged Deleted Seen Draft)
S: * OK [PERMANENTFLAGS (Answered Deleted Seen ]
S: A002 OK [READ-WRITE] Selected completed
4.2. CREATE Referrals
An IMAP4 server MAY respond to the CREATE command with one or more
IMAP mailbox referrals, if it wishes to direct the client to issue
the CREATE against another server. The server can employ any means,
such as examining the hierarchy of the specified mailbox name, in
determining which server the mailbox should be created on.
Example:
C: A001 CREATE "SHARED/FOO"
S: A001 NO [REFERRAL IMAP://user;AUTH=*@SERVER2/SHARED/FOO]
Mailbox should be created on remote server
Alternatively, because a home server is required to maintain a
listing of referred remote mailboxes, a server MAY allow the creation
of a mailbox that will ultimately reside on a remote server against
the home server, and provide referrals on subsequent commands that
manipulate the mailbox.
Example:
C: A001 CREATE "SHARED/FOO"
S: A001 OK CREATE succeeded
C: A002 SELECT "SHARED/FOO"
S: A002 NO [REFERRAL IMAP://user;AUTH=*@SERVER2/SHARED/FOO]
Remote mailbox. Try SERVER2
Gahrns Standards Track [Page 5]
RFC 2193 IMAP4 Mailbox Referrals September 1997
4.3. RENAME Referrals
An IMAP4 server MAY respond to the RENAME command with one or more
pairs of IMAP mailbox referrals. In each pair of IMAP mailbox
referrals, the first one is an URL to the existing mailbox name and
the second is an URL to the requested new mailbox name.
If within an IMAP mailbox referral pair, the existing and new mailbox
URLs are on different servers, the remote servers are unable to
perform the RENAME operation. To achieve the same behavior of
server RENAME, the client MAY issue the constituent CREATE, FETCH,
APPEND, and DELETE commands against both servers.
If within an IMAP mailbox referral pair, the existing and new mailbox
URLs are on the same server it is an indication that the currently
connected server is unable to perform the operation. The client can
simply re-issue the RENAME command on the remote server.
Example:
C: A001 RENAME FOO BAR
S: A001 NO [REFERRAL IMAP://user;AUTH=*@SERVER1/FOO
IMAP://user;AUTH=*@SERVER2/BAR] Unable to rename mailbox
across servers
Since the existing and new mailbox names are on different servers,
the client would be required to make a connection to both servers and
issue the constituent commands require to achieve the RENAME.
Example:
C: A001 RENAME FOO BAR
S: A001 NO [REFERRAL IMAP://user;AUTH=*@SERVER2/FOO
IMAP://user;AUTH=*@SERVER2/BAR] Unable to rename mailbox
located on SERVER2
Since both the existing and new mailbox are on the same remote
server, the client can simply make a connection to the remote server
and re-issue the RENAME command.
4.4. COPY Referrals
An IMAP4 server MAY respond to the COPY command with one or more IMAP
mailbox referrals. This indicates that the destination mailbox is on
a remote server. To achieve the same behavior of a server COPY, the
client MAY issue the constituent FETCH and APPEND commands against
both servers.
Gahrns Standards Track [Page 6]
RFC 2193 IMAP4 Mailbox Referrals September 1997
Example:
C: A001 COPY 1 "SHARED/STUFF"
S: A001 NO [REFERRAL IMAP://user;AUTH=*@SERVER2/SHARED/STUFF]
Unable to copy message(s) to SERVER2.
5.1 RLIST command
Arguments: reference name
mailbox name with possible wildcards
Responses: untagged responses: LIST
Result: OK - RLIST Completed
NO - RLIST Failure
BAD - command unknown or arguments invalid
The RLIST command behaves identically to its LIST counterpart, except
remote mailboxes are returned in addition to local mailboxes in the
LIST responses.
5.2 RLSUB Command
Arguments: reference name
mailbox name with possible wildcards
Responses: untagged responses: LSUB
Result: OK - RLSUB Completed
NO - RLSUB Failure
BAD - command unknown or arguments invalid
The RLSUB command behaves identically to its LSUB counterpart, except
remote mailboxes are returned in addition to local mailboxes in the
LSUB responses.
6. Formal Syntax
The following syntax specification uses the augmented Backus-Naur
Form (BNF) as described in [ABNF].
list_mailbox = <list_mailbox> as defined in [RFC-2060]
mailbox = <mailbox> as defined in [RFC-2060]
mailbox_referral = <tag> SPACE "NO" SPACE
<referral_response_code> (text / text_mime2)
; See [RFC-2060] for <tag>, text and text_mime2 definition
Gahrns Standards Track [Page 7]
RFC 2193 IMAP4 Mailbox Referrals September 1997
referral_response_code = "[" "REFERRAL" 1*(SPACE <url>) "]"
; See [RFC-1738] for <url> definition
rlist = "RLIST" SPACE mailbox SPACE list_mailbox
rlsub = "RLSUB" SPACE mailbox SPACE list_mailbox
6. Security Considerations
The IMAP4 referral mechanism makes use of IMAP URLs, and as such,
have the same security considerations as general internet URLs [RFC-
1738], and in particular IMAP URLs [RFC-2192].
With the MAILBOX-REFERRALS capability, it is potentially easier to
write a rogue server that injects a bogus referral response that
directs a user to an incorrect mailbox. Although referrals reduce
the effort to write such a server, the referral response makes
detection of the intrusion easier.
7. References
[RFC-2060], Crispin, M., "Internet Message Access Protocol - Version
4rev1", RFC 2060, University of Washington, December 1996.
[RFC-2192], Newman, C., "IMAP URL Scheme", RFC 2192, Innosoft,
September 1997.
[RFC-1738], Berners-Lee, T., Masinter, L., and M. McCahill, "Uniform
Resource Locators (URL)", RFC 1738, CERN, Xerox Corporation,
University of Minnesota, December 1994.
[RFC-2119], Bradner, S., "Key words for use in RFCs to Indicate
Requirement Levels", RFC 2119, Harvard University, March 1997.
[ABNF], DRUMS working group, Dave Crocker Editor, "Augmented BNF for
Syntax Specifications: ABNF", Work in Progress, Internet Mail
Consortium, April 1997.
8. Acknowledgments
Many valuable suggestions were received from private discussions and
the IMAP4 mailing list. In particular, Raymond Cheng, Mark Crispin,
Mark Keasling, Chris Newman and Larry Osterman made significant
contributions to this document.
Gahrns Standards Track [Page 8]
RFC 2193 IMAP4 Mailbox Referrals September 1997
9. Author's Address
Mike Gahrns
Microsoft
One Microsoft Way
Redmond, WA, 98072
Phone: (206) 936-9833
EMail: mikega@microsoft.com
Gahrns Standards Track [Page 9]

View File

@ -0,0 +1,283 @@
Network Working Group J. Klensin
Request for Comments: 2195 R. Catoe
Category: Standards Track P. Krumviede
Obsoletes: 2095 MCI
September 1997
IMAP/POP AUTHorize Extension for Simple Challenge/Response
Status of this Memo
This document specifies an Internet standards track protocol for the
Internet community, and requests discussion and suggestions for
improvements. Please refer to the current edition of the "Internet
Official Protocol Standards" (STD 1) for the standardization state
and status of this protocol. Distribution of this memo is unlimited.
Abstract
While IMAP4 supports a number of strong authentication mechanisms as
described in RFC 1731, it lacks any mechanism that neither passes
cleartext, reusable passwords across the network nor requires either
a significant security infrastructure or that the mail server update
a mail-system-wide user authentication file on each mail access.
This specification provides a simple challenge-response
authentication protocol that is suitable for use with IMAP4. Since
it utilizes Keyed-MD5 digests and does not require that the secret be
stored in the clear on the server, it may also constitute an
improvement on APOP for POP3 use as specified in RFC 1734.
1. Introduction
Existing Proposed Standards specify an AUTHENTICATE mechanism for the
IMAP4 protocol [IMAP, IMAP-AUTH] and a parallel AUTH mechanism for
the POP3 protocol [POP3-AUTH]. The AUTHENTICATE mechanism is
intended to be extensible; the four methods specified in [IMAP-AUTH]
are all fairly powerful and require some security infrastructure to
support. The base POP3 specification [POP3] also contains a
lightweight challenge-response mechanism called APOP. APOP is
associated with most of the risks associated with such protocols: in
particular, it requires that both the client and server machines have
access to the shared secret in cleartext form. CRAM offers a method
for avoiding such cleartext storage while retaining the algorithmic
simplicity of APOP in using only MD5, though in a "keyed" method.
Klensin, Catoe & Krumviede Standards Track [Page 1]
RFC 2195 IMAP/POP AUTHorize Extension September 1997
At present, IMAP [IMAP] lacks any facility corresponding to APOP.
The only alternative to the strong mechanisms identified in [IMAP-
AUTH] is a presumably cleartext username and password, supported
through the LOGIN command in [IMAP]. This document describes a
simple challenge-response mechanism, similar to APOP and PPP CHAP
[PPP], that can be used with IMAP (and, in principle, with POP3).
This mechanism also has the advantage over some possible alternatives
of not requiring that the server maintain information about email
"logins" on a per-login basis. While mechanisms that do require such
per-login history records may offer enhanced security, protocols such
as IMAP, which may have several connections between a given client
and server open more or less simultaneous, may make their
implementation particularly challenging.
2. Challenge-Response Authentication Mechanism (CRAM)
The authentication type associated with CRAM is "CRAM-MD5".
The data encoded in the first ready response contains an
presumptively arbitrary string of random digits, a timestamp, and the
fully-qualified primary host name of the server. The syntax of the
unencoded form must correspond to that of an RFC 822 'msg-id'
[RFC822] as described in [POP3].
The client makes note of the data and then responds with a string
consisting of the user name, a space, and a 'digest'. The latter is
computed by applying the keyed MD5 algorithm from [KEYED-MD5] where
the key is a shared secret and the digested text is the timestamp
(including angle-brackets).
This shared secret is a string known only to the client and server.
The `digest' parameter itself is a 16-octet value which is sent in
hexadecimal format, using lower-case ASCII characters.
When the server receives this client response, it verifies the digest
provided. If the digest is correct, the server should consider the
client authenticated and respond appropriately.
Keyed MD5 is chosen for this application because of the greater
security imparted to authentication of short messages. In addition,
the use of the techniques described in [KEYED-MD5] for precomputation
of intermediate results make it possible to avoid explicit cleartext
storage of the shared secret on the server system by instead storing
the intermediate results which are known as "contexts".
Klensin, Catoe & Krumviede Standards Track [Page 2]
RFC 2195 IMAP/POP AUTHorize Extension September 1997
CRAM does not support a protection mechanism.
Example:
The examples in this document show the use of the CRAM mechanism with
the IMAP4 AUTHENTICATE command [IMAP-AUTH]. The base64 encoding of
the challenges and responses is part of the IMAP4 AUTHENTICATE
command, not part of the CRAM specification itself.
S: * OK IMAP4 Server
C: A0001 AUTHENTICATE CRAM-MD5
S: + PDE4OTYuNjk3MTcwOTUyQHBvc3RvZmZpY2UucmVzdG9uLm1jaS5uZXQ+
C: dGltIGI5MTNhNjAyYzdlZGE3YTQ5NWI0ZTZlNzMzNGQzODkw
S: A0001 OK CRAM authentication successful
In this example, the shared secret is the string
'tanstaaftanstaaf'. Hence, the Keyed MD5 digest is produced by
calculating
MD5((tanstaaftanstaaf XOR opad),
MD5((tanstaaftanstaaf XOR ipad),
<1896.697170952@postoffice.reston.mci.net>))
where ipad and opad are as defined in the keyed-MD5 Work in
Progress [KEYED-MD5] and the string shown in the challenge is the
base64 encoding of <1896.697170952@postoffice.reston.mci.net>. The
shared secret is null-padded to a length of 64 bytes. If the
shared secret is longer than 64 bytes, the MD5 digest of the
shared secret is used as a 16 byte input to the keyed MD5
calculation.
This produces a digest value (in hexadecimal) of
b913a602c7eda7a495b4e6e7334d3890
The user name is then prepended to it, forming
tim b913a602c7eda7a495b4e6e7334d3890
Which is then base64 encoded to meet the requirements of the IMAP4
AUTHENTICATE command (or the similar POP3 AUTH command), yielding
dGltIGI5MTNhNjAyYzdlZGE3YTQ5NWI0ZTZlNzMzNGQzODkw
Klensin, Catoe & Krumviede Standards Track [Page 3]
RFC 2195 IMAP/POP AUTHorize Extension September 1997
3. References
[CHAP] Lloyd, B., and W. Simpson, "PPP Authentication Protocols",
RFC 1334, October 1992.
[IMAP] Crispin, M., "Internet Message Access Protocol - Version
4rev1", RFC 2060, University of Washington, December 1996.
[IMAP-AUTH] Myers, J., "IMAP4 Authentication Mechanisms",
RFC 1731, Carnegie Mellon, December 1994.
[KEYED-MD5] Krawczyk, Bellare, Canetti, "HMAC: Keyed-Hashing for
Message Authentication", RFC 2104, February 1997.
[MD5] Rivest, R., "The MD5 Message Digest Algorithm",
RFC 1321, MIT Laboratory for Computer Science, April 1992.
[POP3] Myers, J., and M. Rose, "Post Office Protocol - Version 3",
STD 53, RFC 1939, Carnegie Mellon, May 1996.
[POP3-AUTH] Myers, J., "POP3 AUTHentication command", RFC 1734,
Carnegie Mellon, December, 1994.
4. Security Considerations
It is conjectured that use of the CRAM authentication mechanism
provides origin identification and replay protection for a session.
Accordingly, a server that implements both a cleartext password
command and this authentication type should not allow both methods of
access for a given user.
While the saving, on the server, of "contexts" (see section 2) is
marginally better than saving the shared secrets in cleartext as is
required by CHAP [CHAP] and APOP [POP3], it is not sufficient to
protect the secrets if the server itself is compromised.
Consequently, servers that store the secrets or contexts must both be
protected to a level appropriate to the potential information value
in user mailboxes and identities.
As the length of the shared secret increases, so does the difficulty
of deriving it.
While there are now suggestions in the literature that the use of MD5
and keyed MD5 in authentication procedures probably has a limited
effective lifetime, the technique is now widely deployed and widely
understood. It is believed that this general understanding may
assist with the rapid replacement, by CRAM-MD5, of the current uses
of permanent cleartext passwords in IMAP. This document has been
Klensin, Catoe & Krumviede Standards Track [Page 4]
RFC 2195 IMAP/POP AUTHorize Extension September 1997
deliberately written to permit easy upgrading to use SHA (or whatever
alternatives emerge) when they are considered to be widely available
and adequately safe.
Even with the use of CRAM, users are still vulnerable to active
attacks. An example of an increasingly common active attack is 'TCP
Session Hijacking' as described in CERT Advisory CA-95:01 [CERT95].
See section 1 above for additional discussion.
5. Acknowledgements
This memo borrows ideas and some text liberally from [POP3] and
[RFC-1731] and thanks are due the authors of those documents. Ran
Atkinson made a number of valuable technical and editorial
contributions to the document.
6. Authors' Addresses
John C. Klensin
MCI Telecommunications
800 Boylston St, 7th floor
Boston, MA 02199
USA
EMail: klensin@mci.net
Phone: +1 617 960 1011
Randy Catoe
MCI Telecommunications
2100 Reston Parkway
Reston, VA 22091
USA
EMail: randy@mci.net
Phone: +1 703 715 7366
Paul Krumviede
MCI Telecommunications
2100 Reston Parkway
Reston, VA 22091
USA
EMail: paul@mci.net
Phone: +1 703 715 7251
Klensin, Catoe & Krumviede Standards Track [Page 5]

View File

@ -0,0 +1,283 @@
Network Working Group M. Gahrns
Request for Comments: 2221 Microsoft
Category: Standards Track October 1997
IMAP4 Login Referrals
Status of this Memo
This document specifies an Internet standards track protocol for the
Internet community, and requests discussion and suggestions for
improvements. Please refer to the current edition of the "Internet
Official Protocol Standards" (STD 1) for the standardization state
and status of this protocol. Distribution of this memo is unlimited.
Copyright Notice
Copyright (C) The Internet Society (1997). All Rights Reserved.
1. Abstract
When dealing with large amounts of users and many IMAP4 [RFC-2060]
servers, it is often necessary to move users from one IMAP4 server to
another. For example, hardware failures or organizational changes
may dictate such a move.
Login referrals allow clients to transparently connect to an
alternate IMAP4 server, if their home IMAP4 server has changed.
A referral mechanism can provide efficiencies over the alternative
'proxy method', in which the local IMAP4 server contacts the remote
server on behalf of the client, and then transfers the data from the
remote server to itself, and then on to the client. The referral
mechanism's direct client connection to the remote server is often a
more efficient use of bandwidth, and does not require the local
server to impersonate the client when authenticating to the remote
server.
2. Conventions used in this document
In examples, "C:" and "S:" indicate lines sent by the client and
server respectively.
A home server, is an IMAP4 server that contains the user's inbox.
A remote server is a server that contains remote mailboxes.
Gahrns Standards Track [Page 1]
RFC 2221 IMAP4 Login Referrals October 1997
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
"SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
document are to be interpreted as described in [RFC-2119].
3. Introduction and Overview
IMAP4 servers that support this extension MUST list the keyword
LOGIN-REFERRALS in their CAPABILITY response. No client action is
needed to invoke the LOGIN-REFERRALS capability in a server.
A LOGIN-REFERRALS capable IMAP4 server SHOULD NOT return a referral
to a server that will return a referral. A client MUST NOT follow
more than 10 levels of referral without consulting the user.
A LOGIN-REFERRALS response code MUST contain as an argument a valid
IMAP server URL as defined in [IMAP-URL].
A home server referral consists of either a tagged NO or OK, or an
untagged BYE response that contains a LOGIN-REFERRALS response code.
Example: A001 NO [REFERRAL IMAP://user;AUTH=*@SERVER2/] Remote Server
NOTE: user;AUTH=* is specified as required by [IMAP-URL] to avoid a
client falling back to anonymous login.
4. Home Server Referrals
A home server referral may be returned in response to an AUTHENTICATE
or LOGIN command, or it may appear in the connection startup banner.
If a server returns a home server referral in a tagged NO response,
that server does not contain any mailboxes that are accessible to the
user. If a server returns a home server referral in a tagged OK
response, it indicates that the user's personal mailboxes are
elsewhere, but the server contains public mailboxes which are
readable by the user. After receiving a home server referral, the
client can not make any assumptions as to whether this was a
permanent or temporary move of the user.
4.1. LOGIN and AUTHENTICATE Referrals
An IMAP4 server MAY respond to a LOGIN or AUTHENTICATE command with a
home server referral if it wishes to direct the user to another IMAP4
server.
Example: C: A001 LOGIN MIKE PASSWORD
S: A001 NO [REFERRAL IMAP://MIKE@SERVER2/] Specified user
is invalid on this server. Try SERVER2.
Gahrns Standards Track [Page 2]
RFC 2221 IMAP4 Login Referrals October 1997
Example: C: A001 LOGIN MATTHEW PASSWORD
S: A001 OK [REFERRAL IMAP://MATTHEW@SERVER2/] Specified
user's personal mailboxes located on Server2, but
public mailboxes are available.
Example: C: A001 AUTHENTICATE GSSAPI
<authentication exchange>
S: A001 NO [REFERRAL IMAP://user;AUTH=GSSAPI@SERVER2/]
Specified user is invalid on this server. Try
SERVER2.
4.2. BYE at connection startup referral
An IMAP4 server MAY respond with an untagged BYE and a REFERRAL
response code that contains an IMAP URL to a home server if it is not
willing to accept connections and wishes to direct the client to
another IMAP4 server.
Example: S: * BYE [REFERRAL IMAP://user;AUTH=*@SERVER2/] Server not
accepting connections. Try SERVER2
5. Formal Syntax
The following syntax specification uses the augmented Backus-Naur
Form (BNF) as described in [ABNF].
This amends the "resp_text_code" element of the IMAP4 grammar
described in [RFC-2060]
resp_text_code =/ "REFERRAL" SPACE <imapurl>
; See [IMAP-URL] for definition of <imapurl>
; See [RFC-2060] for base definition of resp_text_code
6. Security Considerations
The IMAP4 login referral mechanism makes use of IMAP URLs, and as
such, have the same security considerations as general internet URLs
[RFC-1738], and in particular IMAP URLs [IMAP-URL].
A server MUST NOT give a login referral if authentication for that
user fails. This is to avoid revealing information about the user's
account to an unauthorized user.
With the LOGIN-REFERRALS capability, it is potentially easier to
write a rogue 'password catching' server that collects login data and
then refers the client to their actual IMAP4 server. Although
referrals reduce the effort to write such a server, the referral
response makes detection of the intrusion easier.
Gahrns Standards Track [Page 3]
RFC 2221 IMAP4 Login Referrals October 1997
7. References
[RFC-2060], Crispin, M., "Internet Message Access Protocol - Version
4rev1", RFC 2060, December 1996.
[IMAP-URL], Newman, C., "IMAP URL Scheme", RFC 2192, Innosoft,
September 1997.
[RFC-1738], Berners-Lee, T., Masinter, L. and M. McCahill, "Uniform
Resource Locators (URL)", RFC 1738, December 1994.
[RFC-2119], Bradner, S., "Key words for use in RFCs to Indicate
Requirement Levels", RFC 2119, March 1997.
[ABNF], DRUMS working group, Dave Crocker Editor, "Augmented BNF for
Syntax Specifications: ABNF", Work in Progress.
8. Acknowledgments
Many valuable suggestions were received from private discussions and
the IMAP4 mailing list. In particular, Raymond Cheng, Mark Crispin,
Mark Keasling Chris Newman and Larry Osterman made significant
contributions to this document.
9. Author's Address
Mike Gahrns
Microsoft
One Microsoft Way
Redmond, WA, 98072
Phone: (206) 936-9833
EMail: mikega@microsoft.com
Gahrns Standards Track [Page 4]
RFC 2221 IMAP4 Login Referrals October 1997
10. Full Copyright Statement
Copyright (C) The Internet Society (1997). All Rights Reserved.
This document and translations of it may be copied and furnished to
others, and derivative works that comment on or otherwise explain it
or assist in its implmentation may be prepared, copied, published
andand distributed, in whole or in part, without restriction of any
kind, provided that the above copyright notice and this paragraph are
included on all such copies and derivative works. However, this
document itself may not be modified in any way, such as by removing
the copyright notice or references to the Internet Society or other
Internet organizations, except as needed for the purpose of
developing Internet standards in which case the procedures for
copyrights defined in the Internet Standards process must be
followed, or as required to translate it into languages other than
English.
The limited permissions granted above are perpetual and will not be
revoked by the Internet Society or its successors or assigns.
This document and the information contained herein is provided on an
"AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE."
Gahrns Standards Track [Page 5]

View File

@ -0,0 +1,899 @@
Network Working Group J. Myers
Request for Comments: 2222 Netscape Communications
Category: Standards Track October 1997
Simple Authentication and Security Layer (SASL)
Status of this Memo
This document specifies an Internet standards track protocol for the
Internet community, and requests discussion and suggestions for
improvements. Please refer to the current edition of the "Internet
Official Protocol Standards" (STD 1) for the standardization state
and status of this protocol. Distribution of this memo is unlimited.
Copyright Notice
Copyright (C) The Internet Society (1997). All Rights Reserved.
Table of Contents
1. Abstract .............................................. 2
2. Organization of this Document ......................... 2
2.1. How to Read This Document ............................. 2
2.2. Conventions Used in this Document ..................... 2
2.3. Examples .............................................. 3
3. Introduction and Overview ............................. 3
4. Profiling requirements ................................ 4
5. Specific issues ....................................... 5
5.1. Client sends data first ............................... 5
5.2. Server returns success with additional data ........... 5
5.3. Multiple authentications .............................. 5
6. Registration procedures ............................... 6
6.1. Comments on SASL mechanism registrations .............. 6
6.2. Location of Registered SASL Mechanism List ............ 6
6.3. Change Control ........................................ 7
6.4. Registration Template ................................. 7
7. Mechanism definitions ................................. 8
7.1. Kerberos version 4 mechanism .......................... 8
7.2. GSSAPI mechanism ...................................... 9
7.2.1 Client side of authentication protocol exchange ....... 9
7.2.2 Server side of authentication protocol exchange ....... 10
7.2.3 Security layer ........................................ 11
7.3. S/Key mechanism ....................................... 11
7.4. External mechanism .................................... 12
8. References ............................................ 13
9. Security Considerations ............................... 13
10. Author's Address ...................................... 14
Myers Standards Track [Page 1]
RFC 2222 SASL October 1997
Appendix A. Relation of SASL to Transport Security .......... 15
Full Copyright Statement .................................... 16
1. Abstract
This document describes a method for adding authentication support to
connection-based protocols. To use this specification, a protocol
includes a command for identifying and authenticating a user to a
server and for optionally negotiating protection of subsequent
protocol interactions. If its use is negotiated, a security layer is
inserted between the protocol and the connection. This document
describes how a protocol specifies such a command, defines several
mechanisms for use by the command, and defines the protocol used for
carrying a negotiated security layer over the connection.
2. Organization of this Document
2.1. How to Read This Document
This document is written to serve two different audiences, protocol
designers using this specification to support authentication in their
protocol, and implementors of clients or servers for those protocols
using this specification.
The sections "Introduction and Overview", "Profiling requirements",
and "Security Considerations" cover issues that protocol designers
need to understand and address in profiling this specification for
use in a specific protocol.
Implementors of a protocol using this specification need the
protocol-specific profiling information in addition to the
information in this document.
2.2. Conventions Used in this Document
In examples, "C:" and "S:" indicate lines sent by the client and
server respectively.
The key words "MUST", "MUST NOT", "SHOULD", "SHOULD NOT", and "MAY"
in this document are to be interpreted as defined in "Key words for
use in RFCs to Indicate Requirement Levels" [RFC 2119].
Myers Standards Track [Page 2]
RFC 2222 SASL October 1997
2.3. Examples
Examples in this document are for the IMAP profile [RFC 2060] of this
specification. The base64 encoding of challenges and responses, as
well as the "+ " preceding the responses are part of the IMAP4
profile, not part of the SASL specification itself.
3. Introduction and Overview
The Simple Authentication and Security Layer (SASL) is a method for
adding authentication support to connection-based protocols. To use
this specification, a protocol includes a command for identifying and
authenticating a user to a server and for optionally negotiating a
security layer for subsequent protocol interactions.
The command has a required argument identifying a SASL mechanism.
SASL mechanisms are named by strings, from 1 to 20 characters in
length, consisting of upper-case letters, digits, hyphens, and/or
underscores. SASL mechanism names must be registered with the IANA.
Procedures for registering new SASL mechanisms are given in the
section "Registration procedures"
If a server supports the requested mechanism, it initiates an
authentication protocol exchange. This consists of a series of
server challenges and client responses that are specific to the
requested mechanism. The challenges and responses are defined by the
mechanisms as binary tokens of arbitrary length. The protocol's
profile then specifies how these binary tokens are then encoded for
transfer over the connection.
After receiving the authentication command or any client response, a
server may issue a challenge, indicate failure, or indicate
completion. The protocol's profile specifies how the server
indicates which of the above it is doing.
After receiving a challenge, a client may issue a response or abort
the exchange. The protocol's profile specifies how the client
indicates which of the above it is doing.
During the authentication protocol exchange, the mechanism performs
authentication, transmits an authorization identity (frequently known
as a userid) from the client to server, and negotiates the use of a
mechanism-specific security layer. If the use of a security layer is
agreed upon, then the mechanism must also define or negotiate the
maximum cipher-text buffer size that each side is able to receive.
Myers Standards Track [Page 3]
RFC 2222 SASL October 1997
The transmitted authorization identity may be different than the
identity in the client's authentication credentials. This permits
agents such as proxy servers to authenticate using their own
credentials, yet request the access privileges of the identity for
which they are proxying. With any mechanism, transmitting an
authorization identity of the empty string directs the server to
derive an authorization identity from the client's authentication
credentials.
If use of a security layer is negotiated, it is applied to all
subsequent data sent over the connection. The security layer takes
effect immediately following the last response of the authentication
exchange for data sent by the client and the completion indication
for data sent by the server. Once the security layer is in effect,
the protocol stream is processed by the security layer into buffers
of cipher-text. Each buffer is transferred over the connection as a
stream of octets prepended with a four octet field in network byte
order that represents the length of the following buffer. The length
of the cipher-text buffer must be no larger than the maximum size
that was defined or negotiated by the other side.
4. Profiling requirements
In order to use this specification, a protocol definition must supply
the following information:
1. A service name, to be selected from the IANA registry of "service"
elements for the GSSAPI host-based service name form [RFC 2078].
2. A definition of the command to initiate the authentication
protocol exchange. This command must have as a parameter the
mechanism name being selected by the client.
The command SHOULD have an optional parameter giving an initial
response. This optional parameter allows the client to avoid a
round trip when using a mechanism which is defined to have the
client send data first. When this initial response is sent by the
client and the selected mechanism is defined to have the server
start with an initial challenge, the command fails. See section
5.1 of this document for further information.
3. A definition of the method by which the authentication protocol
exchange is carried out, including how the challenges and
responses are encoded, how the server indicates completion or
failure of the exchange, how the client aborts an exchange, and
how the exchange method interacts with any line length limits in
the protocol.
Myers Standards Track [Page 4]
RFC 2222 SASL October 1997
4. Identification of the octet where any negotiated security layer
starts to take effect, in both directions.
5. A specification of how the authorization identity passed from the
client to the server is to be interpreted.
5. Specific issues
5.1. Client sends data first
Some mechanisms specify that the first data sent in the
authentication protocol exchange is from the client to the server.
If a protocol's profile permits the command which initiates an
authentication protocol exchange to contain an initial client
response, this parameter SHOULD be used with such mechanisms.
If the initial client response parameter is not given, or if a
protocol's profile does not permit the command which initiates an
authentication protocol exchange to contain an initial client
response, then the server issues a challenge with no data. The
client's response to this challenge is then used as the initial
client response. (The server then proceeds to send the next
challenge, indicates completion, or indicates failure.)
5.2. Server returns success with additional data
Some mechanisms may specify that server challenge data be sent to the
client along with an indication of successful completion of the
exchange. This data would, for example, authenticate the server to
the client.
If a protocol's profile does not permit this server challenge to be
returned with a success indication, then the server issues the server
challenge without an indication of successful completion. The client
then responds with no data. After receiving this empty response, the
server then indicates successful completion.
5.3. Multiple authentications
Unless otherwise stated by the protocol's profile, only one
successful SASL negotiation may occur in a protocol session. In this
case, once an authentication protocol exchange has successfully
completed, further attempts to initiate an authentication protocol
exchange fail.
Myers Standards Track [Page 5]
RFC 2222 SASL October 1997
In the case that a profile explicitly permits multiple successful
SASL negotiations to occur, then in no case may multiple security
layers be simultaneously in effect. If a security layer is in effect
and a subsequent SASL negotiation selects no security layer, the
original security layer remains in effect. If a security layer is in
effect and a subsequent SASL negotiation selects a second security
layer, then the second security layer replaces the first.
6. Registration procedures
Registration of a SASL mechanism is done by filling in the template
in section 6.4 and sending it in to iana@isi.edu. IANA has the right
to reject obviously bogus registrations, but will perform no review
of clams made in the registration form.
There is no naming convention for SASL mechanisms; any name that
conforms to the syntax of a SASL mechanism name can be registered.
While the registration procedures do not require it, authors of SASL
mechanisms are encouraged to seek community review and comment
whenever that is feasible. Authors may seek community review by
posting a specification of their proposed mechanism as an internet-
draft. SASL mechanisms intended for widespread use should be
standardized through the normal IETF process, when appropriate.
6.1. Comments on SASL mechanism registrations
Comments on registered SASL mechanisms should first be sent to the
"owner" of the mechanism. Submitters of comments may, after a
reasonable attempt to contact the owner, request IANA to attach their
comment to the SASL mechanism registration itself. If IANA approves
of this the comment will be made accessible in conjunction with the
SASL mechanism registration itself.
6.2. Location of Registered SASL Mechanism List
SASL mechanism registrations will be posted in the anonymous FTP
directory "ftp://ftp.isi.edu/in-notes/iana/assignments/sasl-
mechanisms/" and all registered SASL mechanisms will be listed in the
periodically issued "Assigned Numbers" RFC [currently STD 2, RFC
1700]. The SASL mechanism description and other supporting material
may also be published as an Informational RFC by sending it to "rfc-
editor@isi.edu" (please follow the instructions to RFC authors [RFC
2223]).
Myers Standards Track [Page 6]
RFC 2222 SASL October 1997
6.3. Change Control
Once a SASL mechanism registration has been published by IANA, the
author may request a change to its definition. The change request
follows the same procedure as the registration request.
The owner of a SASL mechanism may pass responsibility for the SASL
mechanism to another person or agency by informing IANA; this can be
done without discussion or review.
The IESG may reassign responsibility for a SASL mechanism. The most
common case of this will be to enable changes to be made to
mechanisms where the author of the registration has died, moved out
of contact or is otherwise unable to make changes that are important
to the community.
SASL mechanism registrations may not be deleted; mechanisms which are
no longer believed appropriate for use can be declared OBSOLETE by a
change to their "intended use" field; such SASL mechanisms will be
clearly marked in the lists published by IANA.
The IESG is considered to be the owner of all SASL mechanisms which
are on the IETF standards track.
6.4. Registration Template
To: iana@iana.org
Subject: Registration of SASL mechanism X
SASL mechanism name:
Security considerations:
Published specification (optional, recommended):
Person & email address to contact for further information:
Intended usage:
(One of COMMON, LIMITED USE or OBSOLETE)
Author/Change controller:
(Any other information that the author deems interesting may be
added below this line.)
Myers Standards Track [Page 7]
RFC 2222 SASL October 1997
7. Mechanism definitions
The following mechanisms are hereby defined.
7.1. Kerberos version 4 mechanism
The mechanism name associated with Kerberos version 4 is
"KERBEROS_V4".
The first challenge consists of a random 32-bit number in network
byte order. The client responds with a Kerberos ticket and an
authenticator for the principal "service.hostname@realm", where
"service" is the service name specified in the protocol's profile,
"hostname" is the first component of the host name of the server with
all letters in lower case, and where "realm" is the Kerberos realm of
the server. The encrypted checksum field included within the
Kerberos authenticator contains the server provided challenge in
network byte order.
Upon decrypting and verifying the ticket and authenticator, the
server verifies that the contained checksum field equals the original
server provided random 32-bit number. Should the verification be
successful, the server must add one to the checksum and construct 8
octets of data, with the first four octets containing the incremented
checksum in network byte order, the fifth octet containing a bit-mask
specifying the security layers supported by the server, and the sixth
through eighth octets containing, in network byte order, the maximum
cipher-text buffer size the server is able to receive. The server
must encrypt using DES ECB mode the 8 octets of data in the session
key and issue that encrypted data in a second challenge. The client
considers the server authenticated if the first four octets of the
un-encrypted data is equal to one plus the checksum it previously
sent.
The client must construct data with the first four octets containing
the original server-issued checksum in network byte order, the fifth
octet containing the bit-mask specifying the selected security layer,
the sixth through eighth octets containing in network byte order the
maximum cipher-text buffer size the client is able to receive, and
the following octets containing the authorization identity. The
client must then append from one to eight zero-valued octets so that
the length of the data is a multiple of eight octets. The client must
then encrypt using DES PCBC mode the data with the session key and
respond with the encrypted data. The server decrypts the data and
verifies the contained checksum. The server must verify that the
principal identified in the Kerberos ticket is authorized to connect
as that authorization identity. After this verification, the
authentication process is complete.
Myers Standards Track [Page 8]
RFC 2222 SASL October 1997
The security layers and their corresponding bit-masks are as follows:
1 No security layer
2 Integrity (krb_mk_safe) protection
4 Privacy (krb_mk_priv) protection
Other bit-masks may be defined in the future; bits which are not
understood must be negotiated off.
EXAMPLE: The following are two Kerberos version 4 login scenarios to
the IMAP4 protocol (note that the line breaks in the sample
authenticators are for editorial clarity and are not in real
authenticators)
S: * OK IMAP4 Server
C: A001 AUTHENTICATE KERBEROS_V4
S: + AmFYig==
C: BAcAQU5EUkVXLkNNVS5FRFUAOCAsho84kLN3/IJmrMG+25a4DT
+nZImJjnTNHJUtxAA+o0KPKfHEcAFs9a3CL5Oebe/ydHJUwYFd
WwuQ1MWiy6IesKvjL5rL9WjXUb9MwT9bpObYLGOKi1Qh
S: + or//EoAADZI=
C: DiAF5A4gA+oOIALuBkAAmw==
S: A001 OK Kerberos V4 authentication successful
S: * OK IMAP4 Server
C: A001 AUTHENTICATE KERBEROS_V4
S: + gcfgCA==
C: BAcAQU5EUkVXLkNNVS5FRFUAOCAsho84kLN3/IJmrMG+25a4DT
+nZImJjnTNHJUtxAA+o0KPKfHEcAFs9a3CL5Oebe/ydHJUwYFd
WwuQ1MWiy6IesKvjL5rL9WjXUb9MwT9bpObYLGOKi1Qh
S: A001 NO Kerberos V4 authentication failed
7.2. GSSAPI mechanism
The mechanism name associated with all mechanisms employing the
GSSAPI [RFC 2078] is "GSSAPI".
7.2.1 Client side of authentication protocol exchange
The client calls GSS_Init_sec_context, passing in 0 for
input_context_handle (initially) and a targ_name equal to output_name
from GSS_Import_Name called with input_name_type of
GSS_C_NT_HOSTBASED_SERVICE and input_name_string of
"service@hostname" where "service" is the service name specified in
the protocol's profile, and "hostname" is the fully qualified host
name of the server. The client then responds with the resulting
output_token. If GSS_Init_sec_context returns GSS_S_CONTINUE_NEEDED,
Myers Standards Track [Page 9]
RFC 2222 SASL October 1997
then the client should expect the server to issue a token in a
subsequent challenge. The client must pass the token to another call
to GSS_Init_sec_context, repeating the actions in this paragraph.
When GSS_Init_sec_context returns GSS_S_COMPLETE, the client takes
the following actions: If the last call to GSS_Init_sec_context
returned an output_token, then the client responds with the
output_token, otherwise the client responds with no data. The client
should then expect the server to issue a token in a subsequent
challenge. The client passes this token to GSS_Unwrap and interprets
the first octet of resulting cleartext as a bit-mask specifying the
security layers supported by the server and the second through fourth
octets as the maximum size output_message to send to the server. The
client then constructs data, with the first octet containing the
bit-mask specifying the selected security layer, the second through
fourth octets containing in network byte order the maximum size
output_message the client is able to receive, and the remaining
octets containing the authorization identity. The client passes the
data to GSS_Wrap with conf_flag set to FALSE, and responds with the
generated output_message. The client can then consider the server
authenticated.
7.2.2 Server side of authentication protocol exchange
The server passes the initial client response to
GSS_Accept_sec_context as input_token, setting input_context_handle
to 0 (initially). If GSS_Accept_sec_context returns
GSS_S_CONTINUE_NEEDED, the server returns the generated output_token
to the client in challenge and passes the resulting response to
another call to GSS_Accept_sec_context, repeating the actions in this
paragraph.
When GSS_Accept_sec_context returns GSS_S_COMPLETE, the client takes
the following actions: If the last call to GSS_Accept_sec_context
returned an output_token, the server returns it to the client in a
challenge and expects a reply from the client with no data. Whether
or not an output_token was returned (and after receipt of any
response from the client to such an output_token), the server then
constructs 4 octets of data, with the first octet containing a bit-
mask specifying the security layers supported by the server and the
second through fourth octets containing in network byte order the
maximum size output_token the server is able to receive. The server
must then pass the plaintext to GSS_Wrap with conf_flag set to FALSE
and issue the generated output_message to the client in a challenge.
The server must then pass the resulting response to GSS_Unwrap and
interpret the first octet of resulting cleartext as the bit-mask for
the selected security layer, the second through fourth octets as the
maximum size output_message to send to the client, and the remaining
Myers Standards Track [Page 10]
RFC 2222 SASL October 1997
octets as the authorization identity. The server must verify that
the src_name is authorized to authenticate as the authorization
identity. After these verifications, the authentication process is
complete.
7.2.3 Security layer
The security layers and their corresponding bit-masks are as follows:
1 No security layer
2 Integrity protection.
Sender calls GSS_Wrap with conf_flag set to FALSE
4 Privacy protection.
Sender calls GSS_Wrap with conf_flag set to TRUE
Other bit-masks may be defined in the future; bits which are not
understood must be negotiated off.
7.3. S/Key mechanism
The mechanism name associated with S/Key [RFC 1760] using the MD4
digest algorithm is "SKEY".
The client sends an initial response with the authorization identity.
The server then issues a challenge which contains the decimal
sequence number followed by a single space and the seed string for
the indicated authorization identity. The client responds with the
one-time-password, as either a 64-bit value in network byte order or
encoded in the "six English words" format.
The server must verify the one-time-password. After this
verification, the authentication process is complete.
S/Key authentication does not provide for any security layers.
EXAMPLE: The following are two S/Key login scenarios in the IMAP4
protocol.
S: * OK IMAP4 Server
C: A001 AUTHENTICATE SKEY
S: +
C: bW9yZ2Fu
S: + OTUgUWE1ODMwOA==
C: Rk9VUiBNQU5OIFNPT04gRklSIFZBUlkgTUFTSA==
S: A001 OK S/Key authentication successful
Myers Standards Track [Page 11]
RFC 2222 SASL October 1997
S: * OK IMAP4 Server
C: A001 AUTHENTICATE SKEY
S: +
C: c21pdGg=
S: + OTUgUWE1ODMwOA==
C: BsAY3g4gBNo=
S: A001 NO S/Key authentication failed
The following is an S/Key login scenario in an IMAP4-like protocol
which has an optional "initial response" argument to the AUTHENTICATE
command.
S: * OK IMAP4-Like Server
C: A001 AUTHENTICATE SKEY bW9yZ2Fu
S: + OTUgUWE1ODMwOA==
C: Rk9VUiBNQU5OIFNPT04gRklSIFZBUlkgTUFTSA==
S: A001 OK S/Key authentication successful
7.4. External mechanism
The mechanism name associated with external authentication is
"EXTERNAL".
The client sends an initial response with the authorization identity.
The server uses information, external to SASL, to determine whether
the client is authorized to authenticate as the authorization
identity. If the client is so authorized, the server indicates
successful completion of the authentication exchange; otherwise the
server indicates failure.
The system providing this external information may be, for example,
IPsec or TLS.
If the client sends the empty string as the authorization identity
(thus requesting the authorization identity be derived from the
client's authentication credentials), the authorization identity is
to be derived from authentication credentials which exist in the
system which is providing the external authentication.
Myers Standards Track [Page 12]
RFC 2222 SASL October 1997
8. References
[RFC 2060] Crispin, M., "Internet Message Access Protocol - Version
4rev1", RFC 2060, December 1996.
[RFC 2078] Linn, J., "Generic Security Service Application Program
Interface, Version 2", RFC 2078, January 1997.
[RFC 2119] Bradner, S., "Key words for use in RFCs to Indicate
Requirement Levels", RFC 2119, March 1997.
[RFC 2223] Postel, J., and J. Reynolds, "Instructions to RFC
Authors", RFC 2223, October 1997.
[RFC 1760] Haller, N., "The S/Key One-Time Password System", RFC
1760, February 1995.
[RFC 1700] Reynolds, J., and J. Postel, "Assigned Numbers", STD 2,
RFC 1700, October 1994.
9. Security Considerations
Security issues are discussed throughout this memo.
The mechanisms that support integrity protection are designed such
that the negotiation of the security layer and authorization identity
is integrity protected. When the client selects a security layer
with at least integrity protection, this protects against an active
attacker hijacking the connection and modifying the authentication
exchange to negotiate a plaintext connection.
When a server or client supports multiple authentication mechanisms,
each of which has a different security strength, it is possible for
an active attacker to cause a party to use the least secure mechanism
supported. To protect against this sort of attack, a client or
server which supports mechanisms of different strengths should have a
configurable minimum strength that it will use. It is not sufficient
for this minimum strength check to only be on the server, since an
active attacker can change which mechanisms the client sees as being
supported, causing the client to send authentication credentials for
its weakest supported mechanism.
Myers Standards Track [Page 13]
RFC 2222 SASL October 1997
The client's selection of a SASL mechanism is done in the clear and
may be modified by an active attacker. It is important for any new
SASL mechanisms to be designed such that an active attacker cannot
obtain an authentication with weaker security properties by modifying
the SASL mechanism name and/or the challenges and responses.
Any protocol interactions prior to authentication are performed in
the clear and may be modified by an active attacker. In the case
where a client selects integrity protection, it is important that any
security-sensitive protocol negotiations be performed after
authentication is complete. Protocols should be designed such that
negotiations performed prior to authentication should be either
ignored or revalidated once authentication is complete.
10. Author's Address
John G. Myers
Netscape Communications
501 E. Middlefield Road
Mail Stop MV-029
Mountain View, CA 94043-4042
EMail: jgmyers@netscape.com
Myers Standards Track [Page 14]
RFC 2222 SASL October 1997
Appendix A. Relation of SASL to Transport Security
Questions have been raised about the relationship between SASL and
various services (such as IPsec and TLS) which provide a secured
connection.
Two of the key features of SASL are:
1. The separation of the authorization identity from the identity in
the client's credentials. This permits agents such as proxy
servers to authenticate using their own credentials, yet request
the access privileges of the identity for which they are proxying.
2. Upon successful completion of an authentication exchange, the
server knows the authorization identity the client wishes to use.
This allows servers to move to a "user is authenticated" state in
the protocol.
These features are extremely important to some application protocols,
yet Transport Security services do not always provide them. To
define SASL mechanisms based on these services would be a very messy
task, as the framing of these services would be redundant with the
framing of SASL and some method of providing these important SASL
features would have to be devised.
Sometimes it is desired to enable within an existing connection the
use of a security service which does not fit the SASL model. (TLS is
an example of such a service.) This can be done by adding a command,
for example "STARTTLS", to the protocol. Such a command is outside
the scope of SASL, and should be different from the command which
starts a SASL authentication protocol exchange.
In certain situations, it is reasonable to use SASL underneath one of
these Transport Security services. The transport service would
secure the connection, either service would authenticate the client,
and SASL would negotiate the authorization identity. The SASL
negotiation would be what moves the protocol from "unauthenticated"
to "authenticated" state. The "EXTERNAL" SASL mechanism is
explicitly intended to handle the case where the transport service
secures the connection and authenticates the client and SASL
negotiates the authorization identity.
When using SASL underneath a sufficiently strong Transport Security
service, a SASL security layer would most likely be redundant. The
client and server would thus probably want to negotiate off the use
of a SASL security layer.
Myers Standards Track [Page 15]
RFC 2222 SASL October 1997
Full Copyright Statement
Copyright (C) The Internet Society (1997). All Rights Reserved.
This document and translations of it may be copied and furnished to
others, and derivative works that comment on or otherwise explain it
or assist in its implmentation may be prepared, copied, published
andand distributed, in whole or in part, without restriction of any
kind, provided that the above copyright notice and this paragraph are
included on all such copies and derivative works. However, this
document itself may not be modified in any way, such as by removing
the copyright notice or references to the Internet Society or other
Internet organizations, except as needed for the purpose of
developing Internet standards in which case the procedures for
copyrights defined in the Internet Standards process must be
followed, or as required to translate it into languages other than
English.
The limited permissions granted above are perpetual and will not be
revoked by the Internet Society or its successors or assigns.
This document and the information contained herein is provided on an
"AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
Myers Standards Track [Page 16]

View File

@ -0,0 +1,787 @@
Network Working Group D. Crocker, Ed.
Request for Comments: 2234 Internet Mail Consortium
Category: Standards Track P. Overell
Demon Internet Ltd.
November 1997
Augmented BNF for Syntax Specifications: ABNF
Status of this Memo
This document specifies an Internet standards track protocol for the
Internet community, and requests discussion and suggestions for
improvements. Please refer to the current edition of the "Internet
Official Protocol Standards" (STD 1) for the standardization state
and status of this protocol. Distribution of this memo is unlimited.
Copyright Notice
Copyright (C) The Internet Society (1997). All Rights Reserved.
TABLE OF CONTENTS
1. INTRODUCTION .................................................. 2
2. RULE DEFINITION ............................................... 2
2.1 RULE NAMING .................................................. 2
2.2 RULE FORM .................................................... 3
2.3 TERMINAL VALUES .............................................. 3
2.4 EXTERNAL ENCODINGS ........................................... 5
3. OPERATORS ..................................................... 5
3.1 CONCATENATION RULE1 RULE2 ............................. 5
3.2 ALTERNATIVES RULE1 / RULE2 ................................... 6
3.3 INCREMENTAL ALTERNATIVES RULE1 =/ RULE2 .................... 6
3.4 VALUE RANGE ALTERNATIVES %C##-## ........................... 7
3.5 SEQUENCE GROUP (RULE1 RULE2) ................................. 7
3.6 VARIABLE REPETITION *RULE .................................... 8
3.7 SPECIFIC REPETITION NRULE .................................... 8
3.8 OPTIONAL SEQUENCE [RULE] ..................................... 8
3.9 ; COMMENT .................................................... 8
3.10 OPERATOR PRECEDENCE ......................................... 9
4. ABNF DEFINITION OF ABNF ....................................... 9
5. SECURITY CONSIDERATIONS ....................................... 10
Crocker & Overell Standards Track [Page 1]
RFC 2234 ABNF for Syntax Specifications November 1997
6. APPENDIX A - CORE ............................................. 11
6.1 CORE RULES ................................................... 11
6.2 COMMON ENCODING .............................................. 12
7. ACKNOWLEDGMENTS ............................................... 12
8. REFERENCES .................................................... 13
9. CONTACT ....................................................... 13
10. FULL COPYRIGHT STATEMENT ..................................... 14
1. INTRODUCTION
Internet technical specifications often need to define a format
syntax and are free to employ whatever notation their authors deem
useful. Over the years, a modified version of Backus-Naur Form
(BNF), called Augmented BNF (ABNF), has been popular among many
Internet specifications. It balances compactness and simplicity,
with reasonable representational power. In the early days of the
Arpanet, each specification contained its own definition of ABNF.
This included the email specifications, RFC733 and then RFC822 which
have come to be the common citations for defining ABNF. The current
document separates out that definition, to permit selective
reference. Predictably, it also provides some modifications and
enhancements.
The differences between standard BNF and ABNF involve naming rules,
repetition, alternatives, order-independence, and value ranges.
Appendix A (Core) supplies rule definitions and encoding for a core
lexical analyzer of the type common to several Internet
specifications. It is provided as a convenience and is otherwise
separate from the meta language defined in the body of this document,
and separate from its formal status.
2. RULE DEFINITION
2.1 Rule Naming
The name of a rule is simply the name itself; that is, a sequence of
characters, beginning with an alphabetic character, and followed by
a combination of alphabetics, digits and hyphens (dashes).
NOTE: Rule names are case-insensitive
The names <rulename>, <Rulename>, <RULENAME> and <rUlENamE> all refer
to the same rule.
Crocker & Overell Standards Track [Page 2]
RFC 2234 ABNF for Syntax Specifications November 1997
Unlike original BNF, angle brackets ("<", ">") are not required.
However, angle brackets may be used around a rule name whenever their
presence will facilitate discerning the use of a rule name. This is
typically restricted to rule name references in free-form prose, or
to distinguish partial rules that combine into a string not separated
by white space, such as shown in the discussion about repetition,
below.
2.2 Rule Form
A rule is defined by the following sequence:
name = elements crlf
where <name> is the name of the rule, <elements> is one or more rule
names or terminal specifications and <crlf> is the end-of- line
indicator, carriage return followed by line feed. The equal sign
separates the name from the definition of the rule. The elements
form a sequence of one or more rule names and/or value definitions,
combined according to the various operators, defined in this
document, such as alternative and repetition.
For visual ease, rule definitions are left aligned. When a rule
requires multiple lines, the continuation lines are indented. The
left alignment and indentation are relative to the first lines of the
ABNF rules and need not match the left margin of the document.
2.3 Terminal Values
Rules resolve into a string of terminal values, sometimes called
characters. In ABNF a character is merely a non-negative integer.
In certain contexts a specific mapping (encoding) of values into a
character set (such as ASCII) will be specified.
Terminals are specified by one or more numeric characters with the
base interpretation of those characters indicated explicitly. The
following bases are currently defined:
b = binary
d = decimal
x = hexadecimal
Crocker & Overell Standards Track [Page 3]
RFC 2234 ABNF for Syntax Specifications November 1997
Hence:
CR = %d13
CR = %x0D
respectively specify the decimal and hexadecimal representation of
[US-ASCII] for carriage return.
A concatenated string of such values is specified compactly, using a
period (".") to indicate separation of characters within that value.
Hence:
CRLF = %d13.10
ABNF permits specifying literal text string directly, enclosed in
quotation-marks. Hence:
command = "command string"
Literal text strings are interpreted as a concatenated set of
printable characters.
NOTE: ABNF strings are case-insensitive and
the character set for these strings is us-ascii.
Hence:
rulename = "abc"
and:
rulename = "aBc"
will match "abc", "Abc", "aBc", "abC", "ABc", "aBC", "AbC" and "ABC".
To specify a rule which IS case SENSITIVE,
specify the characters individually.
For example:
rulename = %d97 %d98 %d99
or
rulename = %d97.98.99
Crocker & Overell Standards Track [Page 4]
RFC 2234 ABNF for Syntax Specifications November 1997
will match only the string which comprises only lowercased
characters, abc.
2.4 External Encodings
External representations of terminal value characters will vary
according to constraints in the storage or transmission environment.
Hence, the same ABNF-based grammar may have multiple external
encodings, such as one for a 7-bit US-ASCII environment, another for
a binary octet environment and still a different one when 16-bit
Unicode is used. Encoding details are beyond the scope of ABNF,
although Appendix A (Core) provides definitions for a 7-bit US-ASCII
environment as has been common to much of the Internet.
By separating external encoding from the syntax, it is intended that
alternate encoding environments can be used for the same syntax.
3. OPERATORS
3.1 Concatenation Rule1 Rule2
A rule can define a simple, ordered string of values -- i.e., a
concatenation of contiguous characters -- by listing a sequence of
rule names. For example:
foo = %x61 ; a
bar = %x62 ; b
mumble = foo bar foo
So that the rule <mumble> matches the lowercase string "aba".
LINEAR WHITE SPACE: Concatenation is at the core of the ABNF
parsing model. A string of contiguous characters (values) is
parsed according to the rules defined in ABNF. For Internet
specifications, there is some history of permitting linear white
space (space and horizontal tab) to be freelyPand
implicitlyPinterspersed around major constructs, such as
delimiting special characters or atomic strings.
NOTE: This specification for ABNF does not
provide for implicit specification of linear white
space.
Any grammar which wishes to permit linear white space around
delimiters or string segments must specify it explicitly. It is
often useful to provide for such white space in "core" rules that are
Crocker & Overell Standards Track [Page 5]
RFC 2234 ABNF for Syntax Specifications November 1997
then used variously among higher-level rules. The "core" rules might
be formed into a lexical analyzer or simply be part of the main
ruleset.
3.2 Alternatives Rule1 / Rule2
Elements separated by forward slash ("/") are alternatives.
Therefore,
foo / bar
will accept <foo> or <bar>.
NOTE: A quoted string containing alphabetic
characters is special form for specifying alternative
characters and is interpreted as a non-terminal
representing the set of combinatorial strings with the
contained characters, in the specified order but with
any mixture of upper and lower case..
3.3 Incremental Alternatives Rule1 =/ Rule2
It is sometimes convenient to specify a list of alternatives in
fragments. That is, an initial rule may match one or more
alternatives, with later rule definitions adding to the set of
alternatives. This is particularly useful for otherwise- independent
specifications which derive from the same parent rule set, such as
often occurs with parameter lists. ABNF permits this incremental
definition through the construct:
oldrule =/ additional-alternatives
So that the rule set
ruleset = alt1 / alt2
ruleset =/ alt3
ruleset =/ alt4 / alt5
is the same as specifying
ruleset = alt1 / alt2 / alt3 / alt4 / alt5
Crocker & Overell Standards Track [Page 6]
RFC 2234 ABNF for Syntax Specifications November 1997
3.4 Value Range Alternatives %c##-##
A range of alternative numeric values can be specified compactly,
using dash ("-") to indicate the range of alternative values. Hence:
DIGIT = %x30-39
is equivalent to:
DIGIT = "0" / "1" / "2" / "3" / "4" / "5" / "6" /
"7" / "8" / "9"
Concatenated numeric values and numeric value ranges can not be
specified in the same string. A numeric value may use the dotted
notation for concatenation or it may use the dash notation to specify
one value range. Hence, to specify one printable character, between
end of line sequences, the specification could be:
char-line = %x0D.0A %x20-7E %x0D.0A
3.5 Sequence Group (Rule1 Rule2)
Elements enclosed in parentheses are treated as a single element,
whose contents are STRICTLY ORDERED. Thus,
elem (foo / bar) blat
which matches (elem foo blat) or (elem bar blat).
elem foo / bar blat
matches (elem foo) or (bar blat).
NOTE: It is strongly advised to use grouping
notation, rather than to rely on proper reading of
"bare" alternations, when alternatives consist of
multiple rule names or literals.
Hence it is recommended that instead of the above form, the form:
(elem foo) / (bar blat)
be used. It will avoid misinterpretation by casual readers.
The sequence group notation is also used within free text to set off
an element sequence from the prose.
Crocker & Overell Standards Track [Page 7]
RFC 2234 ABNF for Syntax Specifications November 1997
3.6 Variable Repetition *Rule
The operator "*" preceding an element indicates repetition. The full
form is:
<a>*<b>element
where <a> and <b> are optional decimal values, indicating at least
<a> and at most <b> occurrences of element.
Default values are 0 and infinity so that *<element> allows any
number, including zero; 1*<element> requires at least one;
3*3<element> allows exactly 3 and 1*2<element> allows one or two.
3.7 Specific Repetition nRule
A rule of the form:
<n>element
is equivalent to
<n>*<n>element
That is, exactly <N> occurrences of <element>. Thus 2DIGIT is a
2-digit number, and 3ALPHA is a string of three alphabetic
characters.
3.8 Optional Sequence [RULE]
Square brackets enclose an optional element sequence:
[foo bar]
is equivalent to
*1(foo bar).
3.9 ; Comment
A semi-colon starts a comment that continues to the end of line.
This is a simple way of including useful notes in parallel with the
specifications.
Crocker & Overell Standards Track [Page 8]
RFC 2234 ABNF for Syntax Specifications November 1997
3.10 Operator Precedence
The various mechanisms described above have the following precedence,
from highest (binding tightest) at the top, to lowest and loosest at
the bottom:
Strings, Names formation
Comment
Value range
Repetition
Grouping, Optional
Concatenation
Alternative
Use of the alternative operator, freely mixed with concatenations can
be confusing.
Again, it is recommended that the grouping operator be used to
make explicit concatenation groups.
4. ABNF DEFINITION OF ABNF
This syntax uses the rules provided in Appendix A (Core).
rulelist = 1*( rule / (*c-wsp c-nl) )
rule = rulename defined-as elements c-nl
; continues if next line starts
; with white space
rulename = ALPHA *(ALPHA / DIGIT / "-")
defined-as = *c-wsp ("=" / "=/") *c-wsp
; basic rules definition and
; incremental alternatives
elements = alternation *c-wsp
c-wsp = WSP / (c-nl WSP)
c-nl = comment / CRLF
; comment or newline
comment = ";" *(WSP / VCHAR) CRLF
alternation = concatenation
*(*c-wsp "/" *c-wsp concatenation)
Crocker & Overell Standards Track [Page 9]
RFC 2234 ABNF for Syntax Specifications November 1997
concatenation = repetition *(1*c-wsp repetition)
repetition = [repeat] element
repeat = 1*DIGIT / (*DIGIT "*" *DIGIT)
element = rulename / group / option /
char-val / num-val / prose-val
group = "(" *c-wsp alternation *c-wsp ")"
option = "[" *c-wsp alternation *c-wsp "]"
char-val = DQUOTE *(%x20-21 / %x23-7E) DQUOTE
; quoted string of SP and VCHAR
without DQUOTE
num-val = "%" (bin-val / dec-val / hex-val)
bin-val = "b" 1*BIT
[ 1*("." 1*BIT) / ("-" 1*BIT) ]
; series of concatenated bit values
; or single ONEOF range
dec-val = "d" 1*DIGIT
[ 1*("." 1*DIGIT) / ("-" 1*DIGIT) ]
hex-val = "x" 1*HEXDIG
[ 1*("." 1*HEXDIG) / ("-" 1*HEXDIG) ]
prose-val = "<" *(%x20-3D / %x3F-7E) ">"
; bracketed string of SP and VCHAR
without angles
; prose description, to be used as
last resort
5. SECURITY CONSIDERATIONS
Security is truly believed to be irrelevant to this document.
Crocker & Overell Standards Track [Page 10]
RFC 2234 ABNF for Syntax Specifications November 1997
6. APPENDIX A - CORE
This Appendix is provided as a convenient core for specific grammars.
The definitions may be used as a core set of rules.
6.1 Core Rules
Certain basic rules are in uppercase, such as SP, HTAB, CRLF,
DIGIT, ALPHA, etc.
ALPHA = %x41-5A / %x61-7A ; A-Z / a-z
BIT = "0" / "1"
CHAR = %x01-7F
; any 7-bit US-ASCII character,
excluding NUL
CR = %x0D
; carriage return
CRLF = CR LF
; Internet standard newline
CTL = %x00-1F / %x7F
; controls
DIGIT = %x30-39
; 0-9
DQUOTE = %x22
; " (Double Quote)
HEXDIG = DIGIT / "A" / "B" / "C" / "D" / "E" / "F"
HTAB = %x09
; horizontal tab
LF = %x0A
; linefeed
LWSP = *(WSP / CRLF WSP)
; linear white space (past newline)
OCTET = %x00-FF
; 8 bits of data
SP = %x20
Crocker & Overell Standards Track [Page 11]
RFC 2234 ABNF for Syntax Specifications November 1997
; space
VCHAR = %x21-7E
; visible (printing) characters
WSP = SP / HTAB
; white space
6.2 Common Encoding
Externally, data are represented as "network virtual ASCII", namely
7-bit US-ASCII in an 8-bit field, with the high (8th) bit set to
zero. A string of values is in "network byte order" with the
higher-valued bytes represented on the left-hand side and being sent
over the network first.
7. ACKNOWLEDGMENTS
The syntax for ABNF was originally specified in RFC 733. Ken L.
Harrenstien, of SRI International, was responsible for re-coding the
BNF into an augmented BNF that makes the representation smaller and
easier to understand.
This recent project began as a simple effort to cull out the portion
of RFC 822 which has been repeatedly cited by non-email specification
writers, namely the description of augmented BNF. Rather than simply
and blindly converting the existing text into a separate document,
the working group chose to give careful consideration to the
deficiencies, as well as benefits, of the existing specification and
related specifications available over the last 15 years and therefore
to pursue enhancement. This turned the project into something rather
more ambitious than first intended. Interestingly the result is not
massively different from that original, although decisions such as
removing the list notation came as a surprise.
The current round of specification was part of the DRUMS working
group, with significant contributions from Jerome Abela , Harald
Alvestrand, Robert Elz, Roger Fajman, Aviva Garrett, Tom Harsch, Dan
Kohn, Bill McQuillan, Keith Moore, Chris Newman , Pete Resnick and
Henning Schulzrinne.
Crocker & Overell Standards Track [Page 12]
RFC 2234 ABNF for Syntax Specifications November 1997
8. REFERENCES
[US-ASCII] Coded Character Set--7-Bit American Standard Code for
Information Interchange, ANSI X3.4-1986.
[RFC733] Crocker, D., Vittal, J., Pogran, K., and D. Henderson,
"Standard for the Format of ARPA Network Text Message," RFC 733,
November 1977.
[RFC822] Crocker, D., "Standard for the Format of ARPA Internet Text
Messages", STD 11, RFC 822, August 1982.
9. CONTACT
David H. Crocker Paul Overell
Internet Mail Consortium Demon Internet Ltd
675 Spruce Dr. Dorking Business Park
Sunnyvale, CA 94086 USA Dorking
Surrey, RH4 1HN
UK
Phone: +1 408 246 8253
Fax: +1 408 249 6205
EMail: dcrocker@imc.org paulo@turnpike.com
Crocker & Overell Standards Track [Page 13]
RFC 2234 ABNF for Syntax Specifications November 1997
10. Full Copyright Statement
Copyright (C) The Internet Society (1997). All Rights Reserved.
This document and translations of it may be copied and furnished to
others, and derivative works that comment on or otherwise explain it
or assist in its implementation may be prepared, copied, published
and distributed, in whole or in part, without restriction of any
kind, provided that the above copyright notice and this paragraph are
included on all such copies and derivative works. However, this
document itself may not be modified in any way, such as by removing
the copyright notice or references to the Internet Society or other
Internet organizations, except as needed for the purpose of
developing Internet standards in which case the procedures for
copyrights defined in the Internet Standards process must be
followed, or as required to translate it into languages other than
English.
The limited permissions granted above are perpetual and will not be
revoked by the Internet Society or its successors or assigns.
This document and the information contained herein is provided on an
"AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
Crocker & Overell Standards Track [Page 14]

View File

@ -0,0 +1,283 @@
Network Working Group C. Newman
Request for Comments: 2245 Innosoft
Category: Standards Track November 1997
Anonymous SASL Mechanism
Status of this Memo
This document specifies an Internet standards track protocol for the
Internet community, and requests discussion and suggestions for
improvements. Please refer to the current edition of the "Internet
Official Protocol Standards" (STD 1) for the standardization state
and status of this protocol. Distribution of this memo is unlimited.
Copyright Notice
Copyright (C) The Internet Society (1997). All Rights Reserved.
Abstract
It is common practice on the Internet to permit anonymous access to
various services. Traditionally, this has been done with a plain
text password mechanism using "anonymous" as the user name and
optional trace information, such as an email address, as the
password. As plaintext login commands are not permitted in new IETF
protocols, a new way to provide anonymous login is needed within the
context of the SASL [SASL] framework.
1. Conventions Used in this Document
The key words "MUST", "MUST NOT", "SHOULD", "SHOULD NOT", and "MAY"
in this document are to be interpreted as defined in "Key words for
use in RFCs to Indicate Requirement Levels" [KEYWORDS].
2. Anonymous SASL mechanism
The mechanism name associated with anonymous access is "ANONYMOUS".
The mechanism consists of a single message from the client to the
server. The client sends optional trace information in the form of a
human readable string. The trace information should take one of
three forms: an Internet email address, an opaque string which does
not contain the '@' character and can be interpreted by the system
administrator of the client's domain, or nothing. For privacy
reasons, an Internet email address should only be used with
permission from the user.
Newman Standards Track [Page 1]
RFC 2245 Anonymous SASL Mechanism November 1997
A server which permits anonymous access will announce support for the
ANONYMOUS mechanism, and allow anyone to log in using that mechanism,
usually with restricted access.
The formal grammar for the client message using Augmented BNF [ABNF]
follows.
message = [email / token]
TCHAR = %x20-3F / %x41-7E
;; any printable US-ASCII character except '@'
email = addr-spec
;; as defined in [IMAIL], except with no free
;; insertion of linear-white-space, and the
;; local-part MUST either be entirely enclosed in
;; quotes or entirely unquoted
token = 1*255TCHAR
3. Example
Here is a sample anonymous login between an IMAP client and server.
In this example, "C:" and "S:" indicate lines sent by the client and
server respectively. If such lines are wrapped without a new "C:" or
"S:" label, then the wrapping is for editorial clarity and is not
part of the command.
Note that this example uses the IMAP profile [IMAP4] of SASL. The
base64 encoding of challenges and responses, as well as the "+ "
preceding the responses are part of the IMAP4 profile, not part of
SASL itself. Newer profiles of SASL will include the client message
with the AUTHENTICATE command itself so the extra round trip below
(the server response with an empty "+ ") can be eliminated.
In this example, the user's opaque identification token is "sirhc".
S: * OK IMAP4 server ready
C: A001 CAPABILITY
S: * CAPABILITY IMAP4 IMAP4rev1 AUTH=CRAM-MD5 AUTH=ANONYMOUS
S: A001 OK done
C: A002 AUTHENTICATE ANONYMOUS
S: +
C: c2lyaGM=
S: A003 OK Welcome, trace information has been logged.
Newman Standards Track [Page 2]
RFC 2245 Anonymous SASL Mechanism November 1997
4. Security Considerations
The anonymous mechanism grants access to information by anyone. For
this reason it should be disabled by default so the administrator can
make an explicit decision to enable it.
If the anonymous user has any write privileges, a denial of service
attack is possible by filling up all available space. This can be
prevented by disabling all write access by anonymous users.
If anonymous users have read and write access to the same area, the
server can be used as a communication mechanism to anonymously
exchange information. Servers which accept anonymous submissions
should implement the common "drop box" model which forbids anonymous
read access to the area where anonymous submissions are accepted.
If the anonymous user can run many expensive operations (e.g., an
IMAP SEARCH BODY command), this could enable a denial of service
attack. Servers are encouraged to limit the number of anonymous
users and reduce their priority or limit their resource usage.
If there is no idle timeout for the anonymous user and there is a
limit on the number of anonymous users, a denial of service attack is
enabled. Servers should implement an idle timeout for anonymous
users.
The trace information is not authenticated so it can be falsified.
This can be used as an attempt to get someone else in trouble for
access to questionable information. Administrators trying to trace
abuse need to realize this information may be falsified.
A client which uses the user's correct email address as trace
information without explicit permission may violate that user's
privacy. Information about who accesses an anonymous archive on a
sensitive subject (e.g., sexual abuse) has strong privacy needs.
Clients should not send the email address without explicit permission
of the user and should offer the option of supplying no trace token
-- thus only exposing the source IP address and time. Anonymous
proxy servers could enhance this privacy, but would have to consider
the resulting potential denial of service attacks.
Anonymous connections are susceptible to man in the middle attacks
which view or alter the data transferred. Clients and servers are
encouraged to support external integrity and encryption mechanisms.
Protocols which fail to require an explicit anonymous login are more
susceptible to break-ins given certain common implementation
techniques. Specifically, Unix servers which offer user login may
Newman Standards Track [Page 3]
RFC 2245 Anonymous SASL Mechanism November 1997
initially start up as root and switch to the appropriate user id
after an explicit login command. Normally such servers refuse all
data access commands prior to explicit login and may enter a
restricted security environment (e.g., the Unix chroot function) for
anonymous users. If anonymous access is not explicitly requested,
the entire data access machinery is exposed to external security
attacks without the chance for explicit protective measures.
Protocols which offer restricted data access should not allow
anonymous data access without an explicit login step.
5. References
[ABNF] Crocker, D. and P. Overell, "Augmented BNF for Syntax
Specifications: ABNF", RFC 2234, November 1997.
[IMAIL] Crocker, D., "Standard for the Format of Arpa Internet Text
Messages", STD 11, RFC 822, August 1982.
[IMAP4] Crispin, M., "Internet Message Access Protocol - Version
4rev1", RFC 2060, December 1996.
[KEYWORDS] Bradner, S., "Key words for use in RFCs to Indicate
Requirement Levels", RFC 2119, March 1997.
[SASL] Myers, J., "Simple Authentication and Security Layer (SASL)",
RFC 2222, October 1997.
6. Author's Address
Chris Newman
Innosoft International, Inc.
1050 Lakes Drive
West Covina, CA 91790 USA
Email: chris.newman@innosoft.com
Newman Standards Track [Page 4]
RFC 2245 Anonymous SASL Mechanism November 1997
7. Full Copyright Statement
Copyright (C) The Internet Society (1997). All Rights Reserved.
This document and translations of it may be copied and furnished to
others, and derivative works that comment on or otherwise explain it
or assist in its implementation may be prepared, copied, published
and distributed, in whole or in part, without restriction of any
kind, provided that the above copyright notice and this paragraph are
included on all such copies and derivative works. However, this
document itself may not be modified in any way, such as by removing
the copyright notice or references to the Internet Society or other
Internet organizations, except as needed for the purpose of
developing Internet standards in which case the procedures for
copyrights defined in the Internet Standards process must be
followed, or as required to translate it into languages other than
English.
The limited permissions granted above are perpetual and will not be
revoked by the Internet Society or its successors or assigns.
This document and the information contained herein is provided on an
"AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
Newman Standards Track [Page 5]

View File

@ -0,0 +1,563 @@
Network Working Group M. Gahrns
Request for Comments: 2342 Microsoft
Category: Standards Track C. Newman
Innosoft
May 1998
IMAP4 Namespace
Status of this Memo
This document specifies an Internet standards track protocol for the
Internet community, and requests discussion and suggestions for
improvements. Please refer to the current edition of the "Internet
Official Protocol Standards" (STD 1) for the standardization state
and status of this protocol. Distribution of this memo is unlimited.
Copyright Notice
Copyright (C) The Internet Society (1998). All Rights Reserved.
1. Abstract
IMAP4 [RFC-2060] does not define a default server namespace. As a
result, two common namespace models have evolved:
The "Personal Mailbox" model, in which the default namespace that is
presented consists of only the user's personal mailboxes. To access
shared mailboxes, the user must use an escape mechanism to reach
another namespace.
The "Complete Hierarchy" model, in which the default namespace that
is presented includes the user's personal mailboxes along with any
other mailboxes they have access to.
These two models, create difficulties for certain client operations.
This document defines a NAMESPACE command that allows a client to
discover the prefixes of namespaces used by a server for personal
mailboxes, other users' mailboxes, and shared mailboxes. This allows
a client to avoid much of the manual user configuration that is now
necessary when mixing and matching IMAP4 clients and servers.
2. Conventions used in this document
In examples, "C:" and "S:" indicate lines sent by the client and
server respectively. If such lines are wrapped without a new "C:" or
"S:" label, then the wrapping is for editorial clarity and is not
part of the command.
Gahrns & Newman Standards Track [Page 1]
RFC 2342 IMAP4 Namespace May 1998
Personal Namespace: A namespace that the server considers within the
personal scope of the authenticated user on a particular connection.
Typically, only the authenticated user has access to mailboxes in
their Personal Namespace. It is the part of the namespace that
belongs to the user that is allocated for mailboxes. If an INBOX
exists for a user, it MUST appear within the user's personal
namespace. In the typical case, there SHOULD be only one Personal
Namespace on a server.
Other Users' Namespace: A namespace that consists of mailboxes from
the Personal Namespaces of other users. To access mailboxes in the
Other Users' Namespace, the currently authenticated user MUST be
explicitly granted access rights. For example, it is common for a
manager to grant to their secretary access rights to their mailbox.
In the typical case, there SHOULD be only one Other Users' Namespace
on a server.
Shared Namespace: A namespace that consists of mailboxes that are
intended to be shared amongst users and do not exist within a user's
Personal Namespace.
The namespaces a server uses MAY differ on a per-user basis.
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
"SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
document are to be interpreted as described in [RFC-2119].
3. Introduction and Overview
Clients often attempt to create mailboxes for such purposes as
maintaining a record of sent messages (e.g. "Sent Mail") or
temporarily saving messages being composed (e.g. "Drafts"). For
these clients to inter-operate correctly with the variety of IMAP4
servers available, the user must enter the prefix of the Personal
Namespace used by the server. Using the NAMESPACE command, a client
is able to automatically discover this prefix without manual user
configuration.
In addition, users are often required to manually enter the prefixes
of various namespaces in order to view the mailboxes located there.
For example, they might be required to enter the prefix of #shared to
view the shared mailboxes namespace. The NAMESPACE command allows a
client to automatically discover the namespaces that are available on
a server. This allows a client to present the available namespaces to
the user in what ever manner it deems appropriate. For example, a
Gahrns & Newman Standards Track [Page 2]
RFC 2342 IMAP4 Namespace May 1998
client could choose to initially display only personal mailboxes, or
it may choose to display the complete list of mailboxes available,
and initially position the user at the root of their Personal
Namespace.
A server MAY choose to make available to the NAMESPACE command only a
subset of the complete set of namespaces the server supports. To
provide the ability to access these namespaces, a client SHOULD allow
the user the ability to manually enter a namespace prefix.
4. Requirements
IMAP4 servers that support this extension MUST list the keyword
NAMESPACE in their CAPABILITY response.
The NAMESPACE command is valid in the Authenticated and Selected
state.
5. NAMESPACE Command
Arguments: none
Response: an untagged NAMESPACE response that contains the prefix
and hierarchy delimiter to the server's Personal
Namespace(s), Other Users' Namespace(s), and Shared
Namespace(s) that the server wishes to expose. The
response will contain a NIL for any namespace class
that is not available. Namespace_Response_Extensions
MAY be included in the response.
Namespace_Response_Extensions which are not on the IETF
standards track, MUST be prefixed with an "X-".
Result: OK - Command completed
NO - Error: Can't complete command
BAD - argument invalid
Example 5.1:
===========
< A server that supports a single personal namespace. No leading
prefix is used on personal mailboxes and "/" is the hierarchy
delimiter.>
C: A001 NAMESPACE
S: * NAMESPACE (("" "/")) NIL NIL
S: A001 OK NAMESPACE command completed
Gahrns & Newman Standards Track [Page 3]
RFC 2342 IMAP4 Namespace May 1998
Example 5.2:
===========
< A user logged on anonymously to a server. No personal mailboxes
are associated with the anonymous user and the user does not have
access to the Other Users' Namespace. No prefix is required to
access shared mailboxes and the hierarchy delimiter is "." >
C: A001 NAMESPACE
S: * NAMESPACE NIL NIL (("" "."))
S: A001 OK NAMESPACE command completed
Example 5.3:
===========
< A server that contains a Personal Namespace and a single Shared
Namespace. >
C: A001 NAMESPACE
S: * NAMESPACE (("" "/")) NIL (("Public Folders/" "/"))
S: A001 OK NAMESPACE command completed
Example 5.4:
===========
< A server that contains a Personal Namespace, Other Users'
Namespace and multiple Shared Namespaces. Note that the hierarchy
delimiter used within each namespace can be different. >
C: A001 NAMESPACE
S: * NAMESPACE (("" "/")) (("~" "/")) (("#shared/" "/")
("#public/" "/")("#ftp/" "/")("#news." "."))
S: A001 OK NAMESPACE command completed
The prefix string allows a client to do things such as automatically
creating personal mailboxes or LISTing all available mailboxes within
a namespace.
Example 5.5:
===========
< A server that supports only the Personal Namespace, with a
leading prefix of INBOX to personal mailboxes and a hierarchy
delimiter of ".">
C: A001 NAMESPACE
S: * NAMESPACE (("INBOX." ".")) NIL NIL
S: A001 OK NAMESPACE command completed
Gahrns & Newman Standards Track [Page 4]
RFC 2342 IMAP4 Namespace May 1998
< Automatically create a mailbox to store sent items.>
C: A002 CREATE "INBOX.Sent Mail"
S: A002 OK CREATE command completed
Although typically a server will support only a single Personal
Namespace, and a single Other User's Namespace, circumstances exist
where there MAY be multiples of these, and a client MUST be prepared
for them. If a client is configured such that it is required to
create a certain mailbox, there can be circumstances where it is
unclear which Personal Namespaces it should create the mailbox in.
In these situations a client SHOULD let the user select which
namespaces to create the mailbox in.
Example 5.6:
===========
< In this example, a server supports 2 Personal Namespaces. In
addition to the regular Personal Namespace, the user has an
additional personal namespace to allow access to mailboxes in an
MH format mailstore. >
< The client is configured to save a copy of all mail sent by the
user into a mailbox called 'Sent Mail'. Furthermore, after a
message is deleted from a mailbox, the client is configured to
move that message to a mailbox called 'Deleted Items'.>
< Note that this example demonstrates how some extension flags can
be passed to further describe the #mh namespace. >
C: A001 NAMESPACE
S: * NAMESPACE (("" "/")("#mh/" "/" "X-PARAM" ("FLAG1" "FLAG2")))
NIL NIL
S: A001 OK NAMESPACE command completed
< It is desired to keep only one copy of sent mail. It is unclear
which Personal Namespace the client should use to create the 'Sent
Mail' mailbox. The user is prompted to select a namespace and
only one 'Sent Mail' mailbox is created. >
C: A002 CREATE "Sent Mail"
S: A002 OK CREATE command completed
< The client is designed so that it keeps two 'Deleted Items'
mailboxes, one for each namespace. >
C: A003 CREATE "Delete Items"
S: A003 OK CREATE command completed
Gahrns & Newman Standards Track [Page 5]
RFC 2342 IMAP4 Namespace May 1998
C: A004 CREATE "#mh/Deleted Items"
S: A004 OK CREATE command completed
The next level of hierarchy following the Other Users' Namespace
prefix SHOULD consist of <username>, where <username> is a user name
as per the IMAP4 LOGIN or AUTHENTICATE command.
A client can construct a LIST command by appending a "%" to the Other
Users' Namespace prefix to discover the Personal Namespaces of other
users that are available to the currently authenticated user.
In response to such a LIST command, a server SHOULD NOT return user
names that have not granted access to their personal mailboxes to the
user in question.
A server MAY return a LIST response containing only the names of
users that have explicitly granted access to the user in question.
Alternatively, a server MAY return NO to such a LIST command,
requiring that a user name be included with the Other Users'
Namespace prefix before listing any other user's mailboxes.
Example 5.7:
===========
< A server that supports providing a list of other user's
mailboxes that are accessible to the currently logged on user. >
C: A001 NAMESPACE
S: * NAMESPACE (("" "/")) (("Other Users/" "/")) NIL
S: A001 OK NAMESPACE command completed
C: A002 LIST "" "Other Users/%"
S: * LIST () "/" "Other Users/Mike"
S: * LIST () "/" "Other Users/Karen"
S: * LIST () "/" "Other Users/Matthew"
S: * LIST () "/" "Other Users/Tesa"
S: A002 OK LIST command completed
Example 5.8:
===========
< A server that does not support providing a list of other user's
mailboxes that are accessible to the currently logged on user.
The mailboxes are listable if the client includes the name of the
other user with the Other Users' Namespace prefix. >
Gahrns & Newman Standards Track [Page 6]
RFC 2342 IMAP4 Namespace May 1998
C: A001 NAMESPACE
S: * NAMESPACE (("" "/")) (("#Users/" "/")) NIL
S: A001 OK NAMESPACE command completed
< In this example, the currently logged on user has access to the
Personal Namespace of user Mike, but the server chose to suppress
this information in the LIST response. However, by appending the
user name Mike (received through user input) to the Other Users'
Namespace prefix, the client is able to get a listing of the
personal mailboxes of user Mike. >
C: A002 LIST "" "#Users/%"
S: A002 NO The requested item could not be found.
C: A003 LIST "" "#Users/Mike/%"
S: * LIST () "/" "#Users/Mike/INBOX"
S: * LIST () "/" "#Users/Mike/Foo"
S: A003 OK LIST command completed.
A prefix string might not contain a hierarchy delimiter, because
in some cases it is not needed as part of the prefix.
Example 5.9:
===========
< A server that allows access to the Other Users' Namespace by
prefixing the others' mailboxes with a '~' followed by <username>,
where <username> is a user name as per the IMAP4 LOGIN or
AUTHENTICATE command.>
C: A001 NAMESPACE
S: * NAMESPACE (("" "/")) (("~" "/")) NIL
S: A001 OK NAMESPACE command completed
< List the mailboxes for user mark >
C: A002 LIST "" "~mark/%"
S: * LIST () "/" "~mark/INBOX"
S: * LIST () "/" "~mark/foo"
S: A002 OK LIST command completed
Historical convention has been to start all namespaces with the "#"
character. Namespaces that include the "#" character are not IMAP
URL [IMAP-URL] friendly requiring the "#" character to be represented
as %23 when within URLs. As such, server implementers MAY instead
consider using namespace prefixes that do not contain the "#"
character.
Gahrns & Newman Standards Track [Page 7]
RFC 2342 IMAP4 Namespace May 1998
6. Formal Syntax
The following syntax specification uses the augmented Backus-Naur
Form (BNF) as described in [ABNF].
atom = <atom>
; <atom> as defined in [RFC-2060]
Namespace = nil / "(" 1*( "(" string SP (<"> QUOTED_CHAR <"> /
nil) *(Namespace_Response_Extension) ")" ) ")"
Namespace_Command = "NAMESPACE"
Namespace_Response_Extension = SP string SP "(" string *(SP string)
")"
Namespace_Response = "*" SP "NAMESPACE" SP Namespace SP Namespace SP
Namespace
; The first Namespace is the Personal Namespace(s)
; The second Namespace is the Other Users' Namespace(s)
; The third Namespace is the Shared Namespace(s)
nil = <nil>
; <nil> as defined in [RFC-2060]
QUOTED_CHAR = <QUOTED_CHAR>
; <QUOTED_CHAR> as defined in [RFC-2060]
string = <string>
; <string> as defined in [RFC-2060]
; Note that the namespace prefix is to a mailbox and following
; IMAP4 convention, any international string in the NAMESPACE
; response MUST be of modified UTF-7 format as described in
; [RFC-2060].
7. Security Considerations
In response to a LIST command containing an argument of the Other
Users' Namespace prefix, a server SHOULD NOT list users that have not
granted list access to their personal mailboxes to the currently
authenticated user. Providing such a list, could compromise security
by potentially disclosing confidential information of who is located
on the server, or providing a starting point of a list of user
accounts to attack.
Gahrns & Newman Standards Track [Page 8]
RFC 2342 IMAP4 Namespace May 1998
8. References
[RFC-2060], Crispin, M., "Internet Message Access Protocol Version
4rev1", RFC 2060, December 1996.
[RFC-2119], Bradner, S., "Key words for use in RFCs to Indicate
Requirement Levels", BCP 14, RFC 2119, March 1997.
[ABNF] Crocker, D., Editor, and P. Overell, "Augmented BNF for Syntax
Specifications: ABNF", RFC 2234, November 1997.
[IMAP-URL], Newman, C., "IMAP URL Scheme", RFC 2192, September 1997.
9. Acknowledgments
Many people have participated in the discussion of IMAP namespaces on
the IMAP mailing list. In particular, the authors would like to
thank Mark Crispin for many of the concepts relating to the Personal
Namespace and accessing the Personal Namespace of other users, Steve
Hole for summarizing the two namespace models, John Myers and Jack De
Winter for their work in a preceding effort trying to define a
standardized personal namespace, and Larry Osterman for his review
and collaboration on this document.
11. Authors' Addresses
Mike Gahrns
Microsoft
One Microsoft Way
Redmond, WA, 98072, USA
Phone: (425) 936-9833
EMail: mikega@microsoft.com
Chris Newman
Innosoft International, Inc.
1050 East Garvey Ave. South
West Covina, CA, 91790, USA
EMail: chris.newman@innosoft.com
Gahrns & Newman Standards Track [Page 9]
RFC 2342 IMAP4 Namespace May 1998
12. Full Copyright Statement
Copyright (C) The Internet Society (1998). All Rights Reserved.
This document and translations of it may be copied and furnished to
others, and derivative works that comment on or otherwise explain it
or assist in its implementation may be prepared, copied, published
and distributed, in whole or in part, without restriction of any
kind, provided that the above copyright notice and this paragraph are
included on all such copies and derivative works. However, this
document itself may not be modified in any way, such as by removing
the copyright notice or references to the Internet Society or other
Internet organizations, except as needed for the purpose of
developing Internet standards in which case the procedures for
copyrights defined in the Internet Standards process must be
followed, or as required to translate it into languages other than
English.
The limited permissions granted above are perpetual and will not be
revoked by the Internet Society or its successors or assigns.
This document and the information contained herein is provided on an
"AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
Gahrns & Newman Standards Track [Page 10]

View File

@ -0,0 +1,339 @@
Network Working Group J. Myers
Request for Comments: 2359 Netscape Communications
Category: Standards Track June 1998
IMAP4 UIDPLUS extension
Status of this Memo
This document specifies an Internet standards track protocol for the
Internet community, and requests discussion and suggestions for
improvements. Please refer to the current edition of the "Internet
Official Protocol Standards" (STD 1) for the standardization state
and status of this protocol. Distribution of this memo is unlimited.
Copyright Notice
Copyright (C) The Internet Society (1998). All Rights Reserved.
IESG NOTE
The IMAP extension described here assumes a particular means of using
IMAP to support disconnected operation. However, this means of
supporting disconnected operation is not yet documented. Also, there
are multiple theories about how best to do disconnected operation in
IMAP, and as yet, there is no consensus on which one should be
adopted as a standard.
This document is being approved as a Proposed Standard because it
does not appear to have technical flaws in itelf. However, approval
of this document as a Proposed Standard should not be considered an
IETF endorsement of any particular means of doing disconnected
operation in IMAP.
Table of Contents
1. Abstract .............................................. 2
2. Conventions Used in this Document ..................... 2
3. Introduction and Overview ............................. 2
4. Features .............................................. 2
4.1. UID EXPUNGE Command ................................... 2
4.2. APPENDUID response code ............................... 3
4.3. COPYUID response code ................................. 4
5. Formal Syntax ......................................... 4
6. References ............................................ 4
7. Security Considerations ............................... 5
8. Author's Address ...................................... 5
9. Full Copyright Statement .............................. 6
Myers Standards Track [Page 1]
RFC 2359 IMAP4 UIDPLUS extension June 1998
1. Abstract
The UIDPLUS extension of the Internet Message Access Protocol [IMAP4]
provides a set of features intended to reduce the amount of time and
resources used by some client operations. The features in UIDPLUS
are primarily intended for disconnected-use clients.
2. Conventions Used in this Document
In examples, "C:" and "S:" indicate lines sent by the client and
server respectively.
The key words "MUST", "MUST NOT", "SHOULD", "SHOULD NOT", and "MAY"
in this document are to be interpreted as defined in "Key words for
use in RFCs to Indicate Requirement Levels" [KEYWORDS].
3. Introduction and Overview
The UIDPLUS extension is present in any IMAP4 server implementation
which returns "UIDPLUS" as one of the supported capabilities to the
CAPABILITY command. The UIDPLUS extension contains one additional
command and additional data returned with successful APPEND and COPY
commands.
Clients that wish to use the new command in UIDPLUS must of course
first test for the presence of the extension by issuing a CAPABILITY
command. Each of the features in UIDPLUS are optimizations; clients
can provide the same functionality, albeit more slowly, by using
commands in the base protocol. With each feature, this document
recommends a fallback approach to take when the UIDPLUS extension is
not supported by the server.
4. Features
4.1. UID EXPUNGE Command
Arguments: message set
Data: untagged responses: EXPUNGE
Result: OK - expunge completed
NO - expunge failure (e.g. permission denied)
BAD - command unknown or arguments invalid
Myers Standards Track [Page 2]
RFC 2359 IMAP4 UIDPLUS extension June 1998
The UID EXPUNGE command permanently removes from the currently
selected mailbox all messages that both have the \Deleted flag set
and have a UID that is included in the specified message set. If
a message either does not have the \Deleted flag set or is has a
UID that is not included in the specified message set, it is not
affected.
This command may be used to ensure that a replayed EXPUNGE command
does not remove any messages that have been marked as \Deleted
between the time that the user requested the expunge operation and
the time the server processes the command.
If the server does not support the UIDPLUS capability, the client
should fall back to using the STORE command to temporarily remove
the \Deleted flag from messages it does not want to remove. The
client could alternatively fall back to using the EXPUNGE command,
risking the unintended removal of some messages.
Example: C: A003 UID EXPUNGE 3000:3002
S: * 3 EXPUNGE
S: * 3 EXPUNGE
S: * 3 EXPUNGE
S: A003 OK UID EXPUNGE completed
4.2. APPENDUID response code
Successful APPEND commands return an APPENDUID response code in the
tagged OK response. The APPENDUID response code contains as
arguments the UIDVALIDITY of the destination mailbox and the UID
assigned to the appended message.
If the server does not support the UIDPLUS capability, the client can
only discover this information by selecting the destination mailbox
and issuing FETCH commands.
Example: C: A003 APPEND saved-messages (\Seen) {310}
C: Date: Mon, 7 Feb 1994 21:52:25 -0800 (PST)
C: From: Fred Foobar <foobar@Blurdybloop.COM>
C: Subject: afternoon meeting
C: To: mooch@owatagu.siam.edu
C: Message-Id: <B27397-0100000@Blurdybloop.COM>
C: MIME-Version: 1.0
C: Content-Type: TEXT/PLAIN; CHARSET=US-ASCII
C:
C: Hello Joe, do you think we can meet at 3:30 tomorrow?
C:
S: A003 OK [APPENDUID 38505 3955] APPEND completed
Myers Standards Track [Page 3]
RFC 2359 IMAP4 UIDPLUS extension June 1998
4.3. COPYUID response code
Successful COPY and UID COPY commands return a COPYUID response code
in the tagged OK response whenever at least one message was copied.
The COPYUID response code contains as an argument the UIDVALIDITY of
the appended-to mailbox, a message set containing the UIDs of the
messages copied to the destination mailbox, in the order they were
copied, and a message containing the UIDs assigned to the copied
messages, in the order they were assigned. Neither of the message
sets may contain extraneous UIDs or the symbol '*'.
If the server does not support the UIDPLUS capability, the client can
only discover this information by selecting the destination mailbox
and issuing FETCH commands.
Example: C: A003 COPY 2:4 MEETING
S: A003 OK [COPYUID 38505 304,319:320 3956:3958] Done
C: A003 UID COPY 305:310 MEETING
S: A003 OK Done
5. Formal Syntax
The following syntax specification uses the augmented Backus-Naur
Form (BNF) notation as specified in [RFC-822] as modified by [IMAP4].
Non-terminals referenced but not defined below are as defined by
[IMAP4].
Except as noted otherwise, all alphabetic characters are case-
insensitive. The use of upper or lower case characters to define
token strings is for editorial clarity only. Implementations MUST
accept these strings in a case-insensitive fashion.
resp_code_apnd ::= "APPENDUID" SPACE nz_number SPACE uniqueid
resp_code_copy ::= "COPYUID" SPACE nz_number SPACE set SPACE set
uid_expunge ::= "UID" SPACE "EXPUNGE" SPACE set
6. References
[IMAP4] Crispin, M., "Internet Message Access Protocol -
Version 4rev1", RFC 2060, December 1996.
[KEYWORDS] Bradner, S., "Key words for use in RFCs to Indicate
Requirement Levels", BCP 14, RFC 2119, March 1997.
[RFC-822] Crocker, D., "Standard for the Format of ARPA Internet
Text Messages", STD 11, RFC 822, August 1982.
Myers Standards Track [Page 4]
RFC 2359 IMAP4 UIDPLUS extension June 1998
7. Security Considerations
There are no known security issues with this extension.
8. Author's Address
John Gardiner Myers
Netscape Communications
501 East Middlefield Road
Mail Stop MV-029
Mountain View, CA 94043
EMail: jgmyers@netscape.com
Myers Standards Track [Page 5]
RFC 2359 IMAP4 UIDPLUS extension June 1998
9. Full Copyright Statement
Copyright (C) The Internet Society (1998). All Rights Reserved.
This document and translations of it may be copied and furnished to
others, and derivative works that comment on or otherwise explain it
or assist in its implementation may be prepared, copied, published
and distributed, in whole or in part, without restriction of any
kind, provided that the above copyright notice and this paragraph are
included on all such copies and derivative works. However, this
document itself may not be modified in any way, such as by removing
the copyright notice or references to the Internet Society or other
Internet organizations, except as needed for the purpose of
developing Internet standards in which case the procedures for
copyrights defined in the Internet Standards process must be
followed, or as required to translate it into languages other than
English.
The limited permissions granted above are perpetual and will not be
revoked by the Internet Society or its successors or assigns.
This document and the information contained herein is provided on an
"AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
Myers Standards Track [Page 6]

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,21 @@
COPYRIGHT
Copyright 1999, 2000, 2001, 2002 , 2003 The Kernen Group, Inc.
All rights reserved.
This program is free software; you can redistribute it and/or modify it
under the terms of either:
a) the "Artistic License" which comes with this Kit, or
b) the GNU General Public License as published by the Free Software
Foundation; either version 1, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See either the GNU
General Public License or the Artistic License for more details. All your
base are belong to us.

View File

@ -0,0 +1,808 @@
# Before `make install' is performed this script should be runnable with
# `make test'. After `make install' it should work as `perl test.pl'
# $Id: basic.t,v 19991216.27 2003/06/12 21:38:35 dkernen Exp $
######################### We start with some black magic to print on failure.
# Change 1..1 below to 1..last_test_to_print .
END {print "not ok 1\n" unless $main::loaded;}
use Mail::IMAPClient;
######################### End of black magic.
my $test = 0;
my %parms;
my $imap;
my @tests;
my $uid;
$fast||=0;
$range||=0;
$uidplus||=0;
$authmech||=0;
use vars qw/*TMP $imap/;
BEGIN {
$^W++;
# $ARGV[0]||=1;
my $target; my $sep; my $target2;
push @tests, sub { $test++ } ; # Dummy test 1
push @tests, sub { # 2
if (ref($imap)) {
print "ok ",++$test,"\n"; # ok 2
} else {
print "not ok ",++$test,"\n";
print STDERR "\nTest $test failed:\n$@\n";
}
};
push @tests, sub { # 3
if ($sep = $imap->separator) {
print "ok ",++$test,"\n"; # ok 3
} else {
print "not ok ",++$test,"\n";
print STDERR "\nTest $test failed:\n$@\n";
}
};
push @tests, sub { # 4
my $isparent;
$isparent = $imap->is_parent(INBOX);
if (defined($isparent)) {
$target = "INBOX${sep}IMAPClient_$$";
$target2 = "INBOX${sep}IMAPClient_2_$$";
print "ok ",++$test,"\n"; # ok 4
} else {
$target = "IMAPClient_$$";
$target2 = "IMAPClient_2_$$";
print "ok ",++$test,"\n"; # ok 4
}
# print "target is $target\n";
};
push @tests, sub { # 5
if ( eval { $imap->select('inbox') } ) {
print "ok ",++$test,"\n"; # ok 5
} else {
print "not ok ",++$test,"\n";
print STDERR "\nTest $test failed:\n$@\n";
# print $imap->History,"\n";
}
};
push @tests, sub { # 6
if ( eval { $imap->create("$target") } ) {
print "ok ",++$test,"\n"; # ok 6
} else {
print "not ok ",++$test,"\n";
print STDERR "\nTest $test failed:\n$@\n";
}
};
push @tests,
sub { return "dummy test 8" },
sub { return "dummy test 9" };
push @tests, sub { # 7,8,9
if (defined($imap->is_parent($target))) { #7
if ( eval { $imap->create(qq($target${sep}has "quotes")) } ) {
print "ok ",++$test,"\n"; # ok 7
} else {
if ($imap->LastError =~ /NO Invalid.*name/) {
print "ok ",++$test,
" $parms{server} doesn't support quotes in folder names--",
"skipping next 2 tests\n"; # ok 7
print "ok ", ++$test," (skipped)\n"; # ok 8
print "ok ", ++$test," (skipped)\n"; # ok 9
return;
} else {
print "not ok ",++$test,"\n";
print STDERR "\nTest $test failed:\n$@\n";
print "ok ", ++$test," (skipped)\n"; # ok 8
print "ok ", ++$test," (skipped)\n"; # ok 9
return;
}
}
if ( eval { $imap->select(qq($target${sep}has "quotes")) } ) { #8
print "ok ",++$test,"\n"; # ok 8
} else {
print "not ok ",++$test,"\n";
print STDERR "\nTest $test failed:\n$@\n";
}
$imap->close;
$imap->select('inbox');
if ( eval { $imap->delete(qq($target${sep}has "quotes")) } ) { #9
print "ok ",++$test,"\n"; # ok 9
} else {
print "not ok ",++$test,"\n";
print STDERR "\nTest $test failed:\n$@\n";
}
} else {
print "ok ",++$test,"\n"; # ok 7
print "ok ",++$test,"\n"; # ok 8
print "ok ",++$test,"\n"; # ok 9
}
};
push @tests, sub { # 10
# print $db $imap->Report;
if ( eval { $imap->exists("$target") } ) {
print "ok ",++$test,"\n";
} else {
print "not ok ",++$test,"\n";
print STDERR "\nTest $test failed:\n$@\n";
}
};
push @tests, sub { # 11
if ( eval { $imap->create($target2) } ) {
print "ok ",++$test,"\n";
} else {
print "not ok ",++$test,"\n";
print STDERR "\nTest $test failed:\n$@\n";
}
}, sub { # 12
if ( eval { $imap->exists($target2) } ) {
print "ok ",++$test,"\n";
} else {
print "not ok ",++$test,"\n";
print STDERR "\nTest $test failed:\n$@\n";
}
};
push @tests, sub { # 13
if ( eval { $uid = $imap->append("$target",&testmsg)} ) {
print "ok ",++$test,"\n";
} else {
print "not ok ",++$test,"\n";
print STDERR "\nTest $test failed:\n$@\n";
}
};
push @tests, sub { # 14
if ( eval { $imap->select("$target") } ) {
print "ok ",++$test,"\n";
} else {
print "not ok ",++$test,"\n";
print STDERR "\nTest $test failed:\n$@\n";
}
};
{
my $size; my $string; my $target;
my $file = "./test_message_to_file";
push @tests, sub { # 15, 16, 17, 18, 19
$target = ref($uid) ? ($imap->search("ALL"))[0] : $uid;
if ( eval { $size = $imap->size($target) } ) { # 15 test size
print "ok ",++$test,"\n"; #15
} else {
print "not ok ",++$test,"\n";
print STDERR "\nTest $test failed:\n$@\n";
}
}, sub {
if ( eval { $string = $imap->message_string($target) } ) { # 16 test message_string
print "ok ",++$test,"\n"; #16
} else {
print "not ok ",++$test,"\n";
print STDERR "\nTest $test failed:\n$@\n";
}
}, sub {
if ( $size == length($string) ) { # 17 test size = length of string
print "ok ",++$test,"\n"; #17
} else {
print "not ok ",++$test,"\n";
print STDERR "\nTest $test failed:\n$@\n";
}
};
push @tests, sub {
eval { $imap->message_to_file($file,$target)};
if ( $@ ) { # 18 test message_to_file success
print "not ok ",++$test,"\n";
print STDERR "\nTest $test failed:\n$@\n";
} else {
print "ok ",++$test,"\n"; #18
}
};
push @tests, sub {
my $array_ref = ""; # 19 test for proper search failure
eval { $array_ref = $imap->search("HEADER","Message-id","NOT_A_MESSAGE_ID")};
if ( $array_ref ) { # should have returned undef
print "not ok ",++$test,"(arrayref=$array_ref)\n";
print STDERR "\nTest $test failed:\n$@\n";
} else {
print "ok ",++$test,"\n"; #19
}
};
push @tests, sub {
if ( -s $file == $size ) { # 20 test message_to_file size
print "ok ",++$test,"\n"; #20
} else {
print "not ok ",++$test,"\n"; #20
print STDERR "\nTest $test failed:\n$@\n";
}
unlink "$file" or warn "$! unlinking $file\n";
};
} # wrap up closure
push @tests, sub { # 21, 22, 23, 24, 25 26, 27
my @unseen; my @seen;
if ( eval { @seen = $imap->seen } ) { # 21 test seen's success
print "ok ",++$test,"\n"; #21
} else {
print "not ok ",++$test,"\n";
print STDERR "\nTest $test failed:\n$@\n";
}
if ( @seen == 1 ) { # 22 test seen's results
print "ok ",++$test,"\n"; #22
} else {
print "not ok ",++$test,"\n";
print STDERR "\nTest $test failed:\n$@\n";
}
if ( eval { $imap->deny_seeing(\@seen) } ) { # 23 test deny_seeing's success
print "ok ",++$test,"\n"; #23
} else {
print "not ok ",++$test,"\n";
print STDERR "\nTest $test failed:\n$@\n";
}
if ( eval { @unseen = $imap->unseen } ) { # 24 test unseen's success
print "ok ",++$test,"\n"; #24
} else {
print "not ok ",++$test,"\n";
print STDERR "\nTest $test failed:\n$@\n";
}
if ( @unseen == 1 ) { # 25 test deny_seeing's and unseen's results
print "ok ",++$test,"\n"; #25
} else {
print "not ok ",++$test,"\n";
print STDERR "\nTest $test failed:\n$@\n";
}
if ( eval { $imap->see(\@seen) } ) { # 26 test see's success
print "ok ",++$test,"\n"; #26
} else {
print "not ok ",++$test,"\n";
print STDERR "\nTest $test failed:\n$@\n";
}
if ( @seen == 1 ) { # 27 test seen's and see's success
print "ok ",++$test,"\n"; #27
} else {
print "not ok ",++$test,"\n";
print STDERR "\nTest $test failed:\n$@\n";
}
eval { $imap->deny_seeing(@seen) };
my $subject;
eval { $imap->Peek(1) };
eval { $subject = $imap->parse_headers($seen[0],"Subject")->{Subject}[0] };
if ( join("",$imap->flags($seen[0])) =~ /\\Seen/i ) { # 28 test "Peek = 1"
print "not ok ",++$test,"\n";
print STDERR "\nTest $test failed:\n$@\n";
} else {
print "ok ",++$test,"\n"; #28
}
eval { $imap->deny_seeing(@seen) };
eval { $imap->Peek(0) };
eval { $subject = $imap->parse_headers($seen[0],"Subject")->{Subject}[0] };
if ( join("",$imap->flags($seen[0])) =~ /\\Seen/i ) { # 29 test "Peek = 0"
print "ok ",++$test,"\n"; #29
} else {
print "not ok ",++$test,"\n";
print STDERR "\nTest $test failed:\n$@\n";
}
eval { $imap->deny_seeing(@seen) };
eval { $imap->Peek(undef) };
eval { $subject = $imap->parse_headers($seen[0],"Subject")->{Subject}[0] };
if ( join("",$imap->flags($seen[0])) =~ /\\Seen/i ) { # 30 test "Peek = undef"
print "not ok ",++$test,"\n";
print STDERR "\nTest $test failed:\n$@\n";
} else {
print "ok ",++$test,"\n"; #30
}
};
# Add dummy tests to come up to right number of test routines:
push @tests, sub { 22 }, sub { 23 } , sub { 24 }, sub { 25 }, sub { 26 }, sub {27},
sub {28}, sub {29}, sub {30};
push @tests, sub { # 31
if ( eval { my $uid2 = $imap->copy($target2,1)} ) {
print "ok ",++$test,"\n"; #31
} else {
print "not ok ",++$test,"\n";
print STDERR "\nTest $test failed:\n$@\n";
}
};
push @tests, sub { # 32
my @res;
if ( eval { @res = $imap->fetch(1,"RFC822.TEXT") } ) {
print "ok ",++$test,"\n"; #32
} else {
print "not ok ",++$test,"\n";
print STDERR "\nTest $test failed:\n$@\n";
}
};
push @tests, sub { # 33
my $h;
if ( eval { $h = $imap->parse_headers(1,"Subject")
and $h->{Subject}[0] =~ /^Testing from pid/o } ) {
print "ok ",++$test,"\n"; #33
} else {
use Data::Dumper;
print Dumper($h);
print "$h->{Subject}[0] \n";
print "not ok ",++$test,"\n";
print STDERR "\nTest $test failed:\n$@\n";
print $imap->Results;
}
};
my @hits = ();
push @tests, sub { # 34
$imap->select("$target");
eval { @hits = $imap->search('SUBJECT','Testing') } ;
if ( scalar(@hits) == 1 ) {
print "ok ",++$test,"\n"; #34
} else {
print "not ok ",++$test,"\n"; #34
print STDERR "\nTest $test failed:\n$@\n";
print "Found ",scalar(@hits),
" hits (",join(", ",@hits),")-- expected 2\n";
}
};
push @tests, sub { # 35, 36
if ( $imap->delete_message(@hits) ) {
print "ok ",++$test,"\n"; #35
my $flaghash = $imap->flags(\@hits);
my $flagflag = 0;
foreach my $v ( values %$flaghash ) {
foreach my $f (@$v) { $flagflag++ if $f =~ /\\Deleted/}
}
if ( $flagflag == scalar(@hits) ) {
print "ok ", ++$test,"\n"; #36
} else {
print "not ok ", ++$test,"\n";
print STDERR "\nTest $test failed:\n$@\n";
}
} else {
print "not ok ",++$test,"\n"; #35
print STDERR "\nTest $test failed:\n$@\n";
print "not ok ",++$test,"\n"; #36
}
}, sub { return "Dummy test 35"} ;
push @tests, sub { # 37
eval {
my @nohits = $imap->search(qq(SUBJECT "Productioning")) ;
unless ( scalar(@nohits) ) {
print "ok ",++$test,"\n"; #37
} else {
print "not ok ",++$test," (",scalar(@nohits),")\n";
print STDERR "\nTest $test failed:\n$@\n";
}
};
};
push @tests, sub { # 38, 39
if ( $imap->restore_message(@hits) ) {
print "ok ",++$test,"\n"; #38
my $flaghash = $imap->flags(\@hits);
my $flagflag = scalar(@hits);
foreach my $v ( values %$flaghash ) {
foreach my $f (@$v) { $flagflag-- if $f =~ /\\Deleted/}
}
if ( $flagflag == scalar(@hits) ) {
print "ok ", ++$test,"\n"; #39
} else {
print "not ok ", ++$test,"\n";
print STDERR "\nTest $test failed:\n$@\n";
}
} else {
print "not ok ",++$test,"\n"; #38
print STDERR "\nTest $test failed:\n$@\n";
print "not ok ",++$test,"\n"; #39
}
}, sub { $imap->delete_message(@hits) } ; # dummy 39
push @tests, sub { # 40
$imap->select($target2);
if ( $imap->delete_message(scalar($imap->search("ALL")))
and $imap->close and
$imap->delete($target2)
) {
print "ok ",++$test,"\n"; #40
} else {
print "not ok ",++$test,"\n";
print STDERR "\nTest $test failed:\n$@\n";
print $imap->Report;
}
};
push @tests, sub { # 41
eval {
$imap->select("INBOX");
$@ = ""; # clear $@
@hits = $imap->search( "BEFORE",
Mail::IMAPClient::Rfc2060_date(time),
"UNDELETED"
) ;
} ;
if ($@ ) {
$@ =~ s/\r\n$//;
print "not ok ",++$test, " ($@)\n";
print STDERR "\nTest $test failed:\n$@\n";
} else {
print "ok ",++$test,"\n"; #41
}
};
# Test migrate method
{ # start new scope for these tests
my($im2,$migtarget);
push @tests, sub { # 42
eval {
$im2 = Mail::IMAPClient->new(
Server => "$parms{server}"||"localhost",
Port => "$parms{port}" || '143',
User => "$parms{user}" || scalar(getpwuid($<)),
( $authmech ? ( Authmechanism => $authmech) :
( $parms{authmechanism} eq "LOGIN" ? () :
( Authmechanism => $parms{authmechanism}||undef ) )
),
Password=> "$parms{passed}"|| scalar(getpwuid($<)),
Clear => 0,
Timeout => 30,
Debug => $ARGV[0],
Debug_fh => ($ARGV[0]?IO::File->new(">./imap2.debug"):undef),
Fast_IO => $fast,
Uid => $uidplus,
) or
print STDERR "\nCannot log into $parms{server} as $parms{user}. ",
"Are server/user/password correct?\n"
and die ;
my $source = $target;
$imap->select($source) or die "cannot select source $source: $@";
for (1...5) { $imap->append($source,&testmsg)};
$imap->close; $imap->select($source);
$migtarget = "${target}_mirror";
$im2->create($migtarget) or die "can't create $migtarget: $@" ;
$im2->select($migtarget) or die "can't select $migtarget: $@";
$imap->migrate($im2,scalar($imap->search("ALL")),$migtarget)
or die "couldn't migrate: $@";
$im2->close; $im2->select($migtarget) or die "can't select $migtarget: $@";
} ;
if ( $@ ) {
$@=~s/\r\n$//;
print "not ok ",++$test," ($@)\n";
print STDERR "\nTest $test failed:\n$@\n";
} else {
print "ok ",++$test,"\n"; #42
}
}, # 43
sub {
my($total_bytes1,$total_bytes2) ;
eval {
for ($imap->search("ALL")) { my $s = $imap->size($_); $total_bytes1 += $s; print "Size of msg $_ is $s\n" if $ARGV[0]};
for ( $im2->search("ALL")) { my $s = $im2->size($_); $total_bytes2 += $s; print "Size of msg $_ is $s\n" if $ARGV[0]};
};
for ($total_bytes1,$total_bytes2) { $_||=0};
if ($@) {
$@=~s/\r\n$//;
print "not ok ",++$test," ($@)\n";
print STDERR "\nTest $test failed:\n$@\n";
} elsif ( $total_bytes1 != $total_bytes2 ) {
print "not ok ",++$test," (source has $total_bytes1 bytes and ",
"target has $total_bytes2)\n";
print STDERR "\nTest $test failed:\n$@\n";
} else {
print "ok ",++$test,"\n"; #43
$im2->select($migtarget);
$im2->delete_message(@{$im2->messages}) if $im2->message_count;
$im2->close;
$im2->delete($migtarget);
}
$im2->logout;
}; # end of the anonysub and push
} # end of migrate method tests' scope
push @tests, sub { # 44
if ( $imap->has_capability("IDLE") ) {
eval {
my $idle = $imap->idle;
sleep 1;
$imap->done($idle);
} ;
if ($@) {
print "not ok ",++$test,"\n$@\n";
} else {
print "ok ",++$test,"\n"; #44
}
} else {
print "ok (skipped)",++$test,"\n";
}
};
push @tests, sub { # 45
$imap->select('inbox');
if ( $imap->rename($target,"${target}NEW") ) {
print "ok ",++$test,"\n"; #45
$imap->close;
$imap->select("${target}NEW") ;
$imap->delete_message(@{$imap->messages}) if $imap->message_count;
$imap->close;
$imap->delete("${target}NEW") ;
} else {
print "not ok ",++$test,"\n";
print STDERR "\nTest $test failed:\n$@\n";
$imap->delete_message(@{$imap->messages})
if $imap->message_count;
$imap->close;
$imap->delete("$target") ;
}
} ;
#push @tests, sub { "commented out #46" } ;
if (open TST,"./test.txt" ) {
while (defined(my $l = <TST>)) {
chomp $l;
my($p,$v)=split(/=/,$l);
for($p,$v) { s/(?:^\s+)|(?:\s+$)//g; }
$parms{$p}=$v if $v;
}
close TST;
}
if ( -f "./test.txt"
and %parms
and length $parms{server}
and length $parms{user}
and length $parms{passed}
) {
print "1..${\(scalar @tests)}\n"; # update here if adding test to existing sub
} else {
print "1..1\n";
}
$main::loaded = 1;
print "ok 1\n";
$| = 1;
unless ( -f "./test.txt" ) { exit;}
}
=begin debugging
$db = IO::File->new(">/tmp/de.bug");
local *TMP = $db ;
open(STDERR,">&TMP");
select(((select($db),$|=1))[0]);
=end debugging
=cut
exit unless %parms
and length $parms{server}
and length $parms{user}
and length $parms{passed} ;
# print "Uid=$uidplus and Fast = $fast\n";
eval { $imap = Mail::IMAPClient->new(
Server => "$parms{server}"||"localhost",
Port => "$parms{port}" || '143',
User => "$parms{user}" || scalar(getpwuid($<)),
( $authmech ? ( Authmechanism => $authmech) :
( $parms{authmechanism}&&$parms{authmechanism} eq "LOGIN" ? () :
( Authmechanism => $parms{authmechanism}||undef) )
),
Password=> "$parms{passed}"|| scalar(getpwuid($<)),
Clear => 0,
Timeout => 30,
Debug => $ARGV[0],
Debug_fh => ($ARGV[0]?IO::File->new(">imap1.debug"):undef),
Fast_IO => $fast,
Uid => $uidplus,
Range => $range,
) or
print STDERR "\nCannot log into $parms{server} as $parms{user}. Are server/user/password correct?\n"
and exit
} ;
$imap->Debug_fh and $imap->Debug_fh->autoflush();
for my $test (@tests) { $test->(); }
#print $db $imap->Report,"\n";
sub testmsg {
my $m = qq{Date: @{[$imap->Rfc822_date(time)]}
To: <$parms{user}\@$parms{server}>
From: Perl <$parms{user}\@$parms{server}>
Subject: Testing from pid $$
This is a test message generated by $0 during a 'make test' as part of the installation of
that nifty Mail::IMAPClient module from CPAN. Like all things perl, it's
way cool.
};
return $m;
}
# History:
# $Log: basic.t,v $
# Revision 19991216.27 2003/06/12 21:38:35 dkernen
#
# Preparing 2.2.8
# Added Files: COPYRIGHT
# Modified Files: Parse.grammar
# Added Files: Makefile.old
# Makefile.PL Todo sample.perldb
# BodyStructure.pm
# Parse.grammar Parse.pod
# range.t
# Thread.grammar
# draft-crispin-imapv-17.txt rfc1731.txt rfc2060.txt rfc2062.txt
# rfc2221.txt rfc2359.txt rfc2683.txt
#
# Revision 19991216.26 2002/12/13 18:08:50 dkernen
# Made changes for version 2.2.6 (see Changes file for more info)
#
# Revision 19991216.25 2002/11/08 15:49:05 dkernen
#
# Modified Files: Changes
# IMAPClient.pm
# MessageSet.pm
# t/basic.t
#
# Revision 19991216.24 2002/10/23 20:46:09 dkernen
#
# Modified Files: Changes IMAPClient.pm MANIFEST Makefile.PL
# Added Files: Makefile.PL MessageSet.pm
# Added Files: range.t
# Modified Files: basic.t
#
# Revision 19991216.23 2002/09/26 17:56:58 dkernen
#
# Modified Files:
# BUG_REPORTS Changes IMAPClient.pm INSTALL_perl5.80 MANIFEST
# Makefile.PL for version 2.2.3. See the Changes file for details.
# Modified Files: BodyStructure.pm -- cosmetic changes to pod doc
# Modified Files:
# migrate_mail2.pl -- fixed a small little bug and added a feature
# Modified Files: basic.t -- to add tests for idle/done
#
# Revision 19991216.22 2002/08/30 20:48:52 dkernen
#
# #
# Modified Files:
# Changes IMAPClient.pm MANIFEST Makefile Makefile.PL README
# Todo test.txt
# BodyStructure/Parse/Makefile
# BodyStructure/Parse/Parse.pm
# BodyStructure/Parse/Parse.pod
# BodyStructure/Parse/t/parse.t
# t/basic.t
# for version 2.2.1
# #
#
# Revision 19991216.21 2002/08/23 13:29:59 dkernen
#
# Modified Files: Changes IMAPClient.pm INSTALL MANIFEST Makefile Makefile.PL README Todo test.txt
# Made changes to create version 2.1.6.
# Modified Files:
# imap_to_mbox.pl populate_mailbox.pl
# Added Files:
# cleanTest.pl migrate_mbox.pl
# Modified Files: basic.t
#
# Revision 19991216.20 2001/02/07 20:20:43 dkernen
#
# Modified Files: Changes IMAPClient.pm MANIFEST Makefile test.txt -- up to version 2.1.0
# Added Files: cyrus_expunge.pl -- a new example script
# Modified Files: basic.t -- to close folders before trying to delete them
# Added Files: uidfast.t -- a new test suite
#
# Revision 19991216.19 2001/01/09 19:24:37 dkernen
#
# Modified Files:
# Changes IMAPClient.pm Makefile test.txt -- to add Phil Lobbe's patch.
#
# Revision 19991216.18 2000/12/20 19:37:02 dkernen
#
# ---------------------------------------------------------------------------------
# Modified Files: IMAPClient.pm -- added bug fix to I/O engine, also cleaned up doc
# Changes -- documented same
# ---------------------------------------------------------------------------------
#
# Revision 19991216.17 2000/11/10 22:08:15 dkernen
#
# Modified Files: Changes IMAPClient.pm Makefile t/basic.t -- to add Peek parm and to make several bug fixes
#
# Revision 19991216.16 2000/10/30 21:04:11 dkernen
#
# Modified Files: Changes IMAPClient.pm -- to update documentation
# Modified Files: basic.t -- added tests for message_to_string.
#
# Revision 19991216.15 2000/10/30 18:40:50 dkernen
#
# Modified Files: Changes IMAPClient.pm INSTALL MANIFEST Makefile README test.txt -- for 2.0.1
# Added Files:
# rfc1731.txt rfc1732.txt rfc1733.txt rfc2061.txt rfc2062.txt
# rfc2086.txt rfc2087.txt rfc2088.txt rfc2177.txt rfc2180.txt
# rfc2192.txt rfc2193.txt rfc2195.txt rfc2221.txt rfc2222.txt
# rfc2234.txt rfc2245.txt rfc2342.txt rfc2359.txt rfc2683.txt
#
# Revision 19991216.14 2000/10/27 14:43:59 dkernen
#
# Modified Files: Changes IMAPClient.pm Todo -- major rewrite of I/O et al.
# Modified Files: basic.t fast_io.t uidplus.t -- more tests in basic.t. Other
# tests just "do basic.t" with different options set.
#
# Revision 19991216.13 2000/07/10 20:54:19 dkernen
#
# Modified Files: Changes IMAPClient.pm MANIFEST Makefile README
# Modified Files: find_dup_msgs.pl
# : Modified Files: basic.t fast_io.t
#
# Revision 19991216.12 2000/06/23 19:08:40 dkernen
#
# Modified Files:
# Changes IMAPClient.pm Makefile test.txt -- for v1.16
# Modified Files: basic.t -- to remove uidplus tests and to make copy test copy to different folder
# Added Files: uidplus.t -- moved all uidplus tests here
#
# Revision 19991216.11 2000/06/21 21:07:44 dkernen
#
# Modified Files: Changes IMAPClient.pm Makefile
# Modified Files: basic.t
#
# Revision 19991216.10 2000/04/27 18:00:15 dkernen
# Modified Files: basic.t
#
# Revision 19991216.9 2000/03/10 16:04:39 dkernen
#
# Renamed .test file to test.txt to support weird platforms that don't support filenames
# beginning with a dot.
#
# Modified Files: Changes INSTALL MANIFEST Makefile Makefile.PL
#
# Added Files: test.txt test_template.txt
#
# Removed Files: .test .test_template Makefile.old
#
# Revision 19991216.8 2000/03/02 19:59:15 dkernen
#
# Modified Files: build_ldif.pl -- to support new option to all "To:" and "Cc:" to be included in ldif file
# Modified Files: basic.t -- to work better with UW IMAP server
#
# Revision 19991216.7 2000/01/12 18:58:05 dkernen
# *** empty log message ***
#
# Revision 19991216.6 1999/12/28 13:57:22 dkernen
# tested with v1.08
#
# Revision 19991216.5 1999/12/16 17:19:17 dkernen
# Bring up to same level
#
# Revision 19991124.7 1999/12/16 17:14:27 dkernen
# Incorporate changes for exists method performance enhancement
#
# Revision 19991124.6 1999/12/01 22:11:06 dkernen
# Enhance support for UID and add tests to t/basic for same
#
# Revision 19991124.5 1999/11/30 20:41:55 dkernen
# Bring CVS repository up to latest level
#
# Revision 19991124.4 1999/11/24 19:58:45 dkernen
#
# Modified Files:
# basic.t - to add $Id and $Log data in comments
#

View File

@ -0,0 +1,106 @@
# Before `make install' is performed this script should be runnable with
# `make test'. After `make install' it should work as `perl test.pl'
# $Id: cram-md5.t,v 19991216.1 2003/06/12 21:38:36 dkernen Exp $
######################### We start with some black magic to print on failure.
# Change 1..1 below to 1..last_test_to_print .
use Mail::IMAPClient;
######################### End of black magic.
my $test = 0;
my %parms;
my $imap;
my @tests;
my $uid;
=begin debugging
$db = IO::File->new(">/tmp/de.bug");
local *TMP = $db ;
open(STDERR,">&TMP");
select(((select($db),$|=1))[0]);
=end debugging
=cut
if (open TST,"./test.txt" ) {
while (defined(my $l = <TST>)) {
chomp $l;
my($p,$v)=split(/=/,$l);
for($p,$v) { s/(?:^\s+)|(?:\s+$)//g; }
$parms{$p}=$v if $v;
}
close TST;
} else {
print "1..1\n";
print "ok 1 (skipped)\n";
exit;
}
exit unless %parms
and length $parms{server}
and length $parms{user}
and length $parms{passed} ;
eval { $imap = Mail::IMAPClient->new(
Server => "$parms{server}"||"localhost",
Port => "$parms{port}" || '143',
Clear => 0,
Timeout => 30,
Debug => $ARGV[0],
Debug_fh => $ARGV[0]?IO::File->new(">imap1.debug"):undef,
Fast_IO => 1,
Uid => 1,
Authmechanism => $parms{authmechanism}||undef,
) or
print STDERR "\nCannot connect to $parms{server} to get capabilities. ",
"Are server/user/password correct?\n"
and exit
} ;
$imap->Debug_fh and $imap->Debug_fh->autoflush();
if ( $imap->has_capability("AUTH=CRAM-MD5") ) {
$authmech = "CRAM-MD5";
$authmech = "CRAM-MD5";
do "./t/basic.t";
} else {
print "1..1\n";
print "ok 1 (skipped)\n";
exit;
}
# History:
# $Log: cram-md5.t,v $
# Revision 19991216.1 2003/06/12 21:38:36 dkernen
#
# Preparing 2.2.8
# Added Files: COPYRIGHT
# Modified Files: Parse.grammar
# Added Files: Makefile.old
# Makefile.PL Todo sample.perldb
# BodyStructure.pm
# Parse.grammar Parse.pod
# range.t
# Thread.grammar
# draft-crispin-imapv-17.txt rfc1731.txt rfc2060.txt rfc2062.txt
# rfc2221.txt rfc2359.txt rfc2683.txt
#
# Revision 1.1 2003/06/12 21:38:17 dkernen
#
# Preparing 2.2.8
# Added Files: COPYRIGHT
# Modified Files: Parse.grammar
# Added Files: Makefile.old
# Makefile.PL Todo sample.perldb
# BodyStructure.pm
# Parse.grammar Parse.pod
# range.t
# Thread.grammar
# draft-crispin-imapv-17.txt rfc1731.txt rfc2060.txt rfc2062.txt
# rfc2221.txt rfc2359.txt rfc2683.txt
#
#

View File

@ -0,0 +1,2 @@
$fast++; $fast++;
do "./t/basic.t";

View File

@ -0,0 +1,3 @@
$fast++; $fast++;
$range++; $range++;
do "./t/basic.t";

View File

@ -0,0 +1,3 @@
$uid++; $uid++;
$fast_io++; $fast_io++;
do "./t/basic.t";

View File

@ -0,0 +1,2 @@
$uid++; $uid++;
do "./t/basic.t";

View File

@ -1,39 +0,0 @@
COPYRIGHT
Changes
INSTALL
MANIFEST
Makefile.PL
README
Todo
examples/build_dist.pl
examples/build_ldif.pl
examples/cleanTest.pl
examples/copy_folder.pl
examples/cyrus_expire.pl
examples/cyrus_expunge.pl
examples/find_dup_msgs.pl
examples/imap_to_mbox.pl
examples/imtestExample.pl
examples/migrate_mail2.pl
examples/migrate_mbox.pl
examples/populate_mailbox.pl
examples/sharedFolder.pl
lib/Mail/IMAPClient.pm
lib/Mail/IMAPClient.pod
lib/Mail/IMAPClient/BodyStructure.pm
lib/Mail/IMAPClient/BodyStructure/Parse.grammar
lib/Mail/IMAPClient/BodyStructure/Parse.pm
lib/Mail/IMAPClient/BodyStructure/Parse.pod
lib/Mail/IMAPClient/MessageSet.pm
lib/Mail/IMAPClient/Thread.grammar
lib/Mail/IMAPClient/Thread.pm
lib/Mail/IMAPClient/Thread.pod
prepare_dist
sample.perldb
t/basic.t
t/bodystructure.t
t/messageset.t
t/pod.t
t/thread.t
test_template.txt
META.yml Module meta-data (added by MakeMaker)

View File

@ -1,26 +0,0 @@
--- #YAML:1.0
name: Mail-IMAPClient
version: 3.05
abstract: IMAP4 client library
license: ~
author: ~
generated_by: ExtUtils::MakeMaker version 6.42
distribution_type: module
requires:
Carp: 0
Data::Dumper: 0
Digest::HMAC_MD5: 0
Errno: 0
Fcntl: 0
File::Temp: 0.18
IO::File: 0
IO::Select: 0
IO::Socket: 0
IO::Socket::INET: 1.26
MIME::Base64: 0
Parse::RecDescent: 1.94
Test::More: 0
Test::Pod: 0
meta-spec:
url: http://module-build.sourceforge.net/META-spec-v1.3.html
version: 1.3

View File

@ -1,111 +0,0 @@
use ExtUtils::MakeMaker;
use warnings;
use strict;
sub set_test_data();
WriteMakefile
( NAME => 'Mail::IMAPClient',
, ABSTRACT => 'IMAP4 client library'
, VERSION_FROM => 'lib/Mail/IMAPClient.pm'
, PREREQ_PM =>
{ 'Errno' => 0
, 'IO::Socket' => 0
, 'Fcntl' => 0
, 'IO::Select' => 0
, 'IO::File' => 0
, 'Data::Dumper' => 0
, 'Carp' => 0
, 'IO::Socket::INET' => 1.26
, 'Parse::RecDescent' => 1.94
, 'Digest::HMAC_MD5' => 0
, 'MIME::Base64' => 0
, 'Test::More' => 0
, 'File::Temp' => 0.18
, 'Test::Pod' => 0
}
, clean => { FILES => 'test.txt' }
);
set_test_data();
exit 0;
###
### HELPERS
###
sub set_test_data()
{ unless(-f "lib/Mail/IMAPClient.pm")
{ warn "ERROR: not in installation directory\n";
return;
}
return if -f "./test.txt";
print <<'__INTRO';
You have the option of running an extended suite of tests during
'make test'. This requires an IMAP server name, user account, and
password to test with.
__INTRO
my $yes = prompt "Do you want to run the extended tests? (n/y)";
return if $yes !~ /^[Yy](?:[Ee]:[Ss]?)?$/ ;
unless(open TST, '>', "./test.txt")
{ warn "ERROR: couldn't open ./test.txt: $!\n";
return;
}
my $server = "";
until($server)
{ $server = prompt "\nPlease provide the hostname or IP address of "
. "a host running an\nIMAP server (or QUIT to skip "
. "the extended tests)";
chomp $server;
return if $server =~ /^\s*quit\s*$/i ;
}
print TST "server=$server\n";
my $user = "";
until($user)
{ $user = prompt "\nProvide the username of an account on $server (or QUIT)";
chomp $user;
return if $user =~ /^\s*quit\s*$/i ;
}
print TST "user=$user\n";
my $passed = "";
until($passed)
{ $passed = prompt "\nProvide the password for $user (or QUIT)";
chomp $passed;
return if $passed =~ /^\s+$|^quit$/i ;
}
print TST "passed=$passed\n";
my $port = prompt "\nPlease provide the port to connect to on $server "
. "to run the test\n(default is 143)";
chomp $port;
$port ||= 143;
print TST "port=$port\n";
my $authmech = prompt "\nProvide the authentication mechanism to use "
. "on $server to\nrun the test (default is LOGIN)";
chomp $authmech;
$authmech ||= 'LOGIN';
print TST "authmechanism=$authmech\n";
close TST;
print <<'__THANKS';
Gracias! The information you provided (including the password!) has
been stored in test.txt and SHOULD BE REMOVED (either by hand or by
'make clean') after testing.
__THANKS
}

View File

@ -1,147 +0,0 @@
Mail::IMAPClient
Copyright 1999-2003 The Kernen Group, Inc.
Copyright 2007 Mark Overmeer
All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of either:
a) the "Artistic License" which comes with this Kit, or
b) the GNU General Public License as published by the Free Software
Foundation; either version 1, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See either
the GNU General Public License or the Artistic License for more details.
DESCRIPTION
This module provides perl routines that simplify a sockets connection
to and an IMAP conversation with an IMAP server.
COMPATIBILITY
This module was developed on Solaris 2.5.1 and 2.6 against Netscape IMAP
servers versions 3.6 and 4.1. However, since it is written in perl and
designed for flexibility, it should run on any OS with a TCP/IP stack and
a version of perl that includes the Socket and IO::Socket modules. It also
should be able to talk to any IMAP server, even those that have, um,
proprietary features (assuming that the programmer knows what those features
are).
To date, I know that the test suite runs successfully with the following IMAP
servers:
-Netscape Messenging Server v4.x
-Netscape Messenging Server v3.x
-UW-IMAP (I think it was 4.5)
-Cyrus IMAP4 v1.5.19
-Mirapoint Message Server Appliances (OS versions 1.6.1, 1.7.1, and 2.0.2)
I also know that it has some problems running against the InterMail
server vM.4.001.02.00 (and probably other versions of InterMail as well).
Version 2.0.3 has been tested with the mdaemon server with mixed
results. It seems that mdaemon does not comply strictly with RFC2060 and
so you may have problems using this module with mdaemon, especially with
folder names with embedded spaces or embedded double quotes. You may be
able to get some simple tasks to work but you won't be able to run the
test suite successfully. Use with caution.
If your server requires the use of the AUTHENTICATE IMAP client command
(say, for strong authentication) then you can still use this module,
provided you can come up with the appropriate responses to any challenges
offered by your server. Mark Bush's Authen::NTLM module can assist with
this if you specifically are interested in NTLM authentication.
DEPENDENCIES
The Mail::IMAPClient module uses the IO::Socket module to make a socket
connection to an IMAP server and the Socket module to get some constants.
It also uses Errno, Fcntl (for faster I/O) and IO::Select, IO::File,
Data::Dumper, and Carp.
You can verify that your system has a sufficient perl installation by
entering on the command line:
perl -e "use constant; use Socket; use IO::Socket; use IO::File; \
use IO::Select; use Fcntl; use Errno; use Carp; use Data::Dumper;"
If you get compile errors then you'll have trouble using Mail::IMAPClient.
If you need to use the bodystructure helper module
Mail::IMAPClient::BodyStructure then you also need Parse::RecDescent. Try
this on the command line:
perl -e "use Parse::RecDescent;"
If you get compile errors then you will not be able to use the
Mail::IMAPClient::BodyStructure module (or the get_bodystructure method
in Mail::IMAPClient). You will also get errors when you run 'make test'
in t/bodystructure and/or t/parse. If these tests fail you can still
use Mail::IMAPClient safely (assuming the other tests passed!) but
you will not be able to use Mail::IMAPClient::BodyStructure or the
get_bodystructure method in Mail::IMAPClient.
(Note that as of version 2.2.0 the above is somewhat obsolete, since
Makefile.PL will detect whether or not you have Parse::RecDescent and
will either choose to or decline to install the ::BodyStructure stuff
accordingly.)
REPORING BUGS
See http://rt.cpan.org/Public/Dist/Display.html?Name=Mail-IMAPClient
INSTALLATION
Generally, gunzipping and untarring the source file, running 'perl
Makefile.PL' and 'make install' are all it takes to install this
module. And if that's too much work you can always use the CPAN module!
OVERVIEW OF FUNCTIONALITY
Mail::IMAPClient.pm provides methods to simplify the connection to and
the conversation between a perl script and an IMAP server. Virtually
all IMAP Client commands (as defined in rfc2060) are supported, either
through IMAPClient object methods or the 'default method', which is an
AUTOLOAD hack that assumes a default syntax for IMAP Client commands of:
tagvalue COMMAND [Arg1 [Arg2 [... Arg3]]]"
By remarkable coincidence, AUTOLOAD's default syntax mimics the
general syntax of IMAP Client commands. This means that if a script
tries to use any undefined method then that method will be interpreted
as an unimplemented IMAP command, and the default syntax will be used
to create the command string. I did this as a short cut to writing a
bunch of methods that were practically the same. There are inheritance
implications because of this approach but as far as I can tell this is
not a serious limitation. However, if you decide to write modules that
inherit from this class that require AUTOLOAD logic of their own then you
will have to take the Mail::IMAPClient's AUTOLOAD strategy into account.
Where methods are defined, they usually exist to add functionality,
perhaps by massaging output or by supplying default arguments. An example
is the search method, which accepts the same arguments as the SEARCH
IMAP Client command (as documented in RFC2060) but which massages the
results so that the return value is an array of message sequence numbers
matching the search criteria, rather than a line of text listing the
sequence numbers.
Some methods exists solely to add functionality, such as the folders
method, which invokes the list method but then massages the results to
produce an array containing all folder names. The message_count and
delete_messsage methods are similarly examples of methods that add
function to "raw" IMAP Client commands.
Further information is provided in the module's documentation, which you are
encouraged to read and enjoy.
Good Luck!
Dave Kernen
The Kernen Group, Inc.
DJKERNEN@cpan.org

View File

@ -1,65 +0,0 @@
Starting with release 2.99_01, I (Mark Overmeer) try to revive the
module. The original author David Kernen cannot be reached and didn't
release any fixes in four years. That is too long.
In version 3.0, the installation procedure is been cleaned-up
radically, and some minimal improvements in the code are made to
fix things people reported.
=== wishlist:
- A start was made in cleanup of the code in Mail/IMAPClient.pm
The file Mail/IMAPClient-cleanup shows the progress (30%)
But I lack the time (a weeks work at least) to complete this
task. There is a lot of code replication to be stripped.
If anyone buys me time, I will complete that task.
=== wishlist from the original author:
The following is a list of some items that I hope to include in a future
release:
- Support for threaded perl programs (still pending as of version 2.2.0.).
- Support for imaps (Imap via SSL). I don't have any way to test this
right now but if you get this to work or know someone who has I'd be
really interested in hearing from you.
- Support for more authentication mechanisms. Currently plain
authentication and cram-md5 authentication are supported. I have
DIGEST-MD5 working at the AUTH qop, but haven't incorporated it into
a released version because I'm still trying to get at least the
integrity qop working, and maybe even privacy, but considering how
much trouble I'm having with just the integrity level I wouldn't
hold my breath if I were you ;-).
- Currently a number of IMAP Client commands are implemented using the
'default method', which is an AUTOLOAD hack. I'd like to reduce that
if possible to a bare minimum. (Some are still pending as of version 2.2.7.)
- I'd like to see this module certified for more OS's and more IMAP servers.
This is (hopefully) just a matter of testing; the code should already
be compatible with the IMAP servers that are out there and with any OS
that allows the IO::Socket module to work. ** A number of platforms
have been added to the list of tested platforms since this was first
written. Please contact DJKernen@cpan.org if you have any to add.
- Support for newer/older/other versions of IMAP. Currently only RFC2060 is
explicitly supported, although thanks to the 'default method'
(implemented via an AUTOLOAD hack) virtually any IMAP command is
supported, even proprietary commands, X- extensions, and so forth. But
not necessarily other authentication mechanisms... :-( (NOTE: the
AUTHENTICATE method partially addresses this issue.)
- Support for piping output from (some?) imap commands directly to a
thingy of some sort (perhaps a coderef, a filehandle, or both).
- Your thingy here!!! Send me your request, and I'll do it in the order of
($popularity/$difficulty ).
- Support for perl version 6. This will probably involve a rewrite that
will make portions of the Mail::IMAPClient module look more like the
Mail::IMAPClient::BodyStructure module. (Perl 6 will have built-in
support for semantics that look remarkably like Damian Conway's
Parse::RecDescent module, which will solve a lot of problems for me.)

File diff suppressed because it is too large Load Diff

View File

@ -1,557 +0,0 @@
use warnings;
use strict;
package Mail::IMAPClient::BodyStructure;
use Mail::IMAPClient::BodyStructure::Parse;
# my has file scope, not limited to package!
my $parser = Mail::IMAPClient::BodyStructure::Parse->new
or die "Cannot parse rules: $@\n"
. "Try remaking Mail::IMAPClient::BodyStructure::Parse.\n";
sub new
{ my $class = shift;
my $bodystructure = shift;
my $self = $parser->start($bodystructure)
or return undef;
$self->{_prefix} = "";
$self->{_id} = exists $self->{bodystructure} ? 'HEAD' : 1;
$self->{_top} = 1;
bless $self, ref($class)||$class;
}
sub _get_thingy
{ my $thingy = shift;
my $object = shift || (ref $thingy ? $thingy : undef);
unless ($object && ref $object)
{ warn $@ = "No argument passed to $thingy method.";
return undef;
}
unless(UNIVERSAL::isa($object, 'HASH') && exists $object->{$thingy})
{ my $a = $thingy =~ /^[aeiou]/i ? 'an' : 'a';
my $has = ref $object eq 'HASH' ? join(", ",keys %$object) : '';
warn $@ = ref($object)." $object does not have $a $thingy. "
. ($has ? "It has $has" : '');
return undef;
}
my $value = $object->{$thingy};
$value =~ s/\\ ( [\\\(\)"\x0d\x0a] )/$1/gx;
$value =~ s/^"(.*)"$/$1/;
$value;
}
BEGIN
{ no strict 'refs';
foreach my $datum (
qw/ bodytype bodysubtype bodyparms bodydisp bodyid bodydesc bodyenc
bodysize bodylang envelopestruct textlines / )
{ *$datum = sub { _get_thingy($datum, @_) };
}
}
sub parts
{ my $self = shift;
return wantarray ? @{$self->{PartsList}} : $self->{PartsList}
if exists $self->{PartsList};
my @parts;
$self->{PartsList} = \@parts;
unless(exists $self->{bodystructure})
{ $self->{PartsIndex}{1} = $self;
@parts = ("HEAD", 1);
return wantarray ? @parts : \@parts;
}
foreach my $p ($self->bodystructure)
{ my $id = $p->id;
push @parts, $id;
$self->{PartsIndex}{$id} = $p ;
my $type = uc $p->bodytype || '';
push @parts, "$id.HEAD"
if $type eq 'MESSAGE';
}
wantarray ? @parts : \@parts;
}
sub bodystructure
{ my $self = shift;
my $partno = 0;
my @parts;
if($self->{_top})
{ $self->{_id} ||= "HEAD";
$self->{_prefix} ||= "HEAD";
$partno = 0;
foreach my $b ( @{$self->{bodystructure}} )
{ $b->{_id} = ++$partno;
$b->{_prefix} = $partno;
push @parts, $b, $b->bodystructure;
}
return wantarray ? @parts : \@parts;
}
my $prefix = $self->{_prefix} || "";
$prefix =~ s/\.?$/./;
foreach my $p ( @{$self->{bodystructure}} )
{ $partno++;
$p->{_prefix} = "$prefix$partno";
$p->{_id} ||= "$prefix$partno";
push @parts, $p, $p->{bodystructure} ? $p->bodystructure : ();
}
wantarray ? @parts : \@parts;
}
sub id
{ my $self = shift;
return $self->{_id}
if exists $self->{_id};
return "HEAD"
if $self->{_top};
if ($self->{bodytype} eq 'MULTIPART')
{ my $p = $self->{_id} || $self->{_prefix};
$p =~ s/\.$//;
return $p;
}
else
{ return $self->{_id} ||= 1;
}
}
package Mail::IMAPClient::BodyStructure::Part;
our @ISA = qw/Mail::IMAPClient::BodyStructure/;
package Mail::IMAPClient::BodyStructure::Envelope;
our @ISA = qw/Mail::IMAPClient::BodyStructure/;
sub new
{ my ($class, $envelope) = @_;
$parser->envelope($envelope);
}
sub from_addresses { shift->_addresses(from => 1) }
sub sender_addresses { shift->_addresses(sender => 1) }
sub replyto_addresses { shift->_addresses(replyto => 1) }
sub to_addresses { shift->_addresses(to => 0) }
sub cc_addresses { shift->_addresses(cc => 0) }
sub bcc_addresses { shift->_addresses(bcc => 0) }
sub _address($$$)
{ my ($self, $name, $isSender) = @_;
ref $self->{$name} eq 'ARRAY'
or return ();
my @list;
foreach ( @{$self->{$name}} )
{ my $pn = $_->personalname;
my $name = $pn && $pn ne 'NIL' ? "$pn " : '';
push @list, $pn. '<'.$_->mailboxname .'@'. $_->hostname.'>';
}
wantarray ? @list
: $isSender ? $list[0]
: \@list;
}
BEGIN
{ no strict 'refs';
for my $datum ( qw(subject inreplyto from messageid bcc date
replyto to sender cc))
{ *$datum = sub { @_ > 1 ? $_[0]->{$datum} = $_[1] : $_[0]->{$datum} }
}
}
package Mail::IMAPClient::BodyStructure::Address;
our @ISA = qw/Mail::IMAPClient::BodyStructure/;
for my $datum ( qw(personalname mailboxname hostname sourcename) )
{ no strict 'refs';
*$datum = sub { shift->{$datum}; };
}
1;
__END__
=head1 NAME
Mail::IMAPClient::BodyStructure - parse fetched results
=head1 SYNOPSIS
use Mail::IMAPClient::BodyStructure;
use Mail::IMAPClient;
my $imap = Mail::IMAPClient->new(Server=>$serv,User=>$usr,Password=>$pwd);
$imap->select("INBOX") or die "cannot select the inbox for $usr: $@\n";
my @recent = $imap->search("recent");
foreach my $id (@recent)
{ my $fetched = $imap->fetch($id, "bodystructure");
my $struct = Mail::IMAPClient::BodyStructure->new($fetched);
my $mime = $struct->bodytype."/".$struct->bodysubtype;
my $parts =join "\n\t", $struct->parts;
print "Msg $id (Content-type: $mime) contains these parts:\n\t$parts\n";
}
=head1 DESCRIPTION
This extension will parse the result of an IMAP FETCH BODYSTRUCTURE
command into a perl data structure. It also provides helper methods that
will help you pull information out of the data structure.
Use of this extension requires Parse::RecDescent. If you don't have
Parse::RecDescent then you must either get it or refrain from using
this module.
=head2 EXPORT
Nothing is exported by default. C<$parser> is exported upon
request. C<$parser> is the BodyStucture object's Parse::RecDescent object,
which you'll probably only need for debugging purposes.
=head1 Class Methods
The following class method is available:
=head2 new
This class method is the constructor method for instantiating new
Mail::IMAPClient::BodyStructure objects. The B<new> method accepts one
argument, a string containing a server response to a FETCH BODYSTRUCTURE
directive. Only one message's body structure should be described in this
string, although that message may contain an arbitrary number of parts.
If you know the messages sequence number or unique ID (UID)
but haven't got its body structure, and you want to get the body
structure and parse it into a B<Mail::IMAPClient::BodyStructure>
object, then you might as well save yourself some work and use
B<Mail::IMAPClient>'s B<get_bodystructure> method, which accepts
a message sequence number (or UID if I<Uid> is true) and returns a
B<Mail::IMAPClient::BodyStructure> object. It's functionally equivalent
to issuing the FETCH BODYSTRUCTURE IMAP client command and then passing
the results to B<Mail::IMAPClient::BodyStructure>'s B<new> method but
it does those things in one simple method call.
=head1 Object Methods
The following object methods are available:
=head2 bodytype
The B<bodytype> object method requires no arguments. It returns the
bodytype for the message whose structure is described by the calling
B<Mail::IMAPClient::Bodystructure> object.
=head2 bodysubtype
The B<bodysubtype> object method requires no arguments. It returns the
bodysubtype for the message whose structure is described by the calling
B<Mail::IMAPClient::Bodystructure> object.
=head2 bodyparms
The B<bodyparms> object method requires no arguments. It returns the
bodyparms for the message whose structure is described by the calling
B<Mail::IMAPClient::Bodystructure> object.
=head2 bodydisp
The B<bodydisp> object method requires no arguments. It returns the
bodydisp for the message whose structure is described by the calling
B<Mail::IMAPClient::Bodystructure> object.
=head2 bodyid
The B<bodyid> object method requires no arguments. It returns the
bodyid for the message whose structure is described by the calling
B<Mail::IMAPClient::Bodystructure> object.
=head2 bodydesc
The B<bodydesc> object method requires no arguments. It returns the
bodydesc for the message whose structure is described by the calling
B<Mail::IMAPClient::Bodystructure> object.
=head2 bodyenc
The B<bodyenc> object method requires no arguments. It returns the
bodyenc for the message whose structure is described by the calling
B<Mail::IMAPClient::Bodystructure> object.
=head2 bodysize
The B<bodysize> object method requires no arguments. It returns the
bodysize for the message whose structure is described by the calling
B<Mail::IMAPClient::Bodystructure> object.
=head2 bodylang
The B<bodylang> object method requires no arguments. It returns the
bodylang for the message whose structure is described by the calling
B<Mail::IMAPClient::Bodystructure> object.
=head2 bodystructure
The B<bodystructure> object method requires no arguments. It returns
the bodystructure for the message whose structure is described by the
calling B<Mail::IMAPClient::Bodystructure> object.
=head2 envelopestruct
The B<envelopestruct> object method requires no arguments. It returns
the envelopestruct for the message whose structure is described by the
calling B<Mail::IMAPClient::Bodystructure> object. This envelope structure
is blessed into the B<Mail::IMAPClient::BodyStructure::Envelope> subclass,
which is explained more fully below.
=head2 textlines
The B<textlines> object method requires no arguments. It returns the
textlines for the message whose structure is described by the calling
B<Mail::IMAPClient::Bodystructure> object.
=head1 Envelopes and the Mail::IMAPClient::BodyStructure::Envelope Subclass
The IMAP standard specifies that output from the IMAP B<FETCH
ENVELOPE> command will be an RFC2060 envelope structure. It further
specifies that output from the B<FETCH BODYSTRUCTURE> command may also
contain embedded envelope structures (if, for example, a message's
subparts contain one or more included messages). Objects belonging to
B<Mail::IMAPClient::BodyStructure::Envelope> are Perl representations
of these envelope structures, which is to say the nested parenthetical
lists of RFC2060 translated into a Perl datastructure.
Note that all of the fields relate to the specific part to which they
belong. In other words, output from a FETCH nnnn ENVELOPE command (or,
in B<Mail::IMAPClient>, C<$imap->fetch($msgid,"ENVELOPE")> or C<my $env =
$imap->get_envelope($msgid)>) are for the message, but fields from within
a bodystructure relate to the message subpart and not the parent message.
An envelope structure's B<Mail::IMAPClient::BodyStructure::Envelope>
representation is a hash of thingies that looks like this:
{
subject => "subject",
inreplyto => "reference_message_id",
from => [ addressStruct1 ],
messageid => "message_id",
bcc => [ addressStruct1, addressStruct2 ],
date => "Tue, 09 Jul 2002 14:15:53 -0400",
replyto => [ adressStruct1, addressStruct2 ],
to => [ adressStruct1, addressStruct2 ],
sender => [ adressStruct1 ],
cc => [ adressStruct1, addressStruct2 ],
}
The B<...::Envelope> object also has methods for accessing data in the
structure. They are:
=over 4
=item date
Returns the date of the message.
=item inreplyto
Returns the message id of the message to which this message is a reply.
=item subject
Returns the subject of the message.
=item messageid
Returns the message id of the message.
=back
You can also use the following methods to get addressing
information. Each of these methods returns an array of
B<Mail::IMAPClient::BodyStructure::Address> objects, which are perl
data structures representing RFC2060 address structures. Some of these
arrays would naturally contain one element (such as B<from>, which
normally contains a single "From:" address); others will often contain
more than one address. However, because RFC2060 defines all of these as
"lists of address structures", they are all translated into arrays of
B<...::Address> objects.
See the section on B<Mail::IMAPClient::BodyStructure::Address>", below,
for alternate (and preferred) ways of accessing these data.
The methods available are:
=over 4
=item bcc
Returns an array of blind cc'ed recipients' address structures. (Don't
expect much in here unless the message was sent from the mailbox you're
poking around in, by the way.)
=item cc
Returns an array of cc'ed recipients' address structures.
=item from
Returns an array of "From:" address structures--usually just one.
=item replyto
Returns an array of "Reply-to:" address structures. Once again there is
usually just one address in the list.
=item sender
Returns an array of senders' address structures--usually just one and
usually the same as B<from>.
=item to
Returns an array of recipients' address structures.
=back
Each of the methods that returns a list of address structures (i.e. a
list of B<Mail::IMAPClient::BodyStructure::Address> arrays) also has an
analagous method that will return a list of E-Mail addresses instead. The
addresses are in the format C<personalname E<lt>mailboxname@hostnameE<gt>>
(see the section on B<Mail::IMAPClient::BodyStructure::Address>,
below) However, if the personal name is 'NIL' then it is omitted from
the address.
These methods are:
=over 4
=item bcc_addresses
Returns a list (or an array reference if called in scalar context)
of blind cc'ed recipients' email addresses. (Don't expect much in here
unless the message was sent from the mailbox you're poking around in,
by the way.)
=item cc_addresses
Returns a list of cc'ed recipients' email addresses. If called in a scalar
context it returns a reference to an array of email addresses.
=item from_addresses
Returns a list of "From:" email addresses. If called in a scalar context
it returns the first email address in the list. (It's usually a list of just
one anyway.)
=item replyto_addresses
Returns a list of "Reply-to:" email addresses. If called in a scalar context
it returns the first email address in the list.
=item sender_addresses
Returns a list of senders' email addresses. If called in a scalar context
it returns the first email address in the list.
=item to_addresses
Returns a list of recipients' email addresses. If called in a scalar context
it returns a reference to an array of email addresses.
=back
Note that context affects the behavior of all of the above methods.
Those fields that will commonly contain multiple entries (i.e. they are
recipients) will return an array reference when called in scalar context.
You can use this behavior to optimize performance.
Those fields that will commonly contain just one address (the sender's) will
return the first (and usually only) address. You can use this behavior to
optimize your development time.
=head1 Addresses and the Mail::IMAPClient::BodyStructure::Address
Several components of an envelope structure are address
structures. They are each parsed into their own object,
B<Mail::IMAPClient::BodyStructure::Address>, which looks like this:
{ mailboxname => 'somebody.special'
, hostname => 'somplace.weird.com'
, personalname => 'Somebody Special
, sourceroute => 'NIL'
}
RFC2060 specifies that each address component of a bodystructure is a
list of address structures, so B<Mail::IMAPClient::BodyStructure> parses
each of these into an array of B<Mail::IMAPClient::BodyStructure::Address>
objects.
Each of these objects has the following methods available to it:
=over 4
=item mailboxname
Returns the "mailboxname" portion of the address, which is the part to
the left of the '@' sign.
=item hostname
Returns the "hostname" portion of the address, which is the part to the
right of the '@' sign.
=item personalname
Returns the "personalname" portion of the address, which is the part of
the address that's treated like a comment.
=item sourceroute
Returns the "sourceroute" portion of the address, which is typically "NIL".
=back
Taken together, the parts of an address structure form an address that will
look something like this:
C<personalname E<lt>mailboxname@hostnameE<gt>>
Note that because the B<Mail::IMAPClient::BodyStructure::Address>
objects come in arrays, it's generally easier to use the methods
available to B<Mail::IMAPClient::BodyStructure::Envelope> to obtain
all of the addresses in a particular array in one operation. These
methods are provided, however, in case you'd rather do things
the hard way. (And also because the aforementioned methods from
B<Mail::IMAPClient::BodyStructure::Envelope> need them anyway.)
=cut
=head1 AUTHOR
David J. Kernen
Reworked by Mark Overmeer.
=head1 SEE ALSO
perl(1), Mail::IMAPClient, and RFC2060. See also Parse::RecDescent if you
want to understand the internals of this module.
=cut

View File

@ -1,185 +0,0 @@
# Directives
# ( none)
# Start-up Actions
{
my $mibs = "Mail::IMAPClient::BodyStructure";
my $subpartCount = 0;
my $partCount = 0;
sub take_optional_items($$@)
{ my ($r, $items) = (shift, shift);
foreach (@_)
{ my $opt = $_ .'(?)';
exists $items->{$opt} or next;
$r->{$_} = UNIVERSAL::isa($items->{$opt}, 'ARRAY')
? $items->{$opt}[0] : $items->{$opt};
}
}
sub merge_hash($$)
{ my $to = shift;
my $from = shift or return;
while( my($k,$v) = each %$from) { $to->{$k} = $v }
}
}
# Atoms
TEXT: /^"TEXT"|^TEXT/i { $return = "TEXT" }
PLAIN: /^"PLAIN"|^PLAIN/i { $return = "PLAIN" }
HTML: /"HTML"|HTML/i { $return = "HTML" }
MESSAGE: /^"MESSAGE"|^MESSAGE/i { $return = "MESSAGE"}
RFC822: /^"RFC822"|^RFC822/i { $return = "RFC822" }
NIL: /^NIL/i { $return = "NIL" }
NUMBER: /^(\d+)/ { $return = $item[1] }
# Strings:
SINGLE_QUOTED_STRING: "'" /(?:\\'|[^'])*/ "'" { $return = $item{__PATTERN1__} }
DOUBLE_QUOTED_STRING: '"' /(?:\\"|[^"])*/ '"' { $return = $item{__PATTERN1__} }
BARESTRING: ...!/^[)('"]/ /^(?!\(|\))(?:\\ |\S)+/
{ $return = $item{__PATTERN1__} }
STRING: DOUBLE_QUOTED_STRING | SINGLE_QUOTED_STRING | BARESTRING
STRINGS: "(" STRING(s) ")" { $return = $item{'STRING(s)'} }
textlines: NIL | NUMBER
rfc822message: MESSAGE RFC822 { $return = "MESSAGE RFC822" }
bodysubtype: PLAIN | HTML | NIL | STRING
key: STRING
value: NIL | NUMBER | STRING | KVPAIRS
kvpair: ...!")" key value
{ $return = { $item{key} => $item{value} } }
KVPAIRS: "(" kvpair(s) ")"
{ $return = { map { (%$_) } @{$item{'kvpair(s)'}} } }
bodytype: STRING
bodyparms: NIL | KVPAIRS
bodydisp: NIL | KVPAIRS
bodyid: ...!/[()]/ NIL | STRING
bodydesc: ...!/[()]/ NIL | STRING
bodysize: ...!/[()]/ NIL | NUMBER
bodyenc: NIL | STRING | KVPAIRS
bodyMD5: NIL | STRING
bodylang: NIL | STRING | STRINGS
bodyextra: NIL | STRING | STRINGS
personalname: NIL | STRING
sourceroute: NIL | STRING
mailboxname: NIL | STRING
hostname: NIL | STRING
addressstruct: "(" personalname sourceroute mailboxname hostname ")"
{ bless { personalname => $item{personalname}
, sourceroute => $item{sourceroute}
, mailboxname => $item{mailboxname}
, hostname => $item{hostname}
}, 'Mail::IMAPClient::BodyStructure::Address';
}
subject: NIL | STRING
inreplyto: NIL | STRING
messageid: NIL | STRING
date: NIL | STRING
ADDRESSES: NIL
| "(" addressstruct(s) ")" { $return = $item{'addressstruct(s)'} }
cc: ADDRESSES
bcc: ADDRESSES
from: ADDRESSES
replyto: ADDRESSES
sender: ADDRESSES
to: ADDRESSES
envelopestruct: "(" date subject from sender replyto to cc
bcc inreplyto messageid ")"
{ $return = bless {}, "Mail::IMAPClient::BodyStructure::Envelope";
$return->{$_} = $item{$_}
for qw/date subject from sender replyto to cc/
, qw/bcc inreplyto messageid/;
1;
}
basicfields: bodysubtype bodyparms(?) bodyid(?)
bodydesc(?) bodyenc(?) bodysize(?)
{ $return = { bodysubtype => $item{bodysubtype} };
take_optional_items($return, \%item,
qw/bodyparms bodyid bodydesc bodyenc bodysize/);
1;
}
textmessage: TEXT <commit> basicfields textlines(?) bodyMD5(?)
bodydisp(?) bodylang(?) bodyextra(?)
{
$return = $item{basicfields} || {};
$return->{bodytype} = 'TEXT';
take_optional_items($return, \%item
, qw/textlines bodyMD5 bodydisp bodylang bodyextra/);
1;
}
othertypemessage: bodytype basicfields bodyparms(?) bodydisp(?)
bodylang(?) bodyextra(?)
{ $return = { bodytype => $item{bodytype} };
take_optional_items($return, \%item
, qw/bodyparms bodydisp bodylang bodyextra/ );
merge_hash($return, $item{basicfields});
1;
}
nestedmessage: rfc822message <commit> bodyparms bodyid bodydesc bodyenc
# bodysize envelopestruct bodystructure textlines
bodysize envelopestruct(?) bodystructure(?) textlines(?)
bodyMD5(?) bodydisp(?) bodylang(?) bodyextra(?)
{
$return = {};
$return->{$_} = $item{$_}
for qw/bodyparms bodyid bodydesc bodyenc bodysize/;
# envelopestruct bodystructure textlines/;
take_optional_items($return, \%item
, qw/envelopestruct bodystructure textlines/
, qw/bodyMD5 bodydisp bodylang bodyextra/);
merge_hash($return, $item{bodystructure}[0]);
merge_hash($return, $item{basicfields});
$return->{bodytype} = "MESSAGE" ;
$return->{bodysubtype} = "RFC822" ;
1;
}
multipart: subpart(s) <commit> basicfields
bodyparms(?) bodydisp(?) bodylang(?) bodyextra(?)
<defer: $subpartCount = 0>
{ $return = $item{basicfields};
$return->{bodytype} = 'MULTIPART';
$return->{bodystructure} = $item{'subpart(s)'};
take_optional_items($return, \%item
, qw/bodyparms bodydisp bodylang bodyextra/);
1;
}
subpart: "(" part ")" {$return = $item{part}} <defer: ++$subpartCount;>
part: multipart { $return = bless $item{multipart}, $mibs }
| textmessage { $return = bless $item{textmessage}, $mibs }
| nestedmessage { $return = bless $item{nestedmessage}, $mibs }
| othertypemessage { $return = bless $item{othertypemessage}, $mibs }
bodystructure: "(" part(s) ")"
{ $return = $item{'part(s)'} }
start: /.*?\(.*?BODYSTRUCTURE \(/i part(1) /\).*\)\r?\n?/
{ $return = $item{'part(1)'}[0] }
envelope: /.*?\(.*?ENVELOPE/ envelopestruct /.*\)/
{ $return = $item{envelopestruct} }

File diff suppressed because it is too large Load Diff

View File

@ -1,17 +0,0 @@
=head1 NAME
Mail::IMAPClient::BodyStructure::Parse -- used internally by Mail::IMAPClient::BodyStructure
=head1 DESCRIPTION
This module is used internally by L<Mail::IMAPClient::BodyStructure>
and is generated using L<Parse::RecDescent>. It is not meant to be used
directly by other scripts nor is there much point in debugging it.
=head1 SYNOPSIS
This module is used internally by L<Mail::IMAPClient::BodyStructure>
and is not meant to be used or called directly from applications. So
don't do that.
=cut

File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More