File Coverage

blib/lib/Mail/Alias/Reader.pm
Criterion Covered Total %
statement 41 41 100.0
branch 12 12 100.0
condition 2 2 100.0
subroutine 10 10 100.0
pod 3 3 100.0
total 68 68 100.0


line stmt bran cond sub pod time code
1             # Copyright (c) 2012, cPanel, Inc.
2             # All rights reserved.
3             # http://cpanel.net/
4             #
5             # This is free software; you can redistribute it and/or modify it under the same
6             # terms as Perl itself. See the LICENSE file for further details.
7              
8             package Mail::Alias::Reader;
9              
10 4     4   20360 use strict;
  4         8  
  4         153  
11 4     4   20 use warnings;
  4         8  
  4         108  
12              
13 4     4   3347 use Mail::Alias::Reader::Parser ();
  4         12  
  4         85  
14              
15 4     4   26 use Carp;
  4         8  
  4         260  
16              
17             BEGIN {
18 4     4   23 use Exporter ();
  4         8  
  4         93  
19 4     4   20 use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS);
  4         8  
  4         488  
20              
21 4     4   8 $VERSION = '0.06';
22 4         72 @ISA = qw(Exporter);
23              
24 4         8 @EXPORT = ();
25 4         29 @EXPORT_OK = ();
26 4         1739 %EXPORT_TAGS = ();
27             }
28              
29             =head1 NAME
30              
31             Mail::Alias::Reader - Read aliases(5) and ~/.forward declarations
32              
33             =head1 SYNOPSIS
34              
35             my $reader = Mail::Alias::Reader->open(
36             'handle' => \*STDIN,
37             'mode' => 'aliases'
38             );
39              
40             while (my ($name, $destinations) = $reader->read) {
41             my @addresses = grep { $_->is_address } @{$destinations};
42              
43             print "$name: " . join(', ', map { $_->to_string } @addresses) . "\n";
44             }
45              
46             $reader->close;
47              
48             =head1 DESCRIPTION
49              
50             Mail::Alias::Reader is a small but oddly flexible module that facilitates the
51             reading of aliases(5)-style mail alias and ~/.forward declarations. It does
52             not directly provide support for the writing and in-memory manipulation of
53             these files as a whole, however its limited feature set may be considered to
54             be a virtue.
55              
56             The module can read mail aliases or ~/.forward declarations from a file, or
57             from an arbitrary file handle, as specified at the time of file reader
58             instantiation. The destination objects returned are the same parser tokens
59             used internally, keeping code footprint low without being too much of a hassle.
60              
61             =head1 STARTING UP THE MODULE
62              
63             =over
64              
65             =item Mail::Alias::Reader->open(%opts)
66              
67             Open a file (C) or stream (C) based on the values provided in
68             C<%opts>, returning a mail alias reader as a result. A parsing C can be
69             supplied; by default, I are expected, whereas a C of I
70             can be specified as well.
71              
72             =back
73              
74             =cut
75              
76             sub open {
77 8     8 1 536432 my ( $class, %opts ) = @_;
78              
79             #
80             # If no parsing mode is specified, then assume a default of 'aliases',
81             # for aliases(5) mode parsing. Otherwise, a value of 'forward' can be
82             # passed, suitable for parsing ~/.forward declarations.
83             #
84 8   100     123 $opts{'mode'} ||= 'aliases';
85              
86 8 100       284 confess('Unknown parsing mode') unless $opts{'mode'} =~ /^aliases|forward$/;
87              
88 7         15 my $fh;
89              
90 7 100       59 if ( defined $opts{'file'} ) {
    100          
91 2 100       106 open( $fh, '<', $opts{'file'} ) or confess("Unable to open aliases file $opts{'file'}: $!");
92             }
93             elsif ( defined $opts{'handle'} ) {
94 4         50 $fh = $opts{'handle'};
95             }
96             else {
97 1         12 confess('No file or file handle specified');
98             }
99              
100 5         142 return bless {
101             'mode' => $opts{'mode'},
102             'handle' => $fh
103             }, $class;
104             }
105              
106             =head1 READING DECLARATIONS
107              
108             =over
109              
110             =item $reader->read()
111              
112             Seeks the current file stream for the next available declaration, and passes it
113             through the parser, returning the data given by the parser, without any further
114             manipulation.
115              
116             Depending on the parsing mode, the nature of the returned data will differ.
117             Each of the following modes will cause C<$reader-Eread()> to operate in the
118             following manners:
119              
120             =over
121              
122             =item C
123              
124             When Mail::Alias::Reader is set to read in C mode, a plain scalar
125             value reflecting the name of the alias, followed by an C reference
126             containing mail destinations, is returned, in list context.
127              
128             my ($name, $destinations) = $reader->read;
129              
130             =item C
131              
132             my $destinations = $reader->read;
133              
134             When Mail::Alias::Reader is set to read in C mode, an C
135             reference containing mail destinations is returned in a single scalar.
136              
137             =back
138              
139             =back
140              
141             =head1 THE MAIL DESTINATION TOKEN
142              
143             Mail destination objects returned by C<$reader-Eread()> are C objects
144             bless()ed into the Mail::Alias::Reader::Token package, and contain a small
145             handful of data attributes, but can be inspected with a variety of helper
146             functions in the form of instance methods. Please see the
147             L documentation for a listing of these helper
148             functions.
149              
150             The mail destination attributes include:
151              
152             =over
153              
154             =item C
155              
156             The type of token dealt with. This can be one of I, I,
157             I, or I.
158              
159             =over
160              
161             =item I
162              
163             A mail destination token of type I may indicate either a full mail
164             address, or a local part.
165              
166             =item I
167              
168             A destination token of type I indicates that mail destined for the
169             current alias is to be pipe()d to the specified command.
170              
171             =item I
172              
173             Any mail destined for the current alias will be appended to the file indicated
174             by this destination token.
175              
176             =item I
177              
178             Indicates any special destination in the format of C<:directive:I>.
179             These are of course specific to the system's configured mail transfer agent.
180             In this case, the name of the directive is captured in the token object's
181             C attribute.
182              
183             =back
184              
185             =item C
186              
187             The textual value of the mail destination, parsed, cleansed of escape sequences
188             that may have been present in the source file, containing only the data that
189             is uniquely specified by the type of mail destination token given. As an
190             example, I destinations do not include the pipe ('|') symbol as a
191             prefix; this is implied in the destination token type, rather.
192              
193             =item C
194              
195             Only appears in the prsence of a token typed I When a mail alias
196             destination in the form of C<:directive:I> is parsed, this contains
197             the name of the 'C' portion. Of course, the value in the
198             'I' portion is contained in the token's C field, but is
199             considered optional, especially in the presence of a directive such as C<:fail>.
200              
201             =back
202              
203             =cut
204              
205             sub read {
206 28     28 1 54122 my ($self) = @_;
207              
208 28         5621 while ( my $line = readline( $self->{'handle'} ) ) {
209 29         364 $line =~ s/^\s+//;
210 29         194 $line =~ s/\s+$//;
211              
212 29 100       88 next unless $line;
213 28 100       135 next if $line =~ /^(#|$)/;
214              
215 27         187 return Mail::Alias::Reader::Parser->parse( $line, $self->{'mode'} );
216             }
217              
218 1         4 return;
219             }
220              
221             =head1 CLOSING THE STREAM
222              
223             =over
224              
225             =item $reader->close()
226              
227             Close the current file stream. Any subsequent C<$reader-Eread()> calls will
228             return nothing.
229              
230             =cut
231              
232             sub close {
233 5     5 1 5258 close shift->{'handle'};
234             }
235              
236             =back
237              
238             =cut
239              
240             1;
241              
242             __END__