SYNOPSIS

 my $mgr     = Mail::Box::Thread::Manager->new;
 my $folder  = $mgr->open(folder => '/tmp/inbox');
 my $threads = $mgr->threads(folder => $folder);
 my $threads = $mgr->threads($folder);   # same

 foreach my $thread ($threads->all) {
     $thread->print;
 }

 $threads->includeFolder($folder);
 $threads->removeFolder($folder);

See SYNOPSIS in Mail::Reporter

DESCRIPTION

A (message-)thread is a message with links to messages which followed in reply of that message. And then the messages with replied to the messages, which replied the original message. And so on. Some threads are only one message long (never replied to), some threads are very long.

The Mail::Box::Thread::Manager is very powerful. Not only is it able to do a descent job on MH-like folders (makes a trade-off between perfection and speed), it also can maintain threads from messages residing in different opened folders. Both facilities are rare for mail-agents. The manager creates flexible trees with Mail::Box::Thread::Node objects.

See DESCRIPTION in Mail::Reporter

DETAILS

This module implements thread-detection on a folder. Messages created by the better mailers will include In-Reply-To and References lines, which are used to figure out how messages are related. If you prefer a better thread detection, they are implementable, but there may be a serious performance hit (depends on the type of folder used).

Maintaining threads

A Mail::Box::Thread::Manager object is created by the Mail::Box::Manager, using Mail::Box::Manager::threads(). Each object can monitor the thread-relations between messages in one or more folders. When more than one folder is specified, the messages are merged while reading the threads, although nothing changes in the folder-structure. Adding and removing folders which have to be maintained is permitted at any moment, although may be quite costly in performance.

An example of the maintained structure is shown below. The Mail::Box::Manager has two open folders, and a thread-builder which monitors them both. The combined folders have two threads, the second is two long (msg3 is a reply on msg2). Msg2 is in two folders at once.

       manager
        |    \
        |     `----------- threads
        |                  |     |
        |                thread thread---thread
        |                  |    /|        /
        |                  |   //        /
        +---- folder1      |  //        /
        |       |         /  //        /
        |       `-----msg1  //        /
        |       `-----msg2-'/        /
        |                  /        /
        `-----folder2     /        /
                |        /        /
                `-----msg2       /
                `-----msg3------'

Delayed thread detection

With all() you get the start-messages of each thread of this folder. When that message was not found in the folder (not saved or already removed), you get a message of the dummy-type. These thread descriptions are in perfect state: all messages of the folder are included somewhere, and each missing message of the threads (holes) are filled by dummies.

However, to be able to detect all threads it is required to have the headers of all messages, which is very slow for some types of folders, especially MH and IMAP folders.

For interactive mail-readers, it is preferred to detect threads only on messages which are in the viewport of the user. This may be sloppy in some situations, but everything is preferable over reading an MH mailbox with 10k e-mails to read only the see most recent messages.

In this object, we take special care not to cause unnecessary parsing (loading) of messages. Threads will only be detected on command, and by default only the message headers are used.

The following reports the Mail::Box::Thread::Node which is related to a message:

 my $thread = $message->thread;

When the message was not put in a thread yet, it is done now. But, more work is done to return the best thread. Based on various parameters, which where specified when the folder was created, the method walks through the folder to fill the holes which are in this thread.

Walking from back to front (recently arrived messages are usually in the back of the folder), message after message are triggered to be included in their thread. At a certain moment, the whole thread of the requested method is found, a certain maximum number of messages was tried, but that didn't help (search window bound reached), or the messages within the folder are getting too old. Then the search to complete the thread will end, although more messages of them might have been in the folder: we don't scan the whole folder for performance reasons.

Finally, for each message where the head is known, for instance for all messages in mbox-folders, the correct thread is determined immediately. Also, all messages where the head get loaded later, are automatically included.