File Coverage

blib/lib/Dezi/Aggregator/MailFS.pm
Criterion Covered Total %
statement 7 9 77.7
branch n/a
condition n/a
subroutine 3 3 100.0
pod n/a
total 10 12 83.3


line stmt bran cond sub pod time code
1             package Dezi::Aggregator::MailFS;
2 1     1   138517 use Moose;
  1         3  
  1         11  
3             extends 'Dezi::Aggregator::FS';
4 1     1   6687 use Path::Class ();
  1         3  
  1         18  
5 1     1   649 use Dezi::Aggregator::Mail; # delegate doc creation
  0            
  0            
6             use Carp;
7             use Data::Dump qw( dump );
8              
9             our $VERSION = '0.014';
10              
11             =pod
12              
13             =head1 NAME
14              
15             Dezi::Aggregator::MailFS - crawl a filesystem of email messages
16              
17             =head1 SYNOPSIS
18              
19             use Dezi::Aggregator::MailFS;
20             my $fs = Dezi::Aggregator::MailFS->new(
21             indexer => Dezi::Indexer->new
22             );
23            
24             $fs->indexer->start;
25             $fs->crawl( $path_to_mail );
26             $fs->indexer->finish;
27            
28             =head1 DESCRIPTION
29              
30             Dezi::Aggregator::MailFS is a subclass of Dezi::Aggregator::FS
31             that expects every file in a filesystem to be an email message.
32             This class is useful for crawling a file tree like those managed by ezmlm.
33              
34             B<NOTE:> This class will B<not> work with personal email boxes
35             in the Mbox format. It might work with maildir format, but that is
36             coincidental. Use Dezi::Aggregator::Mail to handle your personal
37             email box. Use this class to handle mail archives as with a mailing list.
38              
39             =cut
40              
41             =head1 METHODS
42              
43             See Dezi::Aggregator::FS. Only new or overridden methods are documented
44             here.
45              
46             =cut
47              
48             =head2 BUILD
49              
50             Internal constructor method.
51              
52             =cut
53              
54             sub BUILD {
55             my $self = shift;
56              
57             # cache a Mail aggregator to use its get_doc method
58             $self->{_mailer} = Dezi::Aggregator::Mail->new(
59             indexer => $self->indexer,
60             verbose => $self->verbose,
61             debug => $self->debug,
62             );
63              
64             return $self;
65             }
66              
67             =head2 file_ok( I<full_path> )
68              
69             Like the parent class method, but ignores file extension, assuming
70             that all files are email messages.
71              
72             Returns the I<full_path> value if the file is ok for indexing;
73             returns 0 if not ok.
74              
75             =cut
76              
77             sub file_ok {
78             my $self = shift;
79             my $full_path = shift;
80             my $stat = shift;
81              
82             $self->debug and warn "checking file $full_path\n";
83              
84             return 0 if $full_path =~ m![\\/](\.svn|RCS)[\\/]!; # TODO configure this.
85              
86             $stat ||= [ stat($full_path) ];
87             return 0 unless -r _;
88             return 0 if -d _;
89             if ( $self->ok_if_newer_than
90             and $self->ok_if_newer_than >= $stat->[9] )
91             {
92             return 0;
93             }
94             return 0
95             if ( $self->_apply_file_rules($full_path)
96             && !$self->_apply_file_match($full_path) );
97              
98             $self->debug and warn " $full_path -> ok\n";
99             if ( $self->verbose & 4 ) {
100             local $| = 1; # don't buffer
101             print "crawling $full_path\n";
102             }
103              
104             return $full_path;
105             }
106              
107             =head2 get_doc( I<url> )
108              
109             Overrides parent class to delegate the creation of the
110             Dezi::Indexer::Doc object to Dezi::Aggregator::Mail->get_doc().
111              
112             Returns a Dezi::Indexer::Doc object.
113              
114             =cut
115              
116             around 'get_doc' => sub {
117             my $super_method = shift;
118             my $self = shift;
119              
120             # there's some wasted overhead here in creating a
121             # Dezi::Indexer::Doc 2x. But we're optimizing here for
122             # developer time...
123              
124             # mostly a slurp convenience
125             my $doc = $self->$super_method(@_);
126              
127             #carp "first pass for raw doc: " . dump($doc);
128              
129             # get the "folder"
130             my $folder = Path::Class::file( $doc->url )->dir;
131              
132             # now convert the buffer to an email message
133             my $msg = Mail::Message->read( \$doc->content );
134              
135             # and finally convert to the Dezi::Indexer::Doc we intend to return
136             my $mail = $self->{_mailer}->get_doc( $folder, $msg );
137              
138             # reinstate original url from filesystem
139             $mail->url( $doc->url );
140              
141             #carp "second pass for mail doc: " . dump($mail);
142              
143             return $mail;
144             };
145              
146             __PACKAGE__->meta->make_immutable;
147              
148             1;
149              
150             __END__
151              
152             =head1 AUTHOR
153              
154             Peter Karman, E<lt>perl@peknet.comE<gt>
155              
156             =head1 BUGS
157              
158             Please report any bugs or feature requests to C<bug-swish-prog at rt.cpan.org>, or through
159             the web interface at L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Dezi-App>.
160             I will be notified, and then you'll
161             automatically be notified of progress on your bug as I make changes.
162              
163             =head1 SUPPORT
164              
165             You can find documentation for this module with the perldoc command.
166              
167             perldoc Dezi
168              
169              
170             You can also look for information at:
171              
172             =over 4
173              
174             =item * Mailing list
175              
176             L<http://lists.swish-e.org/listinfo/users>
177              
178             =item * RT: CPAN's request tracker
179              
180             L<http://rt.cpan.org/NoAuth/Bugs.html?Dist=Dezi-App>
181              
182             =item * AnnoCPAN: Annotated CPAN documentation
183              
184             L<http://annocpan.org/dist/Dezi-App>
185              
186             =item * CPAN Ratings
187              
188             L<http://cpanratings.perl.org/d/Dezi-App>
189              
190             =item * Search CPAN
191              
192             L<http://search.cpan.org/dist/Dezi-App/>
193              
194             =back
195              
196             =head1 COPYRIGHT AND LICENSE
197              
198             Copyright 2008-2009 by Peter Karman
199              
200             This library is free software; you can redistribute it and/or modify
201             it under the same terms as Perl itself.
202              
203             =head1 SEE ALSO
204              
205             L<http://swish-e.org/>