| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
# This code is part of Perl distribution Mail-Message version 4.04. |
|
2
|
|
|
|
|
|
|
# The POD got stripped from this file by OODoc version 3.06. |
|
3
|
|
|
|
|
|
|
# For contributors see file ChangeLog. |
|
4
|
|
|
|
|
|
|
|
|
5
|
|
|
|
|
|
|
# This software is copyright (c) 2001-2026 by Mark Overmeer. |
|
6
|
|
|
|
|
|
|
|
|
7
|
|
|
|
|
|
|
# This is free software; you can redistribute it and/or modify it under |
|
8
|
|
|
|
|
|
|
# the same terms as the Perl 5 programming language system itself. |
|
9
|
|
|
|
|
|
|
# SPDX-License-Identifier: Artistic-1.0-Perl OR GPL-1.0-or-later |
|
10
|
|
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
|
|
12
|
|
|
|
|
|
|
package Mail::Message::Field;{ |
|
13
|
|
|
|
|
|
|
our $VERSION = '4.04'; |
|
14
|
|
|
|
|
|
|
} |
|
15
|
|
|
|
|
|
|
|
|
16
|
57
|
|
|
57
|
|
24701
|
use parent 'Mail::Reporter'; |
|
|
57
|
|
|
|
|
131
|
|
|
|
57
|
|
|
|
|
552
|
|
|
17
|
|
|
|
|
|
|
|
|
18
|
57
|
|
|
57
|
|
4150
|
use strict; |
|
|
57
|
|
|
|
|
133
|
|
|
|
57
|
|
|
|
|
1793
|
|
|
19
|
57
|
|
|
57
|
|
325
|
use warnings; |
|
|
57
|
|
|
|
|
144
|
|
|
|
57
|
|
|
|
|
5241
|
|
|
20
|
|
|
|
|
|
|
|
|
21
|
57
|
|
|
57
|
|
366
|
use Log::Report 'mail-message', import => [ qw/__x error info panic warning/ ]; |
|
|
57
|
|
|
|
|
211
|
|
|
|
57
|
|
|
|
|
636
|
|
|
22
|
|
|
|
|
|
|
|
|
23
|
57
|
|
|
57
|
|
43298
|
use Mail::Address (); |
|
|
57
|
|
|
|
|
236432
|
|
|
|
57
|
|
|
|
|
2037
|
|
|
24
|
57
|
|
|
57
|
|
12058
|
use IO::Handle (); |
|
|
57
|
|
|
|
|
146275
|
|
|
|
57
|
|
|
|
|
1921
|
|
|
25
|
57
|
|
|
57
|
|
31675
|
use Date::Format qw/strftime/; |
|
|
57
|
|
|
|
|
272840
|
|
|
|
57
|
|
|
|
|
5205
|
|
|
26
|
57
|
|
|
57
|
|
557
|
use Scalar::Util qw/blessed/; |
|
|
57
|
|
|
|
|
192
|
|
|
|
57
|
|
|
|
|
3196
|
|
|
27
|
57
|
|
|
57
|
|
39990
|
use Hash::Case::Preserve (); |
|
|
57
|
|
|
|
|
150937
|
|
|
|
57
|
|
|
|
|
11136
|
|
|
28
|
|
|
|
|
|
|
|
|
29
|
|
|
|
|
|
|
our %_structured; # not to be used directly: call isStructured! |
|
30
|
|
|
|
|
|
|
my $default_wrap_length = 78; |
|
31
|
|
|
|
|
|
|
|
|
32
|
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
use overload |
|
34
|
883
|
|
|
883
|
|
2759
|
qq("") => sub { $_[0]->unfoldedBody }, |
|
35
|
15
|
50
|
|
15
|
|
232
|
'0+' => sub { $_[0]->toInt || 0 }, |
|
36
|
3203
|
|
|
3203
|
|
8728
|
bool => sub {1}, |
|
37
|
238
|
|
|
238
|
|
20496
|
cmp => sub { $_[0]->unfoldedBody cmp "$_[1]" }, |
|
38
|
10
|
100
|
|
10
|
|
461
|
'<=>' => sub { $_[2] ? $_[1] <=> $_[0]->toInt : $_[0]->toInt <=> $_[1] }, |
|
39
|
57
|
|
|
57
|
|
588
|
fallback => 1; |
|
|
57
|
|
|
|
|
201
|
|
|
|
57
|
|
|
|
|
1225
|
|
|
40
|
|
|
|
|
|
|
|
|
41
|
|
|
|
|
|
|
#-------------------- |
|
42
|
|
|
|
|
|
|
|
|
43
|
|
|
|
|
|
|
sub new(@) |
|
44
|
1078
|
|
|
1078
|
1
|
8973
|
{ my $class = shift; |
|
45
|
1078
|
100
|
|
|
|
2903
|
if($class eq __PACKAGE__) # bootstrap |
|
46
|
895
|
|
|
|
|
6288
|
{ require Mail::Message::Field::Fast; |
|
47
|
895
|
|
|
|
|
3244
|
return Mail::Message::Field::Fast->new(@_); |
|
48
|
|
|
|
|
|
|
} |
|
49
|
183
|
|
|
|
|
985
|
$class->SUPER::new(@_); |
|
50
|
|
|
|
|
|
|
} |
|
51
|
|
|
|
|
|
|
|
|
52
|
|
|
|
|
|
|
|
|
53
|
|
|
|
|
|
|
#-------------------- |
|
54
|
|
|
|
|
|
|
|
|
55
|
|
|
|
|
|
|
# attempt to change the case of a tag to that required by RFC822. That |
|
56
|
|
|
|
|
|
|
# being all characters are lowercase except the first of each |
|
57
|
|
|
|
|
|
|
# word. Also if the word is an `acronym' then all characters are |
|
58
|
|
|
|
|
|
|
# uppercase. We, rather arbitrarily, decide that a word is an acronym |
|
59
|
|
|
|
|
|
|
# if it does not contain a vowel and isn't the well-known 'Cc' or |
|
60
|
|
|
|
|
|
|
# 'Bcc' headers. |
|
61
|
|
|
|
|
|
|
|
|
62
|
|
|
|
|
|
|
my %wf_lookup = qw/mime MIME ldap LDAP soap SOAP swe SWE bcc Bcc cc Cc id ID/; |
|
63
|
|
|
|
|
|
|
|
|
64
|
|
|
|
|
|
|
sub wellformedName(;$) |
|
65
|
27
|
|
|
27
|
1
|
8305
|
{ my $thing = shift; |
|
66
|
27
|
100
|
|
|
|
83
|
my $name = @_ ? shift : $thing->name; |
|
67
|
|
|
|
|
|
|
|
|
68
|
|
|
|
|
|
|
join '-', |
|
69
|
27
|
100
|
|
|
|
94
|
map { $wf_lookup{lc $_} || ( /[aeiouyAEIOUY]/ ? ucfirst lc : uc ) } |
|
|
42
|
100
|
|
|
|
410
|
|
|
70
|
|
|
|
|
|
|
split /\-/, $name, -1; |
|
71
|
|
|
|
|
|
|
} |
|
72
|
|
|
|
|
|
|
|
|
73
|
|
|
|
|
|
|
|
|
74
|
0
|
|
|
0
|
1
|
0
|
sub folded { $_[0]->notImplemented } |
|
75
|
|
|
|
|
|
|
|
|
76
|
|
|
|
|
|
|
|
|
77
|
|
|
|
|
|
|
sub body() |
|
78
|
786
|
|
|
786
|
1
|
24751
|
{ my $self = shift; |
|
79
|
786
|
|
|
|
|
2285
|
my $body = $self->unfoldedBody; |
|
80
|
786
|
100
|
|
|
|
2368
|
$self->isStructured or return $body; |
|
81
|
|
|
|
|
|
|
|
|
82
|
565
|
|
|
|
|
18255
|
my ($first) = $body =~ m/^((?:"[^"]*"|'[^']*'|[^;])*)/; |
|
83
|
565
|
|
|
|
|
4129
|
$first =~ s/\s+$//r; |
|
84
|
|
|
|
|
|
|
} |
|
85
|
|
|
|
|
|
|
|
|
86
|
|
|
|
|
|
|
|
|
87
|
0
|
|
|
0
|
1
|
0
|
sub foldedBody { $_[0]->notImplemented } |
|
88
|
|
|
|
|
|
|
|
|
89
|
|
|
|
|
|
|
|
|
90
|
0
|
|
|
0
|
1
|
0
|
sub unfoldedBody { $_[0]->notImplemented } |
|
91
|
|
|
|
|
|
|
|
|
92
|
|
|
|
|
|
|
#-------------------- |
|
93
|
|
|
|
|
|
|
|
|
94
|
172
|
|
|
172
|
1
|
429
|
sub length { length $_[0]->folded } |
|
95
|
|
|
|
|
|
|
|
|
96
|
|
|
|
|
|
|
|
|
97
|
|
|
|
|
|
|
BEGIN { |
|
98
|
57
|
|
|
57
|
|
303601
|
%_structured = map +(lc($_) => 1), qw/ |
|
99
|
|
|
|
|
|
|
To Cc Bcc From Date Reply-To Sender |
|
100
|
|
|
|
|
|
|
Resent-Date Resent-From Resent-Sender Resent-To Return-Path |
|
101
|
|
|
|
|
|
|
List-Help List-Post List-Unsubscribe Mailing-List |
|
102
|
|
|
|
|
|
|
Received References Message-ID In-Reply-To Delivered-To |
|
103
|
|
|
|
|
|
|
Content-Type Content-Disposition Content-ID |
|
104
|
|
|
|
|
|
|
MIME-Version Precedence Status |
|
105
|
|
|
|
|
|
|
/; |
|
106
|
|
|
|
|
|
|
} |
|
107
|
|
|
|
|
|
|
|
|
108
|
|
|
|
|
|
|
sub isStructured(;$) |
|
109
|
828
|
50
|
33
|
828
|
1
|
4023
|
{ my $name = $_[1] // (blessed $_[0] ? $_[0]->name : panic); |
|
110
|
828
|
|
|
|
|
5326
|
exists $_structured{lc $name}; |
|
111
|
|
|
|
|
|
|
} |
|
112
|
|
|
|
|
|
|
|
|
113
|
|
|
|
|
|
|
|
|
114
|
|
|
|
|
|
|
sub print(;$) |
|
115
|
21
|
|
|
21
|
1
|
45
|
{ my $self = shift; |
|
116
|
21
|
|
33
|
|
|
46
|
my $fh = shift || select; |
|
117
|
21
|
|
|
|
|
174
|
$fh->print(scalar $self->folded); |
|
118
|
|
|
|
|
|
|
} |
|
119
|
|
|
|
|
|
|
|
|
120
|
|
|
|
|
|
|
|
|
121
|
27
|
|
|
27
|
0
|
2878
|
sub toString(;$) { shift->string(@_) } |
|
122
|
|
|
|
|
|
|
|
|
123
|
|
|
|
|
|
|
sub string(;$) |
|
124
|
93
|
|
|
93
|
1
|
16716
|
{ my $self = shift; |
|
125
|
93
|
100
|
|
|
|
435
|
return $self->folded unless @_; |
|
126
|
|
|
|
|
|
|
|
|
127
|
5
|
|
33
|
|
|
16
|
my $wrap = shift || $default_wrap_length; |
|
128
|
5
|
|
|
|
|
32
|
my $name = $self->Name; |
|
129
|
5
|
|
|
|
|
18
|
my @lines = $self->fold($name, $self->unfoldedBody, $wrap); |
|
130
|
5
|
|
|
|
|
20
|
$lines[0] = $name . ':' . $lines[0]; |
|
131
|
5
|
50
|
|
|
|
25
|
wantarray ? @lines : join('', @lines); |
|
132
|
|
|
|
|
|
|
} |
|
133
|
|
|
|
|
|
|
|
|
134
|
|
|
|
|
|
|
|
|
135
|
|
|
|
|
|
|
sub toDisclose() |
|
136
|
0
|
|
|
0
|
1
|
0
|
{ $_[0]->name !~ m! ^ |
|
137
|
|
|
|
|
|
|
(?: (?:x-)?status |
|
138
|
|
|
|
|
|
|
| (?:resent-)?bcc |
|
139
|
|
|
|
|
|
|
| content-length |
|
140
|
|
|
|
|
|
|
| x-spam- |
|
141
|
|
|
|
|
|
|
) $ !x; |
|
142
|
|
|
|
|
|
|
} |
|
143
|
|
|
|
|
|
|
|
|
144
|
|
|
|
|
|
|
|
|
145
|
135
|
|
|
135
|
1
|
399
|
sub nrLines() { my @l = $_[0]->foldedBody; scalar @l } |
|
|
135
|
|
|
|
|
609
|
|
|
146
|
|
|
|
|
|
|
|
|
147
|
|
|
|
|
|
|
|
|
148
|
|
|
|
|
|
|
*size = \&length; |
|
149
|
|
|
|
|
|
|
|
|
150
|
|
|
|
|
|
|
#-------------------- |
|
151
|
|
|
|
|
|
|
|
|
152
|
|
|
|
|
|
|
sub stripCFWS($) |
|
153
|
55
|
|
|
55
|
1
|
197410
|
{ my $thing = shift; |
|
154
|
|
|
|
|
|
|
|
|
155
|
|
|
|
|
|
|
# get (folded) data |
|
156
|
55
|
100
|
|
|
|
138
|
my $string = @_ ? shift : $thing->foldedBody; |
|
157
|
|
|
|
|
|
|
|
|
158
|
|
|
|
|
|
|
# remove comments |
|
159
|
55
|
|
|
|
|
97
|
my $r = ''; |
|
160
|
55
|
|
|
|
|
61
|
my $in_dquotes = 0; |
|
161
|
55
|
|
|
|
|
63
|
my $open_paren = 0; |
|
162
|
|
|
|
|
|
|
|
|
163
|
55
|
|
|
|
|
322
|
my @s = split m/([()"])/, $string; |
|
164
|
55
|
|
|
|
|
117
|
while(@s) |
|
165
|
472
|
|
|
|
|
512
|
{ my $s = shift @s; |
|
166
|
|
|
|
|
|
|
|
|
167
|
472
|
100
|
100
|
|
|
1675
|
if(CORE::length($r)&& substr($r, -1) eq "\\") { $r .= $s } |
|
|
4
|
100
|
100
|
|
|
10
|
|
|
|
|
100
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
168
|
40
|
|
|
|
|
47
|
elsif($s eq '"') { $in_dquotes = not $in_dquotes; $r .= $s } |
|
|
40
|
|
|
|
|
57
|
|
|
169
|
80
|
|
|
|
|
112
|
elsif($s eq '(' && !$in_dquotes) { $open_paren++ } |
|
170
|
80
|
|
|
|
|
109
|
elsif($s eq ')' && !$in_dquotes) { $open_paren-- } |
|
171
|
|
|
|
|
|
|
elsif($open_paren) {} # in comment |
|
172
|
156
|
|
|
|
|
257
|
else { $r .= $s } |
|
173
|
|
|
|
|
|
|
} |
|
174
|
|
|
|
|
|
|
|
|
175
|
|
|
|
|
|
|
# beautify and unfold at the same time |
|
176
|
55
|
|
|
|
|
545
|
$r =~ s/\s+/ /grs =~ s/\s+$//r =~ s/^\s+//r; |
|
177
|
|
|
|
|
|
|
} |
|
178
|
|
|
|
|
|
|
|
|
179
|
|
|
|
|
|
|
|
|
180
|
|
|
|
|
|
|
sub comment(;$) |
|
181
|
41
|
|
|
41
|
1
|
3569
|
{ my $self = shift; |
|
182
|
41
|
100
|
|
|
|
116
|
$self->isStructured or return undef; |
|
183
|
|
|
|
|
|
|
|
|
184
|
37
|
|
|
|
|
109
|
my $body = $self->unfoldedBody; |
|
185
|
|
|
|
|
|
|
|
|
186
|
37
|
100
|
|
|
|
148
|
if(@_) |
|
187
|
2
|
|
|
|
|
5
|
{ my $comment = shift; |
|
188
|
2
|
|
|
|
|
6
|
$body =~ s/\s*\;.*//; |
|
189
|
2
|
50
|
33
|
|
|
16
|
$body .= "; $comment" if defined $comment && CORE::length($comment); |
|
190
|
2
|
|
|
|
|
10
|
$self->unfoldedBody($body); |
|
191
|
2
|
|
|
|
|
6
|
return $comment; |
|
192
|
|
|
|
|
|
|
} |
|
193
|
|
|
|
|
|
|
|
|
194
|
35
|
100
|
|
|
|
266
|
$body =~ s/.*?\;\s*// ? $body : ''; |
|
195
|
|
|
|
|
|
|
} |
|
196
|
|
|
|
|
|
|
|
|
197
|
10
|
|
|
10
|
1
|
28
|
sub content() { shift->unfoldedBody } # Compatibility |
|
198
|
|
|
|
|
|
|
|
|
199
|
|
|
|
|
|
|
|
|
200
|
|
|
|
|
|
|
sub attribute($;$) |
|
201
|
477
|
|
|
477
|
1
|
7847
|
{ my ($self, $attr) = (shift, shift); |
|
202
|
|
|
|
|
|
|
|
|
203
|
|
|
|
|
|
|
# Although each attribute can appear only once, some (intentionally) |
|
204
|
|
|
|
|
|
|
# broken messages do repeat them. See github issue 20. Apple Mail and |
|
205
|
|
|
|
|
|
|
# Outlook will take the last of the repeated in such case, so we do that |
|
206
|
|
|
|
|
|
|
# as well. |
|
207
|
477
|
|
|
|
|
1490
|
tie my %attrs, 'Hash::Case::Preserve', [ $self->attributes ]; |
|
208
|
477
|
100
|
|
|
|
30300
|
@_ or return $attrs{$attr}; |
|
209
|
|
|
|
|
|
|
|
|
210
|
|
|
|
|
|
|
# set the value |
|
211
|
153
|
|
|
|
|
334
|
my $value = shift; |
|
212
|
153
|
|
|
|
|
498
|
my $body = $self->unfoldedBody; |
|
213
|
|
|
|
|
|
|
|
|
214
|
153
|
50
|
|
|
|
528
|
unless(defined $value) # remove attribute |
|
215
|
0
|
|
|
|
|
0
|
{ for($body) |
|
216
|
0
|
0
|
|
|
|
0
|
{ s/\b$attr\s*=\s*"(?>[^\\"]|\\.)*"//i or s/\b$attr\s*=\s*[;\s]*//i; |
|
217
|
|
|
|
|
|
|
} |
|
218
|
0
|
|
|
|
|
0
|
$self->unfoldedBody($body); |
|
219
|
0
|
|
|
|
|
0
|
return undef; |
|
220
|
|
|
|
|
|
|
} |
|
221
|
|
|
|
|
|
|
|
|
222
|
153
|
|
|
|
|
502
|
my $quoted = $value =~ s/(["\\])/\\$1/gr; |
|
223
|
|
|
|
|
|
|
|
|
224
|
153
|
|
|
|
|
373
|
for($body) |
|
225
|
|
|
|
|
|
|
{ s/\b$attr\s*=\s*"(?>[^\\"]|\\.){0,1000}"/$attr="$quoted"/i |
|
226
|
|
|
|
|
|
|
or s/\b$attr\s*=\s*[^;\s]*/$attr="$quoted"/i |
|
227
|
153
|
100
|
100
|
|
|
17559
|
or do { $_ .= qq(; $attr="$quoted") } |
|
|
127
|
|
|
|
|
617
|
|
|
228
|
|
|
|
|
|
|
} |
|
229
|
|
|
|
|
|
|
|
|
230
|
153
|
|
|
|
|
679
|
$self->unfoldedBody($body); |
|
231
|
153
|
|
|
|
|
1096
|
$value; |
|
232
|
|
|
|
|
|
|
} |
|
233
|
|
|
|
|
|
|
|
|
234
|
|
|
|
|
|
|
|
|
235
|
|
|
|
|
|
|
sub attributes() |
|
236
|
479
|
|
|
479
|
1
|
1748
|
{ my $self = shift; |
|
237
|
479
|
|
|
|
|
1434
|
my $body = $self->unfoldedBody; |
|
238
|
|
|
|
|
|
|
|
|
239
|
479
|
|
|
|
|
850
|
my @attrs; |
|
240
|
479
|
|
|
|
|
4857
|
while($body =~ m/ \b(\w+)\s*\=\s* ( "( (?: [^"]|\\" )* )" | '( (?: [^']|\\' )* )' | ([^;\s]*) ) /xig) |
|
241
|
246
|
|
|
|
|
1555
|
{ push @attrs, $1 => $+; |
|
242
|
|
|
|
|
|
|
} |
|
243
|
|
|
|
|
|
|
|
|
244
|
479
|
|
|
|
|
4693
|
@attrs; |
|
245
|
|
|
|
|
|
|
} |
|
246
|
|
|
|
|
|
|
|
|
247
|
|
|
|
|
|
|
|
|
248
|
|
|
|
|
|
|
sub toInt() |
|
249
|
25
|
|
|
25
|
1
|
50
|
{ my $self = shift; |
|
250
|
25
|
50
|
|
|
|
69
|
$self->body =~ m/^\s*(\d+)\s*$/ |
|
251
|
|
|
|
|
|
|
and return $1; |
|
252
|
|
|
|
|
|
|
|
|
253
|
0
|
|
|
|
|
0
|
warning __x"field content is not numerical: {content}", content => $self->toString; |
|
254
|
0
|
|
|
|
|
0
|
undef; |
|
255
|
|
|
|
|
|
|
} |
|
256
|
|
|
|
|
|
|
|
|
257
|
|
|
|
|
|
|
|
|
258
|
|
|
|
|
|
|
my @weekday = qw/Sun Mon Tue Wed Thu Fri Sat Sun/; |
|
259
|
|
|
|
|
|
|
my @month = qw/Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec/; |
|
260
|
|
|
|
|
|
|
|
|
261
|
|
|
|
|
|
|
sub toDate(@) |
|
262
|
16
|
|
|
16
|
1
|
35
|
{ my $class = shift; |
|
263
|
16
|
0
|
|
|
|
931
|
my @time = @_== 0 ? localtime() : @_==1 ? localtime(shift) : @_; |
|
|
|
50
|
|
|
|
|
|
|
264
|
16
|
|
|
|
|
81
|
my $format = "$weekday[$time[6]], %d $month[$time[4]] %Y %H:%M:%S %z"; |
|
265
|
16
|
|
|
|
|
147
|
my $time = strftime $format, @time; |
|
266
|
|
|
|
|
|
|
|
|
267
|
|
|
|
|
|
|
# for C libs which do not (GNU compliantly) support %z |
|
268
|
16
|
|
|
|
|
4690
|
$time =~ s/ (\%z|[A-Za-z ]+)$/_tz_offset($1)/re; |
|
|
0
|
|
|
|
|
0
|
|
|
269
|
|
|
|
|
|
|
} |
|
270
|
|
|
|
|
|
|
|
|
271
|
|
|
|
|
|
|
sub _tz_offset($) |
|
272
|
0
|
|
|
0
|
|
0
|
{ my $zone = shift; |
|
273
|
0
|
|
|
|
|
0
|
require Time::Zone; |
|
274
|
|
|
|
|
|
|
|
|
275
|
0
|
0
|
|
|
|
0
|
my $diff = $zone eq '%z' ? Time::Zone::tz_local_offset() : Time::Zone::tz_offset($zone); |
|
276
|
0
|
|
|
|
|
0
|
my $minutes = int((abs($diff)+0.01) / 60); # float rounding errors |
|
277
|
0
|
|
|
|
|
0
|
my $hours = int(($minutes+0.01) / 60); |
|
278
|
0
|
|
|
|
|
0
|
$minutes -= $hours * 60; |
|
279
|
0
|
0
|
|
|
|
0
|
sprintf +($diff < 0 ? " -%02d%02d" : " +%02d%02d"), $hours, $minutes; |
|
280
|
|
|
|
|
|
|
} |
|
281
|
|
|
|
|
|
|
|
|
282
|
|
|
|
|
|
|
|
|
283
|
18
|
|
|
18
|
1
|
62
|
sub addresses() { Mail::Address->parse(shift->unfoldedBody) } |
|
284
|
|
|
|
|
|
|
|
|
285
|
|
|
|
|
|
|
|
|
286
|
|
|
|
|
|
|
sub study() |
|
287
|
93
|
|
|
93
|
1
|
456
|
{ my $self = shift; |
|
288
|
93
|
|
|
|
|
733
|
require Mail::Message::Field::Full; |
|
289
|
93
|
|
|
|
|
448
|
Mail::Message::Field::Full->new(scalar $self->folded); |
|
290
|
|
|
|
|
|
|
} |
|
291
|
|
|
|
|
|
|
|
|
292
|
|
|
|
|
|
|
|
|
293
|
|
|
|
|
|
|
sub dateToTimestamp($) |
|
294
|
1
|
|
|
1
|
1
|
6
|
{ my $string = $_[0]->stripCFWS($_[1]); |
|
295
|
|
|
|
|
|
|
|
|
296
|
|
|
|
|
|
|
# in RFC822, FWSes can appear within the time. |
|
297
|
1
|
|
|
|
|
16
|
$string =~ s/(\d\d)\s*\:\s*(\d\d)\s*\:\s*(\d\d)/$1:$2:$3/; |
|
298
|
|
|
|
|
|
|
|
|
299
|
1
|
|
|
|
|
9
|
require Date::Parse; |
|
300
|
1
|
|
|
|
|
7
|
Date::Parse::str2time($string, 'GMT'); |
|
301
|
|
|
|
|
|
|
} |
|
302
|
|
|
|
|
|
|
|
|
303
|
|
|
|
|
|
|
#-------------------- |
|
304
|
|
|
|
|
|
|
|
|
305
|
|
|
|
|
|
|
sub consume($;$) |
|
306
|
1977
|
|
|
1977
|
1
|
3407
|
{ my $self = shift; |
|
307
|
1977
|
100
|
|
|
|
5729
|
my ($name, $body) = defined $_[1] ? @_ : split(/\s*\:\s*/, (shift), 2); |
|
308
|
|
|
|
|
|
|
|
|
309
|
1977
|
50
|
|
|
|
8197
|
$name !~ m/[^\041-\071\073-\176]/ |
|
310
|
|
|
|
|
|
|
or warning __x"illegal character in field name '{name}'.", name => $name; |
|
311
|
1977
|
50
|
|
|
|
5141
|
panic $name if $name =~ m/[^\041-\071\073-\176]/; |
|
312
|
|
|
|
|
|
|
|
|
313
|
|
|
|
|
|
|
# |
|
314
|
|
|
|
|
|
|
# Compose the body. |
|
315
|
|
|
|
|
|
|
# |
|
316
|
|
|
|
|
|
|
|
|
317
|
1977
|
100
|
|
|
|
8785
|
if(ref $body) # Objects or array |
|
|
|
100
|
|
|
|
|
|
|
318
|
28
|
|
50
|
|
|
106
|
{ my $flat = $self->stringifyData($body) // return (); |
|
319
|
28
|
|
|
|
|
103
|
$body = $self->fold($name, $flat); |
|
320
|
|
|
|
|
|
|
} |
|
321
|
|
|
|
|
|
|
elsif($body !~ s/\n+$/\n/g) # Added by user... |
|
322
|
1144
|
|
|
|
|
3258
|
{ $body = $self->fold($name, $body); |
|
323
|
|
|
|
|
|
|
} |
|
324
|
|
|
|
|
|
|
else # Created by parser |
|
325
|
|
|
|
|
|
|
{ # correct erroneous wrap-seperators (dos files under UNIX) |
|
326
|
805
|
|
|
|
|
4927
|
$body =~ s/[\012\015]+/\n/g; |
|
327
|
805
|
|
|
|
|
2789
|
$body =~ s/^[ \t]*/ /; # start with one blank, folding kept unchanged |
|
328
|
|
|
|
|
|
|
} |
|
329
|
|
|
|
|
|
|
|
|
330
|
1977
|
|
|
|
|
7269
|
($name, $body); |
|
331
|
|
|
|
|
|
|
} |
|
332
|
|
|
|
|
|
|
|
|
333
|
|
|
|
|
|
|
|
|
334
|
|
|
|
|
|
|
sub stringifyData($) |
|
335
|
28
|
|
|
28
|
1
|
67
|
{ my ($self, $arg) = (shift, shift); |
|
336
|
28
|
|
|
|
|
53
|
my @addr; |
|
337
|
28
|
100
|
|
|
|
110
|
foreach my $obj (ref $arg eq 'ARRAY' ? @$arg : ($arg)) |
|
338
|
33
|
50
|
|
|
|
92
|
{ defined $obj or next; |
|
339
|
|
|
|
|
|
|
|
|
340
|
33
|
100
|
|
|
|
83
|
if(!ref $obj) { push @addr, $obj; next } |
|
|
1
|
|
|
|
|
3
|
|
|
|
1
|
|
|
|
|
4
|
|
|
341
|
32
|
100
|
|
|
|
606
|
if($obj->isa('Mail::Address')) { push @addr, $obj->format; next } |
|
|
19
|
|
|
|
|
77
|
|
|
|
19
|
|
|
|
|
966
|
|
|
342
|
|
|
|
|
|
|
|
|
343
|
13
|
100
|
100
|
|
|
170
|
if($obj->isa('Mail::Identity') || $obj->isa('User::Identity')) |
|
|
|
100
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
344
|
7
|
|
|
|
|
770
|
{ require Mail::Message::Field::Address; |
|
345
|
7
|
|
|
|
|
31
|
push @addr, Mail::Message::Field::Address->coerce($obj)->string; |
|
346
|
|
|
|
|
|
|
} |
|
347
|
|
|
|
|
|
|
elsif($obj->isa('User::Identity::Collection::Emails')) |
|
348
|
1
|
50
|
|
|
|
6
|
{ my @roles = $obj->roles or next; |
|
349
|
1
|
|
|
|
|
61
|
require Mail::Message::Field::AddrGroup; |
|
350
|
1
|
|
|
|
|
8
|
my $group = Mail::Message::Field::AddrGroup->coerce($obj); |
|
351
|
1
|
50
|
|
|
|
105
|
push @addr, $group->string if $group; |
|
352
|
|
|
|
|
|
|
} |
|
353
|
|
|
|
|
|
|
elsif($obj->isa('Mail::Message::Field')) |
|
354
|
5
|
|
|
|
|
21
|
{ my $folded = join ' ', $obj->foldedBody; |
|
355
|
5
|
|
|
|
|
48
|
push @addr, $folded =~ s/^ //r =~ s/\n\z//r; |
|
356
|
|
|
|
|
|
|
} |
|
357
|
|
|
|
|
|
|
else |
|
358
|
0
|
|
|
|
|
0
|
{ push @addr, "$obj"; # any other object is stringified |
|
359
|
|
|
|
|
|
|
} |
|
360
|
|
|
|
|
|
|
} |
|
361
|
|
|
|
|
|
|
|
|
362
|
28
|
50
|
|
|
|
141
|
@addr ? join(', ',@addr) : undef; |
|
363
|
|
|
|
|
|
|
} |
|
364
|
|
|
|
|
|
|
|
|
365
|
|
|
|
|
|
|
|
|
366
|
|
|
|
|
|
|
sub setWrapLength(;$) |
|
367
|
368
|
|
|
368
|
1
|
582
|
{ my $self = shift; |
|
368
|
|
|
|
|
|
|
|
|
369
|
368
|
100
|
|
|
|
1587
|
$self->foldedBody(scalar $self->fold($self->Name, $self->unfoldedBody, $_[0])) |
|
370
|
|
|
|
|
|
|
if @_; |
|
371
|
|
|
|
|
|
|
|
|
372
|
368
|
|
|
|
|
634
|
$self; |
|
373
|
|
|
|
|
|
|
} |
|
374
|
|
|
|
|
|
|
|
|
375
|
|
|
|
|
|
|
|
|
376
|
|
|
|
|
|
|
sub defaultWrapLength(;$) |
|
377
|
0
|
|
|
0
|
1
|
0
|
{ my $self = shift; |
|
378
|
0
|
0
|
|
|
|
0
|
@_ ? ($default_wrap_length = shift) : $default_wrap_length; |
|
379
|
|
|
|
|
|
|
} |
|
380
|
|
|
|
|
|
|
|
|
381
|
|
|
|
|
|
|
|
|
382
|
|
|
|
|
|
|
sub fold($$;$) |
|
383
|
1443
|
|
|
1443
|
1
|
2557
|
{ my $thing = shift; |
|
384
|
1443
|
|
|
|
|
2319
|
my $name = shift; |
|
385
|
1443
|
|
|
|
|
2503
|
my $line = shift; |
|
386
|
1443
|
|
66
|
|
|
6593
|
my $wrap = shift || $default_wrap_length; |
|
387
|
1443
|
|
100
|
|
|
3349
|
$line //= ''; |
|
388
|
|
|
|
|
|
|
|
|
389
|
1443
|
|
|
|
|
2910
|
$line =~ s/\n(\s)/$1/gms; # Remove accidental folding |
|
390
|
1443
|
100
|
|
|
|
3520
|
CORE::length($line) or return " \n"; # empty field |
|
391
|
|
|
|
|
|
|
|
|
392
|
1440
|
|
|
|
|
2440
|
my $lname = CORE::length($name); |
|
393
|
1440
|
50
|
|
|
|
3430
|
$lname <= $wrap -5 # Cannot find a real limit in the spec |
|
394
|
|
|
|
|
|
|
or error __x"field name too long (max {count}), in '{name}'.", count => $wrap - 5, name => $name; |
|
395
|
|
|
|
|
|
|
|
|
396
|
1440
|
|
|
|
|
5804
|
my @folded; |
|
397
|
1440
|
|
|
|
|
3980
|
while(1) |
|
398
|
1495
|
100
|
|
|
|
3765
|
{ my $max = $wrap - (@folded ? 1 : $lname + 2); |
|
399
|
1495
|
|
|
|
|
2791
|
my $min = $max >> 2; |
|
400
|
1495
|
100
|
|
|
|
4094
|
last if CORE::length($line) < $max; |
|
401
|
|
|
|
|
|
|
|
|
402
|
55
|
100
|
100
|
|
|
3264
|
$line =~ s/^ ( .{$min,$max} # $max to 30 chars |
|
|
|
|
100
|
|
|
|
|
|
403
|
|
|
|
|
|
|
[;,] # followed at a ; or , |
|
404
|
|
|
|
|
|
|
)[ \t] # and then a WSP |
|
405
|
|
|
|
|
|
|
//x |
|
406
|
|
|
|
|
|
|
|| $line =~ s/^ ( .{$min,$max} ) # $max to 30 chars |
|
407
|
|
|
|
|
|
|
[ \t] # followed by a WSP |
|
408
|
|
|
|
|
|
|
//x |
|
409
|
|
|
|
|
|
|
|| $line =~ s/^ ( .{$max,}? ) # longer, but minimal chars |
|
410
|
|
|
|
|
|
|
[ \t] # followed by a WSP |
|
411
|
|
|
|
|
|
|
//x |
|
412
|
|
|
|
|
|
|
|| $line =~ s/^ (.*) //x; # everything |
|
413
|
|
|
|
|
|
|
|
|
414
|
55
|
|
|
|
|
285
|
push @folded, " $1\n"; |
|
415
|
|
|
|
|
|
|
} |
|
416
|
|
|
|
|
|
|
|
|
417
|
1440
|
100
|
|
|
|
4987
|
push @folded, " $line\n" if CORE::length($line); |
|
418
|
1440
|
100
|
|
|
|
7013
|
wantarray ? @folded : join('', @folded); |
|
419
|
|
|
|
|
|
|
} |
|
420
|
|
|
|
|
|
|
|
|
421
|
|
|
|
|
|
|
|
|
422
|
|
|
|
|
|
|
sub unfold($) |
|
423
|
2897
|
|
|
2897
|
1
|
5154
|
{ my $string = $_[1]; |
|
424
|
2897
|
|
|
|
|
5703
|
for($string) |
|
425
|
2897
|
|
|
|
|
7343
|
{ s/\r?\n(\s)/$1/gs; # remove FWS |
|
426
|
2897
|
|
|
|
|
16838
|
s/\r?\n/ /gs; |
|
427
|
2897
|
|
|
|
|
13384
|
s/^\s+//; |
|
428
|
2897
|
|
|
|
|
12790
|
s/\s+$//; |
|
429
|
|
|
|
|
|
|
} |
|
430
|
2897
|
|
|
|
|
14094
|
$string; |
|
431
|
|
|
|
|
|
|
} |
|
432
|
|
|
|
|
|
|
|
|
433
|
|
|
|
|
|
|
#-------------------- |
|
434
|
|
|
|
|
|
|
|
|
435
|
|
|
|
|
|
|
1; |