File Coverage

blib/lib/Mail/Lite/Message.pm
Criterion Covered Total %
statement 74 88 84.0
branch 22 40 55.0
condition 13 28 46.4
subroutine 12 16 75.0
pod 0 9 0.0
total 121 181 66.8


line stmt bran cond sub pod time code
1             #
2             #===============================================================================
3             #
4             # FILE: Message.pm
5             #
6             # DESCRIPTION: Mail::Lite::Message -- extra lite message parsing.
7             #
8             # FILES: ---
9             # BUGS: ---
10             # NOTES: ---
11             # AUTHOR: Pavel Boldin (),
12             # COMPANY:
13             # VERSION: 1.0
14             # CREATED: 11.08.2008 14:25:41 MSD
15             # REVISION: ---
16             #===============================================================================
17              
18             package Mail::Lite::Message;
19              
20 2     2   16 use strict;
  2         7  
  2         90  
21 2     2   12 use warnings;
  2         5  
  2         71  
22              
23 2     2   1934 use MIME::Words;
  2         8892  
  2         124  
24              
25 2     2   31 use Smart::Comments -ENV;
  2         6  
  2         62  
26              
27 2     2   3295 use Carp;
  2         11  
  2         3455  
28              
29             # Init message object / parse_mail
30             # IN: message_body
31             sub new {
32 75     75 0 251690 my $self = {};
33              
34 75         266 bless $self, shift;
35              
36 75         156 my ($message) = @_;
37              
38 75         1272 @$self{ qw/raw_header body/ } = split (/\r?\n\r?\n/, $message, 2);
39              
40 75         788 $self->{raw_header} = "\n".$self->{raw_header}."\n";
41              
42 75 50       449 unless ( $self->{body} ) {
43 0         0 die "FATAL: no head/body separator found";
44             }
45              
46 75         385 return $self;
47             }
48              
49             sub _received {
50 21     21   25 my $self = shift;
51 21         27 my $value = shift;
52              
53 21 100 100     152 if ( $value =~ m/for ?;/is
54             && index( $1, '@localhost') < 0 ) {
55              
56 6   100     9 push @{ $self->{received_recipients} ||= [] }, $1;
  6         38  
57             }
58             }
59              
60             #sub _subject {
61             # my ($self, $value, $header) = @_;
62             #
63             # $self->{subject} = $header->{subject} = $value;
64             #}
65              
66             sub charset {
67 0     0 0 0 my $self = shift;
68              
69 0 0 0     0 $self->{charset} ||= ($self->header( 'content_type' ) && $self->header( 'content_type' ) =~ /charset=\"?([-\w]+)/ios) ? lc $1 : 'us-ascii';
      0        
70             }
71              
72             sub bound {
73 0     0 0 0 my $self = shift;
74              
75 0 0 0     0 $self->{bound} ||= $1 if $self->header( 'content_type' ) && $self->header( 'content_type' ) =~ m/multipart\/(?:mixed|report);.*?boundary=\"(.+?)\"/ios;
      0        
76             }
77              
78             sub raw_header {
79 0     0 0 0 my $self = shift;
80              
81 0         0 $self->{raw_header};
82             }
83              
84             sub _check_mime_and_reencode {
85 475     475   2284 my $value_ref = shift;
86 475         676 my $origname = shift;
87 475 100 66     3600 if ( $value_ref && $$value_ref && $$value_ref =~ m/\=\?(.+?)\?(.)\?/i ) {
      100        
88 1         9 my @values = MIME::Words::decode_mimewords( $$value_ref,
89             Field => $origname );
90              
91             # note -- code page
92 1         84 $$value_ref = join q{}, map { $_->[0] } @values;
  2         10  
93             }
94             }
95              
96             sub header {
97 552     552 0 1196 my ($self, $field) = @_;
98              
99 552 50       1085 confess unless $field;
100 552 100       3538 return $self->{header}{$field} if exists $self->{header}{$field};
101              
102 205         705 my $nfield = join '-', map { ucfirst } split /_/, $field;
  263         1348  
103              
104             #$field = 'Received';
105             #study($self->{raw_header});
106              
107             #my @data =
108             #pos($self->{raw_header}) = 0;
109             #my $r = $_header_regexps->{$field} ||= qr/\n$field:\s*((?:.+\n)(?:\s[^\n]+\n)*)/;
110 205         7753 $self->{raw_header} =~ /\n?$nfield:\s*((?:.+\n)(?:\s[^\n]+\n)*)/;
111              
112             # m/
113             # [\t ]* # skip all spaces
114             # ( # match
115             # (?: # group of
116             # (?!^[\w_\-]+:) # starting not with word after which ':' is present
117             # .+\n? # and all the string
118             # )+ # few times
119             # )
120             # /mx );
121              
122             #use Data::Dumper;
123             #warn Dumper \@data;
124             #die $self->{raw_header};
125 205         695 my $value = $1;
126 205         562 _check_mime_and_reencode( \$value, $nfield );
127              
128 205   100     1481 return $self->{header}{$field} = ($value || undef);
129             }
130              
131             sub headers {
132 29     29 0 53 my $self = shift;
133              
134 29 50       91 return $self->{header} if $self->{parsed_headers};
135              
136 29         49 my %header;
137            
138 29         47 my ($name, $origname, $value);
139              
140 29         93 $self->{raw_header} =~ s/^(From .*)\n//g;
141             #$self->{from} = $1;
142              
143 29         355 while ( $self->{raw_header} =~ /
144             (^[^:]+?) # start of field name
145             : # separator
146             [\t ]* # skip all spaces
147             ( # match
148             (?: # group of
149             (?!^[\w_\-]+:) # starting not with word after which ':' is present
150             .+\n? # and all the string
151             )+ # few times
152             )
153             /gmx )
154             {
155 270 50       799 next unless $2;
156             # next if $1 eq 'From' || $1 eq 'Subject';
157              
158 270         581 ($origname, $value) = ($1, $2);
159              
160 270         365 chomp $value;
161              
162 270         419 ($name = $origname) =~ tr/-A-Z/_a-z/;
163              
164 270         567 _check_mime_and_reencode( \$value, $origname );
165              
166 270 100       1674 if ( my $sub = $self->can("_$name") ) {
167 21         45 $sub->( $self, $value, \%header );
168 21         142 next;
169             }
170              
171 249 50       2330 $header{$name} = exists $header{$name} ?
172             $header{$name}."\n $value" : $value;
173             }
174              
175             #$header{subject } = $self->{subject };
176             #$header{from } = $self->{from };
177              
178             #### %header
179              
180             #use Data::Dumper;
181             #warn Dumper \%header;
182              
183 29         63 $self->{parsed_headers} = 1;
184 29         107 return $self->{header} = \%header;
185             }
186              
187             sub body {
188 464     464 0 688 my $self = shift;
189              
190 464         2516 $self->{body}
191             }
192              
193             sub recipients {
194 29     29 0 60 my $self = shift;
195              
196 29 50       132 unless ($self->{recipients}) {
197 29         112 my $header = $self->headers;
198 29 100       70 my @to = @{ $self->{received_recipients} || [] };
  29         177  
199 29 100       94 push @to, map { /<(.+?)>/ ? $1 : $_ } split /\n\s*/, $self->header('to') if $self->header('to');
  29 50       155  
200 29 0       92 push @to, map { /<(.+?)>/ ? $1 : $_ } split /\n\s*/, $self->header('cc') if $self->header('cc');
  0 50       0  
201 29 50 33     93 push @to, $1 if $self->header('x_rcpt_to')
202             && $self->header('x_rcpt_to') =~ m/^?$/i;
203              
204 29 50       94 my %tmp_to = map { index($_, '@') > 0 ? (lc $_ => 1) : () } @to;
  35         262  
205 29         170 $self->{recipients} = [ keys %tmp_to ];
206             }
207              
208 29         169 $self->{recipients};
209             }
210              
211             # protected
212              
213             sub slurp_file {
214 0     0 0   my ($filename) = @_;
215 0 0         open( my $fh, '<', $filename) or die "Can't open $filename!\n";
216 0           local($/) = undef;
217 0           my $temp = <$fh>;
218 0           close $fh;
219 0           return $temp;
220             }
221              
222             1;