NAME
Mail::Box::Message - Manage one message within a mail-folder
SYNOPSIS
use Mail::Box::Message;
my $folder = new Mail::Box::Message 'text';
DESCRIPTION
Read Mail::Box::Manager first. This page also describes Mail::Box::Message::Runtime
, Mail::Box::Message::NotParsed
, Mail::Box::Message::NotReadHead
, and Mail::Box:Message::Dummy
.
These objects are used as base-classes for messages which are not totally read, are fully read, or to be written to some kind of folder.
During its life, a message will pass through certain stages. These stages were introduced to reduce the access-time to the folder. Changing from stage, the message changes from object-class (try to do this in any other language than Perl!).
Classes described in this manual-page
This page handles three types of messages:
Mail::Box::Message
A read message. This is a full decendent of MIME::Entity, with all information on the message and its parts stored in easily and fast accessible memory-structures.
Mail::Box::Message::NotParsed
This is a nearly ready-to-go message. When scanning a folder, the
lazy_extract
parameter ofMail::Box::new
determines which messages are directly parsed into a Mail::Box::Message, and which are not yet parsed.Messages which are not directly parsed into a real message object are stored as an Mail::Box::Message::NotParsed object. This object only contains a few important header-lines, and triggers to load the message for real on the moment other information on this message is needed.
Which header-lines are taken is determined by the
take_headers
parameter ofMail::Box::new
. Taking too few headers for your task will result in bad performance: all message will be read. When you take too many headers, this is bad for the memory usage of your program.Mail::Box::Message::Dummy
A message which is a place-holder in a thread description. This object-type is used to fill holes in the linked list of thread messages. See Mail::Box::Threads.
Two more classes are defined, to help the message-types to function properly:
Mail::Box::Message::Runtime
Data and functionality which is not stored in the folder, but is shared by various message-types (a real-message, a dummy, and a not-parsed)
Mail::Box::Message::NotReadHead
A header which is part of a Mail::Box::Message::NotParsed. It contains some header-lines, but far from all. It can trigger the not-parsed to load itself from the folder.
The bottom of this page provides more details about the implementation, but first the use.
CLASS Mail::Box::Message::Runtime
This class is a base for all kinds of messages. It defines the simularities between messages in various stages: dummy, not-parsed, or parsed.
- new ARGS
-
Initialize the runtime variables of a message. The following options are supported:
folder => FOLDER
(obligatory) The folder where this message appeared in. The argument is an instance of (a sub-class of) a Mail::Box.
size => INTEGER
The size of the message inclusive headers and accompanying lines (such as the `From' line in mboxes) in bytes.
messageID => STRING
The id on which this message can be recognized. If none specified, there will be one assigned to the message to be able to pass unique message-ids between objects.
modified => BOOL
Whether there are some modifications to the message from the start-on. For instance, new message will be flagged modified immediately.
deleted => BOOL
Is the file deleted from the start?
labels => [ STRING => VALUE, ... ]
Set the specified labels to their accompanying value. In most cases, this value will only be used as boolean, but it might be more complex.
- messageID
-
Retreive the message's id. Every message has a unique message-id. This id is used mainly for recognizing discussion threads.
- folder [FOLDER]
-
In with folder did we detect this message/dummy? This is a reference to the folder-object.
- size
-
Returns the size of the message, including headers.
Example:
print $folder->message(8)->size;
- isParsed
-
isParsed
checks whether the message is parsed (read from file). Returns true or false. Only a Mail::Box::Message will return true. - isDummy
-
isDummy
Checks whether the message is only found in a thread, but not (yet) in the folder. Only aMail::Box::Message::Dummy
will return true. - headIsRead
-
Checks if the head of the message is read. This is true for fully parsed messages and messages where the header was accessed once.
- modified [BOOL]
-
Check (or set, when an argument is supplied) that the message-contents has been changed by the program. This is used later, when the messages are written back to file.
Examples:
if($message->modified) {...} $message->modified(1);
- delete
-
Flag the message to be deleted. The real deletion only takes place on a synchronization of the folder.
Examples:
$message->delete; delete $message;
- deleted [BOOL]
-
Check or set the deleted flag for this message. This method returns undef (not deleted, false) or the time of deletion (true). With a BOOL argument, the status is changed first.
Examples:
if($message->deleted) {...} $message->deleted(0); # undelete
- seqnr [INTEGER]
-
Get (add set) the number of this message is the current folder.
- timestamp
-
Returns an indication on the moment that the message was originally sent. The exact value which is returned is operating-system dependent, but on UNIX systems will be in seconds since 1 January 1970.
Label management
Labels are used to store knowledge about handling of the message within the folder. Flags about whether a message was read, replied to, or (in some cases) scheduled for deletion.
- setLabel LIST
- label STRING [ ,STRING ,...]
-
Get the value related to the label(s). This returns a list of values, which may be empty, undefined, or a value which evaluates to TRUE.
Example:
if($message->label('seen')) {...} my ($seen, $current) = $msg->label('seen', 'current');
- labels
-
Returns all known labels. In SCALAR context, it returns the knowledge as reference to a hash. This is a reference to the original data, but you shall *not* change that data directly: call
setLabel()
for changes!In LIST context, you get a list of names which are defined. Be warned that they will not all evaluate to true, although most of them will.
- shortString
-
Convert the message header to a short string, representing the most important facts (for debugging purposes only).
- diskDelete
-
Remove a message from disk. This is not from the folder, but everything else, like parts of the message which are stored externally from the folder.
CLASS Mail::Box::Message
This object extends a MIME::Entity. This is the only object type defined in this set of packages which represents a real message (which parsed into memory, with access to all headers, and writeable)
METHODS
- new [OPTIONS]
-
Create a new message. The options available are taken from
Mail::Box::Message::Runtime::new()
, as described above.If you want to add a message to a folder, which is derived from some strange source, then you do:
use MIME::Parser; my $parser = MIME::Parser->new; my $entity = $parser->parse(@lines); $folder->addMessage($entity);
The
addMessage()
accepts anything what is based on Mail::Internet. - coerce FOLDER, MESSAGE [,OPTIONS]
-
(Class method) Coerce a MESSAGE into a Mail::Box::Message. This method is automatically called if you add a strange message-type to a FOLDER. You usually do not need to call this yourself.
The coerced message is returned on success, else
undef
.Example:
my $folder = Mail::Box::Mbox->new; my $entity = MIME::Entity->new(...); Mail::Box::MBox::Message->coerce($inbox, $entity); # now $entity is a Mail::Box::Mbox::Message
It better to use
$folder->coerce($entity);
which does exacty the same, by calling coerce in the right package.
- forceLoad
-
This method is called to signal that the message must be loaded, although the method only returns the folder.
- body
-
Call
body
to get the whole message-body in storable message format (multiparts are folded back into one message). This may be useful to print the whole message. If you want to access the message content, you should used "bodyhandle" or "parts" which are described below. - bodyhandle
-
Some messages are multi-parts, other are plain. Check which type of message you have (with
is_multipart
as described in MIME::Entity) before accessing its content.If the parsing of the folder was delayed (controlled by the `lazy_extract' option at folder-creation) this implies that the message-body is read from folder and parsed. This is performed automatically.
If you do not have a multipart message, you call
bodyhandle
, which returns a handle to a handle-type object which can be opened to read the body of the message.Example:
sub print_body($) { my ($self,$message) = @_; if($message->is_multipart) { $self->print_body($_) foreach $message->parts } else { $message->bodyhandle->print } }
- parts [ARRAY]
-
Some messages are multi-parts, other are plain. Check which type of message you have (with
is_multipart
as described in MIME::Entity) before accessing its content.If the parsing of the folder was delayed (controlled by the `lazy_extract' option at folder-creation) this implies that the message-body is read from folder and parsed. This is performed automatically.
When you do have a multipart message, you have to call
parts
to get a list of Mail::Box::Message objects, each representing one part of the message. Be warned that even such part can be split in nested parts. You can pass an array-reference with messages to set a new list of parts.See "body" and "bodyhandle" above.
- removePart PART|INDEX
-
Remove one part of the list of parts from this message. Specify a PART (Mail::Box::Message instance) or an index (sequence-number is list of parts)
- isPart
-
A part of a message is of the same type as the message itself. This call can distinguish between the two.
Mail::Box::Message::NotParsed
A message where most of the data still resides in the folder-file, is a 'message which is not read' (yet). This status is signalled by the type of the object.
METHODS
- new ARGS
-
Create a not-parsed message. The message can have a
not-read-head
, which means that only a few of the header-lines are kept, or a real MIME::Head to start with. - AUTOLOAD
-
When any method is called which can not be performed without parsing the whole folder message, Perl calls the autoloader. A check is performed to see if not anyone has accidentally an old message-handle: we may otherwise read the message twice.
- head
-
This function returns a Mail::Box::Message::NotReadHead object on which you may perform any actions as expected from MIME::Header object. Performing actions on a header which is part of a non-parsed message is complicated by the fact that we have some header-lines, but not all.
See "Mail::Box::Message::NotReadHead" below.
CLASS Mail::Box::Message::Dummy
A dummy message is a placeholder, for instance for messages in threads which are found in a reference-list, but not (yet) in the folder.
- new
-
(Class method) Create a new dummy message.
Examples:
my $message = Mail::Box::Message::Dummy->new($msgid); if($message->isDummy) {...}
CLASS Mail::Box::Message::NotReadHead
This object contains a few header-lines which were captured during the initial reading of the folder. It will also automagically load the messages on any other call to head
.
METHODS
See MIME::Header for all methods you can perform on this object. The following methods need extra consideration.
- new ARGS
-
(Class method) Called by the
Mail::Box::Message::NotParsed
methodnew
to store some header-lines which were capurtured during the initial reading through the folder file. See thetake_headers
option on how to add header-lines to this structure.The following parameters can be passed to new:
expect FIELDNAMES
(obligatory) Which fields will be taken from the folder-file. Even when we do not actually find all these fields, we still have to know when the message lacks the field, to avoid that the message is read from the folder to find-out that the line isn't there either.
- get TAG [, INDEX]
- get_all TAG
- count TAG
-
Overruled methods, which first check if we know about the header. In case we do, the values can be returned immediately. Otherwise we trigger the message to be read from the folder-file and then retry on the real Mail::Box::Message object.
- setField NAME, CONTENT
-
Store a content into a field. Do only specify fields which are defined with
expect
when this object was instantiated.You may add the same name more than once. In that case, the
get
method in list context (and theget_all
method) will return all definition in the order that they were added. For theReceived:
field in messages, that means that the most recently added line to the message is put first in the list (they are in reverse order in the mime-header. - message [MESSAGE]
-
Get (or check) the message to which this header belongs.
- AUTOLOAD
-
Load the message, then capture the real header, and finally calls the method on the what should have been called in the first place.
Example:
$message->head->get('some-field')
where $message is a
Mail::Box::Message::NotParsed
, will return aMail::Box::Message::NotReadHead
from itshead
call. A get of a previously captured header returns the right value, however in case not, the following steps are taken:get
callsAUTOLOAD
to get a new header.NotReadHead::AUTOLOAD
will callNotParsed::AUTOLOAD
to read the message.NotParsed::AUTOLOAD
reads the message from the folder and returns it to the header autoloader.The header autoloader calls the real
get
method of theMail::Box::Message
, as autoloaders should do.
IMPLEMENTATION
Extending MIME::Entity
Because reading MIME::Entity objects from file is quite time-consuming and memory flooding, this module actively tries to keep most messages in the folder-files where they are stored in un-parsed form. When a folder is opened, only some of the header-lines of the messages are taken and stored in objects. Not before the message is seriously used, the message is translated into a real MIME::Entity.
Delayed loading of messages
When a folder is read, the lazy_extract
option to Mail::Box::new
determines if the content of the message is to be parsed immediately into a Mail::Box::Message or should be left unparsed in the folder-file. In the latter case, a Mail::Box::Message::NotParsed is created.
Not-parsing messages improves the speed of folder reading, and reduce the memory footprint of your program considerably. However, it keeps the folder-file locked, so should not be used on the incoming messages mail-box.
The parsing of a message (reading the non-parsed messages from the folder file and translating it into Mail::Box::Message type objects) is automatically triggered when you access head-lines which were not specified in take_headers
when the folder was read, and when you call methods which are not defined on a non-parsed message.
State transition
Messages are detected when reading a folder, or composed by the user when it is sent by a used. The relationships shown below are only about reading existing folders.
unknown references
Mail::Box and reply-to's Mail::Box
finds message ---------------------> ::Message::Dummy
| |
v messages |
| |
| |
/ \was dummy |
| '--------------> merge <-----------'
| |
| |
\new |
`-->-----, ,-----<--'
lazy
extract?
yes/ \no
/ `--->-------,
v |
Mail::Box |
::Message::NotParsed |
| v
|serious use Mail::Box
`---------------->-- ::Message
Class structure for messages
As example, the next scheme uses the fake folder-type XYZ
, which may be for instance mbox
or MH
.
::XYZ::Message ::XYZ::NotParsed
| \ / |
| \ / |
^ ::XYZ::Runtime ^
| |
| |
::Message ::Message::Dummy ::Message
| ^ | ::NotParsed
| \ ^ ^
^ \ | /
| ::Message::Runtime
| |
MIME::Entity ^
| |
^ ::Thread
|
Mail::Internet
AUTHOR
Mark Overmeer (Mark@Overmeer.net). All rights reserved. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
VERSION
This code is beta, version 1.004