File Coverage

blib/lib/Mail/TieFolder.pm
Criterion Covered Total %
statement 40 40 100.0
branch 7 8 87.5
condition n/a
subroutine 7 7 100.0
pod 0 1 0.0
total 54 56 96.4


line stmt bran cond sub pod time code
1             package Mail::TieFolder;
2              
3             require 5.005_62;
4 2     2   1382 use strict;
  2         4  
  2         66  
5 2     2   10 use warnings;
  2         3  
  2         69  
6 2     2   10 use vars qw(@ISA);
  2         7  
  2         122  
7              
8             require Exporter;
9 2     2   1878 use AutoLoader qw(AUTOLOAD);
  2         3518  
  2         11  
10              
11             @ISA = qw(Exporter);
12              
13             # Items to export into callers namespace by default. Note: do not export
14             # names by default without a very good reason. Use EXPORT_OK instead.
15             # Do not simply export all your public functions/methods/constants.
16              
17             # This allows declaration use Mail::TieFolder ':all';
18             # If you do not need this, moving things directly into @EXPORT or @EXPORT_OK
19             # will save memory.
20             our %EXPORT_TAGS = ( 'all' => [ qw(
21            
22             ) ] );
23              
24             our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
25              
26             our @EXPORT = qw(
27            
28             );
29             our $VERSION = '0.03';
30              
31              
32             =head1 NAME
33              
34             Mail::TieFolder - Tied hash interface for mail folders
35              
36             =head1 SYNOPSIS
37              
38             use Mail::TieFolder;
39              
40             # assuming inbox is an MH folder, and the
41             # Mail::TieFolder::mh module is installed:
42             tie (%inbox, 'Mail::TieFolder', 'mh', 'inbox');
43              
44             # get list of all message IDs in folder
45             @messageIDs = keys (%inbox);
46              
47             # fetch message (as Mail::Internet object) by ID
48             $msg = $inbox{'9287342.2138749@foo.com'};
49              
50             =head1 DESCRIPTION
51              
52             Mail::TieFolder implements a tied hash interface for manipulating
53             folder contents. Messages in the hash are accessed by Message-Id.
54              
55             See the Mail::TieFolder::* modules on CPAN for supported folder
56             formats. If the format you're looking for isn't supported, please
57             feel free to implement your own module and upload it to CPAN as
58             Mail::TieFolder::yourformat. New formats are by design relatively
59             easy to implement -- see L<"IMPLEMENTING A NEW MAILBOX FORMAT"> for
60             guidelines.
61              
62             =head1 COMPARISON WITH OTHER MODULES
63              
64             As with all things in Perl, There Is More Than One Way To Do It.
65              
66             Mail::TieFolder and the Mail::TieFolder::* modules provide a
67             lightweight API for manipulating the contents of mail folders in
68             various formats. These modules only put, fetch, create, delete, or
69             refile messages in folders, using Message-ID as the message handle.
70             They don't pretend to know anything about the internal formatting of
71             the messages themselves (leaving that to Mail::Internet), they don't
72             do indexing, searches, address books, or other MUA stuff, nor do they
73             pretend to provide any overall management of your folders. They
74             can, however, be used to move or copy messages between folders, and
75             will create a new folder if you name a non-existent folder in the
76             tie().
77              
78             The Mail::Folder, Mail::Box, and Mail::MsgStore modules also provide
79             for managing folders and their contents. Those modules generally have
80             more of a concept of managing your whole mail world of multiple
81             folders, including address books, folder searches, indexes, and
82             other MUA tools. I didn't need this, and the additional overhead
83             was prohibitive. The additional capabilities of those modules also
84             mean that implementing modules to support new folder formats is a
85             more complex undertaking.
86              
87             I went with a tie() interface for Mail::TieFolder because it
88             constrained the API to a reasonably small and well-defined set of
89             functions. This lowers the bar of entry for other authors who want to
90             add Mail::TieFolder::* modules to support additional folder formats.
91              
92             Both Mail::Folder and the Mail::Box::Tie modules use message sequence
93             numbers as the primary key into a folder. Message sequence numbers
94             are not fixed attributes uniquely attached to one and only one
95             message, and can change as a folder is resorted and packed, and as
96             messages are moved between folders.
97              
98             For Mail::TieFolder, I instead used Message-ID as the key into a mail
99             folder, since it's theoretically a globally unique identifier. This
100             way you can sort, renumber, pack, and so on, and still have safe,
101             immutable, persistent handles on individual messages.
102              
103             (Note that Mail::Box does support a messageID() method, and if you
104             were so inclined, you could use Mail::Box as the backend for a
105             Mail::TieFolder::* module, provided that the correct Mail::Box::*
106             module exists to support your desired folder format. This would be
107             putting a lightweight and constrained interface on the front of a much
108             more capable and heavyweight engine, but might meet your needs.)
109              
110             =head1 IMPLEMENTING A NEW MAILBOX FORMAT
111              
112             Mail::TieFolder::* modules to support additional mailbox formats are
113             easy to implement; you only need to support the API functions for a
114             tied hash (TIEHASH, FETCH, FIRSTKEY, NEXTKEY, EXISTS, STORE, and
115             DELETE). See the Perl Cookbook, L or the Mail::TieFolder::mh
116             module code for examples. I'd suggest using 'h2xs -Xn` to create a
117             template for your module.
118              
119             To ensure compatibility with other Mail::TieFolder::* modules, make a
120             ./t directory under the distribution tree for your new module, then
121             copy the test scripts and other data files from the ./t directory of
122             the Mail::TieFolder::mh distribution into the ./t directory of your
123             own module's tree, and edit them accordingly to get rid of the
124             mh-specific stuff and add any setup which your mailbox format needs.
125              
126             These test scripts will exercise your new module via the
127             Mail::TieFolder module to make sure they are talking to each other
128             correctly.
129              
130             Make sure when you edit the test scripts that you change the folder
131             format in the tie() calls. You'll also want to delete the dummy
132             ./test.pl script which h2xs generated and then re-run 'perl
133             Makefile.PL' to generate a Makefile which recognizes the ./t
134             subdirectory.
135              
136             If you run into "can't find subroutine" problems, you may not be
137             doing the inheritance right -- careful, Mail::TieFolder ISA
138             Mail::TieFolder::yourformat, not the other way around. See the
139             TIEHASH functions in Mail::TieFolder and Mail::TieFolder::mh -- note
140             in particular the @ISA stuff in Mail::TieFolder and the ref() calls in
141             the Mail::TieFolder::mh bless(). Also make sure you've removed the
142             'our @ISA' line in your new h2xs generated code -- it masks the @ISA
143             in Mail::TieFolder.
144              
145             When you're happy with your module, you'll want to upload it to CPAN
146             -- see ftp://cpan.org/pub/CPAN/modules/04pause.html.
147              
148             =cut
149              
150             sub TIEHASH
151             {
152 1     1   45 my $class = shift;
153 1         3 my $format = shift;
154 1         3 my @args = @_;
155              
156 1         3 my $self={};
157 1         3 bless $self, $class;
158              
159 1         4 my $module = $class . "::$format";
160 1     1   504 eval "use $module";
  1         32  
  1         20  
  1         73  
161 1         17 push @ISA, $module;
162              
163 1         9 return $self->SUPER::TIEHASH(@args);
164             }
165              
166             sub supported
167             {
168 4 50   4 0 59 my $class = ref(shift) if ref($_[0]);
169 4 100       7 $class = "Mail::TieFolder" unless $class;
170 4         6 my $relpath = $class;
171 4         11 $relpath =~ s/::/\//g;
172 4         5 my $format = shift;
173              
174 4 100       8 if ($format)
175             {
176             # is it supported?
177 3         6 my $module = $class . "::$format";
178 3         142 return eval "require $module";
179             }
180             else
181             {
182             # find all supported
183 1         1 my @supported;
184 1         3 for (@INC)
185             {
186 10         18 my $dir="$_/$relpath";
187 10         181 opendir(DIR,$dir);
188 10         87 for(readdir(DIR))
189             {
190 4 100       14 next unless /^(\w+).pm$/;
191 2         7 push @supported, $1;
192             }
193             }
194 1         6 return @supported;
195             }
196             }
197              
198             =head1 AUTHOR
199              
200             Steve Traugott, stevegt@TerraLuna.Org
201              
202             =head1 SEE ALSO
203              
204             L,
205             L,
206             L,
207             L,
208             L
209              
210             =cut
211              
212             1;
213             __END__