
=head1 NAME


Mail::Box::Mbox - handle folders in Mbox format

=head1 CLASS INHERITANCE

Mail::Box::Mbox
   is a Mail::Box
   is a Mail::Reporter

=head1 SYNOPSIS


 use Mail::Box::Mbox;
 my $folder = Mail::Box::Mbox->new(folder => $ENV{MAIL}, ...);

=head1 DESCRIPTION


This documentation describes how Mbox mailboxes work, and also describes
what you can do with the Mbox folder object Mail::Box::Mbox.

=head1 METHODS

=head2 Initiation

=over 4

=item B<new> OPTIONS X<new>

 OPTION               DEFAULT
 access               'r'
 body_delayed_type    'Mail::Message::Body::Delayed'
 body_type            <see description>
 coerce_options       []
 create               <false>
 extract              10240
 field_type           undef
 folder               $ENV{MAIL}
 folderdir            $ENV{HOME}.'/Mail'
 head_delayed_type    'Mail::Message::Head::Delayed'
 head_type            'Mail::Message::Head::Complete'
 head_wrap            72
 keep_dups            <false>
 lock_extension       '.lock'
 lock_file            foldername.lock-extension
 lock_timeout         1 hour
 lock_type            'Mail::Box::Locker::DotLock'
 lock_wait            10 seconds
 locker               undef
 log                  'WARNINGS'
 manager              undef
 message_type         'Mail::Box::Mbox::Message'
 multipart_type       'Mail::Message::Body::Multipart'
 remove_when_empty    <true>
 save_on_exit         <true>
 subfolder_extension  '.d'
 trace                'WARNINGS'
 trusted              <depends on folder location>
 write_policy         undef

=over 4

=item B<access> =E<gt> MODE

See Mail::Box::new(access)

=item B<body_delayed_type> =E<gt> CLASS

See Mail::Box::new(body_delayed_type)

=item B<body_type> =E<gt> CLASS|CODE X<new(body_type)>

The C<body_type> option for Mbox folders defaults to

 sub determine_body_type($$)
 {   my $head = shift;
     my $size = shift || 0;
     'Mail::Message::Body::' . ($size > 10000 ? 'File' : 'Lines');
 }

which will cause messages larger than 10kB to be stored in files, and
smaller files in memory.

=item B<coerce_options> =E<gt> ARRAY

See Mail::Box::new(coerce_options)

=item B<create> =E<gt> BOOLEAN

See Mail::Box::new(create)

=item B<extract> =E<gt> INTEGER | CODE | METHOD | 'LAZY'|'ALWAYS'

See Mail::Box::new(extract)

=item B<field_type> =E<gt> CLASS

See Mail::Box::new(field_type)

=item B<folder> =E<gt> FOLDERNAME

See Mail::Box::new(folder)

=item B<folderdir> =E<gt> DIRECTORY

See Mail::Box::new(folderdir)

=item B<head_delayed_type> =E<gt> CLASS

See Mail::Box::new(head_delayed_type)

=item B<head_type> =E<gt> CLASS

See Mail::Box::new(head_type)

=item B<head_wrap> =E<gt> INTEGER

See Mail::Box::new(head_wrap)

=item B<keep_dups> =E<gt> BOOLEAN

See Mail::Box::new(keep_dups)

=item B<lock_extension> =E<gt> FILENAME|STRING X<new(lock_extension)>

When the dotlock locking mechanism is used, the lock is created by
the creation of a file.  For Mail::Box::Mbox type of folders, this
file is by default named the same as the folder-file itself, followed by
C<.lock>.

You may specify an absolute filename, a relative (to the folder's
directory) filename, or an extension (preceded by a dot).  So valid
examples are:

 .lock                  # append to filename
 my_own_lockfile.test   # full filename, same dir
 /etc/passwd            # somewhere else

=item B<lock_file> =E<gt> FILENAME

See Mail::Box::new(lock_file)

=item B<lock_timeout> =E<gt> SECONDS

See Mail::Box::new(lock_timeout)

=item B<lock_type> =E<gt> CLASS|STRING

See Mail::Box::new(lock_type)

=item B<lock_wait> =E<gt> SECONDS

See Mail::Box::new(lock_wait)

=item B<locker> =E<gt> OBJECT

See Mail::Box::new(locker)

=item B<log> =E<gt> LEVEL

See Mail::Reporter::new(log)

=item B<manager> =E<gt> MANAGER

See Mail::Box::new(manager)

=item B<message_type> =E<gt> CLASS

See Mail::Box::new(message_type)

=item B<multipart_type> =E<gt> CLASS

See Mail::Box::new(multipart_type)

=item B<remove_when_empty> =E<gt> BOOLEAN

See Mail::Box::new(remove_when_empty)

=item B<save_on_exit> =E<gt> BOOLEAN

See Mail::Box::new(save_on_exit)

=item B<subfolder_extension> =E<gt> STRING X<new(subfolder_extension)>

Mail folders which store their messages in files usually do not
support sub-folders, as do mail folders which store messages
in a directory.

However, this module can simulate sub-directories if the user wants it to.
When a subfolder of folder C<xyz> is created, we create a directory which
is called C<xyz.d> to contain them.  This extension C<.d> can be changed
using this option.

=item B<trace> =E<gt> LEVEL

See Mail::Reporter::new(trace)

=item B<trusted> =E<gt> BOOLEAN

See Mail::Box::new(trusted)

=item B<write_policy> =E<gt> 'REPLACE'|'INPLACE'|undef X<new(write_policy)>

Sets the default write policy.  See the C<policy> option to write().

=back

=back

=head2 Opening folders

=over 4

=item B<clone> OPTIONS

See Mail::Box::clone()

=item B<create> FOLDERNAME, OPTIONS X<create>

 OPTION               DEFAULT
 folderdir            undef
 subfolder_extension  undef

=over 4

=item B<folderdir> =E<gt> DIRECTORY

See Mail::Box::create(folderdir)

=item B<subfolder_extension> =E<gt> STRING X<create(subfolder_extension)>

=back

=item B<folderdir> [DIRECTORY]

See Mail::Box::folderdir()

=item B<foundIn> [FOLDERNAME] [,OPTIONS] X<foundIn>

If no FOLDERNAME is specified, then the C<folder> option is taken.

 OPTION               DEFAULT
 folder               undef
 folderdir            undef
 subfolder_extension  <from object>

=over 4

=item B<folder> =E<gt> FOLDERNAME X<foundIn(folder)>

=item B<folderdir> =E<gt> DIRECTORY

See Mail::Box::foundIn(folderdir)

=item B<subfolder_extension> =E<gt> STRING X<foundIn(subfolder_extension)>

=back

=back

=head2 On open folders

=over 4

=item B<addMessage> MESSAGE

See Mail::Box::addMessage()

=item B<addMessages> MESSAGE [, MESSAGE, ...]

See Mail::Box::addMessages()

=item B<copyTo> FOLDER, OPTIONS

See Mail::Box::copyTo()

=item B<filename>  X<filename>

Returns the filename for this folder.

Examples:

 print $folder->filename;

=item B<modified> [BOOLEAN]

See Mail::Box::modified()

=item B<name> 

See Mail::Box::name()

=item B<organization> 

See Mail::Box::organization()

=item B<update> OPTIONS

See Mail::Box::update()

=item B<writable> 

See Mail::Box::writable()

=back

=head2 Closing the folder

=over 4

=item B<DESTROY> 

See Mail::Box::DESTROY()

=item B<close> OPTIONS

See Mail::Box::close()

=item B<delete> 

See Mail::Box::delete()

=back

=head2 The messages

=over 4

=item B<current> [NUMBER|MESSAGE|MESSAGE-ID]

See Mail::Box::current()

=item B<find> MESSAGE-ID

See Mail::Box::find()

=item B<message> INDEX [,MESSAGE]

See Mail::Box::message()

=item B<messageId> MESSAGE-ID [,MESSAGE]

See Mail::Box::messageId()

=item B<messageIds> 

See Mail::Box::messageIds()

=item B<messages> ['ALL',RANGE,'ACTIVE','DELETED',LABEL,!LABEL,FILTER]

See Mail::Box::messages()

=item B<scanForMessages> MESSAGE, MESSAGE-IDS, TIMESTAMP, WINDOW

See Mail::Box::scanForMessages()

=back

=head2 Sub-folders

=over 4

=item B<listSubFolders> OPTIONS X<listSubFolders>

 OPTION               DEFAULT
 check                <false>
 folder               <obligatory>
 folderdir            <from folder>
 skip_empty           <false>
 subfolder_extension  <from object>

=over 4

=item B<check> =E<gt> BOOLEAN

See Mail::Box::listSubFolders(check)

=item B<folder> =E<gt> FOLDERNAME

See Mail::Box::listSubFolders(folder)

=item B<folderdir> =E<gt> DIRECTORY

See Mail::Box::listSubFolders(folderdir)

=item B<skip_empty> =E<gt> BOOL

See Mail::Box::listSubFolders(skip_empty)

=item B<subfolder_extension> =E<gt> STRING X<listSubFolders(subfolder_extension)>

=back

=item B<openRelatedFolder> OPTIONS

See Mail::Box::openRelatedFolder()

=item B<openSubFolder> NAME, OPTIONS

See Mail::Box::openSubFolder()

=back

=head2 Message threads [internals]

=over 4

=item B<toBeThreaded> MESSAGES

See Mail::Box::toBeThreaded()

=item B<toBeUnthreaded> MESSAGES

See Mail::Box::toBeUnthreaded()

=back

=head2 Reading and Writing [internals]

=over 4

=item B<appendMessages> OPTIONS

See Mail::Box::appendMessages()

=item B<coerce> MESSAGE

See Mail::Box::coerce()

=item B<determineBodyType> MESSAGE, HEAD

See Mail::Box::determineBodyType()

=item B<folderToFilename> FOLDERNAME, FOLDERDIR, EXTENSION X<folderToFilename>

(Class method)  Translate a folder name into a filename, using the
FOLDERDIR value to replace a leading C<=>.

=item B<lineSeparator> [STRING|'CR'|'LF'|'CRLF']

See Mail::Box::lineSeparator()

=item B<locker> 

See Mail::Box::locker()

=item B<parser>  X<parser>

Create a parser for this mailbox.  The parser stays alive as long as
the folder is open.

=item B<parserClose>  X<parserClose>

Destroy the parser explicilty.  This will free various data-structures,
and close open file-handles.

=item B<read> OPTIONS

See Mail::Box::read()

=item B<readMessages> OPTIONS

See Mail::Box::readMessages()

=item B<storeMessage> MESSAGE

See Mail::Box::storeMessage()

=item B<updateMessages> OPTIONS

See Mail::Box::updateMessages()

=item B<write> OPTIONS X<write>

 OPTION               DEFAULT
 force                <false>
 head_wrap            72
 keep_deleted         <false>
 policy               undef
 save_deleted         <false>

=over 4

=item B<force> =E<gt> BOOLEAN

See Mail::Box::write(force)

=item B<head_wrap> =E<gt> INTEGER

See Mail::Box::write(head_wrap)

=item B<keep_deleted> =E<gt> BOOLEAN

See Mail::Box::write(keep_deleted)

=item B<policy> =E<gt> 'REPLACE'|'INPLACE'|undef X<write(policy)>

In what way will the mail folder be updated.  If not specified during the
write, the value of the C<write_policy> at folder creation is taken.

Valid values:

=over 4

=item * C<REPLACE>

First a new folder is written in the same directory as the folder which has
to be updated, and then a call to move will throw away the old immediately
replacing it by the new.  The name of the folder's temporary file is
produced in tmpNewFolder().

Writing in C<REPLACE> module is slightly optimized: messages which are not 
modified are copied from file to file, byte by byte.  This is much
faster than printing the data which is will be done for modified messages.

=item * C<INPLACE>

The original folder file will be opened read/write.  All message which where
not changed will be left untouched, until the first deleted or modified
message is detected.  All further messages are printed again.

=item * C<undef>

As default, or when C<undef> is explicitly specified, first C<REPLACE> mode
is tried.  Only when that fails, an C<INPLACE> update is performed.

=back

C<INPLACE> will be much faster than C<REPLACE> when applied on large
folders, however requires the C<truncate> function to be implemented on
your operating system.  It is also dangerous: when the program is interrupted
during the update process, the folder is corrupted.  Data may be lost.

However, in some cases it is not possible to write the folder with
C<REPLACE>.  For instance, the usual incoming mail folder on UNIX is
stored in a directory where a user can not write.  Of course, the
C<root> and C<mail> users can, but if you want to use this Perl module
with permission of a normal user, you can only get it to work in C<INPLACE>
mode.  Be warned that in this case folder locking via a lockfile is not
possible as well.

=item B<save_deleted> =E<gt> BOOLEAN

See Mail::Box::write(save_deleted)

=back

=item B<writeMessages> 

See Mail::Box::writeMessages()

=back

=head2 Logging and Tracing

=over 4

=item B<errors> 

See Mail::Reporter::errors()

=item B<log> [LEVEL [,STRINGS]]

See Mail::Reporter::log()

=item B<report> [LEVEL]

See Mail::Reporter::report()

=item B<reportAll> [LEVEL]

See Mail::Reporter::reportAll()

=item B<trace> [LEVEL]

See Mail::Reporter::trace()

=item B<warnings> 

See Mail::Reporter::warnings()

=back

=head2 Other Methods

=over 4

=item B<AUTOLOAD> 

See Mail::Reporter::AUTOLOAD()

=item B<inGlobalDestruction> 

See Mail::Reporter::inGlobalDestruction()

=item B<logPriority> LEVEL

See Mail::Reporter::logPriority()

=item B<logSettings> 

See Mail::Reporter::logSettings()

=item B<notImplemented> 

See Mail::Reporter::notImplemented()

=item B<timespan2seconds> TIME

See Mail::Box::timespan2seconds()

=back

=head1 IMPLEMENTATION


=head2 How Mbox folders work

Mbox folders store many messages in one file (let's call this a
`file-based' folder, in comparison to a `directory-based' folder types
like MH and Maildir).

In file-based folders, each message begins with a line which starts with
the string C<From >.  Lines inside a message which accidentally start with
C<From> are, in the file, preceded by `E<gt>'. This character is stripped
when the message is read.

In this module, the name of a folder may be an absolute or relative path.
You can also precede the foldername by C<=>, which means that it is
relative to new(folderdir).

=head2 Simulation of sub-folders

File-based folders do not really have a sub-folder concept as directory-based
folders do, but this module tries to simulate them.  In this implementation
a directory like

 Mail/subject1/

is taken as an empty folder C<Mail/subject1>, with the folders in that
directory as sub-folders for it.  You may also use

 Mail/subject1
 Mail/subject1.d/

where C<Mail/subject1> is the folder, and the folders in the
C<Mail/subject1.d> directory are used as sub-folders.  If your situation
is similar to the first example and you want to put messages in that empty
folder, the directory is automatically (and transparently) renamed, so
that the second situation is reached.

Because of these simulated sub-folders, the folder manager does not need to
distinguish between file- and directory-based folders in this respect.

=head1 SEE ALSO

A good start to read is Mail::Box-Overview.
More documentation and a mailinglist are available from the project's
website at L<http://perl.overmeer.net/mailbox/>.

=head1 AUTHOR

Mark Overmeer (L<mark@overmeer.net|mailto:mark@overmeer.net>) with the help of many.

=head1 VERSION

This code is beta, version 2.019.

Copyright (c) 2001-2002 Mark Overmeer. All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the same terms as Perl itself.
