File Coverage

blib/lib/Email/Filter.pm
Criterion Covered Total %
statement 63 88 71.5
branch 9 24 37.5
condition 3 11 27.2
subroutine 16 24 66.6
pod 9 13 69.2
total 100 160 62.5


line stmt bran cond sub pod time code
1 1     1   902 use strict;
  1         3  
  1         74  
2             package Email::Filter;
3             {
4             $Email::Filter::VERSION = '1.034';
5             }
6             # ABSTRACT: Library for creating easy email filters
7              
8 1     1   765 use Email::LocalDelivery;
  1         25665  
  1         27  
9 1     1   1020 use Email::Simple;
  1         5777  
  1         38  
10 1     1   871 use Class::Trigger;
  1         1137  
  1         7  
11 1     1   1331 use IPC::Run qw(run);
  1         36997  
  1         64  
12              
13 1     1   11 use constant DELIVERED => 0;
  1         1  
  1         67  
14 1     1   7 use constant TEMPFAIL => 75;
  1         1  
  1         42  
15 1     1   6 use constant REJECTED => 100;
  1         2  
  1         456  
16              
17              
18             sub done_ok {
19 2     2 0 9 my $self = shift;
20 2         9 $self->{delivered} = 1;
21 2 50       21 exit DELIVERED unless $self->{noexit};
22             }
23              
24             sub fail_badly {
25 0     0 0 0 my $self = shift;
26 0         0 $self->{giveup} = 1; # Don't get caught by DESTROY
27 0 0       0 exit TEMPFAIL unless $self->{noexit};
28 0         0 warn "Message ".$self->simple->header("Message-ID").
29             "was never handled properly\n";
30             }
31              
32             sub fail_gracefully {
33 0     0 0 0 my $self = shift;
34 0         0 our $FAILING_GRACEFULLY;
35 0 0 0     0 if ($self->{emergency} and ! $FAILING_GRACEFULLY) {
36 0         0 local $FAILING_GRACEFULLY = 1;
37 0 0       0 $self->done_ok if $self->accept($self->{emergency});
38             }
39 0         0 $self->fail_badly;
40             }
41              
42             sub DESTROY {
43 1     1   841 my $self = shift;
44 1 0 33     250 return if $self->{delivered} # All OK.
      33        
45             or $self->{giveup} # Tried emergency, didn't work.
46             or !$self->{emergency}; # Not much we can do.
47 0         0 $self->fail_gracefully();
48             }
49              
50              
51             sub new {
52 1     1 1 920 my $class = shift;
53 1         4 my %stuff = @_;
54 1         1 my $data;
55              
56             {
57 1         3 local $/;
  1         9  
58 1 50       3 $data = exists $stuff{data} ? $stuff{data} : scalar ;
59             # shave any leading From_ line
60 1         4 $data =~ s/^From .*?[\x0a\x0d]//
61             }
62              
63 1   50     10 my $obj = bless {
64             mail => Email::Simple->new($data),
65             emergency => $stuff{emergency},
66             noexit => ($stuff{noexit} || 0)
67             }, $class;
68 1         376 $obj->call_trigger("new");
69 1         70 return $obj;
70             }
71              
72              
73 1     1 1 906 sub exit { $_[0]->{noexit} = !$_[1]; }
74 0     0 0 0 sub noexit { $_[0]->{noexit} = $_[1]; }
75              
76              
77             sub simple {
78 3     3 1 8 my ($filter, $mail) = @_;
79 3 50       9 if ($mail) { $filter->{mail} = $mail; }
  0         0  
80 3         26 return $filter->{mail};
81             }
82              
83              
84 0     0 1 0 sub header { my ($mail, $head) = @_; $mail->simple->header($head); }
  0         0  
85              
86              
87 0     0 1 0 sub body { $_[0]->simple->body }
88              
89              
90 1     1   6 { no strict 'refs';
  1         1  
  1         387  
91             for my $head (qw(From To CC Bcc Subject Received)) {
92 0     0   0 *{lc $head} = sub { $_[0]->header($head) }
93             }
94             }
95              
96              
97             sub ignore {
98 0     0 1 0 $_[0]->call_trigger("ignore");
99 0         0 $_[0]->done_ok;
100             }
101              
102              
103             sub accept {
104 1     1 1 1193 my ($self, @where) = @_;
105 1         5 $self->call_trigger("before_accept", \@where);
106             # Unparsing and reparsing is so fast we prefer to do that in order
107             # to keep to LocalDelivery's clean interface.
108 1 50       49 if (Email::LocalDelivery->deliver($self->simple->as_string, @where)) {
109 1         10273 $self->call_trigger("after_accept", \@where);
110 1         78 $self->done_ok;
111             } else {
112 0         0 $self->fail_gracefully();
113             }
114             }
115              
116              
117             sub reject {
118 0     0 1 0 my $self = shift;
119 0         0 $self->call_trigger("reject");
120 0         0 $self->{delivered} = 1;
121 0         0 $! = REJECTED; die @_,"\n";
  0         0  
122             }
123              
124              
125             sub pipe {
126 2     2 1 2221 my ($self, @program) = @_;
127 2         11 my $arg;
128 2 50       34 $arg = (ref $program[-1] eq 'HASH') ? (pop @program) : {};
129              
130 2         4 my $stdout;
131              
132 2 50       16 my $string = $arg->{header_only}
133             ? $self->simple->header_obj->as_string
134             : $self->simple->as_string;
135              
136 2         313 $self->call_trigger("pipe", \@program, $arg);
137 2 100       122 if (eval {run(\@program, \$string, \$stdout)} ) {
  2         11  
138 1         24784 $self->done_ok;
139 1         15 return $stdout;
140             }
141 1 50       2665 $self->fail_gracefully() unless $self->{noexit};
142 1         19 return;
143             }
144              
145             1;
146              
147             __END__