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::Head::Complete; |
10
|
35
|
|
|
35
|
|
2884
|
use vars '$VERSION'; |
|
35
|
|
|
|
|
65
|
|
|
35
|
|
|
|
|
1687
|
|
11
|
|
|
|
|
|
|
$VERSION = '3.012'; |
12
|
|
|
|
|
|
|
|
13
|
35
|
|
|
35
|
|
177
|
use base 'Mail::Message::Head'; |
|
35
|
|
|
|
|
70
|
|
|
35
|
|
|
|
|
13919
|
|
14
|
|
|
|
|
|
|
|
15
|
35
|
|
|
35
|
|
242
|
use strict; |
|
35
|
|
|
|
|
66
|
|
|
35
|
|
|
|
|
611
|
|
16
|
35
|
|
|
35
|
|
149
|
use warnings; |
|
35
|
|
|
|
|
63
|
|
|
35
|
|
|
|
|
816
|
|
17
|
|
|
|
|
|
|
|
18
|
35
|
|
|
35
|
|
8520
|
use Mail::Box::Parser; |
|
35
|
|
|
|
|
72
|
|
|
35
|
|
|
|
|
760
|
|
19
|
35
|
|
|
35
|
|
14382
|
use Mail::Message::Head::Partial; |
|
35
|
|
|
|
|
84
|
|
|
35
|
|
|
|
|
1061
|
|
20
|
|
|
|
|
|
|
|
21
|
35
|
|
|
35
|
|
191
|
use Scalar::Util qw/weaken/; |
|
35
|
|
|
|
|
69
|
|
|
35
|
|
|
|
|
1464
|
|
22
|
35
|
|
|
35
|
|
181
|
use List::Util qw/sum/; |
|
35
|
|
|
|
|
69
|
|
|
35
|
|
|
|
|
2423
|
|
23
|
35
|
|
|
35
|
|
6218
|
use Sys::Hostname qw/hostname/; |
|
35
|
|
|
|
|
15004
|
|
|
35
|
|
|
|
|
98604
|
|
24
|
|
|
|
|
|
|
|
25
|
|
|
|
|
|
|
|
26
|
|
|
|
|
|
|
sub clone(;@) |
27
|
49
|
|
|
49
|
1
|
576
|
{ my $self = shift; |
28
|
49
|
|
|
|
|
259
|
my $copy = ref($self)->new($self->logSettings); |
29
|
|
|
|
|
|
|
|
30
|
49
|
|
|
|
|
204
|
$copy->addNoRealize($_->clone) for $self->grepNames(@_); |
31
|
49
|
|
|
|
|
238
|
$copy->modified(1); |
32
|
49
|
|
|
|
|
240
|
$copy; |
33
|
|
|
|
|
|
|
} |
34
|
|
|
|
|
|
|
|
35
|
|
|
|
|
|
|
|
36
|
|
|
|
|
|
|
sub build(@) |
37
|
4
|
|
|
4
|
1
|
105
|
{ my $class = shift; |
38
|
4
|
|
|
|
|
41
|
my $self = $class->new; |
39
|
4
|
|
|
|
|
19
|
while(@_) |
40
|
25
|
|
|
|
|
37
|
{ my $name = shift; |
41
|
25
|
50
|
|
|
|
46
|
defined $name or next; |
42
|
|
|
|
|
|
|
|
43
|
25
|
50
|
|
|
|
152
|
if($name->isa('Mail::Message::Field')) |
44
|
0
|
|
|
|
|
0
|
{ $self->add($name); |
45
|
0
|
|
|
|
|
0
|
next; |
46
|
|
|
|
|
|
|
} |
47
|
|
|
|
|
|
|
|
48
|
25
|
|
|
|
|
46
|
my $content = shift; |
49
|
25
|
50
|
|
|
|
46
|
defined $content or next; |
50
|
|
|
|
|
|
|
|
51
|
25
|
50
|
33
|
|
|
58
|
if(ref $content && $content->isa('Mail::Message::Field')) |
52
|
0
|
|
|
|
|
0
|
{ $self->log(WARNING => "Field objects have an implied name ($name)"); |
53
|
0
|
|
|
|
|
0
|
$self->add($content); |
54
|
0
|
|
|
|
|
0
|
next; |
55
|
|
|
|
|
|
|
} |
56
|
|
|
|
|
|
|
|
57
|
25
|
|
|
|
|
53
|
$self->add($name, $content); |
58
|
|
|
|
|
|
|
} |
59
|
|
|
|
|
|
|
|
60
|
4
|
|
|
|
|
15
|
$self; |
61
|
|
|
|
|
|
|
} |
62
|
|
|
|
|
|
|
|
63
|
|
|
|
|
|
|
#------------------------------------------ |
64
|
|
|
|
|
|
|
|
65
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
sub isDelayed() {0} |
67
|
|
|
|
|
|
|
|
68
|
|
|
|
|
|
|
|
69
|
42
|
|
|
42
|
1
|
1633
|
sub nrLines() { sum 1, map $_->nrLines, shift->orderedFields } |
70
|
55
|
|
|
55
|
1
|
142
|
sub size() { sum 1, map $_->size, shift->orderedFields } |
71
|
|
|
|
|
|
|
|
72
|
|
|
|
|
|
|
|
73
|
|
|
|
|
|
|
sub wrap($) |
74
|
0
|
|
|
0
|
1
|
0
|
{ my ($self, $length) = @_; |
75
|
0
|
|
|
|
|
0
|
$_->setWrapLength($length) for $self->orderedFields; |
76
|
|
|
|
|
|
|
} |
77
|
|
|
|
|
|
|
|
78
|
|
|
|
|
|
|
#------------------------------------------ |
79
|
|
|
|
|
|
|
|
80
|
|
|
|
|
|
|
|
81
|
|
|
|
|
|
|
sub add(@) |
82
|
176
|
|
|
176
|
1
|
2342
|
{ my $self = shift; |
83
|
|
|
|
|
|
|
|
84
|
|
|
|
|
|
|
# Create object for this field. |
85
|
|
|
|
|
|
|
|
86
|
|
|
|
|
|
|
my $field |
87
|
|
|
|
|
|
|
= @_==1 && ref $_[0] ? shift # A fully qualified field is added. |
88
|
176
|
50
|
33
|
|
|
1047
|
: ($self->{MMH_field_type} || 'Mail::Message::Field::Fast')->new(@_); |
|
|
|
50
|
|
|
|
|
89
|
|
|
|
|
|
|
|
90
|
176
|
50
|
|
|
|
350
|
return if !defined $field; |
91
|
|
|
|
|
|
|
|
92
|
176
|
|
|
|
|
479
|
$field->setWrapLength; |
93
|
|
|
|
|
|
|
|
94
|
|
|
|
|
|
|
# Put it in place. |
95
|
|
|
|
|
|
|
|
96
|
176
|
|
|
|
|
255
|
my $known = $self->{MMH_fields}; |
97
|
176
|
|
|
|
|
399
|
my $name = $field->name; # is already lower-cased |
98
|
|
|
|
|
|
|
|
99
|
176
|
|
|
|
|
542
|
$self->addOrderedFields($field); |
100
|
|
|
|
|
|
|
|
101
|
176
|
100
|
|
|
|
357
|
if(defined $known->{$name}) |
102
|
3
|
100
|
|
|
|
12
|
{ if(ref $known->{$name} eq 'ARRAY') { push @{$known->{$name}}, $field } |
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
3
|
|
103
|
2
|
|
|
|
|
6
|
else { $known->{$name} = [ $known->{$name}, $field ] } |
104
|
|
|
|
|
|
|
} |
105
|
|
|
|
|
|
|
else |
106
|
173
|
|
|
|
|
378
|
{ $known->{$name} = $field; |
107
|
|
|
|
|
|
|
} |
108
|
|
|
|
|
|
|
|
109
|
176
|
|
|
|
|
241
|
$self->{MMH_modified}++; |
110
|
176
|
|
|
|
|
391
|
$field; |
111
|
|
|
|
|
|
|
} |
112
|
|
|
|
|
|
|
|
113
|
|
|
|
|
|
|
|
114
|
|
|
|
|
|
|
sub count($) |
115
|
0
|
|
|
0
|
1
|
0
|
{ my $known = shift->{MMH_fields}; |
116
|
0
|
|
|
|
|
0
|
my $value = $known->{lc shift}; |
117
|
|
|
|
|
|
|
|
118
|
0
|
0
|
|
|
|
0
|
! defined $value ? 0 |
|
|
0
|
|
|
|
|
|
119
|
|
|
|
|
|
|
: ref $value ? @$value |
120
|
|
|
|
|
|
|
: 1; |
121
|
|
|
|
|
|
|
} |
122
|
|
|
|
|
|
|
|
123
|
|
|
|
|
|
|
|
124
|
10
|
|
|
10
|
1
|
1122
|
sub names() {shift->knownNames} |
125
|
|
|
|
|
|
|
|
126
|
|
|
|
|
|
|
|
127
|
|
|
|
|
|
|
sub grepNames(@) |
128
|
55
|
|
|
55
|
1
|
91
|
{ my $self = shift; |
129
|
55
|
|
|
|
|
90
|
my @take; |
130
|
55
|
50
|
|
|
|
145
|
push @take, (ref $_ eq 'ARRAY' ? @$_ : $_) foreach @_; |
131
|
|
|
|
|
|
|
|
132
|
55
|
100
|
|
|
|
231
|
return $self->orderedFields unless @take; |
133
|
|
|
|
|
|
|
|
134
|
6
|
|
|
|
|
8
|
my $take; |
135
|
6
|
50
|
33
|
|
|
21
|
if(@take==1 && ref $take[0] eq 'Regexp') |
136
|
6
|
|
|
|
|
12
|
{ $take = $take[0]; # one regexp prepared already |
137
|
|
|
|
|
|
|
} |
138
|
|
|
|
|
|
|
else |
139
|
|
|
|
|
|
|
{ # I love this trick: |
140
|
0
|
|
|
|
|
0
|
local $" = ')|(?:'; |
141
|
0
|
|
|
|
|
0
|
$take = qr/^(?:(?:@take))/i; |
142
|
|
|
|
|
|
|
} |
143
|
|
|
|
|
|
|
|
144
|
6
|
|
|
|
|
15
|
grep {$_->name =~ $take} $self->orderedFields; |
|
24
|
|
|
|
|
49
|
|
145
|
|
|
|
|
|
|
} |
146
|
|
|
|
|
|
|
|
147
|
|
|
|
|
|
|
|
148
|
|
|
|
|
|
|
my @skip_none = qw/content-transfer-encoding content-disposition |
149
|
|
|
|
|
|
|
content-description content-id/; |
150
|
|
|
|
|
|
|
|
151
|
|
|
|
|
|
|
my %skip_none = map { ($_ => 1) } @skip_none; |
152
|
|
|
|
|
|
|
|
153
|
|
|
|
|
|
|
sub set(@) |
154
|
454
|
|
|
454
|
1
|
1246
|
{ my $self = shift; |
155
|
454
|
|
50
|
|
|
1185
|
my $type = $self->{MMH_field_type} || 'Mail::Message::Field::Fast'; |
156
|
454
|
|
|
|
|
621
|
$self->{MMH_modified}++; |
157
|
|
|
|
|
|
|
|
158
|
|
|
|
|
|
|
# Create object for this field. |
159
|
454
|
100
|
66
|
|
|
1827
|
my $field = @_==1 && ref $_[0] ? shift->clone : $type->new(@_); |
160
|
|
|
|
|
|
|
|
161
|
454
|
|
|
|
|
1045
|
my $name = $field->name; # is already lower-cased |
162
|
454
|
|
|
|
|
698
|
my $known = $self->{MMH_fields}; |
163
|
|
|
|
|
|
|
|
164
|
|
|
|
|
|
|
# Internally, non-existing content-info are in the body stored as 'none' |
165
|
|
|
|
|
|
|
# The header will not contain these lines. |
166
|
|
|
|
|
|
|
|
167
|
454
|
100
|
100
|
|
|
1320
|
if($skip_none{$name} && $field->body eq 'none') |
168
|
289
|
|
|
|
|
507
|
{ delete $known->{$name}; |
169
|
289
|
|
|
|
|
730
|
return $field; |
170
|
|
|
|
|
|
|
} |
171
|
|
|
|
|
|
|
|
172
|
165
|
|
|
|
|
517
|
$field->setWrapLength; |
173
|
165
|
|
|
|
|
410
|
$known->{$name} = $field; |
174
|
|
|
|
|
|
|
|
175
|
165
|
|
|
|
|
547
|
$self->addOrderedFields($field); |
176
|
165
|
|
|
|
|
296
|
$field; |
177
|
|
|
|
|
|
|
} |
178
|
|
|
|
|
|
|
|
179
|
|
|
|
|
|
|
|
180
|
|
|
|
|
|
|
sub reset($@) |
181
|
8
|
|
|
8
|
1
|
1238
|
{ my ($self, $name) = (shift, lc shift); |
182
|
|
|
|
|
|
|
|
183
|
8
|
|
|
|
|
15
|
my $known = $self->{MMH_fields}; |
184
|
|
|
|
|
|
|
|
185
|
8
|
100
|
|
|
|
21
|
if(@_==0) |
186
|
7
|
100
|
|
|
|
19
|
{ $self->{MMH_modified}++ if delete $known->{$name}; |
187
|
7
|
|
|
|
|
17
|
return (); |
188
|
|
|
|
|
|
|
} |
189
|
|
|
|
|
|
|
|
190
|
1
|
|
|
|
|
2
|
$self->{MMH_modified}++; |
191
|
|
|
|
|
|
|
|
192
|
|
|
|
|
|
|
# Cloning required, otherwise double registrations will not be |
193
|
|
|
|
|
|
|
# removed from the ordered list: that's controled by 'weaken' |
194
|
|
|
|
|
|
|
|
195
|
1
|
|
|
|
|
6
|
my @fields = map $_->clone, @_; |
196
|
|
|
|
|
|
|
|
197
|
1
|
50
|
|
|
|
4
|
if(@_==1) { $known->{$name} = $fields[0] } |
|
0
|
|
|
|
|
0
|
|
198
|
1
|
|
|
|
|
3
|
else { $known->{$name} = [@fields] } |
199
|
|
|
|
|
|
|
|
200
|
1
|
|
|
|
|
5
|
$self->addOrderedFields(@fields); |
201
|
1
|
|
|
|
|
3
|
$self; |
202
|
|
|
|
|
|
|
} |
203
|
|
|
|
|
|
|
|
204
|
|
|
|
|
|
|
|
205
|
6
|
|
|
6
|
1
|
16
|
sub delete($) { $_[0]->reset($_[1]) } |
206
|
|
|
|
|
|
|
|
207
|
|
|
|
|
|
|
|
208
|
|
|
|
|
|
|
sub removeField($) |
209
|
8
|
|
|
8
|
1
|
13
|
{ my ($self, $field) = @_; |
210
|
8
|
|
|
|
|
15
|
my $name = $field->name; |
211
|
8
|
|
|
|
|
12
|
my $known = $self->{MMH_fields}; |
212
|
|
|
|
|
|
|
|
213
|
8
|
50
|
|
|
|
31
|
if(!defined $known->{$name}) |
|
|
100
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
214
|
|
|
|
|
|
|
{ ; } # complain |
215
|
|
|
|
|
|
|
elsif(ref $known->{$name} eq 'ARRAY') |
216
|
2
|
|
|
|
|
3
|
{ for(my $i=0; $i < @{$known->{$name}}; $i++) |
|
2
|
|
|
|
|
6
|
|
217
|
|
|
|
|
|
|
{ |
218
|
2
|
|
|
|
|
8
|
return splice @{$known->{$name}}, $i, 1 |
219
|
2
|
50
|
|
|
|
5
|
if $known->{$name}[$i] eq $field; |
220
|
|
|
|
|
|
|
} |
221
|
|
|
|
|
|
|
} |
222
|
|
|
|
|
|
|
elsif($known->{$name} eq $field) |
223
|
6
|
|
|
|
|
15
|
{ return delete $known->{$name}; |
224
|
|
|
|
|
|
|
} |
225
|
|
|
|
|
|
|
|
226
|
0
|
|
|
|
|
0
|
$self->log(WARNING => "Cannot remove field $name from header: not found."); |
227
|
|
|
|
|
|
|
|
228
|
0
|
|
|
|
|
0
|
return; |
229
|
|
|
|
|
|
|
} |
230
|
|
|
|
|
|
|
|
231
|
|
|
|
|
|
|
|
232
|
|
|
|
|
|
|
sub removeFields(@) |
233
|
46
|
|
|
46
|
1
|
91
|
{ my $self = shift; |
234
|
46
|
|
|
|
|
293
|
(bless $self, 'Mail::Message::Head::Partial')->removeFields(@_); |
235
|
|
|
|
|
|
|
} |
236
|
|
|
|
|
|
|
|
237
|
|
|
|
|
|
|
|
238
|
|
|
|
|
|
|
sub removeFieldsExcept(@) |
239
|
0
|
|
|
0
|
1
|
0
|
{ my $self = shift; |
240
|
0
|
|
|
|
|
0
|
(bless $self, 'Mail::Message::Head::Partial')->removeFieldsExcept(@_); |
241
|
|
|
|
|
|
|
} |
242
|
|
|
|
|
|
|
|
243
|
|
|
|
|
|
|
|
244
|
83
|
|
|
83
|
1
|
568
|
sub removeContentInfo() { shift->removeFields(qr/^Content-/, 'Lines') } |
245
|
|
|
|
|
|
|
|
246
|
|
|
|
|
|
|
|
247
|
|
|
|
|
|
|
sub removeResentGroups(@) |
248
|
0
|
|
|
0
|
1
|
0
|
{ my $self = shift; |
249
|
0
|
|
|
|
|
0
|
(bless $self, 'Mail::Message::Head::Partial')->removeResentGroups(@_); |
250
|
|
|
|
|
|
|
} |
251
|
|
|
|
|
|
|
|
252
|
|
|
|
|
|
|
|
253
|
|
|
|
|
|
|
sub removeListGroup(@) |
254
|
0
|
|
|
0
|
1
|
0
|
{ my $self = shift; |
255
|
0
|
|
|
|
|
0
|
(bless $self, 'Mail::Message::Head::Partial')->removeListGroup(@_); |
256
|
|
|
|
|
|
|
} |
257
|
|
|
|
|
|
|
|
258
|
|
|
|
|
|
|
|
259
|
|
|
|
|
|
|
sub removeSpamGroups(@) |
260
|
0
|
|
|
0
|
1
|
0
|
{ my $self = shift; |
261
|
0
|
|
|
|
|
0
|
(bless $self, 'Mail::Message::Head::Partial')->removeSpamGroups(@_); |
262
|
|
|
|
|
|
|
} |
263
|
|
|
|
|
|
|
|
264
|
|
|
|
|
|
|
|
265
|
|
|
|
|
|
|
sub spamDetected() |
266
|
0
|
|
|
0
|
1
|
0
|
{ my $self = shift; |
267
|
0
|
0
|
|
|
|
0
|
my @sgs = $self->spamGroups or return undef; |
268
|
0
|
|
|
|
|
0
|
grep { $_->spamDetected } @sgs; |
|
0
|
|
|
|
|
0
|
|
269
|
|
|
|
|
|
|
} |
270
|
|
|
|
|
|
|
|
271
|
|
|
|
|
|
|
|
272
|
|
|
|
|
|
|
sub print(;$) |
273
|
35
|
|
|
35
|
1
|
1539
|
{ my $self = shift; |
274
|
35
|
|
33
|
|
|
87
|
my $fh = shift || select; |
275
|
|
|
|
|
|
|
|
276
|
|
|
|
|
|
|
$_->print($fh) |
277
|
35
|
|
|
|
|
199
|
foreach $self->orderedFields; |
278
|
|
|
|
|
|
|
|
279
|
35
|
50
|
|
|
|
84
|
if(ref $fh eq 'GLOB') { print $fh "\n" } |
|
0
|
|
|
|
|
0
|
|
280
|
35
|
|
|
|
|
81
|
else { $fh->print("\n") } |
281
|
|
|
|
|
|
|
|
282
|
35
|
|
|
|
|
317
|
$self; |
283
|
|
|
|
|
|
|
} |
284
|
|
|
|
|
|
|
|
285
|
|
|
|
|
|
|
|
286
|
|
|
|
|
|
|
sub printUndisclosed($) |
287
|
0
|
|
|
0
|
1
|
0
|
{ my ($self, $fh) = @_; |
288
|
|
|
|
|
|
|
|
289
|
|
|
|
|
|
|
$_->print($fh) |
290
|
0
|
|
|
|
|
0
|
foreach grep {$_->toDisclose} $self->orderedFields; |
|
0
|
|
|
|
|
0
|
|
291
|
|
|
|
|
|
|
|
292
|
0
|
0
|
|
|
|
0
|
if(ref $fh eq 'GLOB') { print $fh "\n" } |
|
0
|
|
|
|
|
0
|
|
293
|
0
|
|
|
|
|
0
|
else { $fh->print("\n") } |
294
|
|
|
|
|
|
|
|
295
|
0
|
|
|
|
|
0
|
$self; |
296
|
|
|
|
|
|
|
} |
297
|
|
|
|
|
|
|
|
298
|
|
|
|
|
|
|
|
299
|
|
|
|
|
|
|
sub printSelected($@) |
300
|
0
|
|
|
0
|
1
|
0
|
{ my ($self, $fh) = (shift, shift); |
301
|
|
|
|
|
|
|
|
302
|
0
|
|
|
|
|
0
|
foreach my $field ($self->orderedFields) |
303
|
0
|
|
|
|
|
0
|
{ my $Name = $field->Name; |
304
|
0
|
|
|
|
|
0
|
my $name = $field->name; |
305
|
|
|
|
|
|
|
|
306
|
0
|
|
|
|
|
0
|
my $found; |
307
|
0
|
|
|
|
|
0
|
foreach my $pattern (@_) |
308
|
0
|
0
|
|
|
|
0
|
{ $found = ref $pattern?($Name =~ $pattern):($name eq lc $pattern); |
309
|
0
|
0
|
|
|
|
0
|
last if $found; |
310
|
|
|
|
|
|
|
} |
311
|
|
|
|
|
|
|
|
312
|
0
|
0
|
|
|
|
0
|
if(!$found) { ; } |
|
|
0
|
|
|
|
|
|
313
|
0
|
|
|
|
|
0
|
elsif(ref $fh eq 'GLOB') { print $fh "\n" } |
314
|
0
|
|
|
|
|
0
|
else { $fh->print("\n") } |
315
|
|
|
|
|
|
|
} |
316
|
|
|
|
|
|
|
|
317
|
0
|
|
|
|
|
0
|
$self; |
318
|
|
|
|
|
|
|
} |
319
|
|
|
|
|
|
|
|
320
|
|
|
|
|
|
|
|
321
|
1
|
|
|
1
|
0
|
454
|
sub toString() {shift->string} |
322
|
|
|
|
|
|
|
sub string() |
323
|
6
|
|
|
6
|
1
|
12
|
{ my $self = shift; |
324
|
|
|
|
|
|
|
|
325
|
6
|
|
|
|
|
27
|
my @lines = map {$_->string} $self->orderedFields; |
|
44
|
|
|
|
|
121
|
|
326
|
6
|
|
|
|
|
19
|
push @lines, "\n"; |
327
|
|
|
|
|
|
|
|
328
|
6
|
50
|
|
|
|
54
|
wantarray ? @lines : join('', @lines); |
329
|
|
|
|
|
|
|
} |
330
|
|
|
|
|
|
|
|
331
|
|
|
|
|
|
|
|
332
|
|
|
|
|
|
|
sub resentGroups() |
333
|
3
|
|
|
3
|
1
|
554
|
{ my $self = shift; |
334
|
3
|
|
|
|
|
385
|
require Mail::Message::Head::ResentGroup; |
335
|
3
|
|
|
|
|
16
|
Mail::Message::Head::ResentGroup->from($self); |
336
|
|
|
|
|
|
|
} |
337
|
|
|
|
|
|
|
|
338
|
|
|
|
|
|
|
|
339
|
|
|
|
|
|
|
sub addResentGroup(@) |
340
|
3
|
|
|
3
|
1
|
490
|
{ my $self = shift; |
341
|
|
|
|
|
|
|
|
342
|
3
|
|
|
|
|
17
|
require Mail::Message::Head::ResentGroup; |
343
|
3
|
100
|
|
|
|
15
|
my $rg = @_==1 ? (shift) : Mail::Message::Head::ResentGroup->new(@_); |
344
|
|
|
|
|
|
|
|
345
|
3
|
|
|
|
|
8
|
my @fields = $rg->orderedFields; |
346
|
3
|
|
|
|
|
7
|
my $order = $self->{MMH_order}; |
347
|
|
|
|
|
|
|
|
348
|
|
|
|
|
|
|
# Look for the first line which relates to resent groups |
349
|
3
|
|
|
|
|
5
|
my $i; |
350
|
3
|
|
|
|
|
11
|
for($i=0; $i < @$order; $i++) |
351
|
13
|
50
|
|
|
|
29
|
{ next unless defined $order->[$i]; |
352
|
13
|
100
|
|
|
|
22
|
last if $rg->isResentGroupFieldName($order->[$i]->name); |
353
|
|
|
|
|
|
|
} |
354
|
|
|
|
|
|
|
|
355
|
3
|
|
|
|
|
5
|
my $known = $self->{MMH_fields}; |
356
|
3
|
|
|
|
|
9
|
while(@fields) |
357
|
15
|
|
|
|
|
18
|
{ my $f = pop @fields; |
358
|
|
|
|
|
|
|
|
359
|
|
|
|
|
|
|
# Add to the order of fields |
360
|
15
|
|
|
|
|
28
|
splice @$order, $i, 0, $f; |
361
|
15
|
|
|
|
|
35
|
weaken( $order->[$i] ); |
362
|
15
|
|
|
|
|
29
|
my $name = $f->name; |
363
|
|
|
|
|
|
|
|
364
|
|
|
|
|
|
|
# Adds *before* in the list for get(). |
365
|
15
|
100
|
|
|
|
31
|
if(!defined $known->{$name}) {$known->{$name} = $f} |
|
13
|
50
|
|
|
|
27
|
|
366
|
0
|
|
|
|
|
0
|
elsif(ref $known->{$name} eq 'ARRAY'){unshift @{$known->{$name}},$f} |
|
0
|
|
|
|
|
0
|
|
367
|
2
|
|
|
|
|
5
|
else {$known->{$name} = [$f, $known->{$name}]} |
368
|
|
|
|
|
|
|
} |
369
|
|
|
|
|
|
|
|
370
|
3
|
|
|
|
|
12
|
$rg->messageHead($self); |
371
|
|
|
|
|
|
|
|
372
|
|
|
|
|
|
|
# Oh, the header has changed! |
373
|
3
|
|
|
|
|
13
|
$self->modified(1); |
374
|
|
|
|
|
|
|
|
375
|
3
|
|
|
|
|
18
|
$rg; |
376
|
|
|
|
|
|
|
} |
377
|
|
|
|
|
|
|
|
378
|
|
|
|
|
|
|
|
379
|
|
|
|
|
|
|
sub listGroup() |
380
|
0
|
|
|
0
|
1
|
0
|
{ my $self = shift; |
381
|
0
|
|
|
|
|
0
|
eval "require 'Mail::Message::Head::ListGroup'"; |
382
|
0
|
|
|
|
|
0
|
Mail::Message::Head::ListGroup->from($self); |
383
|
|
|
|
|
|
|
} |
384
|
|
|
|
|
|
|
|
385
|
|
|
|
|
|
|
|
386
|
|
|
|
|
|
|
sub addListGroup($) |
387
|
0
|
|
|
0
|
1
|
0
|
{ my ($self, $lg) = @_; |
388
|
0
|
|
|
|
|
0
|
$lg->attach($self); |
389
|
|
|
|
|
|
|
} |
390
|
|
|
|
|
|
|
|
391
|
|
|
|
|
|
|
|
392
|
|
|
|
|
|
|
sub spamGroups(@) |
393
|
0
|
|
|
0
|
1
|
0
|
{ my $self = shift; |
394
|
0
|
|
|
|
|
0
|
require Mail::Message::Head::SpamGroup; |
395
|
0
|
0
|
|
|
|
0
|
my @types = @_ ? (types => \@_) : (); |
396
|
0
|
|
|
|
|
0
|
my @sgs = Mail::Message::Head::SpamGroup->from($self, @types); |
397
|
0
|
0
|
0
|
|
|
0
|
wantarray || @_ != 1 ? @sgs : $sgs[0]; |
398
|
|
|
|
|
|
|
} |
399
|
|
|
|
|
|
|
|
400
|
|
|
|
|
|
|
|
401
|
|
|
|
|
|
|
sub addSpamGroup($) |
402
|
0
|
|
|
0
|
1
|
0
|
{ my ($self, $sg) = @_; |
403
|
0
|
|
|
|
|
0
|
$sg->attach($self); |
404
|
|
|
|
|
|
|
} |
405
|
|
|
|
|
|
|
|
406
|
|
|
|
|
|
|
#------------------------------------------ |
407
|
|
|
|
|
|
|
|
408
|
|
|
|
|
|
|
|
409
|
2
|
50
|
|
2
|
1
|
10
|
sub timestamp() {shift->guessTimestamp || time} |
410
|
|
|
|
|
|
|
|
411
|
|
|
|
|
|
|
|
412
|
|
|
|
|
|
|
sub recvstamp() |
413
|
2
|
|
|
2
|
1
|
7
|
{ my $self = shift; |
414
|
|
|
|
|
|
|
|
415
|
2
|
100
|
|
|
|
15
|
return $self->{MMH_recvstamp} if exists $self->{MMH_recvstamp}; |
416
|
|
|
|
|
|
|
|
417
|
|
|
|
|
|
|
my $recvd = $self->get('received', 0) or |
418
|
1
|
50
|
|
|
|
3
|
return $self->{MMH_recvstamp} = undef; |
419
|
|
|
|
|
|
|
|
420
|
0
|
|
|
|
|
0
|
my $stamp = Mail::Message::Field->dateToTimestamp($recvd->comment); |
421
|
|
|
|
|
|
|
|
422
|
0
|
0
|
0
|
|
|
0
|
$self->{MMH_recvstamp} = defined $stamp && $stamp > 0 ? $stamp : undef; |
423
|
|
|
|
|
|
|
} |
424
|
|
|
|
|
|
|
|
425
|
|
|
|
|
|
|
|
426
|
|
|
|
|
|
|
sub guessTimestamp() |
427
|
2
|
|
|
2
|
0
|
6
|
{ my $self = shift; |
428
|
2
|
100
|
|
|
|
25
|
return $self->{MMH_timestamp} if exists $self->{MMH_timestamp}; |
429
|
|
|
|
|
|
|
|
430
|
1
|
|
|
|
|
3
|
my $stamp; |
431
|
1
|
50
|
|
|
|
5
|
if(my $date = $self->get('date')) |
432
|
1
|
|
|
|
|
5
|
{ $stamp = Mail::Message::Field->dateToTimestamp($date); |
433
|
|
|
|
|
|
|
} |
434
|
|
|
|
|
|
|
|
435
|
1
|
50
|
|
|
|
640
|
unless($stamp) |
436
|
0
|
|
|
|
|
0
|
{ foreach (reverse $self->get('received')) |
437
|
0
|
|
|
|
|
0
|
{ $stamp = Mail::Message::Field->dateToTimestamp($_->comment); |
438
|
0
|
0
|
|
|
|
0
|
last if $stamp; |
439
|
|
|
|
|
|
|
} |
440
|
|
|
|
|
|
|
} |
441
|
|
|
|
|
|
|
|
442
|
1
|
50
|
33
|
|
|
41
|
$self->{MMH_timestamp} = defined $stamp && $stamp > 0 ? $stamp : undef; |
443
|
|
|
|
|
|
|
} |
444
|
|
|
|
|
|
|
|
445
|
|
|
|
|
|
|
sub guessBodySize() |
446
|
12
|
|
|
12
|
1
|
26
|
{ my $self = shift; |
447
|
|
|
|
|
|
|
|
448
|
12
|
|
|
|
|
29
|
my $cl = $self->get('Content-Length'); |
449
|
12
|
50
|
33
|
|
|
48
|
return $1 if defined $cl && $cl =~ m/(\d+)/; |
450
|
|
|
|
|
|
|
|
451
|
12
|
|
|
|
|
28
|
my $lines = $self->get('Lines'); # 40 chars per lines |
452
|
12
|
50
|
33
|
|
|
28
|
return $1 * 40 if defined $lines && $lines =~ m/(\d+)/; |
453
|
|
|
|
|
|
|
|
454
|
12
|
|
|
|
|
21
|
undef; |
455
|
|
|
|
|
|
|
} |
456
|
|
|
|
|
|
|
|
457
|
|
|
|
|
|
|
#------------------------------------------ |
458
|
|
|
|
|
|
|
|
459
|
|
|
|
|
|
|
|
460
|
|
|
|
|
|
|
sub createFromLine() |
461
|
0
|
|
|
0
|
1
|
0
|
{ my $self = shift; |
462
|
0
|
|
|
|
|
0
|
my $sender = $self->message->sender; |
463
|
0
|
|
0
|
|
|
0
|
my $stamp = $self->recvstamp || $self->timestamp || time; |
464
|
0
|
0
|
|
|
|
0
|
my $addr = defined $sender ? $sender->address : 'unknown'; |
465
|
0
|
|
|
|
|
0
|
"From $addr ".(gmtime $stamp)."\n" |
466
|
|
|
|
|
|
|
} |
467
|
|
|
|
|
|
|
|
468
|
|
|
|
|
|
|
|
469
|
|
|
|
|
|
|
my $msgid_creator; |
470
|
|
|
|
|
|
|
|
471
|
|
|
|
|
|
|
sub createMessageId() |
472
|
91
|
|
66
|
91
|
1
|
311
|
{ $msgid_creator ||= $_[0]->messageIdPrefix; |
473
|
91
|
|
|
|
|
261
|
$msgid_creator->(@_); |
474
|
|
|
|
|
|
|
} |
475
|
|
|
|
|
|
|
|
476
|
|
|
|
|
|
|
|
477
|
|
|
|
|
|
|
sub messageIdPrefix(;$$) |
478
|
10
|
|
|
10
|
1
|
24
|
{ my $thing = shift; |
479
|
10
|
50
|
33
|
|
|
65
|
return $msgid_creator |
480
|
|
|
|
|
|
|
unless @_ || !defined $msgid_creator; |
481
|
|
|
|
|
|
|
|
482
|
10
|
50
|
33
|
|
|
54
|
return $msgid_creator = shift |
483
|
|
|
|
|
|
|
if @_==1 && ref $_[0] eq 'CODE'; |
484
|
|
|
|
|
|
|
|
485
|
10
|
|
33
|
|
|
71
|
my $prefix = shift || "mailbox-$$"; |
486
|
|
|
|
|
|
|
|
487
|
10
|
|
|
|
|
25
|
my $hostname = shift; |
488
|
10
|
50
|
|
|
|
56
|
if(!defined $hostname) |
489
|
10
|
|
|
|
|
770
|
{ eval "require Net::Domain"; |
490
|
10
|
50
|
|
|
|
81297
|
$@ or $hostname = Net::Domain::hostfqdn(); |
491
|
|
|
|
|
|
|
} |
492
|
10
|
|
0
|
|
|
61557
|
$hostname ||= hostname || 'localhost'; |
|
|
|
33
|
|
|
|
|
493
|
|
|
|
|
|
|
|
494
|
10
|
|
|
|
|
626
|
eval "require Time::HiRes"; |
495
|
10
|
50
|
|
|
|
13146
|
if(Time::HiRes->can('gettimeofday')) |
496
|
|
|
|
|
|
|
{ |
497
|
|
|
|
|
|
|
return $msgid_creator |
498
|
91
|
|
|
91
|
|
376
|
= sub { my ($sec, $micro) = Time::HiRes::gettimeofday(); |
499
|
91
|
|
|
|
|
492
|
"$prefix-$sec-$micro\@$hostname"; |
500
|
10
|
|
|
|
|
118
|
}; |
501
|
|
|
|
|
|
|
} |
502
|
|
|
|
|
|
|
|
503
|
0
|
|
|
|
|
|
my $unique_id = time; |
504
|
|
|
|
|
|
|
$msgid_creator |
505
|
0
|
|
|
0
|
|
|
= sub { $unique_id++; |
506
|
0
|
|
|
|
|
|
"$prefix-$unique_id\@$hostname"; |
507
|
0
|
|
|
|
|
|
}; |
508
|
|
|
|
|
|
|
} |
509
|
|
|
|
|
|
|
|
510
|
|
|
|
|
|
|
1; |