=head1 NAME

Net::IMAP::SimpleX - Addons for Net::IMAP::Simple

=head1 SYNOPSIS

    use strict;
    use warnings;
    use Net::IMAP::SimpleX;

L<Net::IMAP::SimpleX> uses L<Net::IMAP::Simple> as a base so the object creation
is the same as it is for the ancestor:

    my $imap = Net::IMAP::SimpleX->new('imap.example.com') ||
       die "Unable to connect to IMAP: $Net::IMAP::Simple::errstr\n";

    $imap->select("INBOX");

L<Net::IMAP::SimpleX> is a collection of handy methods that are
not simple, require L<Parse::RecDescent>, or are experimental.

=head1 DESCRIPTION

This module adds some useful, yet not so simple, extensions on top of
L<Net::IMAP::Simple>.

=head1 METHODS

=over 4

=item new

For details on the invocation, read L<Net::IMAP::Simple>.

=item body_summary

Typical invocations will take this overall shape.

    # get an object representation of the message body
    my $summary = $imap->body_summary($message_number);

    # multipart message
    if ($summary->has_parts) {
        for my $subpart ($summary->parts) {
            if ($subpart->has_parts) { ... }
            # examine the message part
            my @attr = map { $subpart->$_ } qw/content_type encoding encoded_size/;
            # fetch the raw message part
            my $subpart_body = $imap->get($message_number, $subpart->part_number);
        }
    } else {
        my $body = $summary->body;
        my @attr = map { $body->$_ } qw/content_type encoding encoded_size/
    }


This method returns a simple object that contains a representation of the body
of a message.  The object is built by a L<Parse::RecDescent> parser using the
output of an IMAP I<fetch body> command.  The parser uses the formal syntax as
defined by RFC3501 L<http://tools.ietf.org/html/rfc3501#section-9>.

    my $body = $summary->body;
    my @attr = map { $body->$_ } qw/
        content_description
        encoded_size
        charset
        content_type
        part_number
        format
        id
        encoding
    /;


For multipart messages, the object contains sub-objects for each message part,
accessible via the parts() method and inspected via the has_parts() method.
The type method describes the type of multipart (such as mixed or alternative).
The parts method returns a list of sub parts, which themselves may have
subparts, and so on.

An example of a multipart, alternative message with a text body and an html
version of the body would looke something like:

    if ($summary->has_parts) {
        if ($summary->type eq 'alternative') {
            my ($html) = grep { $_->content_type eq 'text/html' } $summary->parts;
        }
    }

A really complex, multipart message could look something like this:

    if ($summary->has_parts && $summary->type eq 'mixed') {

        for my $part ($summary->parts) {
            if ($part->has_parts && $part->type eq 'mixed') { ... }
            ...
        }

    }

=item fetch

The fetch command returns the various parts of messages that users request.  It
is fairly complicated (following RFC3501 using a grammar/parser), but there are
some basic patterns that it follows.

    my $res  =$imap->fetch('30:32' => 'UID BODY.PEEK[HEADER.FIELDS (DATE)] FLAGS')
    # $res = {
    #   30 => {
    #           "BODY[HEADER.FIELDS (DATE)]" => "Date: Sun, 18 Jul 2010 20:54:48 -0400\r\n\r\n",
    #           "FLAGS" => ["\\Flagged", "\\Seen"],
    #           "UID" => 58890,
    #         },
    #   31 => {
    #           "BODY[HEADER.FIELDS (DATE)]" => "Date: Wed, 21 Jul 2010 09:09:04 -0400\r\n\r\n",
    #           "FLAGS" => ["\\Seen"],
    #           "UID" => 58891,
    #         },
    #   32 => {
    #           "BODY[HEADER.FIELDS (DATE)]" => "Date: Sat, 24 Jul 2010 05:12:06 -0700\r\n\r\n",
    #           "FLAGS" => ["\\Seen"],
    #           "UID" => 58892,
    #         },
    # }

So-called "parenthized" lists will be returned as an array (see C<FLAGS>) but
nearly everything else will come back as strings.  This includes parenthized
queries.  Take C<BODY.PEAK[HEADER.FIELDS (DATE FROM SUBJECT)]>), for example.
The result would come back as the RFC822 header lines (as the above C<Date: Sun,
...> has done).

For more information about the different types of queries, see RFC3501.  There's
a surprising number of things that can be queried.

=item uidfetch

This is roughly the same thing as the C<fetch()> method above, but the query
runs on UIDs instead of sequence numbers.  The keys of the C<$res> are still the
sequence numbers though.

    my $res  =$imap->fetch('58890' => 'UID BODY.PEEK[HEADER.FIELDS (DATE)] FLAGS')
    # $res = {
    #   30 => {
    #           "BODY[HEADER.FIELDS (DATE)]" => "Date: Sun, 18 Jul 2010 20:54:48 -0400\r\n\r\n",
    #           "FLAGS" => ["\\Flagged", "\\Seen"],
    #           "UID" => 58890,
    #         },
    #   ...

=back

=head1 AUTHOR

=over 4

=item INITIAL AUTHOR

Jason Woodward C<< <woodwardj@jaos.org> >>

=item ADDITIONAL CONTRIBUTIONS

Paul Miller C<< <jettero@cpan.org> >>  [I<fetch()>]

=back

=head1 COPYRIGHT

Copyright (c) 2010 Jason Woodward

All rights reserved. This program is free software; you can redistribute it
and/or modify it under the same terms as Perl itself.

=head1 LICENSE

This module is free software.  You can redistribute it and/or
modify it under the terms of the Artistic License 2.0.

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.

=head1 BUGS

L<https://rt.cpan.org/Dist/Display.html?Queue=Net-IMAP-Simple>

=head1 SEE ALSO

L<perl>, L<Net::IMAP::Simple>, L<Parse::RecDescent>