The London Perl and Raku Workshop takes place on 26th Oct 2024. If your company depends on Perl, please consider sponsoring and/or attending.

NAME

Mail::Box::MH::Message - a message in a MH-folder

SYNOPSIS

   my $folder = new Mail::Box::MH ...
   my $message = $folder->message(10);

DESCRIPTION

This manual-page describes the classes Mail::Box::MH::Message, Mail::Box::MH::Parsed, and Mail::Box::MH::NotParsed. These objects are used to store messages which are not totally read, fully read, or to be written to a Mail::Box::MH type 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!).

All information which is required during the full life-span of the message is stored in a Mail::Box::MH::Message, which is extended by the Mail::Box::MH::NotParsed and the Mail::Box::MH::Parsed. The last object (Mail::Box::MH::NotReadHead) maintains some header-lines of the message.

The bottom of this page provides more details about details about the implementation, but first the use.

CLASS Mail::Box::MH::Message

This object contains methods which are part of as well delay-loaded (not-parsed) as loaded messages, but not general for all folders.

METHODS

new ARGS

Messages in directory-based folders use the following extra options for creation:

  • filename => FILENAME

    The file where the message is stored in.

Write one message to a file-handle. Unmodified messages are taken from the folder-file where they were stored in. Modified messages are written as in memory. Specify a file-handle to write TO (defaults to STDOUT).

printIndex [FILEHANDLE]

Print the information of this message which is required to maintain an index-file. By default, this prints to STDOUT.

readIndex CLASS [,FILEHANDLE]

Read the headers of one message from the index into a CLASS structure. CLASS is (a sub-class of) a MIME::Head. If no FILEHANDLE is specified, the data is read from STDIN.

filename [FILENAME]

Returns the name of the file in which this message is actually stored. This will return undef when the message is not stored in a file.

CLASS Mail::Box::MH::Parsed

This object extends a Mail::Box::Message with extra tools and facts on what is special to messages in file-based folders, with respect to messages in other types of folders.

METHODS

coerce FOLDER, MESSAGE [,OPTIONS]

(Class method) Coerce a MESSAGE into a Mail::Box::MH::Parsed, ready to be stored in FOLDER. When any message is offered to be stored in the mailbox, it first should have all fields which are specific for MH-folders.

The coerced message is returned on success, else undef.

Example:

   my $mh = Mail::Box::MH->new(...);
   my $message = Mail::Box::Mbox::Message->new(...);
   Mail::Box::MH::Parsed->coerce($mh, $message);
   # Now $message is ready to be stored in $mh.

However, you can better use

   $mh->coerce($message);

which will call coerce on the right message type for sure.

CLASS Mail::Box::MH::NotParsed

Not parsed messages stay in the file until the message is used. Because this folder structure uses many messages in the same file, the byte-locations are remembered.

METHODS

load CLASS [, ARRAY-OF-LINES]

This method is called by the autoloader then the data of the message is required. If you specified REAL for the take_headers option for new(), you did have a MIME::Head in your hands, however this will be destroyed when the whole message is loaded.

If an array of lines is provided, that is parsed as message. Otherwise, the file of the message is opened and parsed.

Get the head of the message. This may return immediately, because the head is already read. However, when we do not have a header yet, we read the message. At this moment, the lazy_extract option of new comes into action: will we read the whole message now, or only the header?

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.

messageID

Retreive the message's id. Every message has a unique message-id. This id is used mainly for recognizing discussion threads.

IMPLEMENTATION

The user of a folder gets his hand on a message-object, and is not bothered with the actual data which is stored in the object at that moment. As implementor of a mail-package, you might be.

A message is simple to use, but has a quite complex class structure. A message is not a real message from the start, but only if you access the body from it. Till then, you only have a hollow placeholder. Below is depicted how the internal status of a message-object changes based on actions on the object and parameters.

The inheritance relation is like this:

     read()
     =====#
          V              load()
       ::MH::NotParsed ========> ::MH::Parsed
           |       \               /    |
           ^        \             /     ^
           |          ::MH::Message     |
           |                            |
         ::Message                ::Message
        ::NotParsed                ::Parsed
                \                  /    |
                 `--- ::Message --'     ^
                           |            |
                           ^        MIME::Entity
                           |            |
                       ::Thread         ^
                                        |
                                    Mail::Internet

The Mail::Box::MH::Parsed stage, means that the whole message is in memory. It then is a full decendent of a MIME::Entity. But at the same time, it consumes a considerable amount of memory, and spent quite some processor time. All the intermediate stati are created to avoid full loading, so to be cheap in memory and time. Random folder access will be much faster by this strategy, under normal circumstances.

For trained eyes only the transition diagram:

   read()     !lazy && !DELAY
   -------> +----------------------------------> Mail::Box::
            |                                    MH::Parsed
            | lazy && !DELAY && !index                ^
            +--------------.                          |
            |           \   \    NotParsed    load    |
            |            \   `-> NotReadHead ------>-'|
            |        REAL \                           |
            |              \                          |
            | index         v    NotParsed    load    |
            +------------------> MIME::Head ------->-'|
            |                       ^                 |
            |                       |                 |
            |                       |load_head        |
            |                       |                 |
            | DELAY && !index    NotParsed    load    |
            +------------------> <no head> -------->--'


         ,-------------------------+---.
        |                      ALL |   | regexps && taken
        v                          |   |
   NotParsed    head()    get()   /   /
   NotReadHead --------> ------->+---'
             \          \         \
              \ other()  \ other() \regexps && !taken
               \          \         \
                \          \         \    load    Mail::Box::
                 `----->----+---------+---------> MH::Parsed

         ,---------------.
        |                |
        v                |
   NotParsed     head()  |
   MIME::Head -------->--'
            \                           Mail::Box::
             `------------------------> MH::Parsed


                            load_head   NotParsed
                           ,----------> MIME::Head
                          /
   NotParsed    head()   / lazy
   <no head>  --------->+
                         \ !lazy
                          \
                           `-----------> Mail::Box::
                             load        MH::Parsed

Terms: lazy refers to the evaluation of the lazy_extract() option. The load and load_head are triggers to the AUTOLOAD mothods. All terms like head() refer to method-calls. The index is true if there is an index-file kept, and the message-header found in there seems still valid (see the keep_index option of new()).

Finally, ALL, REAL, DELAY (default), and regexps refer to values of the take_headers option of new(). Notice that take_headers on DELAY is more important than lazy_extract.

Hm... not that easy... Happily, the implementation takes fewer lines than the documentation.

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.3.19