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::Body::Multipart; |
10
|
31
|
|
|
31
|
|
193
|
use vars '$VERSION'; |
|
31
|
|
|
|
|
68
|
|
|
31
|
|
|
|
|
1644
|
|
11
|
|
|
|
|
|
|
$VERSION = '3.012'; |
12
|
|
|
|
|
|
|
|
13
|
31
|
|
|
31
|
|
169
|
use base 'Mail::Message::Body'; |
|
31
|
|
|
|
|
60
|
|
|
31
|
|
|
|
|
4179
|
|
14
|
|
|
|
|
|
|
|
15
|
31
|
|
|
31
|
|
199
|
use strict; |
|
31
|
|
|
|
|
59
|
|
|
31
|
|
|
|
|
684
|
|
16
|
31
|
|
|
31
|
|
177
|
use warnings; |
|
31
|
|
|
|
|
78
|
|
|
31
|
|
|
|
|
943
|
|
17
|
|
|
|
|
|
|
|
18
|
31
|
|
|
31
|
|
187
|
use Mail::Message::Body::Lines; |
|
31
|
|
|
|
|
72
|
|
|
31
|
|
|
|
|
855
|
|
19
|
31
|
|
|
31
|
|
310
|
use Mail::Message::Part; |
|
31
|
|
|
|
|
85
|
|
|
31
|
|
|
|
|
895
|
|
20
|
|
|
|
|
|
|
|
21
|
31
|
|
|
31
|
|
11837
|
use Mail::Box::FastScalar; |
|
31
|
|
|
|
|
76
|
|
|
31
|
|
|
|
|
887
|
|
22
|
31
|
|
|
31
|
|
234
|
use Carp; |
|
31
|
|
|
|
|
66
|
|
|
31
|
|
|
|
|
76931
|
|
23
|
|
|
|
|
|
|
|
24
|
|
|
|
|
|
|
|
25
|
|
|
|
|
|
|
sub init($) |
26
|
33
|
|
|
33
|
0
|
94
|
{ my ($self, $args) = @_; |
27
|
33
|
|
|
|
|
79
|
my $based = $args->{based_on}; |
28
|
33
|
100
|
66
|
|
|
286
|
$args->{mime_type} ||= defined $based ? $based->type : 'multipart/mixed'; |
29
|
|
|
|
|
|
|
|
30
|
33
|
|
|
|
|
168
|
$self->SUPER::init($args); |
31
|
|
|
|
|
|
|
|
32
|
33
|
|
|
|
|
63
|
my @parts; |
33
|
33
|
100
|
|
|
|
122
|
if($args->{parts}) |
34
|
29
|
|
|
|
|
52
|
{ foreach my $raw (@{$args->{parts}}) |
|
29
|
|
|
|
|
98
|
|
35
|
50
|
50
|
|
|
|
122
|
{ next unless defined $raw; |
36
|
50
|
|
|
|
|
202
|
my $cooked = Mail::Message::Part->coerce($raw, $self); |
37
|
|
|
|
|
|
|
|
38
|
50
|
50
|
|
|
|
130
|
$self->log(ERROR => 'Data not convertible to a message (type is ' |
39
|
|
|
|
|
|
|
, ref $raw,")\n"), next unless defined $cooked; |
40
|
|
|
|
|
|
|
|
41
|
50
|
|
|
|
|
129
|
push @parts, $cooked; |
42
|
|
|
|
|
|
|
} |
43
|
|
|
|
|
|
|
} |
44
|
|
|
|
|
|
|
|
45
|
33
|
|
|
|
|
71
|
my $preamble = $args->{preamble}; |
46
|
33
|
50
|
66
|
|
|
141
|
$preamble = Mail::Message::Body->new(data => $preamble) |
47
|
|
|
|
|
|
|
if defined $preamble && ! ref $preamble; |
48
|
|
|
|
|
|
|
|
49
|
33
|
|
|
|
|
71
|
my $epilogue = $args->{epilogue}; |
50
|
33
|
50
|
66
|
|
|
121
|
$epilogue = Mail::Message::Body->new(data => $epilogue) |
51
|
|
|
|
|
|
|
if defined $epilogue && ! ref $epilogue; |
52
|
|
|
|
|
|
|
|
53
|
33
|
100
|
|
|
|
115
|
if($based) |
54
|
22
|
|
33
|
|
|
156
|
{ $self->boundary($args->{boundary} || $based->boundary); |
55
|
|
|
|
|
|
|
$self->{MMBM_preamble} |
56
|
22
|
100
|
|
|
|
110
|
= defined $preamble ? $preamble : $based->preamble; |
57
|
|
|
|
|
|
|
|
58
|
|
|
|
|
|
|
$self->{MMBM_parts} |
59
|
|
|
|
|
|
|
= @parts ? \@parts |
60
|
22
|
100
|
66
|
|
|
105
|
: !$args->{parts} && $based->isMultipart |
|
|
100
|
|
|
|
|
|
61
|
|
|
|
|
|
|
? [ $based->parts('ACTIVE') ] |
62
|
|
|
|
|
|
|
: []; |
63
|
|
|
|
|
|
|
|
64
|
|
|
|
|
|
|
$self->{MMBM_epilogue} |
65
|
22
|
100
|
|
|
|
89
|
= defined $epilogue ? $epilogue : $based->epilogue; |
66
|
|
|
|
|
|
|
} |
67
|
|
|
|
|
|
|
else |
68
|
11
|
|
66
|
|
|
114
|
{ $self->boundary($args->{boundary} ||$self->type->attribute('boundary')); |
69
|
11
|
|
|
|
|
41
|
$self->{MMBM_preamble} = $preamble; |
70
|
11
|
|
|
|
|
41
|
$self->{MMBM_parts} = \@parts; |
71
|
11
|
|
|
|
|
26
|
$self->{MMBM_epilogue} = $epilogue; |
72
|
|
|
|
|
|
|
} |
73
|
|
|
|
|
|
|
|
74
|
33
|
|
|
|
|
179
|
$self; |
75
|
|
|
|
|
|
|
} |
76
|
|
|
|
|
|
|
|
77
|
|
|
|
|
|
|
sub isMultipart() {1} |
78
|
|
|
|
|
|
|
|
79
|
|
|
|
|
|
|
# A multipart body is never binary itself. The parts may be. |
80
|
|
|
|
|
|
|
sub isBinary() {0} |
81
|
|
|
|
|
|
|
|
82
|
|
|
|
|
|
|
sub clone() |
83
|
2
|
|
|
2
|
1
|
6
|
{ my $self = shift; |
84
|
2
|
|
|
|
|
6
|
my $preamble = $self->preamble; |
85
|
2
|
|
|
|
|
7
|
my $epilogue = $self->epilogue; |
86
|
|
|
|
|
|
|
|
87
|
|
|
|
|
|
|
my $body = ref($self)->new |
88
|
|
|
|
|
|
|
( $self->logSettings |
89
|
|
|
|
|
|
|
, based_on => $self |
90
|
|
|
|
|
|
|
, preamble => ($preamble ? $preamble->clone : undef) |
91
|
|
|
|
|
|
|
, epilogue => ($epilogue ? $epilogue->clone : undef) |
92
|
2
|
100
|
|
|
|
10
|
, parts => [ map {$_->clone} $self->parts('ACTIVE') ] |
|
5
|
100
|
|
|
|
25
|
|
93
|
|
|
|
|
|
|
); |
94
|
|
|
|
|
|
|
|
95
|
|
|
|
|
|
|
} |
96
|
|
|
|
|
|
|
|
97
|
|
|
|
|
|
|
sub nrLines() |
98
|
20
|
|
|
20
|
1
|
41
|
{ my $self = shift; |
99
|
20
|
|
|
|
|
45
|
my $nr = 1; # trailing part-sep |
100
|
|
|
|
|
|
|
|
101
|
20
|
100
|
|
|
|
56
|
if(my $preamble = $self->preamble) |
102
|
1
|
|
|
|
|
5
|
{ $nr += $preamble->nrLines; |
103
|
1
|
50
|
|
|
|
5
|
$nr++ if $preamble->endsOnNewline; |
104
|
|
|
|
|
|
|
} |
105
|
|
|
|
|
|
|
|
106
|
20
|
|
|
|
|
70
|
foreach my $part ($self->parts('ACTIVE')) |
107
|
29
|
|
|
|
|
97
|
{ $nr += 1 + $part->nrLines; |
108
|
29
|
100
|
|
|
|
84
|
$nr++ if $part->body->endsOnNewline; |
109
|
|
|
|
|
|
|
} |
110
|
|
|
|
|
|
|
|
111
|
20
|
100
|
|
|
|
60
|
if(my $epilogue = $self->epilogue) |
112
|
1
|
|
|
|
|
3
|
{ $nr += $epilogue->nrLines; |
113
|
|
|
|
|
|
|
} |
114
|
|
|
|
|
|
|
|
115
|
20
|
|
|
|
|
53
|
$nr; |
116
|
|
|
|
|
|
|
} |
117
|
|
|
|
|
|
|
|
118
|
|
|
|
|
|
|
sub size() |
119
|
24
|
|
|
24
|
1
|
56
|
{ my $self = shift; |
120
|
24
|
|
|
|
|
69
|
my $bbytes = length($self->boundary) +4; # \n--$b\n |
121
|
|
|
|
|
|
|
|
122
|
24
|
|
|
|
|
52
|
my $bytes = $bbytes +2; # last boundary, \n--$b--\n |
123
|
24
|
100
|
|
|
|
67
|
if(my $preamble = $self->preamble) |
124
|
4
|
|
|
|
|
12
|
{ $bytes += $preamble->size } |
125
|
20
|
|
|
|
|
46
|
else { $bytes -= 1 } # no leading \n |
126
|
|
|
|
|
|
|
|
127
|
24
|
|
|
|
|
163
|
$bytes += $bbytes + $_->size foreach $self->parts('ACTIVE'); |
128
|
24
|
100
|
|
|
|
70
|
if(my $epilogue = $self->epilogue) |
129
|
1
|
|
|
|
|
4
|
{ $bytes += $epilogue->size; |
130
|
|
|
|
|
|
|
} |
131
|
24
|
|
|
|
|
68
|
$bytes; |
132
|
|
|
|
|
|
|
} |
133
|
|
|
|
|
|
|
|
134
|
4
|
|
|
4
|
1
|
16
|
sub string() { join '', shift->lines } |
135
|
|
|
|
|
|
|
|
136
|
|
|
|
|
|
|
sub lines() |
137
|
4
|
|
|
4
|
1
|
7
|
{ my $self = shift; |
138
|
|
|
|
|
|
|
|
139
|
4
|
|
|
|
|
13
|
my $boundary = $self->boundary; |
140
|
4
|
|
|
|
|
9
|
my @lines; |
141
|
|
|
|
|
|
|
|
142
|
4
|
|
|
|
|
15
|
my $preamble = $self->preamble; |
143
|
4
|
50
|
|
|
|
14
|
push @lines, $preamble->lines if $preamble; |
144
|
|
|
|
|
|
|
|
145
|
4
|
|
|
|
|
15
|
foreach my $part ($self->parts('ACTIVE')) |
146
|
|
|
|
|
|
|
{ # boundaries start with \n |
147
|
8
|
100
|
|
|
|
153
|
if(!@lines) { ; } |
|
|
50
|
|
|
|
|
|
148
|
4
|
|
|
|
|
12
|
elsif($lines[-1] =~ m/\n$/) { push @lines, "\n" } |
149
|
0
|
|
|
|
|
0
|
else { $lines[-1] .= "\n" } |
150
|
8
|
|
|
|
|
33
|
push @lines, "--$boundary\n", $part->lines; |
151
|
|
|
|
|
|
|
} |
152
|
|
|
|
|
|
|
|
153
|
4
|
50
|
|
|
|
62
|
if(!@lines) { ; } |
|
|
50
|
|
|
|
|
|
154
|
4
|
|
|
|
|
12
|
elsif($lines[-1] =~ m/\n$/) { push @lines, "\n" } |
155
|
0
|
|
|
|
|
0
|
else { $lines[-1] .= "\n" } |
156
|
4
|
|
|
|
|
13
|
push @lines, "--$boundary--"; |
157
|
|
|
|
|
|
|
|
158
|
4
|
50
|
|
|
|
12
|
if(my $epilogue = $self->epilogue) |
159
|
0
|
|
|
|
|
0
|
{ $lines[-1] .= "\n"; |
160
|
0
|
|
|
|
|
0
|
push @lines, $epilogue->lines; |
161
|
|
|
|
|
|
|
} |
162
|
|
|
|
|
|
|
|
163
|
4
|
50
|
|
|
|
72
|
wantarray ? @lines : \@lines; |
164
|
|
|
|
|
|
|
} |
165
|
|
|
|
|
|
|
|
166
|
|
|
|
|
|
|
sub file() # It may be possible to speed-improve the next |
167
|
0
|
|
|
0
|
1
|
0
|
{ my $self = shift; # code, which first produces a full print of |
168
|
0
|
|
|
|
|
0
|
my $text; # the message in memory... |
169
|
0
|
|
|
|
|
0
|
my $dump = Mail::Box::FastScalar->new(\$text); |
170
|
0
|
|
|
|
|
0
|
$self->print($dump); |
171
|
0
|
|
|
|
|
0
|
$dump->seek(0,0); |
172
|
0
|
|
|
|
|
0
|
$dump; |
173
|
|
|
|
|
|
|
} |
174
|
|
|
|
|
|
|
|
175
|
|
|
|
|
|
|
sub print(;$) |
176
|
8
|
|
|
8
|
1
|
18
|
{ my $self = shift; |
177
|
8
|
|
33
|
|
|
26
|
my $out = shift || select; |
178
|
|
|
|
|
|
|
|
179
|
8
|
|
|
|
|
52
|
my $boundary = $self->boundary; |
180
|
8
|
|
|
|
|
17
|
my $count = 0; |
181
|
8
|
100
|
|
|
|
24
|
if(my $preamble = $self->preamble) |
182
|
2
|
|
|
|
|
10
|
{ $preamble->print($out); |
183
|
2
|
|
|
|
|
2
|
$count++; |
184
|
|
|
|
|
|
|
} |
185
|
|
|
|
|
|
|
|
186
|
8
|
50
|
|
|
|
30
|
if(ref $out eq 'GLOB') |
187
|
0
|
|
|
|
|
0
|
{ foreach my $part ($self->parts('ACTIVE')) |
188
|
0
|
0
|
|
|
|
0
|
{ print $out "\n" if $count++; |
189
|
0
|
|
|
|
|
0
|
print $out "--$boundary\n"; |
190
|
0
|
|
|
|
|
0
|
$part->print($out); |
191
|
|
|
|
|
|
|
} |
192
|
0
|
0
|
|
|
|
0
|
print $out "\n" if $count++; |
193
|
0
|
|
|
|
|
0
|
print $out "--$boundary--"; |
194
|
|
|
|
|
|
|
} |
195
|
|
|
|
|
|
|
else |
196
|
8
|
|
|
|
|
21
|
{ foreach my $part ($self->parts('ACTIVE')) |
197
|
13
|
100
|
|
|
|
34
|
{ $out->print("\n") if $count++; |
198
|
13
|
|
|
|
|
93
|
$out->print("--$boundary\n"); |
199
|
13
|
|
|
|
|
122
|
$part->print($out); |
200
|
|
|
|
|
|
|
} |
201
|
8
|
100
|
|
|
|
32
|
$out->print("\n") if $count++; |
202
|
8
|
|
|
|
|
57
|
$out->print("--$boundary--"); |
203
|
|
|
|
|
|
|
} |
204
|
|
|
|
|
|
|
|
205
|
8
|
100
|
|
|
|
75
|
if(my $epilogue = $self->epilogue) |
206
|
2
|
|
|
|
|
7
|
{ $out->print("\n"); |
207
|
2
|
|
|
|
|
16
|
$epilogue->print($out); |
208
|
|
|
|
|
|
|
} |
209
|
|
|
|
|
|
|
|
210
|
8
|
|
|
|
|
19
|
$self; |
211
|
|
|
|
|
|
|
} |
212
|
|
|
|
|
|
|
|
213
|
|
|
|
|
|
|
|
214
|
|
|
|
|
|
|
sub foreachLine($) |
215
|
0
|
|
|
0
|
1
|
0
|
{ my ($self, $code) = @_; |
216
|
0
|
|
|
|
|
0
|
$self->log(ERROR => "You cannot use foreachLine on a multipart"); |
217
|
0
|
|
|
|
|
0
|
confess; |
218
|
|
|
|
|
|
|
} |
219
|
|
|
|
|
|
|
|
220
|
|
|
|
|
|
|
sub check() |
221
|
0
|
|
|
0
|
1
|
0
|
{ my $self = shift; |
222
|
0
|
|
|
0
|
|
0
|
$self->foreachComponent( sub {$_[1]->check} ); |
|
0
|
|
|
|
|
0
|
|
223
|
|
|
|
|
|
|
} |
224
|
|
|
|
|
|
|
|
225
|
|
|
|
|
|
|
sub encode(@) |
226
|
0
|
|
|
0
|
1
|
0
|
{ my ($self, %args) = @_; |
227
|
0
|
|
|
0
|
|
0
|
$self->foreachComponent( sub {$_[1]->encode(%args)} ); |
|
0
|
|
|
|
|
0
|
|
228
|
|
|
|
|
|
|
} |
229
|
|
|
|
|
|
|
|
230
|
|
|
|
|
|
|
sub encoded() |
231
|
18
|
|
|
18
|
1
|
46
|
{ my $self = shift; |
232
|
18
|
|
|
30
|
|
184
|
$self->foreachComponent( sub {$_[1]->encoded} ); |
|
30
|
|
|
|
|
161
|
|
233
|
|
|
|
|
|
|
} |
234
|
|
|
|
|
|
|
|
235
|
|
|
|
|
|
|
sub read($$$$) |
236
|
2
|
|
|
2
|
1
|
6
|
{ my ($self, $parser, $head, $bodytype) = @_; |
237
|
|
|
|
|
|
|
|
238
|
2
|
|
|
|
|
4
|
my $boundary = $self->boundary; |
239
|
|
|
|
|
|
|
|
240
|
2
|
|
|
|
|
12
|
$parser->pushSeparator("--$boundary"); |
241
|
2
|
|
|
|
|
9
|
my @msgopts = $self->logSettings; |
242
|
|
|
|
|
|
|
|
243
|
2
|
|
|
|
|
3
|
my $te; |
244
|
2
|
100
|
100
|
|
|
6
|
$te = lc $1 |
245
|
|
|
|
|
|
|
if +($head->get('Content-Transfer-Encoding') || '') =~ m/(\w+)/; |
246
|
|
|
|
|
|
|
|
247
|
2
|
|
|
|
|
8
|
my @sloppyopts = |
248
|
|
|
|
|
|
|
( mime_type => 'text/plain' |
249
|
|
|
|
|
|
|
, transfer_encoding => $te |
250
|
|
|
|
|
|
|
); |
251
|
|
|
|
|
|
|
|
252
|
|
|
|
|
|
|
# Get preamble. |
253
|
2
|
|
|
|
|
4
|
my $headtype = ref $head; |
254
|
|
|
|
|
|
|
|
255
|
2
|
|
|
|
|
6
|
my $begin = $parser->filePosition; |
256
|
2
|
|
|
|
|
10
|
my $preamble = Mail::Message::Body::Lines->new(@msgopts, @sloppyopts) |
257
|
|
|
|
|
|
|
->read($parser, $head); |
258
|
|
|
|
|
|
|
|
259
|
2
|
100
|
|
|
|
9
|
$preamble->nrLines |
260
|
|
|
|
|
|
|
or undef $preamble; |
261
|
|
|
|
|
|
|
|
262
|
2
|
100
|
|
|
|
8
|
$self->{MMBM_preamble} = $preamble |
263
|
|
|
|
|
|
|
if defined $preamble; |
264
|
|
|
|
|
|
|
|
265
|
|
|
|
|
|
|
# Get the parts. |
266
|
|
|
|
|
|
|
|
267
|
2
|
|
|
|
|
3
|
my @parts; |
268
|
2
|
|
|
|
|
8
|
while(my $sep = $parser->readSeparator) |
269
|
6
|
100
|
|
|
|
25
|
{ last if $sep eq "--$boundary--\n"; |
270
|
|
|
|
|
|
|
|
271
|
4
|
|
|
|
|
22
|
my $part = Mail::Message::Part->new |
272
|
|
|
|
|
|
|
( @msgopts |
273
|
|
|
|
|
|
|
, container => $self |
274
|
|
|
|
|
|
|
); |
275
|
|
|
|
|
|
|
|
276
|
4
|
50
|
|
|
|
16
|
last unless $part->readFromParser($parser, $bodytype); |
277
|
4
|
50
|
33
|
|
|
11
|
push @parts, $part |
278
|
|
|
|
|
|
|
if $part->head->names || $part->body->size; |
279
|
|
|
|
|
|
|
} |
280
|
2
|
|
|
|
|
7
|
$self->{MMBM_parts} = \@parts; |
281
|
|
|
|
|
|
|
|
282
|
|
|
|
|
|
|
# Get epilogue |
283
|
|
|
|
|
|
|
|
284
|
2
|
|
|
|
|
8
|
$parser->popSeparator; |
285
|
2
|
|
|
|
|
7
|
my $epilogue = Mail::Message::Body::Lines->new(@msgopts, @sloppyopts) |
286
|
|
|
|
|
|
|
->read($parser, $head); |
287
|
|
|
|
|
|
|
|
288
|
2
|
0
|
|
|
|
8
|
my $end = defined $epilogue ? ($epilogue->fileLocation)[1] |
|
|
0
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
289
|
|
|
|
|
|
|
: @parts ? ($parts[-1]->body->fileLocation)[1] |
290
|
|
|
|
|
|
|
: defined $preamble ? ($preamble->fileLocation)[1] |
291
|
|
|
|
|
|
|
: $begin; |
292
|
2
|
|
|
|
|
21
|
$self->fileLocation($begin, $end); |
293
|
|
|
|
|
|
|
|
294
|
2
|
50
|
|
|
|
6
|
$epilogue->nrLines |
295
|
|
|
|
|
|
|
or undef $epilogue; |
296
|
|
|
|
|
|
|
|
297
|
2
|
50
|
|
|
|
6
|
$self->{MMBM_epilogue} = $epilogue |
298
|
|
|
|
|
|
|
if defined $epilogue; |
299
|
|
|
|
|
|
|
|
300
|
2
|
|
|
|
|
10
|
$self; |
301
|
|
|
|
|
|
|
} |
302
|
|
|
|
|
|
|
|
303
|
|
|
|
|
|
|
#------------------------------------------ |
304
|
|
|
|
|
|
|
|
305
|
|
|
|
|
|
|
|
306
|
|
|
|
|
|
|
sub foreachComponent($) |
307
|
18
|
|
|
18
|
1
|
60
|
{ my ($self, $code) = @_; |
308
|
18
|
|
|
|
|
35
|
my $changes = 0; |
309
|
|
|
|
|
|
|
|
310
|
18
|
|
|
|
|
25
|
my $new_preamble; |
311
|
18
|
100
|
|
|
|
59
|
if(my $preamble = $self->preamble) |
312
|
1
|
|
|
|
|
3
|
{ $new_preamble = $code->($self, $preamble); |
313
|
1
|
50
|
|
|
|
5
|
$changes++ unless $preamble == $new_preamble; |
314
|
|
|
|
|
|
|
} |
315
|
|
|
|
|
|
|
|
316
|
18
|
|
|
|
|
31
|
my $new_epilogue; |
317
|
18
|
100
|
|
|
|
47
|
if(my $epilogue = $self->epilogue) |
318
|
1
|
|
|
|
|
3
|
{ $new_epilogue = $code->($self, $epilogue); |
319
|
1
|
50
|
|
|
|
4
|
$changes++ unless $epilogue == $new_epilogue; |
320
|
|
|
|
|
|
|
} |
321
|
|
|
|
|
|
|
|
322
|
18
|
|
|
|
|
29
|
my @new_bodies; |
323
|
18
|
|
|
|
|
66
|
foreach my $part ($self->parts('ACTIVE')) |
324
|
28
|
|
|
|
|
117
|
{ my $part_body = $part->body; |
325
|
28
|
|
|
|
|
72
|
my $new_body = $code->($self, $part_body); |
326
|
|
|
|
|
|
|
|
327
|
28
|
100
|
|
|
|
104
|
$changes++ if $new_body != $part_body; |
328
|
28
|
|
|
|
|
111
|
push @new_bodies, [$part, $new_body]; |
329
|
|
|
|
|
|
|
} |
330
|
|
|
|
|
|
|
|
331
|
18
|
100
|
|
|
|
88
|
return $self unless $changes; |
332
|
|
|
|
|
|
|
|
333
|
9
|
|
|
|
|
20
|
my @new_parts; |
334
|
9
|
|
|
|
|
21
|
foreach (@new_bodies) |
335
|
19
|
|
|
|
|
41
|
{ my ($part, $body) = @$_; |
336
|
19
|
|
|
|
|
71
|
my $new_part = Mail::Message::Part->new |
337
|
|
|
|
|
|
|
( head => $part->head->clone, |
338
|
|
|
|
|
|
|
container => undef |
339
|
|
|
|
|
|
|
); |
340
|
19
|
|
|
|
|
74
|
$new_part->body($body); |
341
|
19
|
|
|
|
|
53
|
push @new_parts, $new_part; |
342
|
|
|
|
|
|
|
} |
343
|
|
|
|
|
|
|
|
344
|
9
|
|
|
|
|
76
|
my $constructed = (ref $self)->new |
345
|
|
|
|
|
|
|
( preamble => $new_preamble |
346
|
|
|
|
|
|
|
, parts => \@new_parts |
347
|
|
|
|
|
|
|
, epilogue => $new_epilogue |
348
|
|
|
|
|
|
|
, based_on => $self |
349
|
|
|
|
|
|
|
); |
350
|
|
|
|
|
|
|
|
351
|
|
|
|
|
|
|
$_->container($constructed) |
352
|
9
|
|
|
|
|
43
|
foreach @new_parts; |
353
|
|
|
|
|
|
|
|
354
|
9
|
|
|
|
|
50
|
$constructed; |
355
|
|
|
|
|
|
|
} |
356
|
|
|
|
|
|
|
|
357
|
|
|
|
|
|
|
|
358
|
|
|
|
|
|
|
sub attach(@) |
359
|
2
|
|
|
2
|
1
|
6
|
{ my $self = shift; |
360
|
2
|
|
|
|
|
7
|
my $new = ref($self)->new |
361
|
|
|
|
|
|
|
( based_on => $self |
362
|
|
|
|
|
|
|
, parts => [$self->parts, @_] |
363
|
|
|
|
|
|
|
); |
364
|
|
|
|
|
|
|
} |
365
|
|
|
|
|
|
|
|
366
|
|
|
|
|
|
|
|
367
|
|
|
|
|
|
|
sub stripSignature(@) |
368
|
1
|
|
|
1
|
1
|
2
|
{ my $self = shift; |
369
|
|
|
|
|
|
|
|
370
|
1
|
|
|
|
|
4
|
my @allparts = $self->parts; |
371
|
1
|
|
|
|
|
2
|
my @parts = grep {! $_->body->mimeType->isSignature} @allparts; |
|
2
|
|
|
|
|
43
|
|
372
|
|
|
|
|
|
|
|
373
|
1
|
50
|
|
|
|
31
|
@allparts==@parts ? $self |
374
|
|
|
|
|
|
|
: (ref $self)->new(based_on => $self, parts => \@parts); |
375
|
|
|
|
|
|
|
} |
376
|
|
|
|
|
|
|
|
377
|
|
|
|
|
|
|
#------------------------------------------ |
378
|
|
|
|
|
|
|
|
379
|
|
|
|
|
|
|
|
380
|
97
|
|
|
97
|
1
|
343
|
sub preamble() {shift->{MMBM_preamble}} |
381
|
|
|
|
|
|
|
|
382
|
|
|
|
|
|
|
|
383
|
97
|
|
|
97
|
1
|
331
|
sub epilogue() {shift->{MMBM_epilogue}} |
384
|
|
|
|
|
|
|
|
385
|
|
|
|
|
|
|
|
386
|
|
|
|
|
|
|
sub parts(;$) |
387
|
147
|
|
|
147
|
1
|
334
|
{ my $self = shift; |
388
|
147
|
100
|
|
|
|
309
|
return @{$self->{MMBM_parts}} unless @_; |
|
64
|
|
|
|
|
326
|
|
389
|
|
|
|
|
|
|
|
390
|
83
|
|
|
|
|
156
|
my $what = shift; |
391
|
83
|
|
|
|
|
118
|
my @parts = @{$self->{MMBM_parts}}; |
|
83
|
|
|
|
|
209
|
|
392
|
|
|
|
|
|
|
|
393
|
0
|
|
|
|
|
0
|
$what eq 'RECURSE' ? (map {$_->parts('RECURSE')} @parts) |
394
|
|
|
|
|
|
|
: $what eq 'ALL' ? @parts |
395
|
0
|
|
|
|
|
0
|
: $what eq 'DELETED' ? (grep {$_->isDeleted} @parts) |
396
|
138
|
|
|
|
|
371
|
: $what eq 'ACTIVE' ? (grep {not $_->isDeleted} @parts) |
397
|
83
|
0
|
|
|
|
411
|
: ref $what eq 'CODE'? (grep {$what->($_)} @parts) |
|
0
|
50
|
|
|
|
0
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
398
|
|
|
|
|
|
|
: ($self->log(ERROR => "Unknown criterium $what to select parts."), return ()); |
399
|
|
|
|
|
|
|
} |
400
|
|
|
|
|
|
|
|
401
|
|
|
|
|
|
|
|
402
|
12
|
|
|
12
|
1
|
163
|
sub part($) { shift->{MMBM_parts}[shift] } |
403
|
|
|
|
|
|
|
|
404
|
|
|
|
|
|
|
sub partNumberOf($) |
405
|
6
|
|
|
6
|
1
|
12
|
{ my ($self, $part) = @_; |
406
|
6
|
|
|
|
|
13
|
my @parts = $self->parts('ACTIVE'); |
407
|
6
|
|
|
|
|
17
|
my $msg = $self->message; |
408
|
6
|
50
|
|
|
|
14
|
unless($msg) |
409
|
0
|
|
|
|
|
0
|
{ $self->log(ERROR => 'multipart is not connected'); |
410
|
0
|
|
|
|
|
0
|
return 'ERROR'; |
411
|
|
|
|
|
|
|
} |
412
|
6
|
50
|
|
|
|
31
|
my $base = $msg->isa('Mail::Message::Part') ? $msg->partNumber.'.' : ''; |
413
|
6
|
|
|
|
|
18
|
foreach my $partnr (0..@parts) |
414
|
12
|
100
|
|
|
|
55
|
{ return $base.($partnr+1) |
415
|
|
|
|
|
|
|
if $parts[$partnr] == $part; |
416
|
|
|
|
|
|
|
} |
417
|
0
|
|
|
|
|
0
|
$self->log(ERROR => 'multipart is not found or not active'); |
418
|
0
|
|
|
|
|
0
|
'ERROR'; |
419
|
|
|
|
|
|
|
} |
420
|
|
|
|
|
|
|
|
421
|
|
|
|
|
|
|
|
422
|
|
|
|
|
|
|
sub boundary(;$) |
423
|
96
|
|
|
96
|
1
|
176
|
{ my $self = shift; |
424
|
96
|
|
|
|
|
248
|
my $mime = $self->type; |
425
|
|
|
|
|
|
|
|
426
|
96
|
100
|
|
|
|
233
|
unless(@_) |
427
|
62
|
|
|
|
|
199
|
{ my $boundary = $mime->attribute('boundary'); |
428
|
62
|
50
|
|
|
|
278
|
return $boundary if defined $boundary; |
429
|
|
|
|
|
|
|
} |
430
|
|
|
|
|
|
|
|
431
|
34
|
100
|
66
|
|
|
425
|
my $boundary = @_ && defined $_[0] ? (shift) : "boundary-".int rand(1000000); |
432
|
34
|
|
|
|
|
103
|
$self->type->attribute(boundary => $boundary); |
433
|
|
|
|
|
|
|
} |
434
|
|
|
|
|
|
|
|
435
|
|
|
|
|
|
|
sub endsOnNewline() { 1 } |
436
|
|
|
|
|
|
|
|
437
|
0
|
0
|
|
0
|
0
|
|
sub toplevel() { my $msg = shift->message; $msg ? $msg->toplevel : undef} |
|
0
|
|
|
|
|
|
|
438
|
|
|
|
|
|
|
|
439
|
|
|
|
|
|
|
#------------------------------------------- |
440
|
|
|
|
|
|
|
|
441
|
|
|
|
|
|
|
|
442
|
|
|
|
|
|
|
1; |