Mail::Box::IMAP4(3pm)

πŸ’– Mail::Box::IMAP4(3pm) πŸ’–

User Contributed Perl Documentation Β· Mail::Box::IMAP4(3pm)

okay bestie, buckle up 🫢 this is the page about treating your IMAP4 folders like a Mail::Box, client-side. big main character energy.


✨ NAME ✨

Mail::Box::IMAP4 β€” handle IMAP4 folders as client


🌸 INHERITANCE 🌸

 Mail::Box::IMAP4
   is a Mail::Box::Net
   is a Mail::Box
   is a Mail::Reporter

 Mail::Box::IMAP4 is extended by
   Mail::Box::IMAP4s

so like, it is all of those things (it inherited their whole personality πŸ’…) and then Mail::Box::IMAP4s is its own little spin-off, we love a franchise.


πŸ¦‹ SYNOPSIS πŸ¦‹

 my $url = 'imap4://user:passwd@host:port/INBOX';
 my $url = 'imap://user:passwd@host:port/INBOX';

 use Mail::Box::IMAP4;
 my $folder = Mail::Box::IMAP4->new(folder => $url, ...);

 use Mail::Box::Manager;
 my $mgr    = Mail::Box::Manager->new;
 my $folder = $msg->open($url, retry => 3, interval => 5);

look at that URL. imap4:// or imap://, both iconic, both valid, pick your fav ✨


🌈 DESCRIPTION 🌈

so basically you're maintaining a folder whose messages are chillin' on a remote server, not on your disk. the client app and the server talk it out using the IMAP4 protocol. also peep Mail::Server::IMAP4 if you're curious πŸ‘€

⚠️ bestie, real talk: this module versions 4.0 and up is not fully compatible with older releases β€” mainly the exception handling changed. so if you're upgrading, please go read https://github.com/markov2/perl5-Mail-Box/wiki/ Version 3 is still maintained and may see new releases as well. no cap.

This class uses Mail::Transport::IMAP4 to hide all the transport of information (the messy part) and focuses solely on the correct handling of messages within a IMAP4 folder (the cute part). and here's the slay: more than one IMAP4 folder can be handled by one single IMAP4 connection. efficiency queen πŸ‘‘

Extends "DESCRIPTION" in Mail::Box::Net.


πŸ’… OVERLOADED πŸ’…

Extends "OVERLOADED" in Mail::Box::Net.

  • overload: "" stringification β€” Inherited, see "OVERLOADED" in Mail::Box
  • overload: @{} use as ARRAY β€” Inherited, see "OVERLOADED" in Mail::Box
  • overload: cmp string comparison β€” Inherited, see "OVERLOADED" in Mail::Box

πŸ‘‘ METHODS πŸ‘‘

Extends "METHODS" in Mail::Box::Net.

πŸŽ€ Constructors πŸŽ€

Extends "Constructors" in Mail::Box::Net.

$class->new(%options)

The new can have many %options. Not only the ones listed here below, but also all the %options for Mail::Transport::IMAP4::new() can be passed. so yeah, options on options on options πŸ’–

The default depends on the value of new(cache_head).

Without a folder name, no folder is selected. Only few methods are available now, for instance listSubFolders() to get the top-level folder names. Usually, the folder named "INBOX" will be present. Improves base, see "Constructors" in Mail::Box

 -Option           --Defined in     --Default
  access             Mail::Box        'r'
  body_delayed_type  Mail::Box        Mail::Message::Body::Delayed
  body_type          Mail::Box        Mail::Message::Body::Lines
  cache_body                          NO
  cache_head                          NO or DELAY
  cache_labels                        NO or DELAY
  coerce_options     Mail::Box        +[]
  create             Mail::Box        false
  extract            Mail::Box        10240
  field_type         Mail::Box        undef
  fix_headers        Mail::Box        false
  folder             Mail::Box        /
  folderdir          Mail::Box        <network location>
  head_delayed_type  Mail::Box        Mail::Message::Head::Delayed
  head_type          Mail::Box        Mail::Box::IMAP4::Head or Mail::Message::Head::Complete
  join_connection                     true
  keep_dups          Mail::Box        false
  lock_file          Mail::Box        undef
  lock_timeout       Mail::Box        1 hour
  lock_type          Mail::Box        'NONE'
  lock_wait          Mail::Box        10 seconds
  locker             Mail::Box        undef
  manager            Mail::Box        undef
  message_type       Mail::Box        Mail::Box::IMAP4::Message
  multipart_type     Mail::Box        Mail::Message::Body::Multipart
  password           Mail::Box::Net   undef
  remove_when_empty  Mail::Box        <false>
  save_on_exit       Mail::Box        true
  server_name        Mail::Box::Net   undef
  server_port        Mail::Box::Net   143
  transporter                         Mail::Transport::IMAP4
  trusted            Mail::Box        <false>
  username           Mail::Box::Net   undef

okay now let's go one by one, no skipping, we're thorough in this house 🧚

  • access => $mode
  • body_delayed_type => CLASS
  • body_type => CLASS|CODE
  • cache_body => 'NO'|'YES'|'DELAY' β€” Body objects are immutable, but may still be cached or not. In the common case, the body of a message is requested via Mail::Message::body() or Mail::Message::decoded(). This returns a handle to a body object. You may decide whether that body object can be reused or not. "NO" means: retrieve the data each time again, "YES" will cache the body data, "DELAY" will send the whole message when the folder is closed.
 [local cache]  [write]
NO         no           no
YES        yes          no
DELAY      yes          yes
  • cache_head => 'NO'|'PARTIAL'|'DELAY' β€” For a read-only folder, "DELAY" is the default, otherwise "NO" is chosen. The four configuration parameter have subtile consequences. To start with a table:
 [local cache]  [write]  [default head_type]
NO         no           no     Mail::Box::IMAP4::Head
PARTIAL    yes          no     Mail::Box::IMAP4::Head
DELAY      yes          yes    Mail::Message::Head::Complete

The default head_type is Mail::Box::IMAP4::Head, the default cached_head_type is Mail::Message::Head::Complete.

Having a local cache means that a lookup for a field is first done in a local data-structure (which extends Mail::Message::Head::Partial), and only on the remote server if it was not found.

⚠️ this is dangerous, bestie, because your locally cached data can be out-of-sync with the server. However, it may give you a nice performance benefit. your call πŸ’€

"DELAY" will always collect the whole header for you. This is required when you want to look for Resent Groups (See Mail::Message::Head::ResentGroup) or other field order dependent header access. A Mail::Message::Head::Delayed will be created first.

  • cache_labels => 'NO'|'WRITE'|'DELAY' β€” When labels from a message are received, these values can be kept. However, this imposes dangers where the server's internal label storage may get out of sync with your data. πŸ™ˆ

With "NO", no caching will take place (but the performance will be worse). With "WRITE", all label access will be cached, but written to the server as well. Both "NO" and "WRITE" will update the labels on the served, even when the folder was opened read-only. "DELAY" will not write the changed information to the server, but delay that till the moment that the folder is closed. It only works when the folder is opened read/write or write is enforced.

The default is "DELAY" for folders which where opened read-only. This means that you still can force an update with close(write). For folders which are opened read-write, the default is the safeset setting, which is "NO".

  • coerce_options => ARRAY
  • create => BOOLEAN
  • extract => INTEGER|CODE|METHOD|'LAZY'|'ALWAYS'
  • field_type => CLASS
  • fix_headers => BOOLEAN
  • folder => $name
  • folderdir => $directory
  • head_delayed_type => CLASS
  • head_type => CLASS
  • join_connection => BOOLEAN β€” Within this Mail::Box::IMAP4 class is registered which transporters are already in use, i.e. which connections to the IMAP server are already in established. When this option is set, multiple folder openings on the same server will try to reuse one connection. sharing is caring 🫢
  • keep_dups => BOOLEAN
  • lock_file => $file
  • lock_timeout => $seconds
  • lock_type => CLASS|STRING|ARRAY
  • lock_wait => $seconds
  • locker => OBJECT
  • manager => $manager
  • message_type => CLASS
  • multipart_type => CLASS
  • password => $password
  • remove_when_empty => BOOLEAN
  • save_on_exit => BOOLEAN
  • server_name => $host
  • server_port => $number
  • transporter => $object|$class β€” The name of the $class which will interface with the connection. When you implement your own extension to Mail::Transport::IMAP4, you can either specify a fully instantiated transporter $object, or the name of your own $class. When an $object is given, most other options will be ignored. noted πŸ“
  • trusted => BOOLEAN
  • username => $username

Β» example:

 my $imap   = Mail::Box::IMAP4->new(username => 'myname',
    password => 'mypassword', server_name => 'imap.xs4all.nl');

 my $url    = 'imap4://user:password@imap.xs4all.nl';
 my $imap   = $mgr->open($url);

 my $client = Mail::IMAPClient->new(...);
 my $imap   = Mail::Box::IMAP4->new(imap_client => $client);

⭐ Attributes ⭐

Extends "Attributes" in Mail::Box::Net.

  • $obj->fixHeaders() β€” Inherited, see "Attributes" in Mail::Box
  • $obj->folderdir( [$directory] ) β€” Inherited, see "Attributes" in Mail::Box
  • $obj->isTrusted() β€” Inherited, see "Attributes" in Mail::Box
  • $obj->name() β€” Inherited, see "Attributes" in Mail::Box
  • $obj->removeEmpty() β€” Inherited, see "Attributes" in Mail::Box
  • $obj->type() β€” Inherited, see "Attributes" in Mail::Box

πŸ“ The folder πŸ“

Extends "The folder" in Mail::Box::Net.

  • $obj->addMessage($message, %options) β€” Inherited, see "The folder" in Mail::Box
  • $obj->addMessages(@messages) β€” Inherited, see "The folder" in Mail::Box
  • $class->appendMessages(%options) β€” Inherited, see "The folder" in Mail::Box

$obj->close(%options)

Close the folder. In the case of IMAP, more than one folder can use the same connection, therefore, closing a folder does not always close the connection to the server. Only when no folder is using the connection anymore, a logout will be invoked by Mail::Transport::IMAP4::DESTROY() Improves base, see "The folder" in Mail::Box

 -Option      --Defined in     --Default
  force         Mail::Box        false
  save_deleted  Mail::Box        false
  write         Mail::Box        'MODIFIED'
  • force => BOOLEAN
  • save_deleted => BOOLEAN
  • write => 'ALWAYS'|'NEVER'|'MODIFIED'
  • $obj->copyTo($folder, %options) β€” Inherited, see "The folder" in Mail::Box
  • $obj->delete(%options) β€” Inherited, see "The folder" in Mail::Box
  • $obj->organization() β€” Inherited, see "The folder" in Mail::Box
  • $obj->size() β€” Inherited, see "The folder" in Mail::Box

part 1 done bestie, don't go anywhere β€” more coming πŸ’–

  • $obj->update(%options) β€” inherited bestie, go read "The folder" in Mail::Box for the tea β˜•
  • $obj->url() β€” also inherited, still "The folder" in Mail::Box, same place, same vibes 🫢

🚩 Folder flags (no seriously, that's the section name)

Extends "Folder flags" in Mail::Box::Net. So everything below is the family recipe, adapted.

  • $obj->access() β€” inherited, see "Folder flags" in Mail::Box ✨
  • $obj->isModified() β€” inherited, see "Folder flags" in Mail::Box πŸ‘€
  • $obj->modified( [BOOLEAN] ) β€” inherited, see "Folder flags" in Mail::Box πŸ’…
  • $obj->writable() β€” inherited, see "Folder flags" in Mail::Box πŸŽ€

πŸ’Œ The messages

Extends "The messages" in Mail::Box::Net. All of these are hand-me-downs, and they're all serving looks:

  • $obj->current( [$number|$message|$message_id] ) β€” inherited, see "The messages" in Mail::Box
  • $obj->find($message_id) β€” inherited, see "The messages" in Mail::Box
  • $obj->findFirstLabeled( $label, [BOOLEAN, [\@msgs]] ) β€” inherited, see "The messages" in Mail::Box
  • $obj->message( $index, [$message] ) β€” inherited, see "The messages" in Mail::Box
  • $obj->messageId( $message_id, [$message] ) β€” inherited, see "The messages" in Mail::Box
  • $obj->messageIds() β€” inherited, see "The messages" in Mail::Box
  • $obj->messages( <'ALL'|$range|'ACTIVE'|'DELETED'|$label|!$label|$filter> ) β€” inherited, see "The messages" in Mail::Box
  • $obj->nrMessages(%options) β€” inherited, see "The messages" in Mail::Box
  • $obj->scanForMessages($message, $message_ids, $timespan, $window) β€” inherited, see "The messages" in Mail::Box

πŸ—‚ Sub-folders

Extends "Sub-folders" in Mail::Box::Net. Folders inside folders, it's giving inception, we love her:

  • $any->listSubFolders(%options) β€” inherited, see "Sub-folders" in Mail::Box
  • $any->nameOfSubFolder( $subname, [$parentname] ) β€” inherited, see "Sub-folders" in Mail::Box
  • $obj->openRelatedFolder(%options) β€” inherited, see "Sub-folders" in Mail::Box
  • $obj->openSubFolder($subname, %options) β€” inherited, see "Sub-folders" in Mail::Box
  • $any->topFolderWithMessages() β€” inherited, see "Sub-folders" in Mail::Box

πŸ”§ Internals

Extends "Internals" in Mail::Box::Net. The guts, the behind-the-scenes, the tech crew at the concert 🎀

  • $obj->body( [$body] ) β€” that's the whole entry, bestie. No note, no "inherited", nothing. It's just standing there, mysterious, main character energy 🌟
  • $obj->coerce($message, %options) β€” inherited, see "Internals" in Mail::Box
  • $any->create($folder, %options) β€” inherited, see "METHODS" in Mail::Box::Net
  • $obj->createTransporter($class, %options) β€” makes you a transporter object (an instance of Mail::Transport::IMAP4), where $class defines the exact object type. For %options, literally everything you can hand a transporter when you initiate it works β€” peep Mail::Transport::IMAP4::new().
 -Option         --Default
  join_connection  true
  • join_connection => BOOLEAN β€” See new(join_connection). When it's false, the connection will never be shared with other IMAP mail boxes. Solo era, no sharing, periodt 🚫
  • $obj->determineBodyType($message, $head) β€” inherited, see "Internals" in Mail::Box
  • $obj->fetch( <$messages|$selection>, $info ) β€” low-key data retrieval about one or more messages over IMAP4, straight from the remote server. Heads up though: some of this data may differ from the info stored in the message objects that MailBox creates, so fr fr, avoid using this method for your own purposes. The IMAP implementation wraps some helpers around this so you get the correct behavior β€” use those instead. πŸ™

You can hand it an ARRAY of $messages, or some message $selection that Mail::Box::messages() would accept. Examples of that second kind: 'ALL', 'DELETED', or "spam" (messages labelled to contain spam, iconic).

The $info holds one or more attributes as defined by the IMAP protocol. To actually see those, you gotta read the full specs of the related RFCs. No shortcuts, sorry πŸ’€

  • $class->foundIn( [$foldername], %options ) β€” inherited, see "Internals" in Mail::Box
  • $obj->getHead($message) β€” reads the header for the specified message from the remote server. If the message vanished, undef comes back at you 🫠
  • $obj->getHeadAndBody($message) β€” reads ALL the data for the specified message from the remote server. Returns head and body of the mesasge as a list, or an empty list if the $message disappeared from the server. (Also: yes, the original says "mesasge". We're keeping it, it's a typo that ate and left no crumbs 😭)
  • $obj->lineSeparator( [<STRING|'CR'|'LF'|'CRLF'>] ) β€” inherited, see "Internals" in Mail::Box
  • $obj->locker() β€” inherited, see "Internals" in Mail::Box
  • $obj->read(%options) β€” inherited, see "Internals" in Mail::Box
  • $obj->readMessages(%options) β€” inherited, see "Internals" in Mail::Box
  • $obj->storeMessage($message) β€” inherited, see "Internals" in Mail::Box
  • $obj->toBeThreaded($messages) β€” inherited, see "Internals" in Mail::Box
  • $obj->toBeUnthreaded($messages) β€” inherited, see "Internals" in Mail::Box
  • $obj->transporter( [$object] ) β€” returns the object that is the interface to the IMAP4 protocol handler. That IMAP4 handler has the current folder selected. If you specify an $object, it becomes the transporter from that moment on. That $object must extend Mail::Transport::IMAP4. πŸ”Œ
  • $obj->updateMessages(%options) β€” inherited, see "Internals" in Mail::Box
  • $obj->write(%options) β€” so the IMAP protocol usually writes the data to the remote server immediately, because that's literally what the protocol wants. But some options passed to new() may delay that for a performance boost. This method, when the folder is being closed, writes that info after all. Improves base, see "Internals" in Mail::Box.
 -Option      --Defined in     --Default
  force         Mail::Box        false
  save_deleted  Mail::Box        false
  • force => BOOLEAN
  • save_deleted => BOOLEAN
  • $obj->writeMessages(%options) β€” inherited, see "Internals" in Mail::Box
 -Option     --Defined in     --Default
  messages     Mail::Box        <required>
  transporter                   <required>
  • messages => ARRAY
  • transporter => OBJECT

🌈 Other methods

Extends "Other methods" in Mail::Box::Net.

  • $any->timespan2seconds($time) β€” inherited, see "Other methods" in Mail::Box

🚨 Error handling

Extends "Error handling" in Mail::Box::Net. When things go wrong, we still go off πŸ’…

  • $obj->AUTOLOAD() β€” inherited, see "Error handling" in Mail::Reporter
  • $obj->notImplemented() β€” inherited, see "Error handling" in Mail::Reporter

🧹 Cleanup

Extends "Cleanup" in Mail::Box::Net. Tidy up, close the tabs, hydrate 🧚

  • $obj->DESTROY() β€” inherited, see "Cleanup" in Mail::Box

πŸ“– DETAILS

Extends "DETAILS" in Mail::Box::Net.


🩺 DIAGNOSTICS

All the little messages this module might scream at you, and what they mean:

  • Warning: cannot find head back for $id in $folder. β€” The header was read before, but now it seems empty: the IMAP4 server does not produce the header lines anymore. Cast by getHeadAndBody()
  • Warning: cannot read body for $id in $folder. β€” The header of the message was retrieved from the IMAP4 server, but the body is not read, for an unknown reason. Cast by getHeadAndBody()
  • Error: class $package does not implement method $method. β€” Fatal error: the specific $package (or one of its superclasses) does not implement this method where it should. This means some other related classes do implement this method, but the class at hand does not. Probably you should investigate this and probably inform the author of the package. Cast by notImplemented()
  • Error: copying failed for one message. β€” For some reason β€” disk full, removed by external process, read-protection, whatever β€” it is impossible to copy one of the messages. Copying will proceed for the other messages. Cast by copyTo()
  • Error: couldn't select IMAP4 folder $name. β€” Cast by transporter()
  • Error: destination folder $name is not writable. β€” The folder where the messages are copied to is not opened with write access (see new(access)). This has no relation with write permission to the folder, which is controlled by your operating system. Cast by copyTo()
  • Warning: different messages with id $msgid. β€” The message id is discovered more than once within the same folder, but the content of the message seems to be different. This should not be possible: each message must be unique. Cast by messageId()
  • Warning: folder $name not deleted: not writable. β€” The folder must be opened with write access via new(access), otherwise removing it will be refused. So you may have write-access according to the operating system, but that will not automatically mean that this delete method permits you to. The reverse remark is valid as well. Cast by delete()
  • Notice: impossible to keep deleted messages in IMAP folder $name. β€” Some folder types have a 'deleted' flag which can be stored in the folder and performed later, and the folder keeps that knowledge even when the folder is rewritten. Well, IMAP4 cannot play that trick. Cast by write()
  • Error: invalid timespan '$span'. β€” The string does not follow the strict rules of the time span syntax which is permitted as parameter. Cast by timespan2seconds()
  • Warning: message $id disappeared from $folder. β€” Trying to get the specific message from the server, but it appears to be gone. Cast by getHeadAndBody()
  • Warning: message {id} disappeared from {folder}. β€” Trying to get the specific message from the server, but it appears to be gone. Cast by getHead()
  • Warning: message-id '$msgid' does not contain a domain. β€” According to the RFCs, message-ids need to contain a unique random part, then an "@", and then a domain name. This is made to avoid the creation of two messages with the same id. The warning emerges when the "@" is missing from the string. Cast by messageId()
  • Error: no IMAP4 transporter configured. β€” Cast by transporter()
  • Error: you cannot add a message which is already part of a folder to a new one. Please use moveTo or copyTo. β€” Cast by addMessage()

πŸ‘€ SEE ALSO

This module is part of Mail-Box-IMAP4 version 4.01, built on December 13, 2025. Website: http://perl.overmeer.net/CPAN/


πŸ“œ LICENSE

For contributors see file ChangeLog.

This software is copyright (c) 2001-2025 by Mark Overmeer.

This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.


okay that's the whole page bestie, we ate and left absolutely no crumbs πŸ’…βœ¨ This one's perl v5.40.1, dated 2026-01-21, and it lives in the Mail::Box::IMAP4(3pm) section of the manual β€” go forth and IMAP responsibly, ily πŸ«ΆπŸŽ€πŸ¦‹

πŸ“¦ where this page comes from