Ricardo SIGNES > Email-Store-0.257 > Email::Store



Annotate this POD (1)


Open  3
View/Report Bugs
Module Version: 0.257   Source  


Email::Store - Framework for database-backed email storage


  use Email::Store 'dbi:mysql:mailstore';
  Email::Store->setup; # Do this once




Email::Store itself is a very lightweight framework, meaning it does not provide very much functionality itself; in effect, it is merely a Class::DBI interface to a database schema which is designed for storing email. Incidentally, if you don't know much about Class::DBI, you're going to need to in order to get much out of this.

Despite its minimalist nature, Email::Store is incredibly powerful. Its power comes from its extensibility, through plugin modules and hooks which allow you to add new database tables and concepts to the system, and so access the mail store from a "different direction". In a sense, Email::Store is a blank canvas, onto which you can pick and choose (or even write!) the plugins which you want for your application.

For instance, the core Email::Store::Entity plugin module addresses the idea of "people" in the email universe, allowing you to search for mails to or from particular people; (despite their changing names or email addresses) Email::Store::Thread interfaces Email::Store to Mail::Thread allowing you to navigate mails by their position in a mail thread; the planned non-core Email::Store::Plucene module plugs into the indexing process and stores information about emails in a Plucene search index for quick retrieval later, and so on.


The generic way to use Email::Store is

    use Email::Store 'dbi:mysql:mailstore';

However you can also pass a has ref in as the first argument.

This hash ref can contain arbitary key/value pairs however the only ones currently supported are only and except which both take an array ref of plugin names. only means that Email::Store will only load those plugins and except means it will load everything except those.

    use Email::Store { only => [ "Email::Store::Mail" ] }, 'dbi:mysql:mailstore';

Core Email::Store modules ^



This is, in a sense, the plugin of plugins. Email::Store::Mail encapsulates individual email messages. Its store method is the means in which emails are indexed and enter the mailstore. How this storing is done, however, is influenced by all the other plugins.



Email::Store::List hooks into the indexing process and examines a mail to see if it came via a mailing list; if so, it associates the mail with one or more lists. This means you can ask a mail object for its lists, and a list object for its posts. Because of this, instead of looking at messages by their message ID, you can start by looking for a mailing list you're interested in and then navigate to the messages you want.


This adds the date method to a mail object, returning a Time::Piece representing the date of the email. It also provides various searches for mails between epoch times and for years, months and days.


Entity is the most fundamental of the plugins but (or perhaps, "thus") the most complex. This module adds the concept of an addressing, which abstracts out the From, To, Cc and Bcc headers of an email. A "To" header, for instance, says that the mail is addressed to a particular name and address, but Email::Store::Entity also provides the potential for associating different names and addresses with the concept of an entity, a unique individual. That is, not all mails addressed to the name "Simon Cozens" are to me (due to the existence of multiple Simon Cozenses in the world) but all mails to .*@simon-cozens.org are, despite their being multiple email addresses which match that pattern.






When you use Email::Store, you should pass a DBI connection string to its use statement:

    use Email::Store 'dbi:SQLite:dbname=mailstore.db';




It should be noted that passing in an optional true value to setup will cause it to be verbose about what it's doing.

This is all the functionality that Email::Store itself provides. See the documentation to the various plugins for their public interface, chiefly Email::Store::Mail.



The first thing to note is that when Email::Store indexes a mail, whether for the first time or when it re-indexes a mail it's seen before, it loads up all the modules it can find under the Email::Store::* hierarchy. Additionally, when Email::Store->setup is called, all the Email::Store::* modules are required. So, to register your new plugin, all you need to do is call it Email::Store::something and put it in Perl's include path in the usual way.


Let us write a very simple plugin as a first example. This will introduce the concept of a mail annotation, an open-ended space where we can store "sticky notes" which relate to a particular email. We'll call the plugin Email::Store::Annotation, and we start by putting the following in Email/Store/Annotation.pm:

    package Email::Store::Annotation;
    use base 'Email::Store::DBI';

This makes us a Class::DBI-based package. Next we need to do the usual Class::DBI thing and ddeclare our table and columns:


Next we declare how this fits into the rest of the world: an Email::Store::Mail has many annotations:




If we did need to hook into a different part of Email::Store, we'd have to use Module::Pluggable::Ordered's plugin mechanism. See Email::Store::Mail for the hooks provided and how to hook into them.

But where does this mail_annotation table come from? How does Email::Store know how to create it? The answer comes when we put the schema into the __DATA__ section: Email::Store->setup reads all the DATA sections for the plugins that it finds, and executes them as SQL in the database. As pretty much every database's SQL is subtly different, the schema should be written in MySQL's SQL and Email::Store will magically translate it for the database in use:

    CREATE TABLE IF NOT EXISTS mail_annotation (
        id INTEGER auto_increment NOT NULL PRIMARY KEY,
        mail INTEGER,
        content TEXT

With this module complete and installed, an Email::Store user can now say:


The really big advantage of this architecture is that everything about a concept and its relationship to the mailstore is encapsulated in a single file and can be dropped in and out at will, without disturbing the rest of the code. This is fantastic extensibility. Email::Store does not need to define a schema of every single table you might possibly need up front, but everything is modularised.

The really big disadvantage is that the interface of one part of the system, such as Email::Store::Mail isn't collected in one place, but gets added to by pretty much every other plugin that gets loaded up. If you look in the Email::Store::Mail POD you'll see nothing about the add_to_annotations method that we've just called.



Understanding Class::DBI is fundamental to using Email::Store.


Any other Email::Store::* modules you find on CPAN.

Module::Pluggable::Ordered is the pluggable hooks system used throughout Email::Store. Those developing additional modules might want to look at its documentation to understand how to hook into the indexing, reindexing and other processes.


The original author is Simon Cozens, <simon@cpan.org> Currently maintained by Simon Wistow <simon@thegestalt.org>


This module is part of the Perl Email Project - http://pep.kwiki.org/

There is a mailing list at pep@perl.org (subscribe at pep-subscribe@perl.org) and an archive available at http://nntp.perl.org/group/pep.php


Many of the ideas (although none of the code) for this package were taken from my work on a project called Twingle, for a company called Kasei. While I was at Kasei, I did a lot of thinking about handling email, storing it, analyzing it and presenting it on the web; I left the company with all that knowledge in my head, and wrote Email::Store with the knowledge and tools that I acquired. Thanks to Kasei for the experience that I gained there and the good grace they've shown as I release Email::Store.


Copyright 2004 by Simon Cozens


syntax highlighting: