line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
# Copyrights 2001-2022 by [Mark Overmeer ]. |
2
|
|
|
|
|
|
|
# For other contributors see ChangeLog. |
3
|
|
|
|
|
|
|
# See the manual pages for details on the licensing terms. |
4
|
|
|
|
|
|
|
# Pod stripped from pm file by OODoc 2.03. |
5
|
|
|
|
|
|
|
# This code is part of distribution Mail-Message. Meta-POD processed with |
6
|
|
|
|
|
|
|
# OODoc into POD and HTML manual-pages. See README.md |
7
|
|
|
|
|
|
|
# Copyright Mark Overmeer. Licensed under the same terms as Perl itself. |
8
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
package Mail::Message::Field; |
10
|
50
|
|
|
50
|
|
1056
|
use vars '$VERSION'; |
|
50
|
|
|
|
|
85
|
|
|
50
|
|
|
|
|
5417
|
|
11
|
|
|
|
|
|
|
$VERSION = '3.012'; |
12
|
|
|
|
|
|
|
|
13
|
50
|
|
|
50
|
|
284
|
use base 'Mail::Reporter'; |
|
50
|
|
|
|
|
1422
|
|
|
50
|
|
|
|
|
10707
|
|
14
|
|
|
|
|
|
|
|
15
|
50
|
|
|
50
|
|
307
|
use strict; |
|
50
|
|
|
|
|
110
|
|
|
50
|
|
|
|
|
985
|
|
16
|
50
|
|
|
50
|
|
218
|
use warnings; |
|
50
|
|
|
|
|
1464
|
|
|
50
|
|
|
|
|
1226
|
|
17
|
|
|
|
|
|
|
|
18
|
50
|
|
|
50
|
|
1492
|
use Carp; |
|
50
|
|
|
|
|
106
|
|
|
50
|
|
|
|
|
2714
|
|
19
|
50
|
|
|
50
|
|
22929
|
use Mail::Address; |
|
50
|
|
|
|
|
106639
|
|
|
50
|
|
|
|
|
1702
|
|
20
|
50
|
|
|
50
|
|
23830
|
use Date::Format 'strftime'; |
|
50
|
|
|
|
|
350795
|
|
|
50
|
|
|
|
|
3646
|
|
21
|
50
|
|
|
50
|
|
8502
|
use IO::Handle; |
|
50
|
|
|
|
|
84885
|
|
|
50
|
|
|
|
|
8322
|
|
22
|
|
|
|
|
|
|
|
23
|
|
|
|
|
|
|
our %_structured; # not to be used directly: call isStructured! |
24
|
|
|
|
|
|
|
my $default_wrap_length = 78; |
25
|
|
|
|
|
|
|
|
26
|
|
|
|
|
|
|
|
27
|
|
|
|
|
|
|
use overload |
28
|
377
|
|
|
377
|
|
978
|
qq("") => sub { $_[0]->unfoldedBody } |
29
|
2
|
50
|
|
2
|
|
26
|
, '0+' => sub { $_[0]->toInt || 0 } |
30
|
2299
|
|
|
2299
|
|
4946
|
, bool => sub {1} |
31
|
142
|
|
|
142
|
|
8671
|
, cmp => sub { $_[0]->unfoldedBody cmp "$_[1]" } |
32
|
10
|
100
|
|
10
|
|
174
|
, '<=>' => sub { $_[2] ? $_[1] <=> $_[0]->toInt : $_[0]->toInt <=> $_[1] } |
33
|
50
|
|
|
50
|
|
15302
|
, fallback => 1; |
|
50
|
|
|
|
|
12385
|
|
|
50
|
|
|
|
|
937
|
|
34
|
|
|
|
|
|
|
|
35
|
|
|
|
|
|
|
#------------------------------------------ |
36
|
|
|
|
|
|
|
|
37
|
|
|
|
|
|
|
|
38
|
|
|
|
|
|
|
sub new(@) |
39
|
599
|
|
|
599
|
1
|
2550
|
{ my $class = shift; |
40
|
599
|
100
|
|
|
|
1358
|
if($class eq __PACKAGE__) # bootstrap |
41
|
468
|
|
|
|
|
2579
|
{ require Mail::Message::Field::Fast; |
42
|
468
|
|
|
|
|
1390
|
return Mail::Message::Field::Fast->new(@_); |
43
|
|
|
|
|
|
|
} |
44
|
131
|
|
|
|
|
549
|
$class->SUPER::new(@_); |
45
|
|
|
|
|
|
|
} |
46
|
|
|
|
|
|
|
|
47
|
|
|
|
|
|
|
|
48
|
|
|
|
|
|
|
|
49
|
|
|
|
|
|
|
#------------------------------------------ |
50
|
|
|
|
|
|
|
|
51
|
|
|
|
|
|
|
|
52
|
161
|
|
|
161
|
1
|
354
|
sub length { length shift->folded } |
53
|
|
|
|
|
|
|
|
54
|
|
|
|
|
|
|
|
55
|
|
|
|
|
|
|
BEGIN { |
56
|
50
|
|
|
50
|
|
11803
|
%_structured = map { (lc($_) => 1) } |
|
1350
|
|
|
|
|
136885
|
|
57
|
|
|
|
|
|
|
qw/To Cc Bcc From Date Reply-To Sender |
58
|
|
|
|
|
|
|
Resent-Date Resent-From Resent-Sender Resent-To Return-Path |
59
|
|
|
|
|
|
|
List-Help List-Post List-Unsubscribe Mailing-List |
60
|
|
|
|
|
|
|
Received References Message-ID In-Reply-To |
61
|
|
|
|
|
|
|
Content-Type Content-Disposition Content-ID |
62
|
|
|
|
|
|
|
Delivered-To |
63
|
|
|
|
|
|
|
MIME-Version |
64
|
|
|
|
|
|
|
Precedence |
65
|
|
|
|
|
|
|
Status/; |
66
|
|
|
|
|
|
|
} |
67
|
|
|
|
|
|
|
|
68
|
|
|
|
|
|
|
sub isStructured(;$) |
69
|
697
|
50
|
|
697
|
1
|
1947
|
{ my $name = ref $_[0] ? shift->name : $_[1]; |
70
|
697
|
|
|
|
|
2538
|
exists $_structured{lc $name}; |
71
|
|
|
|
|
|
|
} |
72
|
|
|
|
|
|
|
|
73
|
|
|
|
|
|
|
|
74
|
|
|
|
|
|
|
sub print(;$) |
75
|
21
|
|
|
21
|
1
|
33
|
{ my $self = shift; |
76
|
21
|
|
33
|
|
|
47
|
my $fh = shift || select; |
77
|
21
|
|
|
|
|
110
|
$fh->print(scalar $self->folded); |
78
|
|
|
|
|
|
|
} |
79
|
|
|
|
|
|
|
|
80
|
|
|
|
|
|
|
|
81
|
27
|
|
|
27
|
0
|
1444
|
sub toString(;$) {shift->string(@_)} |
82
|
|
|
|
|
|
|
sub string(;$) |
83
|
93
|
|
|
93
|
1
|
8426
|
{ my $self = shift; |
84
|
93
|
100
|
|
|
|
282
|
return $self->folded unless @_; |
85
|
|
|
|
|
|
|
|
86
|
5
|
|
33
|
|
|
15
|
my $wrap = shift || $default_wrap_length; |
87
|
5
|
|
|
|
|
13
|
my $name = $self->Name; |
88
|
5
|
|
|
|
|
14
|
my @lines = $self->fold($name, $self->unfoldedBody, $wrap); |
89
|
5
|
|
|
|
|
16
|
$lines[0] = $name . ':' . $lines[0]; |
90
|
5
|
50
|
|
|
|
23
|
wantarray ? @lines : join('', @lines); |
91
|
|
|
|
|
|
|
} |
92
|
|
|
|
|
|
|
|
93
|
|
|
|
|
|
|
|
94
|
|
|
|
|
|
|
sub toDisclose() |
95
|
0
|
|
|
0
|
1
|
0
|
{ shift->name !~ m!^(?: (?:x-)?status |
96
|
|
|
|
|
|
|
| (?:resent-)?bcc |
97
|
|
|
|
|
|
|
| Content-Length |
98
|
|
|
|
|
|
|
| x-spam- |
99
|
|
|
|
|
|
|
) $!x; |
100
|
|
|
|
|
|
|
} |
101
|
|
|
|
|
|
|
|
102
|
|
|
|
|
|
|
|
103
|
122
|
|
|
122
|
1
|
309
|
sub nrLines() { my @l = shift->foldedBody; scalar @l } |
|
122
|
|
|
|
|
461
|
|
104
|
|
|
|
|
|
|
|
105
|
|
|
|
|
|
|
|
106
|
|
|
|
|
|
|
*size = \&length; |
107
|
|
|
|
|
|
|
|
108
|
|
|
|
|
|
|
#------------------------------------------ |
109
|
|
|
|
|
|
|
|
110
|
|
|
|
|
|
|
|
111
|
|
|
|
|
|
|
# attempt to change the case of a tag to that required by RFC822. That |
112
|
|
|
|
|
|
|
# being all characters are lowercase except the first of each |
113
|
|
|
|
|
|
|
# word. Also if the word is an `acronym' then all characters are |
114
|
|
|
|
|
|
|
# uppercase. We, rather arbitrarily, decide that a word is an acronym |
115
|
|
|
|
|
|
|
# if it does not contain a vowel and isn't the well-known 'Cc' or |
116
|
|
|
|
|
|
|
# 'Bcc' headers. |
117
|
|
|
|
|
|
|
|
118
|
|
|
|
|
|
|
my %wf_lookup |
119
|
|
|
|
|
|
|
= qw/mime MIME ldap LDAP soap SOAP swe SWE |
120
|
|
|
|
|
|
|
bcc Bcc cc Cc id ID/; |
121
|
|
|
|
|
|
|
|
122
|
|
|
|
|
|
|
sub wellformedName(;$) |
123
|
27
|
|
|
27
|
1
|
3409
|
{ my $thing = shift; |
124
|
27
|
100
|
|
|
|
75
|
my $name = @_ ? shift : $thing->name; |
125
|
|
|
|
|
|
|
|
126
|
|
|
|
|
|
|
join '-', |
127
|
27
|
100
|
|
|
|
80
|
map { $wf_lookup{lc $_} || ( /[aeiouyAEIOUY]/ ? ucfirst lc : uc ) } |
|
42
|
100
|
|
|
|
274
|
|
128
|
|
|
|
|
|
|
split /\-/, $name, -1; |
129
|
|
|
|
|
|
|
} |
130
|
|
|
|
|
|
|
|
131
|
|
|
|
|
|
|
#------------------------------------------ |
132
|
|
|
|
|
|
|
|
133
|
|
|
|
|
|
|
|
134
|
0
|
|
|
0
|
1
|
0
|
sub folded { shift->notImplemented } |
135
|
|
|
|
|
|
|
|
136
|
|
|
|
|
|
|
|
137
|
|
|
|
|
|
|
sub body() |
138
|
665
|
|
|
665
|
1
|
4730
|
{ my $self = shift; |
139
|
665
|
|
|
|
|
1556
|
my $body = $self->unfoldedBody; |
140
|
665
|
100
|
|
|
|
1521
|
return $body unless $self->isStructured; |
141
|
|
|
|
|
|
|
|
142
|
467
|
|
|
|
|
3105
|
my ($first) = $body =~ m/^((?:"[^"]*"|'[^']*'|[^;])*)/; |
143
|
467
|
|
|
|
|
972
|
$first =~ s/\s+$//; |
144
|
467
|
|
|
|
|
1930
|
$first; |
145
|
|
|
|
|
|
|
} |
146
|
|
|
|
|
|
|
|
147
|
|
|
|
|
|
|
|
148
|
0
|
|
|
0
|
1
|
0
|
sub foldedBody { shift->notImplemented } |
149
|
|
|
|
|
|
|
|
150
|
|
|
|
|
|
|
|
151
|
0
|
|
|
0
|
1
|
0
|
sub unfoldedBody { shift->notImplemented } |
152
|
|
|
|
|
|
|
|
153
|
|
|
|
|
|
|
|
154
|
|
|
|
|
|
|
sub stripCFWS($) |
155
|
55
|
|
|
55
|
1
|
11774
|
{ my $thing = shift; |
156
|
|
|
|
|
|
|
|
157
|
|
|
|
|
|
|
# get (folded) data |
158
|
55
|
100
|
|
|
|
122
|
my $string = @_ ? shift : $thing->foldedBody; |
159
|
|
|
|
|
|
|
|
160
|
|
|
|
|
|
|
# remove comments |
161
|
55
|
|
|
|
|
69
|
my $r = ''; |
162
|
55
|
|
|
|
|
68
|
my $in_dquotes = 0; |
163
|
55
|
|
|
|
|
58
|
my $open_paren = 0; |
164
|
|
|
|
|
|
|
|
165
|
55
|
|
|
|
|
291
|
my @s = split m/([()"])/, $string; |
166
|
55
|
|
|
|
|
125
|
while(@s) |
167
|
472
|
|
|
|
|
548
|
{ my $s = shift @s; |
168
|
|
|
|
|
|
|
|
169
|
472
|
100
|
100
|
|
|
1695
|
if(CORE::length($r)&& substr($r, -1) eq "\\") { $r .= $s } |
|
4
|
100
|
100
|
|
|
9
|
|
|
|
100
|
100
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
170
|
40
|
|
|
|
|
55
|
elsif($s eq '"') { $in_dquotes = not $in_dquotes; $r .= $s } |
|
40
|
|
|
|
|
59
|
|
171
|
80
|
|
|
|
|
129
|
elsif($s eq '(' && !$in_dquotes) { $open_paren++ } |
172
|
80
|
|
|
|
|
118
|
elsif($s eq ')' && !$in_dquotes) { $open_paren-- } |
173
|
|
|
|
|
|
|
elsif($open_paren) {} # in comment |
174
|
156
|
|
|
|
|
293
|
else { $r .= $s } |
175
|
|
|
|
|
|
|
} |
176
|
|
|
|
|
|
|
|
177
|
|
|
|
|
|
|
# beautify and unfold at the same time |
178
|
55
|
|
|
|
|
97
|
for($r) |
179
|
55
|
|
|
|
|
238
|
{ s/\s+/ /gs; |
180
|
55
|
|
|
|
|
162
|
s/\s+$//; |
181
|
55
|
|
|
|
|
126
|
s/^\s+//; |
182
|
|
|
|
|
|
|
} |
183
|
|
|
|
|
|
|
|
184
|
55
|
|
|
|
|
154
|
$r; |
185
|
|
|
|
|
|
|
} |
186
|
|
|
|
|
|
|
|
187
|
|
|
|
|
|
|
#------------------------------------------ |
188
|
|
|
|
|
|
|
|
189
|
|
|
|
|
|
|
|
190
|
|
|
|
|
|
|
sub comment(;$) |
191
|
31
|
|
|
31
|
1
|
57
|
{ my $self = shift; |
192
|
31
|
100
|
|
|
|
55
|
return undef unless $self->isStructured; |
193
|
|
|
|
|
|
|
|
194
|
27
|
|
|
|
|
64
|
my $body = $self->unfoldedBody; |
195
|
|
|
|
|
|
|
|
196
|
27
|
100
|
|
|
|
59
|
if(@_) |
197
|
2
|
|
|
|
|
5
|
{ my $comment = shift; |
198
|
2
|
|
|
|
|
5
|
$body =~ s/\s*\;.*//; |
199
|
2
|
50
|
33
|
|
|
13
|
$body .= "; $comment" if defined $comment && CORE::length($comment); |
200
|
2
|
|
|
|
|
7
|
$self->unfoldedBody($body); |
201
|
2
|
|
|
|
|
6
|
return $comment; |
202
|
|
|
|
|
|
|
} |
203
|
|
|
|
|
|
|
|
204
|
25
|
100
|
|
|
|
165
|
$body =~ s/.*?\;\s*// ? $body : ''; |
205
|
|
|
|
|
|
|
} |
206
|
|
|
|
|
|
|
|
207
|
10
|
|
|
10
|
1
|
24
|
sub content() { shift->unfoldedBody } # Compatibility |
208
|
|
|
|
|
|
|
|
209
|
|
|
|
|
|
|
|
210
|
|
|
|
|
|
|
sub attribute($;$) |
211
|
359
|
|
|
359
|
1
|
802
|
{ my ($self, $attr) = (shift, shift); |
212
|
359
|
|
|
|
|
798
|
my $body = $self->unfoldedBody; |
213
|
|
|
|
|
|
|
|
214
|
359
|
100
|
|
|
|
890
|
unless(@_) |
215
|
|
|
|
|
|
|
{ # only get a value |
216
|
250
|
100
|
|
|
|
5760
|
if($body =~ m/\b$attr\s*\=\s* |
217
|
|
|
|
|
|
|
( "( (?> [^\\"]+|\\. )* )" |
218
|
|
|
|
|
|
|
| ([^";\s]*) |
219
|
|
|
|
|
|
|
)/xi) |
220
|
165
|
|
|
|
|
609
|
{ (my $val = $+) =~ s/\\(.)/$1/g; |
221
|
165
|
|
|
|
|
699
|
return $val; |
222
|
|
|
|
|
|
|
} |
223
|
85
|
|
|
|
|
782
|
return undef; |
224
|
|
|
|
|
|
|
} |
225
|
|
|
|
|
|
|
|
226
|
|
|
|
|
|
|
# set the value |
227
|
109
|
|
|
|
|
229
|
my $value = shift; |
228
|
109
|
50
|
|
|
|
307
|
unless(defined $value) # remove attribute |
229
|
0
|
|
|
|
|
0
|
{ for($body) |
230
|
0
|
0
|
|
|
|
0
|
{ s/\b$attr\s*=\s*"(?>[^\\"]|\\.)*"//i |
231
|
|
|
|
|
|
|
or s/\b$attr\s*=\s*[;\s]*//i; |
232
|
|
|
|
|
|
|
} |
233
|
0
|
|
|
|
|
0
|
$self->unfoldedBody($body); |
234
|
0
|
|
|
|
|
0
|
return undef; |
235
|
|
|
|
|
|
|
} |
236
|
|
|
|
|
|
|
|
237
|
109
|
|
|
|
|
282
|
(my $quoted = $value) =~ s/(["\\])/\\$1/g; |
238
|
|
|
|
|
|
|
|
239
|
109
|
|
|
|
|
219
|
for($body) |
240
|
|
|
|
|
|
|
{ s/\b$attr\s*=\s*"(?>[^\\"]|\\.){0,1000}"/$attr="$quoted"/i |
241
|
|
|
|
|
|
|
or s/\b$attr\s*=\s*[^;\s]*/$attr="$quoted"/i |
242
|
109
|
100
|
100
|
|
|
2758
|
or do { $_ .= qq(; $attr="$quoted") } |
|
84
|
|
|
|
|
374
|
|
243
|
|
|
|
|
|
|
} |
244
|
|
|
|
|
|
|
|
245
|
109
|
|
|
|
|
366
|
$self->unfoldedBody($body); |
246
|
109
|
|
|
|
|
274
|
$value; |
247
|
|
|
|
|
|
|
} |
248
|
|
|
|
|
|
|
|
249
|
|
|
|
|
|
|
#------------------------------------------ |
250
|
|
|
|
|
|
|
|
251
|
|
|
|
|
|
|
|
252
|
|
|
|
|
|
|
sub attributes() |
253
|
1
|
|
|
1
|
1
|
3
|
{ my $self = shift; |
254
|
1
|
|
|
|
|
4
|
my $body = $self->unfoldedBody; |
255
|
|
|
|
|
|
|
|
256
|
1
|
|
|
|
|
2
|
my @attrs; |
257
|
1
|
|
|
|
|
12
|
while($body =~ m/\b(\w+)\s*\=\s* |
258
|
|
|
|
|
|
|
( "( (?: [^"]|\\" )* )" |
259
|
|
|
|
|
|
|
| '( (?: [^']|\\' )* )' |
260
|
|
|
|
|
|
|
| ([^;\s]*) |
261
|
|
|
|
|
|
|
) |
262
|
|
|
|
|
|
|
/xig) |
263
|
3
|
|
|
|
|
15
|
{ push @attrs, $1 => $+; |
264
|
|
|
|
|
|
|
} |
265
|
|
|
|
|
|
|
|
266
|
1
|
|
|
|
|
5
|
@attrs; |
267
|
|
|
|
|
|
|
} |
268
|
|
|
|
|
|
|
|
269
|
|
|
|
|
|
|
#------------------------------------------ |
270
|
|
|
|
|
|
|
|
271
|
|
|
|
|
|
|
|
272
|
|
|
|
|
|
|
sub toInt() |
273
|
12
|
|
|
12
|
1
|
19
|
{ my $self = shift; |
274
|
12
|
50
|
|
|
|
22
|
return $1 if $self->body =~ m/^\s*(\d+)\s*$/; |
275
|
|
|
|
|
|
|
|
276
|
0
|
|
|
|
|
0
|
$self->log(WARNING => "Field content is not numerical: ". $self->toString); |
277
|
|
|
|
|
|
|
|
278
|
0
|
|
|
|
|
0
|
return undef; |
279
|
|
|
|
|
|
|
} |
280
|
|
|
|
|
|
|
|
281
|
|
|
|
|
|
|
#------------------------------------------ |
282
|
|
|
|
|
|
|
|
283
|
|
|
|
|
|
|
|
284
|
|
|
|
|
|
|
my @weekday = qw/Sun Mon Tue Wed Thu Fri Sat Sun/; |
285
|
|
|
|
|
|
|
my @month = qw/Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec/; |
286
|
|
|
|
|
|
|
|
287
|
|
|
|
|
|
|
sub toDate(@) |
288
|
16
|
|
|
16
|
1
|
33
|
{ my $class = shift; |
289
|
16
|
0
|
|
|
|
1099
|
my @time = @_== 0 ? localtime() : @_==1 ? localtime(shift) : @_; |
|
|
50
|
|
|
|
|
|
290
|
16
|
|
|
|
|
117
|
my $format = "$weekday[$time[6]], %d $month[$time[4]] %Y %H:%M:%S %z"; |
291
|
16
|
|
|
|
|
115
|
my $time = strftime $format, @time; |
292
|
|
|
|
|
|
|
|
293
|
|
|
|
|
|
|
# for C libs which do not (GNU compliantly) support %z |
294
|
16
|
|
|
|
|
4144
|
$time =~ s/ (\%z|[A-Za-z ]+)$/_tz_offset($1)/e; |
|
0
|
|
|
|
|
0
|
|
295
|
|
|
|
|
|
|
|
296
|
16
|
|
|
|
|
87
|
$time; |
297
|
|
|
|
|
|
|
} |
298
|
|
|
|
|
|
|
|
299
|
|
|
|
|
|
|
sub _tz_offset($) |
300
|
0
|
|
|
0
|
|
0
|
{ my $zone = shift; |
301
|
0
|
|
|
|
|
0
|
require Time::Zone; |
302
|
|
|
|
|
|
|
|
303
|
0
|
0
|
|
|
|
0
|
my $diff = $zone eq '%z' ? Time::Zone::tz_local_offset() |
304
|
|
|
|
|
|
|
: Time::Zone::tz_offset($zone); |
305
|
0
|
|
|
|
|
0
|
my $minutes = int((abs($diff)+0.01) / 60); # float rounding errors |
306
|
0
|
|
|
|
|
0
|
my $hours = int(($minutes+0.01) / 60); |
307
|
0
|
|
|
|
|
0
|
$minutes -= $hours * 60; |
308
|
0
|
0
|
|
|
|
0
|
sprintf( ($diff < 0 ? " -%02d%02d" : " +%02d%02d"), $hours, $minutes); |
309
|
|
|
|
|
|
|
} |
310
|
|
|
|
|
|
|
|
311
|
|
|
|
|
|
|
#------------------------------------------ |
312
|
|
|
|
|
|
|
|
313
|
|
|
|
|
|
|
|
314
|
18
|
|
|
18
|
1
|
60
|
sub addresses() { Mail::Address->parse(shift->unfoldedBody) } |
315
|
|
|
|
|
|
|
|
316
|
|
|
|
|
|
|
#------------------------------------------ |
317
|
|
|
|
|
|
|
|
318
|
|
|
|
|
|
|
|
319
|
|
|
|
|
|
|
sub study() |
320
|
68
|
|
|
68
|
1
|
162
|
{ my $self = shift; |
321
|
68
|
|
|
|
|
448
|
require Mail::Message::Field::Full; |
322
|
68
|
|
|
|
|
262
|
Mail::Message::Field::Full->new(scalar $self->folded); |
323
|
|
|
|
|
|
|
} |
324
|
|
|
|
|
|
|
|
325
|
|
|
|
|
|
|
#------------------------------------------ |
326
|
|
|
|
|
|
|
|
327
|
|
|
|
|
|
|
|
328
|
|
|
|
|
|
|
sub dateToTimestamp($) |
329
|
1
|
|
|
1
|
1
|
7
|
{ my $string = $_[0]->stripCFWS($_[1]); |
330
|
|
|
|
|
|
|
|
331
|
|
|
|
|
|
|
# in RFC822, FWSes can appear within the time. |
332
|
1
|
|
|
|
|
16
|
$string =~ s/(\d\d)\s*\:\s*(\d\d)\s*\:\s*(\d\d)/$1:$2:$3/; |
333
|
|
|
|
|
|
|
|
334
|
1
|
|
|
|
|
735
|
require Date::Parse; |
335
|
1
|
|
|
|
|
2819
|
Date::Parse::str2time($string, 'GMT'); |
336
|
|
|
|
|
|
|
} |
337
|
|
|
|
|
|
|
|
338
|
|
|
|
|
|
|
|
339
|
|
|
|
|
|
|
#------------------------------------------ |
340
|
|
|
|
|
|
|
|
341
|
|
|
|
|
|
|
|
342
|
|
|
|
|
|
|
#=notice Empty field: $name |
343
|
|
|
|
|
|
|
#Empty fields are not allowed, however sometimes found in messages constructed |
344
|
|
|
|
|
|
|
#by broken applications. You probably want to ignore this message unless you |
345
|
|
|
|
|
|
|
#wrote this broken application yourself. |
346
|
|
|
|
|
|
|
|
347
|
|
|
|
|
|
|
sub consume($;$) |
348
|
777
|
|
|
777
|
1
|
1033
|
{ my $self = shift; |
349
|
777
|
100
|
|
|
|
1807
|
my ($name, $body) = defined $_[1] ? @_ : split(/\s*\:\s*/, (shift), 2); |
350
|
|
|
|
|
|
|
|
351
|
777
|
50
|
|
|
|
2236
|
Mail::Reporter->log(WARNING => "Illegal character in field name $name") |
352
|
|
|
|
|
|
|
if $name =~ m/[^\041-\071\073-\176]/; |
353
|
|
|
|
|
|
|
|
354
|
|
|
|
|
|
|
# |
355
|
|
|
|
|
|
|
# Compose the body. |
356
|
|
|
|
|
|
|
# |
357
|
|
|
|
|
|
|
|
358
|
777
|
100
|
|
|
|
2121
|
if(ref $body) # Objects or array |
|
|
100
|
|
|
|
|
|
359
|
28
|
50
|
|
|
|
101
|
{ my $flat = $self->stringifyData($body) or return (); |
360
|
28
|
|
|
|
|
87
|
$body = $self->fold($name, $flat); |
361
|
|
|
|
|
|
|
} |
362
|
|
|
|
|
|
|
elsif($body !~ s/\n+$/\n/g) # Added by user... |
363
|
702
|
|
|
|
|
1556
|
{ $body = $self->fold($name, $body); |
364
|
|
|
|
|
|
|
} |
365
|
|
|
|
|
|
|
else # Created by parser |
366
|
|
|
|
|
|
|
{ # correct erroneous wrap-seperators (dos files under UNIX) |
367
|
47
|
|
|
|
|
159
|
$body =~ s/[\012\015]+/\n/g; |
368
|
47
|
|
|
|
|
120
|
$body =~ s/^[ \t]*/ /; # start with one blank, folding kept unchanged |
369
|
|
|
|
|
|
|
|
370
|
47
|
50
|
|
|
|
108
|
$self->log(NOTICE => "Empty field: $name") |
371
|
|
|
|
|
|
|
if $body eq " \n"; |
372
|
|
|
|
|
|
|
} |
373
|
|
|
|
|
|
|
|
374
|
777
|
|
|
|
|
2194
|
($name, $body); |
375
|
|
|
|
|
|
|
} |
376
|
|
|
|
|
|
|
|
377
|
|
|
|
|
|
|
#------------------------------------------ |
378
|
|
|
|
|
|
|
|
379
|
|
|
|
|
|
|
|
380
|
|
|
|
|
|
|
sub stringifyData($) |
381
|
28
|
|
|
28
|
1
|
61
|
{ my ($self, $arg) = (shift, shift); |
382
|
28
|
|
|
|
|
46
|
my @addr; |
383
|
28
|
100
|
|
|
|
106
|
foreach my $obj (ref $arg eq 'ARRAY' ? @$arg : ($arg)) |
384
|
33
|
50
|
|
|
|
85
|
{ next unless defined $obj; |
385
|
|
|
|
|
|
|
|
386
|
33
|
100
|
|
|
|
85
|
if(!ref $obj) { push @addr, $obj; next } |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
3
|
|
387
|
32
|
100
|
|
|
|
168
|
if($obj->isa('Mail::Address')) { push @addr, $obj->format; next } |
|
19
|
|
|
|
|
85
|
|
|
19
|
|
|
|
|
718
|
|
388
|
|
|
|
|
|
|
|
389
|
13
|
100
|
100
|
|
|
128
|
if($obj->isa('Mail::Identity') || $obj->isa('User::Identity')) |
|
|
100
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
390
|
7
|
|
|
|
|
431
|
{ require Mail::Message::Field::Address; |
391
|
7
|
|
|
|
|
24
|
push @addr, Mail::Message::Field::Address->coerce($obj)->string; |
392
|
|
|
|
|
|
|
} |
393
|
|
|
|
|
|
|
elsif($obj->isa('User::Identity::Collection::Emails')) |
394
|
1
|
50
|
|
|
|
4
|
{ my @roles = $obj->roles or next; |
395
|
1
|
|
|
|
|
14
|
require Mail::Message::Field::AddrGroup; |
396
|
1
|
|
|
|
|
8
|
my $group = Mail::Message::Field::AddrGroup->coerce($obj); |
397
|
1
|
50
|
|
|
|
44
|
push @addr, $group->string if $group; |
398
|
|
|
|
|
|
|
} |
399
|
|
|
|
|
|
|
elsif($obj->isa('Mail::Message::Field')) |
400
|
|
|
|
|
|
|
{ |
401
|
5
|
|
|
|
|
25
|
my $folded = join ' ', $obj->foldedBody; |
402
|
5
|
|
|
|
|
35
|
$folded =~ s/^ //; |
403
|
5
|
|
|
|
|
20
|
$folded =~ s/\n\z//; |
404
|
5
|
|
|
|
|
15
|
push @addr, $folded; |
405
|
|
|
|
|
|
|
} |
406
|
|
|
|
|
|
|
else |
407
|
0
|
|
|
|
|
0
|
{ push @addr, "$obj"; # any other object is stringified |
408
|
|
|
|
|
|
|
} |
409
|
|
|
|
|
|
|
} |
410
|
|
|
|
|
|
|
|
411
|
28
|
50
|
|
|
|
121
|
@addr ? join(', ',@addr) : undef; |
412
|
|
|
|
|
|
|
} |
413
|
|
|
|
|
|
|
|
414
|
|
|
|
|
|
|
#------------------------------------------ |
415
|
|
|
|
|
|
|
|
416
|
|
|
|
|
|
|
|
417
|
|
|
|
|
|
|
sub setWrapLength(;$) |
418
|
350
|
|
|
350
|
1
|
471
|
{ my $self = shift; |
419
|
|
|
|
|
|
|
|
420
|
350
|
100
|
|
|
|
705
|
$self->foldedBody(scalar $self->fold($self->Name, $self->unfoldedBody, @_)) |
421
|
|
|
|
|
|
|
if @_; |
422
|
|
|
|
|
|
|
|
423
|
350
|
|
|
|
|
526
|
$self; |
424
|
|
|
|
|
|
|
} |
425
|
|
|
|
|
|
|
|
426
|
|
|
|
|
|
|
#------------------------------------------ |
427
|
|
|
|
|
|
|
|
428
|
|
|
|
|
|
|
|
429
|
|
|
|
|
|
|
sub defaultWrapLength(;$) |
430
|
0
|
|
|
0
|
1
|
0
|
{ my $self = shift; |
431
|
0
|
0
|
|
|
|
0
|
@_ ? ($default_wrap_length = shift) : $default_wrap_length; |
432
|
|
|
|
|
|
|
} |
433
|
|
|
|
|
|
|
|
434
|
|
|
|
|
|
|
#------------------------------------------ |
435
|
|
|
|
|
|
|
|
436
|
|
|
|
|
|
|
|
437
|
|
|
|
|
|
|
sub fold($$;$) |
438
|
927
|
|
|
927
|
1
|
1329
|
{ my $thing = shift; |
439
|
927
|
|
|
|
|
1143
|
my $name = shift; |
440
|
927
|
|
|
|
|
1187
|
my $line = shift; |
441
|
927
|
|
66
|
|
|
2386
|
my $wrap = shift || $default_wrap_length; |
442
|
927
|
100
|
|
|
|
1652
|
defined $line or $line = ''; |
443
|
|
|
|
|
|
|
|
444
|
927
|
|
|
|
|
1467
|
$line =~ s/\n\s/ /gms; # Remove accidental folding |
445
|
927
|
100
|
|
|
|
1644
|
return " \n" unless CORE::length($line); # empty field |
446
|
|
|
|
|
|
|
|
447
|
924
|
|
|
|
|
1260
|
my @folded; |
448
|
924
|
|
|
|
|
1099
|
while(1) |
449
|
979
|
100
|
|
|
|
1982
|
{ my $max = $wrap - (@folded ? 1 : CORE::length($name) + 2); |
450
|
979
|
|
|
|
|
1520
|
my $min = $max >> 2; |
451
|
979
|
100
|
|
|
|
2018
|
last if CORE::length($line) < $max; |
452
|
|
|
|
|
|
|
|
453
|
55
|
100
|
100
|
|
|
1293
|
$line =~ s/^ ( .{$min,$max} # $max to 30 chars |
|
|
|
100
|
|
|
|
|
454
|
|
|
|
|
|
|
[;,] # followed at a ; or , |
455
|
|
|
|
|
|
|
)[ \t] # and then a WSP |
456
|
|
|
|
|
|
|
//x |
457
|
|
|
|
|
|
|
|| $line =~ s/^ ( .{$min,$max} ) # $max to 30 chars |
458
|
|
|
|
|
|
|
[ \t] # followed by a WSP |
459
|
|
|
|
|
|
|
//x |
460
|
|
|
|
|
|
|
|| $line =~ s/^ ( .{$max,}? ) # longer, but minimal chars |
461
|
|
|
|
|
|
|
[ \t] # followed by a WSP |
462
|
|
|
|
|
|
|
//x |
463
|
|
|
|
|
|
|
|| $line =~ s/^ (.*) //x; # everything |
464
|
|
|
|
|
|
|
|
465
|
55
|
|
|
|
|
215
|
push @folded, " $1\n"; |
466
|
|
|
|
|
|
|
} |
467
|
|
|
|
|
|
|
|
468
|
924
|
100
|
|
|
|
2597
|
push @folded, " $line\n" if CORE::length($line); |
469
|
924
|
100
|
|
|
|
3231
|
wantarray ? @folded : join('', @folded); |
470
|
|
|
|
|
|
|
} |
471
|
|
|
|
|
|
|
|
472
|
|
|
|
|
|
|
|
473
|
|
|
|
|
|
|
sub unfold($) |
474
|
1630
|
|
|
1630
|
1
|
2200
|
{ my $string = $_[1]; |
475
|
1630
|
|
|
|
|
2655
|
for($string) |
476
|
1630
|
|
|
|
|
7272
|
{ s/\r?\n\s?/ /gs; # remove FWS |
477
|
1630
|
|
|
|
|
4287
|
s/^ +//; |
478
|
1630
|
|
|
|
|
4716
|
s/ +$//; |
479
|
|
|
|
|
|
|
} |
480
|
1630
|
|
|
|
|
5061
|
$string; |
481
|
|
|
|
|
|
|
} |
482
|
|
|
|
|
|
|
|
483
|
|
|
|
|
|
|
#------------------------------------------ |
484
|
|
|
|
|
|
|
|
485
|
|
|
|
|
|
|
|
486
|
|
|
|
|
|
|
1; |