File Coverage

blib/lib/Email/Envelope.pm
Criterion Covered Total %
statement 88 88 100.0
branch 38 42 90.4
condition 10 12 83.3
subroutine 22 22 100.0
pod 15 15 100.0
total 173 179 96.6


line stmt bran cond sub pod time code
1             package Email::Envelope;
2              
3 1     1   31576 use 5.00503;
  1         4  
  1         44  
4 1     1   5 use strict;
  1         2  
  1         29  
5 1     1   5 use warnings;
  1         6  
  1         35  
6 1     1   5 use vars qw($VERSION @ISA);
  1         1  
  1         89  
7              
8             $VERSION = '0.01';
9             $VERSION = eval $VERSION; # see L
10              
11 1     1   5 use Email::Simple;
  1         2  
  1         18  
12 1     1   916 use Email::Address;
  1         41830  
  1         137  
13 1     1   1095 use Regexp::Common qw(net number);
  1         2302  
  1         5  
14              
15             =head1 NAME
16              
17             Email::Envelope - Email with SMTP time information
18              
19             =head1 SYNOPSIS
20              
21             use Email::Envelope;
22             my $mailenv = Email::Envelope->new();
23             $mailenv->remote_host('mx.example.com');
24             ...
25              
26             OR
27              
28             my $mailenv = Email::Envelope->new({
29             remote_port => 29,
30             secure => 1,
31             ...
32             });
33              
34             =head1 DESCRIPTION
35              
36             This module has been designed as a simple container with a few handy
37             methods. Currently Email::Simple contains RFC2822 data, however when
38             dealing with filtering Email, sometimes the information available just
39             isn't enough. Many people may wish to block certain subnets or run
40             SBL/XBL checks. This module has been provided for this very reason.
41              
42             =head1 METHODS
43              
44             =head2 new
45              
46             Currently the constructor supports adding data via hash references for the following data:
47              
48             remote_host
49             remote_port
50             local_host
51             local_port
52             secure
53             rcpt_to
54             mail_from
55             helo
56             data
57             mta_msg_id
58             received_timestamp
59              
60             And can be used as so:
61              
62             my $mailenv = Email::Envelope->new({
63             remote_host => '127.0.0.1',
64             local_host => 'mx.example.com',
65             ...
66             });
67              
68             =cut
69              
70             sub new {
71 1     1 1 1253 my ($class,$args) = @_;
72 1 50       8 my $foo = {
    50          
    50          
73             data => $args,
74             simple => ($args->{data} ? Email::Simple->new($args->{data}) : ''),
75             to_address => ($args->{rcpt_to} ? Email::Address->parse($args->{rcpt_to}) : ''),
76             from_address => ($args->{mail_from} ? Email::Address->parse($args->{mail_from}) : '')
77             };
78            
79 1         1227 return bless $foo, $class;
80             }
81              
82             =head2 remote_host
83              
84             Simple accessor. Will only accept either an IP address or a Fully Qualified Domain Name.
85             Will die upon wrong value being set.
86              
87             $mailenv->remote_host('127.0.0.1');
88             print $mailenv->remote_host;
89              
90             $mailenv->remote_host('mx.example.com');
91             print $mailenv->remote_host;
92              
93             =cut
94              
95             sub remote_host {
96 4     4 1 963 my ($self,$val) = @_;
97 4 100       12 if(defined $val){
98 2 100       18 if($val =~ /^$RE{net}{IPv4}$|^$RE{net}{domain}{-nospace}$/){
99 1         461 $self->{data}{remote_host} = $val;
100             }else{
101 1         255 die "Incorrect IP address or FQDN";
102             }
103             }
104 3         34 return $self->{data}{remote_host};
105             }
106              
107             =head2 remote_port
108              
109             Simple accessor. Will only accept a positive integer.
110             Will die upon wrong value being set.
111              
112             $mailenv->remote_port(25);
113             print $mailenv->remote_port;
114              
115             =cut
116              
117             sub remote_port {
118 6     6 1 1290 my ($self,$val) = @_;
119 6 100       17 if(defined $val){
120 4 100 100     21 if($val =~ /^$RE{num}{int}$/ && (1 <= $val && $val <= 65535)){
      66        
121 1         128 $self->{data}{remote_port} = $val;
122             }else{
123 3         374 die "Incorrect port number";
124             }
125             }
126 3         17 return $self->{data}{remote_port};
127             }
128              
129             =head2 local_host
130              
131             Simple accessor. Will only accept either an IP address or a Fully Qualified Domain Name.
132             Will die upon wrong value being set.
133              
134             $mailenv->local_host('127.0.0.1');
135             print $mailenv->local_host;
136              
137             $mailenv->local_host('mx.example.com');
138             print $mailenv->local_host;
139              
140             =cut
141              
142             sub local_host {
143 4     4 1 421 my ($self,$val) = @_;
144            
145 4 100       12 if(defined $val){
146 2 100       12 if($val =~ /^$RE{net}{IPv4}$|^$RE{net}{domain}{-nospace}$/){
147 1         270 $self->{data}{local_host} = $val;
148             }else{
149 1         348 die "Incorrect IP address or FQDN";
150             }
151             }
152 3         24 return $self->{data}{local_host};
153             }
154              
155             =head2 local_port
156              
157             Simple accessor. Will only accept a positive integer.
158             Will die upon wrong value being set.
159              
160             $mailenv->local_port(25);
161             print $mailenv->local_port;
162              
163             =cut
164              
165             sub local_port {
166 6     6 1 1197 my ($self,$val) = @_;
167 6 100       16 if(defined $val){
168 4 100 100     22 if($val =~ /^$RE{num}{int}$/ && (1 <= $val && $val <= 65535)){
      66        
169 1         118 $self->{data}{local_port} = $val;
170             }else{
171 3         371 die "Incorrect port number";
172             }
173             }
174 3         19 return $self->{data}{local_port};
175             }
176              
177             =head2 secure
178              
179             Simple accessor. Requires either a 'true' or 'false' value.
180              
181             $mailenv->secure(1);
182             $mailenv->secure(0);
183             print "Secured" if $mailenv->secure;
184              
185             =cut
186              
187             sub secure {
188 3     3 1 5 my ($self,$val) = @_;
189 3 100       11 if(defined $val){
190 1 50       5 $self->{data}{secure} = $val ? 1 : 0;
191             }
192 3         14 return $self->{data}{secure};
193             }
194              
195             =head2 mta_msg_id
196              
197             Simple accessor/mutator. Will take an arbitary string representing the message ID that the MTA has assigned.
198              
199             $mailenv->mta_msg_id("Exim-2004/22927437493-189282");
200             print "MTA reports this message as " . $mailenv->mta_msg_id;
201              
202             =cut
203              
204             sub mta_msg_id {
205 3     3 1 801 my ($self,$val) = @_;
206 3 100       8 if($val){
207 1         4 $self->{data}{mta_msg_id} = $val;
208             }
209 3         17 return $self->{data}{mta_msg_id};
210             }
211              
212              
213             =head2 recieved_timestamp
214              
215             Simple accessor/mutator. Will take a unix epoch to represent the time that the message arrived with the MTA.
216              
217             $mailenv->recieved_timestamp(103838934);
218             my $dt = Date::Time->new($mailenv->recieved_timestamp);
219              
220             =cut
221              
222             sub recieved_timestamp {
223 4     4 1 420 my ($self,$val) = @_;
224 4 100       11 if(defined $val){
225 2 100       15 if($val =~ /^$RE{num}{int}$/){
226 1         166 $self->{data}{recieved_timestamp} = $val;
227             }else{
228 1         112 die "Incorrect timestamp";
229             }
230             }
231 3         23 return $self->{data}{recieved_timestamp};
232             }
233              
234             =head2 rcpt_to
235              
236             Simple Accessor.
237              
238             $mailenv->rcpt_to("Example User ");
239             print $mailenv->rcpt_to;
240              
241             $mailenv->rcpt_to("Example User , Another User ");
242             print $mailenv->rcpt_to;
243              
244             =cut
245              
246             sub rcpt_to {
247 4     4 1 8 my ($self,$val) = @_;
248 4 100       12 if($val){
249 2         7 $self->{data}{rcpt_to} = $val;
250 2         8 $self->{to_address} = [ Email::Address->parse($val) ];
251             }
252 4         371 return $self->{data}{rcpt_to};
253             }
254              
255             =head2 mail_from
256              
257             Simple Accessor.
258              
259             $mailenv->mail_from("Example User ");
260             print $mailenv->mail_from;
261              
262             =cut
263              
264             sub mail_from {
265 5     5 1 386 my ($self,$val) = @_;
266 5 100       12 if($val){
267 2         6 $self->{data}{mail_from} = $val;
268 2         15 my ($addr) = Email::Address->parse($val);
269 2         944 $self->{from_address} = $addr;
270 2         10 $self->{data}{mail_from} = $addr->format;
271             }
272 5         116 return $self->{data}{mail_from};
273             }
274              
275             =head2 helo
276              
277             Simple Accessor.
278              
279             $mailenv->helo("HELO mx.example.com");
280             print $mailenv->helo;
281              
282             =cut
283              
284             sub helo {
285 3     3 1 6 my ($self,$val) = @_;
286 3 100       11 $self->{data}{helo} = $val if $val;
287 3         13 return $self->{data}{helo};
288             }
289              
290             =head2 data
291              
292             Simple accessor. Uses an L object internally.
293              
294             $mailenv->data($rfc2822);
295             print $mailenv->data;
296              
297             =cut
298              
299             sub data {
300 3     3 1 532 my ($self,$val) = @_;
301 3 100       13 $self->{simple} = Email::Simple->new($val) if $val;
302 3         482 return $self->{simple}->as_string;
303             }
304              
305             =head2 simple
306              
307             Simple getter. Will return an L object based on the DATA that the current object contains.
308              
309             my $simple = $mailenv->simple;
310              
311             =cut
312              
313             sub simple {
314 1     1 1 3 my ($self) = @_;
315 1         6 return $self->{simple};
316             }
317              
318             =head2 to_address
319              
320             Simple getter. Will return an L object based on the RCPT_TO address that the current object contains.
321              
322             my $address = $mailenv->to_address;
323             my @addresses = $mailenv->to_address;
324              
325             NB: in scalar context to_address() will return the first address in the list.
326              
327             =cut
328              
329             sub to_address {
330 4     4 1 1488 my ($self) = @_;
331 4 100       12 return wantarray ? @{$self->{to_address}} : @{$self->{to_address}}[0];
  2         8  
  2         11  
332             }
333              
334             =head2 from_address
335              
336             Simple getter. Will return an L object based on the MAIL_FROM address that the current object contains.
337              
338             my $address = $mailenv->from_address;
339              
340             NB: Since RFC 2821 states that there can only be one MAIL_FROM address per smtp session, if you supply more than one MAIL_FROM format to mail_from() then you will only recieve back the first address in the list.
341              
342             =cut
343              
344             sub from_address {
345 1     1 1 3 my ($self) = @_;
346 1         4 return $self->{from_address};
347             }
348              
349              
350             1;
351              
352             =head1 COVERAGE
353              
354             This module has been written using test-first development. Below are the
355             Devel::Cover details.
356              
357             ---------------------------- ------ ------ ------ ------ ------ ------ ------
358             File stmt branch cond sub pod time total
359             ---------------------------- ------ ------ ------ ------ ------ ------ ------
360             blib/lib/Email/Envelope.pm 100.0 90.5 100.0 100.0 100.0 100.0 97.8
361             Total 100.0 90.5 100.0 100.0 100.0 100.0 97.8
362             ---------------------------- ------ ------ ------ ------ ------ ------ ------
363              
364             =head1 HISTORY
365              
366             =over
367              
368             =item 0.01
369              
370             Initial release to CPAN.
371              
372             =item 0.00_02
373              
374             Fixes to how Email::Address is used. Added mta_msg_id and received_timestamp.
375              
376             =item 0.00_01
377              
378             Initial implementation.
379              
380             =back
381              
382             =head1 TODO
383              
384             =over
385              
386             =item IPv6 support
387              
388             =back
389              
390             =head1 SEE ALSO
391              
392             L L
393              
394             =head1 AUTHOR
395              
396             Scott McWhirter Ekungfuftr@cpan.orgE
397              
398             =head1 SUPPORT
399              
400             This module is part of the Perl Email Project - http://pep.kwiki.org/
401              
402             There is a mailing list at pep@perl.org (subscribe at pep-subscribe@perl.org)
403             and an archive available at http://nntp.perl.org/group/pep.php
404              
405             =head1 COPYRIGHT AND LICENSE
406              
407             Copyright (C) 2004 by Scott McWhirter
408              
409             This library is released under a BSD licence, please see
410             L for more
411             information.
412              
413             =cut
414