The only and official way for PigeonDeliver to store emails
on the local hard drive is by using the mailStore service.
Purpose of the mailStore service is to save all the
emails being received somewhere on your hard drive,
in the administrator/user specified format.
The mailStore service is modular in nature: depending on
the modules the administrator will choose, users home
directories might be created automatically, lazy allocation
routines might be used, or users/admins might have a greater degree
of freedom by choosing which format to use for the
mailboxes or how to create the directory hierarchy
itself.
Talking about the structure, the mailStore service
is quite simple. It uses two kind of modules:
| |
which takes care of writing the mail in
the mailboxes, mailboxes that can range
from simple directories on the disk to
mailbox files, database or anything
else you may like...
|
| |
which mainly takes care of handling
concurrency when creating new users
(more details will be given later).
|
|
The main idea behind this structure was
to make sure that the user database
was kept as simple as possible: when
a new user is created, how is a web
interface supposed to know which home
directory to use for the user? How is
it supposed to know which uid to use?
What happens in a clustered environment?
What happens if those information get
out of sync for any reason? What happens
if the administrator wants to change
the directory structure or the on-disk format
for mailboxes?
When a new user is created, and when
"mailstore" (mail saving on disk) for
this user is enabled, a simple record is
written into the user database (either by
the administrator, tools or web interfaces). This
simple record just needs to tell the name
of the user and all those configurations wich
the administrator wants to be forced on the user
itself (usually, user quotas, if a paraticular
directory needs to be used, and so on...).
When a new mail is received, the mailStore is
called. The mailStore itself parses the provided
user configuration using the MDA module specified
in the configuration file.
The MDA module will tell if the provided
information is "enough" to deliver the email,
or if some additional information must be provided.
If nothing is missing, the MDA module will
just be called to perform delivery.
If something is missing, the mailStore will
take care to call the "creator" module. The
"creator" module itself will call the MDA
once again, asking it to allocate the user,
which means, to provide all the "missing data".
If everything works, the "creator" will then
add that data in the user structure on the
database. So, in short:
the MDA is able to parse user configurations
and verify if all the necessary informations
are there, which often means that it is able
to tell if the user "has been created on disk"
or not. If it has not, the MDA is able to
"allocate the user", which means it is able to
provide all the missing data, which often means
creating some directories on the disk or writing
some files on the system.
the creator itself is able to write all that
additional data into the user database. But, hey,
what happens in a clustered environment if another
server has been faster than us in allocating the
user and adding his own data into the database? what
happens if another processe receives the same
mail and allocates the mail even if we already
started the allocation? The main purpose of the
creator module is to handle concurrency: some creators
might just lock the database while the user is created,
others may use a test-and-trial procedure, some
others may just ignore the problem.
Keep in mind, however, that what exactly is
done when a mail is received or when a user is allocated
just depends on the MDA being used. For example, a
database based MDA may create a new "table" when an
user is allocated, and then write each mail as a record
into that table. A file system based MDA may just create
the user home directory upon "allocation", and write
the mail in a mailbox file whenever the delivery has
to be processed. Right now, there are not that many
MDA modules, but we are planning to write many of
them with different features. It is fairly easy to
add a new on-disk data storage by simply writing
one more MDA module.