Mail::IMAPTalk(3pm) | User Contributed Perl Documentation | Mail::IMAPTalk(3pm) |
Mail::IMAPTalk - IMAP client interface with lots of features
use Mail::IMAPTalk; $IMAP = Mail::IMAPTalk->new( Server => $IMAPServer, Username => 'foo', Password => 'bar', ) || die "Failed to connect/login to IMAP server"; # Append message to folder open(my $F, 'rfc822msg.txt'); $IMAP->append($FolderName, $F) || die $@; close($F); # Select folder and get first unseen message $IMAP->select($FolderName) || die $@; $MsgId = $IMAP->search('not', 'seen')->[0]; # Get message envelope and print some details $MsgEV = $IMAP->fetch($MsgId, 'envelope')->{$MsgId}->{envelope}; print "From: " . $MsgEv->{From}; print "To: " . $MsgEv->{To}; print "Subject: " . $MsgEv->{Subject}; # Get message body structure $MsgBS = $IMAP->fetch($MsgId, 'bodystructure')->{$MsgId}->{bodystructure}; # Find imap part number of text part of message $MsgTxtHash = Mail::IMAPTalk::find_message($MsgBS); $MsgPart = $MsgTxtHash->{text}->{'IMAP-Partnum'}; # Retrieve message text body $MsgTxt = $IMAP->fetch($MsgId, "body[$MsgPart]")->{$MsgId}->{body}; $IMAP->logout();
This module communicates with an IMAP server. Each IMAP server command is mapped to a method of this object.
Although other IMAP modules exist on CPAN, this has several advantages over other modules.
While the IMAP protocol does allow for asynchronous running of commands, this module is designed to be used in a synchronous manner. That is, you issue a command by calling a method, and the command will block until the appropriate response is returned. The method will then return the parsed results from the given command.
The object methods have been broken in several sections.
All methods return undef on failure. There are four main modes of failure:
In each case, some readable form of error text is placed in $@, or you can call the "get_last_error()" method. For commands which return responses (e.g. fetch, getacl, etc), the result is returned. See each command for details of the response result. For commands with no response but which succeed (e.g. setacl, rename, etc) the result 'ok' is generally returned.
All methods which send data to the IMAP server (e.g. "fetch()", "search()", etc) have their arguments processed before they are sent. Arguments may be specified in several ways:
The string/data in the value is sent as an IMAP literal regardless of the actual data in the string/data.
The string/data in the value is sent as an IMAP quoted string regardless of the actual data in the string/data.
Examples:
# Password is automatically quoted to "nasty%*\"passwd" $IMAP->login("joe", 'nasty%*"passwd'); # Append $MsgTxt as string $IMAP->append("inbox", { Literal => $MsgTxt }) # Append MSGFILE contents as new message $IMAP->append("inbox", \*MSGFILE ])
These constants relate to the standard 4 states that an IMAP connection can be in. They are passed and returned from the "state()" method. See RFC 3501 for more details about IMAP connection states.
This is useful if you want to create an SSL socket connection using IO::Socket::SSL and then pass in the connected socket to the new() call.
It's also useful in conjunction with the "release_socket()" method described below for reusing the same socket beyond the lifetime of the IMAPTalk object. See a description in the section "release_socket()" method for more information.
You must have write flushing enabled for any socket you pass in here so that commands will actually be sent, and responses received, rather than just waiting and eventually timing out. you can do this using the Perl "select()" call and $| ($AUTOFLUSH) variable as shown below.
my $ofh = select($Socket); $| = 1; select ($ofh);
See the "login" method for more information.
Examples:
$imap = Mail::IMAPTalk->new( Server => 'foo.com', Port => 143, Username => 'joebloggs', Password => 'mypassword', Separator => '.', RootFolder => 'INBOX', ) || die "Connection to foo.com failed. Reason: $@"; $imap = Mail::IMAPTalk->new( Socket => $SSLSocket, State => Mail::IMAPTalk::Authenticated, Uid => 0 ) || die "Could not query on existing socket. Reason: $@";
The actual authentication may be done using the "LOGIN" or "AUTHENTICATE" commands, depending on what the server advertises support for.
If $AsUser is supplied, an attempt will be made to login on behalf of that user.
if ($IMAP->capability()->{quota}) { ... }
to test if the server has the QUOTA capability. If you just want a list of capabilities, use the Perl 'keys' function to get a list of keys from the returned hash reference.
Setting this affects all commands that take a folder argument. Basically if the foldername begins with root folder prefix, it's left as is, otherwise the root folder prefix and separator char are prefixed to the folder name.
The AltRootRegexp is a regexp that if the start of the folder name matches, does not have $RootFolder preprended. You can use this to protect other namespaces in your IMAP server.
Examples:
# This is what cyrus uses $IMAP->set_root_folder('INBOX', '.', qr/^user/); # Selects 'Inbox' (because 'Inbox' eq 'inbox' case insensitive) $IMAP->select('Inbox'); # Selects 'INBOX.blah' $IMAP->select('blah'); # Selects 'INBOX.Inbox.fred' #IMAP->select('Inbox.fred'); # Selects 'user.john' (because 'user' is alt root) #IMAP->select('user.john'); # Selects 'user.john'
You should pass a filehandle here that any literal will be read into. To turn off literal reads into a file handle, pass a 0.
Examples:
# Read rfc822 text of message 3 into file # (note that the file will have /r/n line terminators) open(F, ">messagebody.txt"); $IMAP->literal_handle_control(\*F); $IMAP->fetch(3, 'rfc822'); $IMAP->literal_handle_control(0);
This means you can't call any methods on the IMAPTalk object any more.
If the socket is being released and being closed, then $Close is set to true.
This is either the string "ok", "no" or "bad" (always lower case)
Array reference of flags which are stored permanently.
Whether the current UID set is valid. See the IMAP RFC for more information on this. If this value changes, then all UIDs in the folder have been changed.
The next UID number that will be assigned.
Number of messages that exist in the folder.
Number of messages that are recent in the folder.
Other possible responses are alert, newname, parse, trycreate, appenduid, etc.
The values are stored in a hash keyed on the $Response item. They're kept until either overwritten by a future response, or explicitly cleared via clear_response_code().
Examples:
# Select inbox and get list of permanent flags, uidnext and number # of message in the folder $IMAP->select('inbox'); my $NMessages = $IMAP->get_response_code('exists'); my $PermanentFlags = $IMAP->get_response_code('permanentflags'); my $UidNext = $IMAP->get_response_code('uidnext');
For this to work, you must have 'used' Mail::IMAPTalk with:
use Mail::IMAPTalk qw(:utf8support ...)
Note: literals are never passed to the tracer.
Sets whether folder names are expected and returned as perl unicode strings.
The default is currently 0, BUT YOU SHOULD NOT ASSUME THIS, because it will probably change in the future.
If you want to work with perl unicode strings for folder
names, you should call
$ImapTalk->set_unicode_folders(1) and
IMAPTalk will automatically encode the unicode strings into IMAP-UTF7
when sending to the IMAP server, and will also decode IMAP-UTF7 back
into perl unicode strings when returning results from the IMAP
server.
If you want to work with folder names in IMAP-UTF7 bytes, then
call
$ImapTalk->set_unicode_folders(0) and
IMAPTalk will leave folder names as bytes when sending to and returning
results from the IMAP server.
Note: In all cases where a folder name is used, the folder name is first manipulated according to the current root folder prefix as described in "set_root_folder()".
Mail::IMAPTalk will cache the currently selected folder, and if you issue another ->select("XYZ") for the folder that is already selected, it will just return immediately. This can confuse code that expects to get side effects of a select call. For that case, call ->unselect() first, then ->select().
Due to ambiguity in RFC 2086, some existing RFC 2086 server implementations use the "c" right to control the DELETE command. Others chose to use the "d" right to control the DELETE command. See the 2.1.1. Obsolete Rights in RFC 4314 for more details.
The standard access control configurations for cyrus are
Examples:
# Get full access for user 'joe' on his own folder $IMAP->setacl('user.joe', 'joe', 'lrswipcda') || die "IMAP error: $@"; # Remove write, insert, post, create, delete access for user 'andrew' $IMAP->setacl('user.joe', 'andrew', '-wipcd') || die "IMAP error: $@"; # Add lookup, read, keep unseen information for user 'paul' $IMAP->setacl('user.joe', 'paul', '+lrs') || die "IMAP error: $@";
Examples:
my $Rights = $IMAP->getacl('user.joe') || die "IMAP error : $@"; $Rights = [ 'joe', 'lrs', 'andrew', 'lrswipcda' ]; $IMAP->setacl('user.joe', 'joe', 'lrswipcda') || die "IMAP error : $@"; $IMAP->setacl('user.joe', 'andrew', '-wipcd') || die "IMAP error : $@"; $IMAP->setacl('user.joe', 'paul', '+lrs') || die "IMAP error : $@"; $Rights = $IMAP->getacl('user.joe') || die "IMAP error : $@"; $Rights = [ 'joe', 'lrswipcd', 'andrew', 'lrs', 'paul', 'lrs' ];
Examples:
my $Rights = $IMAP->getacl('user.joe') || die "IMAP error : $@"; $Rights = [ 'joe', 'lrswipcd', 'andrew', 'lrs', 'paul', 'lrs' ]; # Delete access information for user 'andrew' $IMAP->deleteacl('user.joe', 'andrew') || die "IMAP error : $@"; $Rights = $IMAP->getacl('user.joe') || die "IMAP error : $@"; $Rights = [ 'joe', 'lrswipcd', 'paul', 'lrs' ];
Examples:
# Set maximum size of folder to 50M and 1000 messages $IMAP->setquota('user.joe', '(storage 50000)') || die "IMAP error: $@"; $IMAP->setquota('user.john', '(messages 1000)') || die "IMAP error: $@"; # Remove quotas $IMAP->setquota('user.joe', '()') || die "IMAP error: $@";
Note that this only returns the quota for a folder if it actually has had a quota set on it. It's possible that a parent folder might have a quota as well which affects sub-folders. Use the getquotaroot to find out if this is true.
Examples:
my $Result = $IMAP->getquota('user.joe') || die "IMAP error: $@"; $Result = [ 'STORAGE', 31, 50000, 'MESSAGE', 5, 1000 ];
Basically it's a hash reference. The 'quotaroot' item is the response which lists the root quotas that apply to the given folder. The first item is the folder name, and the remaining items are the quota root items. There is then a hash item for each quota root item. It's probably easiest to look at the example below.
Examples:
my $Result = $IMAP->getquotaroot('user.joe.blah') || die "IMAP error: $@"; $Result = { 'quotaroot' => [ 'user.joe.blah', 'user.joe', '' ], 'user.joe' => [ 'STORAGE', 31, 50000, 'MESSAGES', 5, 1000 ], '' => [ 'MESSAGES', 3498, 100000 ] };
The $StatusList is a bracketed list of folder items to obtain the status of. Can contain: messages, recent, uidnext, uidvalidity, unseen.
The return value is a hash reference of lc(status-item) => value.
Examples:
my $Res = $IMAP->status('inbox', '(MESSAGES UNSEEN)'); $Res = { 'messages' => 8, 'unseen' => 2 };
Returns a hash ref of folder name => status results.
If an error occurs, the annotation result is a scalar ref to the completion response string (eg 'bad', 'no', etc)
Examples:
my $Result = $IMAP->getannotation('user.joe.blah', '/*' '*') || die "IMAP error: $@"; $Result = { 'user.joe.blah' => { '/vendor/cmu/cyrus-imapd/size' => { 'size.shared' => '5', 'content-type.shared' => 'text/plain', 'value.shared' => '19261' }, '/vendor/cmu/cyrus-imapd/lastupdate' => { 'size.shared' => '26', 'content-type.shared' => 'text/plain', 'value.shared' => '26-Mar-2004 13:31:56 -0800' }, '/vendor/cmu/cyrus-imapd/partition' => { 'size.shared' => '7', 'content-type.shared' => 'text/plain', 'value.shared' => 'default' } } };
If $Options is passed, it is a hashref of options to set.
If foldername is the empty string, gets server annotations
Examples:
my $Result = $IMAP->getmetadata('user.joe.blah', {depth => 'infinity'}, '/shared') || die "IMAP error: $@"; $Result = { 'user.joe.blah' => { '/shared/vendor/cmu/cyrus-imapd/size' => '19261', '/shared/vendor/cmu/cyrus-imapd/lastupdate' => '26-Mar-2004 13:31:56 -0800', '/shared/vendor/cmu/cyrus-imapd/partition' => 'default', } }; my $Result = $IMAP->getmetadata('', "/shared/comment"); $Result => { '' => { '/shared/comment' => "Shared comment", } };
Returns a hash ref of folder name => metadata results.
If an error occurs, the annotation result is a scalar ref to the completion response string (eg 'bad', 'no', etc)
Examples:
my $Result = $IMAP->setannotation('user.joe.blah', '/comment', [ 'value.priv' 'A comment' ]) || die "IMAP error: $@";
Examples:
my $Result = $IMAP->setmetadata('user.joe.blah', '/comment', 'A comment') || die "IMAP error: $@";
If the callback returns 0, the idle continues. If the callback returns 1, the idle is finished and this call returns.
If no timeout is passed, will continue to idle until the callback returns 1 or the server disconnects.
If a timeout is passed (including a 0 timeout), the call will return if no events are received within the given time. It will return the result of the DONE command, and set $Self->get_response_code('timeout') to true.
If the server closes the connection with a "bye" response, it will return undef and $@ =~ /bye/ will be true with the remainder of the bye line following.
The first parameter can be an optional hash reference that overrides particular parse mode parameters just for this fetch. See "parse_mode" for possible keys.
$MessageIds can be one of two forms:
Examples:
Note that , separated lists and : separated ranges can be mixed, but to make sure a certain hack works, if a '*' is used, it must be the last character in the string.
Note: If the "uid()" state has been set to true, then all message ID's must be message UIDs.
$MessageItems can be one of, or a bracketed list of:
It would be a good idea to see RFC 3501 for what all these means.
Examples:
my $Res = $IMAP->fetch('1:*', 'rfc822.size'); my $Res = $IMAP->fetch([1,2,3], '(bodystructure envelope)');
Return results:
The results returned by the IMAP server are parsed into a Perl structure. See the section FETCH RESULTS for all the interesting details.
Note that message can disappear on you, so you may not get back all the entries you expect in the hash
There is one piece of magic. If your request is for a single uid, (eg "123"), and no data is return, we return undef, because it's easier to handle as an error condition.
The $MessageData to append can either be a Perl scalar containing the data, or a file handle to read the data from. In each case, the data must be in proper RFC 822 format with \r\n line terminators.
Any optional fields not needed should be removed, not left blank.
Examples:
# msg.txt should have \r\n line terminators open(F, "msg.txt"); $IMAP->append('inbox', \*F); my $MsgTxt =<<MSG; From: blah\@xyz.com To: whoever\@whereever.com ... MSG $MsgTxt =~ s/\n/\015\012/g; $IMAP->append('inbox', { Literal => $MsgTxt });
@SearchCriteria is a list of search specifications, for example to look for ASCII messages bigger than 2000 bytes you would set the list to be:
my @SearchCriteria = ('CHARSET', 'US-ASCII', 'LARGER', '2000');
Examples:
my $Res = $IMAP->search('1:*', 'NOT', 'DELETED'); $Res = [ 1, 2, 5 ];
Examples:
$IMAP->store('1:*', '+flags', '(\\deleted)'); $IMAP->store('1:*', '-flags.silent', '(\\read)');
It would probably be a good idea to look at the sort RFC 5256 details at somewhere like : http://www.ietf.org/rfc/rfc5256.txt
Examples:
my $Res = $IMAP->sort('(subject)', 'US-ASCII', 'NOT', 'DELETED'); $Res = [ 5, 2, 3, 1, 4 ];
Examples
my $Res = $IMAP->thread('REFERENCES', 'US-ASCII', 'NOT', 'DELETED'); $Res = [ [10, 15, 20], [11], [ [ 12, 16 ], [13, 17] ];
This is just a special fast path version of "fetch".
This is just a special fast path version of "fetch".
Methods provided by extensions to the cyrus IMAP server
Note: In all cases where a folder name is used, the folder name is first manipulated according to the current root folder prefix as described in "set_root_folder()".
CIDs can be a single CID or an array ref of CIDs.
my $Res = $IMAP->xconvfetch('2fc2122a109cb6c8', 0, '(uid cid envelope)') $Res = { state => { CID => [ HighestModSeq ], ... } folders => [ [ FolderName, UidValidity ], ..., ], found => [ [ FolderIndex, Uid, { Details } ], ... ], }
Note: FolderIndex is an integer index into the folders list
CIDs can be a single CID or an array ref of CIDs.
my $Res = $IMAP->xconvmeta('2fc2122a109cb6c8', '(senders exists unseen)') $Res = { CID1 => { senders => { name => ..., email => ... }, exists => ..., unseen => ..., ... }, CID2 => { ... }, }
my $Res = $IMAP->xconvsort( [ qw(reverse arrival) ], [ 'conversations', position => [1, 10] ], 'utf-8', 'ALL') $Res = { sort => [ Uid, ... ], position => N, highestmodseq => M, uidvalidity => V, uidnext => U, total => R, }
my $Res = $IMAP->xconvupdates( [ qw(reverse arrival) ], [ 'conversations', changedsince => [ $mod_seq, $uid_next ] ], 'utf-8', 'ALL'); $Res = { added => [ [ Uid, Pos ], ... ], removed => [ Uid, ... ], changed => [ CID, ... ], highestmodseq => M, uidvalidity => V, uidnext => U, total => R, }
my $Res = $IMAP->xconvmultisort( [ qw(reverse arrival) ], [ 'conversations', position => [1,10] ], 'utf-8', 'ALL') $Res = { folders => [ [ FolderName, UidValidity ], ... ], sort => [ FolderIndex, Uid ], ... ], position => N, highestmodseq => M, total => R, }
Note: FolderIndex is an integer index into the folders list
my $Res = $IMAP->xsnippets( [ [ FolderName, UidValidity, [ Uid, ... ] ], ... ], 'utf-8', 'ALL') $Res = { folders => [ [ FolderName, UidValidity ], ... ], snippets => [ [ FolderIndex, Uid, Location, Snippet ], ... ] ]
Note: FolderIndex is an integer index into the folders list
Examples:
# Fetch body structure my $FR = $IMAP->fetch(1, 'bodystructure'); my $BS = $FR->{1}->{bodystructure}; # Parse further to find particular sub part my $P12 = $IMAP->get_body_part($BS, '1.2'); $P12->{'IMAP->Partnum'} eq '1.2' || die "Unexpected IMAP part number";
text => $best_text_part html => $best_html_part (optional) textlist => [ ... text/html (if no alt text bits)/image (if inline) parts ... ] htmllist => [ ... text (if no alt html bits)/html/image (if inline) parts ... ] att => [ { bs => $part, text => 0/1, html => 0/1, msg => 1/0, }, { ... }, ... ]
For instance, consider a message with text and html pages that's then gone through a list software manager that attaches a header/footer
multipart/mixed text/plain, cd=inline - A multipart/mixed multipart/alternative multipart/mixed text/plain, cd=inline - B image/jpeg, cd=inline - C text/plain, cd=inline - D multipart/related text/html - E image/jpeg - F image/jpeg, cd=attachment - G application/x-excel - H message/rfc822 - J text/plain, cd=inline - K
In this case, we'd have the following list items
text => B html => E textlist => [ A, B, C, D, K ] htmllist => [ A, E, K ] att => [ { bs => C, text => 1, html => 1 }, { bs => F, text => 1, html => 0 }, { bs => G, text => 1, html => 1 }, { bs => H, text => 1, html => 1 }, { bs => J, text => 0, html => 0, msg => 1 }, ]
Examples:
# Fetch body structure my $FR = $IMAP->fetch(1, 'bodystructure'); my $BS = $FR->{1}->{bodystructure}; # Parse further to find message components my $MC = $IMAP->find_message($BS); $MC = { 'plain' => ... text body struct ref part ..., 'html' => ... html body struct ref part (if present) ... 'htmllist' => [ ... html body struct ref parts (if present) ... ] }; # Now get the text part of the message my $MT = $IMAP->fetch(1, 'body[' . $MC->{text}->{'IMAP-Part'} . ']');
The same value should always be returned for a given $Token and $PartBS
If you pass a Mail::IMAPTalk object as the second parameter, the CID map built may be even more detailed. It seems some stupid versions of exchange put details in the Content-Location header rather than the Content-Type header. If that's the case, this will try and fetch the header from the message
Examples:
# Fetch body structure my $FR = $IMAP->fetch(1, 'bodystructure'); my $BS = $FR->{1}->{bodystructure}; # Parse further to get CID links my $CL = build_cid_map($BS); $CL = { '2958293123' => ... ref to body part ..., ... };
By default, these methods do nothing, but you can dervice from Mail::IMAPTalk and override these methods to trap any things you want to catch
The 'fetch' operation is probably the most common thing you'll do with an IMAP connection. This operation allows you to retrieve information about a message or set of messages, including header fields, flags or parts of the message body.
"Mail::IMAPTalk" will always parse the results of a fetch call into a Perl like structure, though 'bodystructure', 'envelope' and 'uid' responses may have additional parsing depending on the "parse_mode" state and the "uid" state (see below).
For an example case, consider the following IMAP commands and responses (C is what the client sends, S is the server response).
C: a100 fetch 5,6 (flags rfc822.size uid) S: * 1 fetch (UID 1952 FLAGS (\recent \seen) RFC822.SIZE 1150) S: * 2 fetch (UID 1958 FLAGS (\recent) RFC822.SIZE 110) S: a100 OK Completed
The fetch command can be sent by calling:
my $Res = $IMAP->fetch('1:*', '(flags rfc822.size uid)');
The result in response will look like this:
$Res = { 1 => { 'uid' => 1952, 'flags' => [ '\\recent', '\\seen' ], 'rfc822.size' => 1150 }, 2 => { 'uid' => 1958, 'flags' => [ '\\recent' ], 'rfc822.size' => 110 } };
A couple of points to note:
In general, this is how all fetch responses are parsed. There is one major difference however when the IMAP connection is in 'uid' mode. In this case, the message IDs in the main hash are changed to message UIDs, and the 'uid' entry in the inner hash is removed. So the above example would become:
my $Res = $IMAP->fetch('1:*', '(flags rfc822.size)'); $Res = { 1952 => { 'flags' => [ '\\recent', '\\seen' ], 'rfc822.size' => 1150 }, 1958 => { 'flags' => [ '\\recent' ], 'rfc822.size' => 110 } };
When dealing with messages, we need to understand the MIME structure of the message, so we can work out what is the text body, what is attachments, etc. This is where the 'bodystructure' item from an IMAP server comes in.
C: a101 fetch 1 (bodystructure) S: * 1 fetch (BODYSTRUCTURE ("TEXT" "PLAIN" NIL NIL NIL "QUOTED-PRINTABLE" 255 11 NIL ("INLINE" NIL) NIL)) S: a101 OK Completed
The fetch command can be sent by calling:
my $Res = $IMAP->fetch(1, 'bodystructure');
As expected, the resultant response would look like this:
$Res = { 1 => { 'bodystructure' => [ 'TEXT', 'PLAIN', undef, undef, undef, 'QUOTED-PRINTABLE', 255, 11, UNDEF, [ 'INLINE', undef ], undef ] } };
However, if you set the "parse_mode(BodyStructure =" 1)>, then the result would be:
$Res = { '1' => { 'bodystructure' => { 'MIME-Type' => 'text', 'MIME-Subtype' => 'plain', 'MIME-TxtType' => 'text/plain', 'Content-Type' => {}, 'Content-ID' => undef, 'Content-Description' => undef, 'Content-Transfer-Encoding' => 'QUOTED-PRINTABLE', 'Size' => '3569', 'Lines' => '94', 'Content-MD5' => undef, 'Disposition-Type' => 'inline', 'Content-Disposition' => {}, 'Content-Language' => undef, 'Remainder' => [], 'IMAP-Partnum' => '' } } };
A couple of points to note here:
In general, the following items are defined for all body structures:
For all bodystructures EXCEPT those that have a MIME-Type of 'multipart', the following are defined:
For bodystructures where MIME-Type is 'text', an extra item 'Lines' is defined.
For bodystructures where MIME-Type is 'message' and MIME-Subtype is 'rfc822', the extra items 'Message-Envelope', 'Message-Bodystructure' and 'Message-Lines' are defined. The 'Message-Bodystructure' item is itself a reference to an entire bodystructure hash with all the format information of the contained message. The 'Message-Envelope' item is a hash structure with the message header information. See the Envelope entry below.
For bodystructures where MIME-Type is 'multipart', an extra item 'MIME-Subparts' is defined. The 'MIME-Subparts' item is an array reference, with each item being a reference to an entire bodystructure hash with all the format information of each MIME sub-part.
For further processing, you can use the find_message() function. This will analyse the body structure and find which part corresponds to the main text/html message parts to display. You can also use the find_cid_parts() function to find CID links in an html message.
The envelope structure contains most of the addressing header fields from an email message. The following shows an example envelope fetch (the response from the IMAP server has been neatened up here)
C: a102 fetch 1 (envelope) S: * 1 FETCH (ENVELOPE ("Tue, 7 Nov 2000 08:31:21 UT" # Date "FW: another question" # Subject (("John B" NIL "jb" "abc.com")) # From (("John B" NIL "jb" "abc.com")) # Sender (("John B" NIL "jb" "abc.com")) # Reply-To (("Bob H" NIL "bh" "xyz.com") # To ("K Jones" NIL "kj" "lmn.com")) NIL # Cc NIL # Bcc NIL # In-Reply-To NIL) # Message-ID ) S: a102 OK Completed
The fetch command can be sent by calling:
my $Res = $IMAP->fetch(1, 'envelope');
And you get the idea of what the resultant response would be. Again if you change "parse_mode(Envelope =" 1)>, you get a neat structure as follows:
$Res = { '1' => { 'envelope' => { 'Date' => 'Tue, 7 Nov 2000 08:31:21 UT', 'Subject' => 'FW: another question', 'From' => '"John B" <jb@abc.com>', 'Sender' => '"John B" <jb@abc.com>', 'Reply-To' => '"John B" <jb@abc.com>', 'To' => '"Bob H" <bh@xyz.com>, "K Jones" <kj@lmn.com>', 'Cc' => '', 'Bcc' => '', 'In-Reply-To' => undef, 'Message-ID' => undef, 'From-Raw' => [ [ 'John B', undef, 'jb', 'abc.com' ] ], 'Sender-Raw' => [ [ 'John B', undef, 'jb', 'abc.com' ] ], 'Reply-To-Raw' => [ [ 'John B', undef, 'jb', 'abc.com' ] ], 'To-Raw' => [ [ 'Bob H', undef, 'bh', 'xyz.com' ], [ 'K Jones', undef, 'kj', 'lmn.com' ], ], 'Cc-Raw' => [], 'Bcc-Raw' => [], } } };
All the fields here are from straight from the email headers. See RFC 822 for more details.
If the server supports RFC 5257 (ANNOTATE Extension), then you can fetch per-message annotations.
Annotation responses would normally be returned as a a nested set of arrays. However it's much easier to access the results as a nested set of hashes, so the results are so converted if the Annotation parse mode is enabled, which is on by default.
Part of an example from the RFC
S: * 12 FETCH (UID 1123 ANNOTATION (/comment (value.priv "My comment" size.priv "10") /altsubject (value.priv "Rhinoceroses!" size.priv "13")
So the fetch command:
my $Res = $IMAP->fetch(1123, 'annotation', [ '/*', [ 'value.priv', 'size.priv' ] ]);
Would have the result:
$Res = { '1123' => { 'annotation' => { '/comment' => { 'value.priv' => 'My comment', 'size.priv => 10 }, '/altsubject' => { 'value.priv' => '"Rhinoceroses', 'size.priv => 13 } } } }
C123 uid fetch 1:* (flags) * 1 FETCH (FLAGS (\Seen) UID 1) * 2 FETCH (FLAGS (\Seen) UID 2) C123 OK Completed
Between the sending of the command and the 'OK Completed' response, we have to pick up all the untagged 'FETCH' response items so we would pass 'fetch' (always use lower case) as the $RespItems to extract.
This can also be a hash ref of callback functions. See _parse_response for more examples
$RespItems is either a string, which is the untagged response(s) to find and return, or for custom processing, it can be a hash ref.
If a hash ref, then each key will be an untagged response to look for, and each value a callback function to call for the corresponding untagged response.
Each callback will be called with 2 or 3 arguments; the untagged response string, the remainder of the line parsed into an array ref, and for fetch type responses, the id will be passed as the third argument.
One other piece of magic, if you pass a 'responseitem' key, then the value should be a string, and will be the untagged response returned from the function
If the next atom is:
In each case, after parsing the atom, it removes any trailing space separator, and then returns the remainder of the line to $Self->{ReadLine} ready for the next call to "_next_atom()".
The number of bytes specified must be available on the IMAP socket, if the function runs out of data it will 'die' with an error.
Wildcard => 1 = a folder name with % or * is left alone NoEncoding => 1 = don't do modified utf-7 encoding, leave as unicode
The $MessageIds parameter may take the following forms:
This is used to parse an envelope structure returned from a fetch call.
See the documentation section 'FETCH RESULTS' for more information.
If $IncludeRaw is true, includes the XXX-Raw fields, otherwise these are left out.
If $DecodeUTF8 is true, then checks if the fields contain any quoted-printable chars, and decodes them to a Perl UTF8 string if they do.
See the documentation section 'FETCH RESULTS' from more information.
See the documentation section 'FETCH RESULTS' from more information
See the documentation section 'FETCH RESULTS' from more information.
See the documentation section 'FETCH RESULTS' from more information.
Net::IMAP, Mail::IMAPClient, IMAP::Admin, RFC 3501
Latest news/details can also be found at:
http://cpan.robm.fastmail.fm/mailimaptalk/
Available on github at:
<https://github.com/robmueller/mail-imaptalk/>
Rob Mueller <cpan@robm.fastmail.fm>. Thanks to Jeremy Howard <j+daemonize@howard.fm> for socket code, support and documentation setup.
Copyright (C) 2003-2016 by FastMail Pty Ltd
This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
2022-06-15 | perl v5.34.0 |