{
    "content": [
        {
            "type": "text",
            "text": "# Mail::Box::Thread::Manager (perldoc)\n\n## NAME\n\nMail::Box::Thread::Manager - maintain threads within a set of folders\n\n## SYNOPSIS\n\nmy $mgr     = Mail::Box::Manager->new;\nmy $folder  = $mgr->open(folder => '/tmp/inbox');\nmy $threads = $mgr->threads();\n$threads->includeFolder($folder);\nmy $threads = $msg->threads(folder => $folder);\nforeach my $thread ($threads->all) {\n$thread->print;\n}\n$threads->removeFolder($folder);\n\n## DESCRIPTION\n\nA (message-)*thread* is a message with links to messages which followed in reply of that\nmessage. And then the messages with replied to the messages, which replied the original message.\nAnd so on. Some threads are only one message long (never replied to), some threads are very\nlong.\n\n## Sections\n\n- **NAME**\n- **INHERITANCE**\n- **SYNOPSIS**\n- **DESCRIPTION**\n- **METHODS** (6 subsections)\n- **DETAILS** (2 subsections)\n- **DIAGNOSTICS**\n- **SEE ALSO**\n- **LICENSE**\n\nUse structuredContent.sections for detailed options, examples, and full documentation.\n"
        }
    ],
    "structuredContent": {
        "command": "Mail::Box::Thread::Manager",
        "section": "",
        "mode": "perldoc",
        "summary": "Mail::Box::Thread::Manager - maintain threads within a set of folders",
        "synopsis": "my $mgr     = Mail::Box::Manager->new;\nmy $folder  = $mgr->open(folder => '/tmp/inbox');\nmy $threads = $mgr->threads();\n$threads->includeFolder($folder);\nmy $threads = $msg->threads(folder => $folder);\nforeach my $thread ($threads->all) {\n$thread->print;\n}\n$threads->removeFolder($folder);",
        "tldr_summary": null,
        "tldr_examples": [],
        "tldr_source": null,
        "flags": [],
        "examples": [],
        "see_also": [],
        "section_outline": [
            {
                "name": "NAME",
                "lines": 2,
                "subsections": []
            },
            {
                "name": "INHERITANCE",
                "lines": 3,
                "subsections": []
            },
            {
                "name": "SYNOPSIS",
                "lines": 14,
                "subsections": []
            },
            {
                "name": "DESCRIPTION",
                "lines": 12,
                "subsections": []
            },
            {
                "name": "METHODS",
                "lines": 2,
                "subsections": [
                    {
                        "name": "Constructors",
                        "lines": 70
                    },
                    {
                        "name": "Grouping Folders",
                        "lines": 23
                    },
                    {
                        "name": "The Threads",
                        "lines": 44
                    },
                    {
                        "name": "Internals",
                        "lines": 22
                    },
                    {
                        "name": "Error handling",
                        "lines": 42
                    },
                    {
                        "name": "Cleanup",
                        "lines": 5
                    }
                ]
            },
            {
                "name": "DETAILS",
                "lines": 5,
                "subsections": [
                    {
                        "name": "Maintaining threads",
                        "lines": 28
                    },
                    {
                        "name": "Delayed thread detection",
                        "lines": 34
                    }
                ]
            },
            {
                "name": "DIAGNOSTICS",
                "lines": 6,
                "subsections": []
            },
            {
                "name": "SEE ALSO",
                "lines": 3,
                "subsections": []
            },
            {
                "name": "LICENSE",
                "lines": 5,
                "subsections": []
            }
        ],
        "sections": {
            "NAME": {
                "content": "Mail::Box::Thread::Manager - maintain threads within a set of folders\n",
                "subsections": []
            },
            "INHERITANCE": {
                "content": "Mail::Box::Thread::Manager\nis a Mail::Reporter\n",
                "subsections": []
            },
            "SYNOPSIS": {
                "content": "my $mgr     = Mail::Box::Manager->new;\nmy $folder  = $mgr->open(folder => '/tmp/inbox');\n\nmy $threads = $mgr->threads();\n$threads->includeFolder($folder);\n\nmy $threads = $msg->threads(folder => $folder);\n\nforeach my $thread ($threads->all) {\n$thread->print;\n}\n\n$threads->removeFolder($folder);\n",
                "subsections": []
            },
            "DESCRIPTION": {
                "content": "A (message-)*thread* is a message with links to messages which followed in reply of that\nmessage. And then the messages with replied to the messages, which replied the original message.\nAnd so on. Some threads are only one message long (never replied to), some threads are very\nlong.\n\nThe \"Mail::Box::Thread::Manager\" is very powerful. Not only is it able to do a descent job on\nMH-like folders (makes a trade-off between perfection and speed), it also can maintain threads\nfrom messages residing in different opened folders. Both facilities are rare for mail-agents.\nThe manager creates flexible trees with Mail::Box::Thread::Node objects.\n\nExtends \"DESCRIPTION\" in Mail::Reporter.\n",
                "subsections": []
            },
            "METHODS": {
                "content": "Extends \"METHODS\" in Mail::Reporter.\n",
                "subsections": [
                    {
                        "name": "Constructors",
                        "content": "Extends \"Constructors\" in Mail::Reporter.\n\nMail::Box::Thread::Manager->new(%options)\nA \"Mail::Box::Thread::Manager\" object is usually created by a Mail::Box::Manager. One\nmanager can produce more than one of these objects. One thread manager can combine messages\nfrom a set of folders, which may be partially overlapping with other objects of the same\ntype.\n\n-Option     --Defined in     --Default\ndummytype                    Mail::Message::Dummy\nfolder                        [ ]\nfolders                       [ ]\nlog          Mail::Reporter   'WARNINGS'\nthreadbody                   <false>\nthreadtype                   Mail::Box::Thread::Node\ntimespan                      '3 days'\ntrace        Mail::Reporter   'WARNINGS'\nwindow                        10\n\ndummytype => CLASS\nThe type of dummy messages. Dummy messages are used to fill holes in detected threads:\nreferred to by messages found in the folder, but itself not in the folder.\n\nfolder => FOLDER | REF-ARRAY-FOLDERS\nSpecifies which folders are to be covered by the threads. You can specify one or more open\nfolders. When you close a folder, the manager will automatically remove the messages of\nthat folder from your threads.\n\nfolders => FOLDER | REF-ARRAY-FOLDERS\nEquivalent to the \"folder\" option.\n\nlog => LEVEL\nthreadbody => BOOLEAN\nMay thread-detection be based on the content of a message? This has a serious performance\nimplication when there are many messages without \"In-Reply-To\" and \"References\" headers in\nthe folder, because it will cause many messages to be parsed. NOT IMPLEMENTED YET.\n\nthreadtype => CLASS\nType of the thread nodes.\n\ntimespan => TIME | 'EVER'\nSpecify how fast threads usually work: the amount of time between an answer and a reply.\nThis is used in combination with the \"window\" option to determine when to give-up filling\nthe holes in threads.\n\nSee Mail::Box::timespan2seconds() for the possibilities for TIME. With 'EVER', the search\nfor messages in a thread will only be limited by the window-size.\n\ntrace => LEVEL\nwindow => INTEGER|'ALL'\nThe thread-window describes how many messages should be checked at maximum to fill `holes'\nin threads for folder which use delay-loading of message headers.\n\nThe constant 'ALL' will cause thread-detection not to stop trying to fill holes, but\ncontinue looking until the first message of the folder is reached. Gives the best quality\nresults, but may perform bad.\n\nexample:\n\nuse Mail::Box::Manager;\nmy $mgr     = Mail::Box::Manager->new;\nmy $inbox   = $mgr->open(folder => $ENV{MAIL});\nmy $read    = $mgr->open(folder => 'Mail/read');\nmy $threads = $mgr->threads(folders => [$inbox, $read]);\n\n# longer alternative for last line:\nmy $threads = $mgr->threads;\n$threads->includeFolder($inbox);\n$threads->includeFolder($read);\n"
                    },
                    {
                        "name": "Grouping Folders",
                        "content": "$obj->folders()\nReturns the folders as managed by this threader.\n\n$obj->includeFolder($folders)\nAdd one or more folders to the list of folders whose messages are organized in the threads\nmaintained by this object. Duplicated inclusions will not cause any problems.\n\nFrom the folders, the messages which have their header lines parsed (see Mail::Box about\nlazy extracting) will be immediately scanned. Messages of which the header is known only\nlater will have to report this (see toBeThreaded()).\n\nexample:\n\n$threads->includeFolder($inbox, $draft);\n\n$obj->removeFolder($folders)\nRemove one or more folders from the list of folders whose messages are organized in the\nthreads maintained by this object.\n\nexample:\n\n$threads->removeFolder($draft);\n"
                    },
                    {
                        "name": "The Threads",
                        "content": "$obj->all()\nReturns all messages which start a thread. The list may contain dummy messages and messages\nwhich are scheduled for deletion.\n\nTo be able to return all threads, thread construction on each message is performed first,\nwhich may be slow for some folder-types because is will enforce parsing of message-bodies.\n\n$obj->known()\nReturns the list of all messages which are known to be the start of a thread. Threads\ncontaining messages which where not read from their folder (like often happens MH-folder\nmessages) are not yet known, and hence will not be returned.\n\nThe list may contain dummy messages, and messages which are scheduled for deletion. Threads\nare detected based on explicitly calling inThread() and thread() with a messages from the\nfolder.\n\nBe warned that, each time a message's header is read from the folder, the return of the\nmethod can change.\n\n$obj->sortedAll( [$prepare, [$compare]] )\nReturns all() the threads by default, but sorted on timestamp.\n\n$obj->sortedKnown( [$prepare, [$compare]] )\nReturns all known() threads, in sorted order. By default, the threads will be sorted on\ntimestamp, But a different $compare method can be specified.\n\n$obj->thread($message)\nReturns the thread where this $message is the start of. However, there is a possibility that\nthis message is a reply itself.\n\nUsually, all messages which are in reply of this message are dated later than the specified\none. All headers of messages later than this one are getting parsed first, for each folder\nin this threads-object.\n\nexample:\n\nmy $threads = $mgr->threads(folder => $inbox);\nmy $thread  = $threads->thread($inbox->message(3));\nprint $thread->string;\n\n$obj->threadStart($message)\nBased on a message, and facts from previously detected threads, try to build solid knowledge\nabout the thread where this message is in.\n"
                    },
                    {
                        "name": "Internals",
                        "content": "$obj->createDummy($messageid)\nGet a replacement message to be used in threads. Be warned that a dummy is not a member of\nany folder, so the program working with threads must test with Mail::Message::isDummy()\nbefore trying things only available to real messages.\n\n$obj->inThread($message)\nCollect the thread-information of one message. The `In-Reply-To' and `Reference'\nheader-fields are processed. If this method is called on a message whose header was not read\nyet (as usual for MH-folders, for instance) the reading of that header will be triggered\nhere.\n\n$obj->outThread($message)\nRemove the message from the thread-infrastructure. A message is replaced by a dummy.\n\n$obj->toBeThreaded($folder, @messages)\nInclude the specified messages in/from the threads managed by this object, if this folder is\nmaintained by this thread-manager.\n\n$obj->toBeUnthreaded($folder, @messages)\nRemove the specified @messages in/from the threads managed by this object, if this folder is\nmaintained by this thread-manager.\n"
                    },
                    {
                        "name": "Error handling",
                        "content": "Extends \"Error handling\" in Mail::Reporter.\n\n$obj->AUTOLOAD()\nInherited, see \"Error handling\" in Mail::Reporter\n\n$obj->addReport($object)\nInherited, see \"Error handling\" in Mail::Reporter\n\n$obj->defaultTrace( [$level]|[$loglevel, $tracelevel]|[$level, $callback] )\nMail::Box::Thread::Manager->defaultTrace( [$level]|[$loglevel, $tracelevel]|[$level, $callback]\n)\nInherited, see \"Error handling\" in Mail::Reporter\n\n$obj->errors()\nInherited, see \"Error handling\" in Mail::Reporter\n\n$obj->log( [$level, [$strings]] )\nMail::Box::Thread::Manager->log( [$level, [$strings]] )\nInherited, see \"Error handling\" in Mail::Reporter\n\n$obj->logPriority($level)\nMail::Box::Thread::Manager->logPriority($level)\nInherited, see \"Error handling\" in Mail::Reporter\n\n$obj->logSettings()\nInherited, see \"Error handling\" in Mail::Reporter\n\n$obj->notImplemented()\nInherited, see \"Error handling\" in Mail::Reporter\n\n$obj->report( [$level] )\nInherited, see \"Error handling\" in Mail::Reporter\n\n$obj->reportAll( [$level] )\nInherited, see \"Error handling\" in Mail::Reporter\n\n$obj->trace( [$level] )\nInherited, see \"Error handling\" in Mail::Reporter\n\n$obj->warnings()\nInherited, see \"Error handling\" in Mail::Reporter\n"
                    },
                    {
                        "name": "Cleanup",
                        "content": "Extends \"Cleanup\" in Mail::Reporter.\n\n$obj->DESTROY()\nInherited, see \"Cleanup\" in Mail::Reporter\n"
                    }
                ]
            },
            "DETAILS": {
                "content": "This module implements thread-detection on a folder. Messages created by the better mailers will\ninclude \"In-Reply-To\" and \"References\" lines, which are used to figure out how messages are\nrelated. If you prefer a better thread detection, they are implementable, but there may be a\nserious performance hit (depends on the type of folder used).\n",
                "subsections": [
                    {
                        "name": "Maintaining threads",
                        "content": "A \"Mail::Box::Thread::Manager\" object is created by the Mail::Box::Manager, using\nMail::Box::Manager::threads(). Each object can monitor the thread-relations between messages in\none or more folders. When more than one folder is specified, the messages are merged while\nreading the threads, although nothing changes in the folder-structure. Adding and removing\nfolders which have to be maintained is permitted at any moment, although may be quite costly in\nperformance.\n\nAn example of the maintained structure is shown below. The Mail::Box::Manager has two open\nfolders, and a thread-builder which monitors them both. The combined folders have two threads,\nthe second is two long (msg3 is a reply on msg2). Msg2 is in two folders at once.\n\nmanager\n|    \\\n|     `----------- threads\n|                  |     |\n|                thread thread---thread\n|                  |    /|        /\n|                  |   //        /\n+---- folder1      |  //        /\n|       |         /  //        /\n|       `-----msg1  //        /\n|       `-----msg2-'/        /\n|                  /        /\n`-----folder2     /        /\n|        /        /\n`-----msg2       /\n`-----msg3------'\n"
                    },
                    {
                        "name": "Delayed thread detection",
                        "content": "With all() you get the start-messages of each thread of this folder. When that message was not\nfound in the folder (not saved or already removed), you get a message of the dummy-type. These\nthread descriptions are in perfect state: all messages of the folder are included somewhere, and\neach missing message of the threads (*holes*) are filled by dummies.\n\nHowever, to be able to detect all threads it is required to have the headers of all messages,\nwhich is very slow for some types of folders, especially MH and IMAP folders.\n\nFor interactive mail-readers, it is preferred to detect threads only on messages which are in\nthe viewport of the user. This may be sloppy in some situations, but everything is preferable\nover reading an MH mailbox with 10k e-mails to read only the see most recent messages.\n\nIn this object, we take special care not to cause unnecessary parsing (loading) of messages.\nThreads will only be detected on command, and by default only the message headers are used.\n\nThe following reports the Mail::Box::Thread::Node which is related to a message:\n\nmy $thread = $message->thread;\n\nWhen the message was not put in a thread yet, it is done now. But, more work is done to return\nthe best thread. Based on various parameters, which where specified when the folder was created,\nthe method walks through the folder to fill the holes which are in this thread.\n\nWalking from back to front (recently arrived messages are usually in the back of the folder),\nmessage after message are triggered to be included in their thread. At a certain moment, the\nwhole thread of the requested method is found, a certain maximum number of messages was tried,\nbut that didn't help (search window bound reached), or the messages within the folder are\ngetting too old. Then the search to complete the thread will end, although more messages of them\nmight have been in the folder: we don't scan the whole folder for performance reasons.\n\nFinally, for each message where the head is known, for instance for all messages in\nmbox-folders, the correct thread is determined immediately. Also, all messages where the head\nget loaded later, are automatically included.\n"
                    }
                ]
            },
            "DIAGNOSTICS": {
                "content": "Error: Package $package does not implement $method.\nFatal error: the specific package (or one of its superclasses) does not implement this\nmethod where it should. This message means that some other related classes do implement this\nmethod however the class at hand does not. Probably you should investigate this and probably\ninform the author of the package.\n",
                "subsections": []
            },
            "SEE ALSO": {
                "content": "This module is part of Mail-Box distribution version 3.009, built on August 18, 2020. Website:\nhttp://perl.overmeer.net/CPAN/\n",
                "subsections": []
            },
            "LICENSE": {
                "content": "Copyrights 2001-2020 by [Mark Overmeer]. For other contributors see ChangeLog.\n\nThis program is free software; you can redistribute it and/or modify it under the same terms as\nPerl itself. See http://dev.perl.org/licenses/\n",
                "subsections": []
            }
        }
    }
}