line
stmt
bran
cond
sub
pod
time
code
1
19
19
298890
use v5.12.0;
19
137
2
19
19
102
use warnings;
19
35
19
976
3
package Email::MIME 1.953;
4
# ABSTRACT: easy MIME message handling
5
6
19
19
8956
use Email::Simple 2.212; # nth header value
19
84486
19
590
7
19
19
6080
use parent qw(Email::Simple);
19
4226
19
116
8
9
19
19
1119
use Carp ();
19
41
19
305
10
19
19
8087
use Email::MessageID;
19
25154
19
633
11
19
19
5696
use Email::MIME::Creator;
19
47
19
652
12
19
19
9765
use Email::MIME::ContentType 1.023; # build_content_type
19
549988
19
1537
13
19
19
8210
use Email::MIME::Encode;
19
48
19
710
14
19
19
7440
use Email::MIME::Encodings 1.314;
19
20979
19
487
15
19
19
127
use Email::MIME::Header;
19
36
19
429
16
19
19
86
use Encode 1.9801 ();
19
243
19
399
17
19
19
86
use Scalar::Util qw(reftype weaken);
19
37
19
42401
18
19
our @CARP_NOT = qw(Email::MIME::ContentType);
20
21
#pod =head1 SYNOPSIS
22
#pod
23
#pod B Before you read this, maybe you just need L, which is
24
#pod a much easier-to-use tool for building simple email messages that might have
25
#pod attachments or both plain text and HTML. If that doesn't do it for you, then
26
#pod by all means keep reading.
27
#pod
28
#pod use Email::MIME;
29
#pod my $parsed = Email::MIME->new($message);
30
#pod
31
#pod my @parts = $parsed->parts; # These will be Email::MIME objects, too.
32
#pod my $decoded = $parsed->body;
33
#pod my $non_decoded = $parsed->body_raw;
34
#pod
35
#pod my $content_type = $parsed->content_type;
36
#pod
37
#pod ...or...
38
#pod
39
#pod use Email::MIME;
40
#pod use IO::All;
41
#pod
42
#pod # multipart message
43
#pod my @parts = (
44
#pod Email::MIME->create(
45
#pod attributes => {
46
#pod filename => "report.pdf",
47
#pod content_type => "application/pdf",
48
#pod encoding => "quoted-printable",
49
#pod name => "2004-financials.pdf",
50
#pod },
51
#pod body => io( "2004-financials.pdf" )->binary->all,
52
#pod ),
53
#pod Email::MIME->create(
54
#pod attributes => {
55
#pod content_type => "text/plain",
56
#pod disposition => "attachment",
57
#pod charset => "US-ASCII",
58
#pod },
59
#pod body_str => "Hello there!",
60
#pod ),
61
#pod );
62
#pod
63
#pod my $email = Email::MIME->create(
64
#pod header_str => [
65
#pod From => 'casey@geeknest.com',
66
#pod To => [ 'user1@host.com', 'Name ' ],
67
#pod Cc => Email::Address::XS->new("Display Name \N{U+1F600}", 'user@example.com'),
68
#pod ],
69
#pod parts => [ @parts ],
70
#pod );
71
#pod
72
#pod # nesting parts
73
#pod $email->parts_set(
74
#pod [
75
#pod $email->parts,
76
#pod Email::MIME->create( parts => [ @parts ] ),
77
#pod ],
78
#pod );
79
#pod
80
#pod # standard modifications
81
#pod $email->header_str_set( 'X-PoweredBy' => 'RT v3.0' );
82
#pod $email->header_str_set( To => rcpts() );
83
#pod $email->header_str_set( Cc => aux_rcpts() );
84
#pod $email->header_str_set( Bcc => sekrit_rcpts() );
85
#pod
86
#pod # more advanced
87
#pod $_->encoding_set( 'base64' ) for $email->parts;
88
#pod
89
#pod # Quick multipart creation
90
#pod my $email = Email::MIME->create(
91
#pod header_str => [
92
#pod From => 'my@address',
93
#pod To => 'your@address',
94
#pod ],
95
#pod parts => [
96
#pod q[This is part one],
97
#pod q[This is part two],
98
#pod q[These could be binary too],
99
#pod ],
100
#pod );
101
#pod
102
#pod print $email->as_string;
103
#pod
104
#pod =head1 DESCRIPTION
105
#pod
106
#pod This is an extension of the L module, to handle MIME
107
#pod encoded messages. It takes a message as a string, splits it up into its
108
#pod constituent parts, and allows you access to various parts of the
109
#pod message. Headers are decoded from MIME encoding.
110
#pod
111
#pod =head1 METHODS
112
#pod
113
#pod Please see L for the base set of methods. It won't take
114
#pod very long. Added to that, you have:
115
#pod
116
#pod =cut
117
118
our $CREATOR = 'Email::MIME::Creator';
119
120
my $NO_ENCODE_RE = qr/
121
\A
122
(?:7bit|8bit|binary)\s*(?:;|$)
123
/ix;
124
125
sub new {
126
164
164
1
70896
my ($class, $text, $arg, @rest) = @_;
127
164
100
484
$arg ||= {};
128
129
my $encode_check = exists $arg->{encode_check}
130
? delete $arg->{encode_check}
131
164
100
415
: Encode::FB_CROAK;
132
133
164
613
my $self = shift->SUPER::new($text, $arg, @rest);
134
164
1825
$self->encode_check_set($encode_check);
135
164
342
$self->{ct} = parse_content_type($self->content_type_raw);
136
164
24469
$self->parts;
137
164
384
return $self;
138
}
139
140
#pod =method create
141
#pod
142
#pod my $single = Email::MIME->create(
143
#pod header_str => [ ... ],
144
#pod body_str => '...',
145
#pod attributes => { ... },
146
#pod );
147
#pod
148
#pod my $multi = Email::MIME->create(
149
#pod header_str => [ ... ],
150
#pod parts => [ ... ],
151
#pod attributes => { ... },
152
#pod );
153
#pod
154
#pod This method creates a new MIME part. The C parameter is a list of
155
#pod headers pairs to include in the message. The value for each pair is expected to
156
#pod be a text string that will be MIME-encoded as needed. Alternatively it can be
157
#pod an object with C method which implements conversion of that
158
#pod object to MIME-encoded string. That object method is called with two named
159
#pod input parameters: C and C. It should return
160
#pod MIME-encoded representation of the object. As of 2017-07-25, the
161
#pod header-value-as-object code is very young, and may yet change.
162
#pod
163
#pod In case header name is registered in C<%Email::MIME::Header::header_to_class_map>
164
#pod hash then registered class is used for conversion from Unicode string to 8bit
165
#pod MIME encoding. Value can be either string or array reference to strings.
166
#pod Object is constructed via method C with string value (or values
167
#pod in case of array reference) and converted to MIME-encoded string via
168
#pod C method.
169
#pod
170
#pod A similar C parameter can be provided in addition to or instead of
171
#pod C. Its values will be used verbatim.
172
#pod
173
#pod C is a hash of MIME attributes to assign to the part, and may
174
#pod override portions of the header set in the C
175
#pod correspond directly to methods for modifying a message. The allowed keys are:
176
#pod content_type, charset, name, format, boundary, encoding, disposition, and
177
#pod filename. They will be mapped to C<"$attr\_set"> for message modification.
178
#pod
179
#pod The C parameter is a list reference containing C
180
#pod objects. Elements of the C list can also be a non-reference
181
#pod string of data. In that case, an C object will be created
182
#pod for you. Simple checks will determine if the part is binary or not, and
183
#pod all parts created in this fashion are encoded with C, just in case.
184
#pod
185
#pod If C is given instead of C, it specifies the body to be used for a
186
#pod flat (subpart-less) MIME message. It is assumed to be a sequence of octets.
187
#pod
188
#pod If C is given instead of C or C, it is assumed to be a
189
#pod character string to be used as the body. If you provide a C
190
#pod parameter, you B provide C and C attributes.
191
#pod
192
#pod =cut
193
194
my %CT_SETTER = map {; $_ => 1 } qw(
195
content_type charset name format boundary
196
encoding
197
disposition filename
198
);
199
200
sub create {
201
54
54
1
34692
my ($class, %args) = @_;
202
203
54
103
my $header = '';
204
54
80
my %headers;
205
54
100
188
if (exists $args{header}) {
206
8
17
my @headers = @{ $args{header} };
8
28
207
8
50
37
pop @headers if @headers % 2 == 1;
208
8
42
while (my ($key, $value) = splice @headers, 0, 2) {
209
16
372
$headers{$key} = 1;
210
16
105
$CREATOR->_add_to_header(\$header, $key, $value);
211
}
212
}
213
214
54
100
520
if (exists $args{header_str}) {
215
11
14
my @headers = @{ $args{header_str} };
11
30
216
11
50
34
pop @headers if @headers % 2 == 1;
217
11
41
while (my ($key, $value) = splice @headers, 0, 2) {
218
23
612
$headers{$key} = 1;
219
220
23
99
$value = Email::MIME::Encode::maybe_mime_encode_header(
221
$key, $value, 'UTF-8'
222
);
223
23
130
$CREATOR->_add_to_header(\$header, $key, $value);
224
}
225
}
226
227
$CREATOR->_add_to_header(\$header, Date => $CREATOR->_date_header)
228
54
50
716
unless exists $headers{Date};
229
54
48641
$CREATOR->_add_to_header(\$header, 'MIME-Version' => '1.0',);
230
231
54
100
1455
my %attrs = $args{attributes} ? %{ $args{attributes} } : ();
31
156
232
233
# XXX: This is awful... but if we don't do this, then Email::MIME->new will
234
# end up calling parse_content_type($self->content_type) which will mean
235
# parse_content_type(undef) which, for some reason, returns the default.
236
# It's really sort of mind-boggling. Anyway, the default ends up being
237
# q{text/plain; charset="us-ascii"} so that if content_type is in the
238
# attributes, but not charset, then charset isn't changed and you up with
239
# something that's q{image/jpeg; charset="us-ascii"} and you look like a
240
# moron. -- rjbs, 2009-01-20
241
54
100
129
if (
242
270
604
grep { exists $attrs{$_} } qw(content_type charset name format boundary)
243
) {
244
30
101
$CREATOR->_add_to_header(\$header, 'Content-Type' => 'text/plain',);
245
}
246
247
54
785
my %pass_on;
248
249
54
100
135
if (exists $args{encode_check}) {
250
3
7
$pass_on{encode_check} = $args{encode_check};
251
}
252
253
54
193
my $email = $class->new($header, \%pass_on);
254
255
54
237
for my $key (sort keys %attrs) {
256
64
177
$email->content_type_attribute_set($key => $attrs{$key});
257
}
258
259
54
450
my $body_args = grep { defined $args{$_} } qw(parts body body_str);
162
359
260
54
50
145
Carp::confess("only one of parts, body, or body_str may be given")
261
if $body_args > 1;
262
263
54
100
66
268
if ($args{parts} && @{ $args{parts} }) {
14
100
52
100
264
14
25
foreach my $part (@{ $args{parts} }) {
14
52
265
25
100
96
$part = $CREATOR->_construct_part($part)
266
unless ref($part);
267
}
268
14
47
$email->parts_set($args{parts});
269
} elsif (defined $args{body}) {
270
33
96
$email->body_set($args{body});
271
} elsif (defined $args{body_str}) {
272
Carp::confess("body_str was given, but no charset is defined")
273
6
50
20
unless my $charset = $attrs{charset};
274
275
Carp::confess("body_str was given, but no encoding is defined")
276
6
50
25
unless $attrs{encoding};
277
278
6
22
my $body_octets = Encode::encode($attrs{charset}, $args{body_str}, $email->encode_check);
279
4
1688
$email->body_set($body_octets);
280
}
281
282
52
702
$email;
283
}
284
285
sub as_string {
286
145
145
1
3171
my $self = shift;
287
return $self->__head->as_string
288
145
50
391
. ($self->{mycrlf} || "\n") # XXX: replace with ->crlf
289
. $self->body_raw;
290
}
291
292
sub parts {
293
302
302
1
4296
my $self = shift;
294
295
302
100
965
$self->fill_parts unless $self->{parts};
296
297
302
404
my @parts = @{ $self->{parts} };
302
559
298
302
100
701
@parts = $self unless @parts;
299
302
765
return @parts;
300
}
301
302
sub subparts {
303
52
52
1
94
my ($self) = @_;
304
305
52
50
126
$self->fill_parts unless $self->{parts};
306
52
73
my @parts = @{ $self->{parts} };
52
91
307
52
143
return @parts;
308
}
309
310
sub fill_parts {
311
193
193
0
292
my $self = shift;
312
313
193
100
66
835
if (
314
$self->{ct}{type} eq "multipart"
315
or $self->{ct}{type} eq "message"
316
) {
317
41
155
$self->parts_multipart;
318
} else {
319
152
326
$self->parts_single_part;
320
}
321
322
193
346
return $self;
323
}
324
325
sub body {
326
106
106
1
1554
my $self = shift;
327
106
310
my $body = $self->SUPER::body;
328
106
100
944
my $cte = $self->header("Content-Transfer-Encoding") || '';
329
330
106
284
$cte =~ s/\A\s+//;
331
106
189
$cte =~ s/\s+\z//;
332
106
159
$cte =~ s/;.+//; # For S/MIME, etc.
333
334
106
100
243
return $body unless $cte;
335
336
55
100
66
133
if (!$self->force_decode_hook and $cte =~ $NO_ENCODE_RE) {
337
26
97
return $body;
338
}
339
340
29
50
208
$body = $self->decode_hook($body) if $self->can("decode_hook");
341
342
29
108
$body = Email::MIME::Encodings::decode($cte, $body, '7bit');
343
29
923
return $body;
344
}
345
346
sub parts_single_part {
347
152
152
0
300
my $self = shift;
348
152
461
$self->{parts} = [];
349
152
243
return $self;
350
}
351
352
sub body_raw {
353
237
66
237
1
10967
return $_[0]->{body_raw} || $_[0]->SUPER::body;
354
}
355
356
sub body_str {
357
14
14
1
1053
my ($self) = @_;
358
14
32
my $encoding = $self->{ct}{attributes}{charset};
359
360
14
100
39
unless ($encoding) {
361
2
50
33
15
if ($self->{ct}{type} eq 'text'
66
362
and
363
($self->{ct}{subtype} eq 'plain' or $self->{ct}{subtype} eq 'html')
364
) {
365
366
# assume that plaintext or html without ANY charset is us-ascii
367
1
5
return $self->body;
368
}
369
370
1
4
Carp::confess("can't get body as a string for " . $self->content_type);
371
}
372
373
12
31
my $str = Encode::decode($encoding, $self->body, $self->encode_check);
374
10
1176
return $str;
375
}
376
377
our $MAX_DEPTH = 10;
378
379
sub parts_multipart {
380
41
41
0
64
my $self = shift;
381
41
165
my $boundary = $self->{ct}->{attributes}->{boundary};
382
383
41
100
189
our $DEPTH ||= 0;
384
385
41
50
33
179
Carp::croak("attempted to parse a MIME message more than $MAX_DEPTH deep")
386
if $MAX_DEPTH && $DEPTH > $MAX_DEPTH;
387
388
# Take a message, join all its lines together. Now try to Email::MIME->new
389
# it with 1.861 or earlier. Death! It tries to recurse endlessly on the
390
# body, because every time it splits on boundary it gets itself. Obviously
391
# that means it's a bogus message, but a mangled result (or exception) is
392
# better than endless recursion. -- rjbs, 2008-01-07
393
41
50
33
152
return $self->parts_single_part
394
unless length $boundary and $self->body_raw =~ /^--\Q$boundary\E\s*$/sm;
395
396
41
184
$self->{body_raw} = $self->SUPER::body;
397
398
# rfc1521 7.2.1
399
41
879
my ($body, $epilogue) = split /^--\Q$boundary\E--\s*$/sm, $self->body_raw, 2;
400
401
41
50
827
my @bits = split /^--\Q$boundary\E\s*$/sm, ($body || '');
402
403
41
158
$self->SUPER::body_set(undef);
404
405
# If there are no headers in the potential MIME part, it's just part of the
406
# body. This is a horrible hack, although it's debatable whether it was
407
# better or worse when it was $self->{body} = shift @bits ... -- rjbs,
408
# 2006-11-27
409
41
50
100
523
$self->SUPER::body_set(shift @bits) if index(($bits[0] || ''), ':') == -1;
410
411
41
281
my $bits = @bits;
412
413
41
69
my @parts;
414
41
83
for my $bit (@bits) {
415
82
429
$bit =~ s/\A[\n\r]+//smg;
416
82
941
$bit =~ s/(?{mycrlf}\Z//sm;
417
82
184
local $DEPTH = $DEPTH + 1;
418
82
232
my $email = (ref $self)->new($bit, { encode_check => $self->encode_check });
419
82
269
push @parts, $email;
420
}
421
422
41
110
$self->{parts} = \@parts;
423
424
41
64
return @{ $self->{parts} };
41
136
425
}
426
427
55
55
0
458
sub force_decode_hook { 0 }
428
29
29
1
64
sub decode_hook { return $_[1] }
429
22
22
1
89
sub content_type { scalar shift->header("Content-type"); }
430
164
164
0
421
sub content_type_raw { scalar shift->header_raw("Content-type"); }
431
432
sub debug_structure {
433
7
7
1
854
my ($self, $level) = @_;
434
7
100
25
$level ||= 0;
435
7
18
my $rv = " " x (5 * $level);
436
7
100
18
$rv .= "+ " . ($self->content_type || '') . "\n";
437
7
20
my @parts = $self->subparts;
438
7
25
$rv .= $_->debug_structure($level + 1) for @parts;
439
7
28
return $rv;
440
}
441
442
my %gcache;
443
444
sub filename {
445
5
5
1
2651
my ($self, $force) = @_;
446
5
100
24
return $gcache{$self} if exists $gcache{$self};
447
448
4
100
14
my $dis = $self->header_raw("Content-Disposition") || '';
449
4
154
my $attrs = parse_content_disposition($dis)->{attributes};
450
my $name = $attrs->{filename}
451
4
100
460
|| $self->{ct}{attributes}{name};
452
4
100
66
23
return $name if $name or !$force;
453
return $gcache{$self} = $self->invent_filename(
454
2
9
$self->{ct}->{type} . "/" . $self->{ct}->{subtype});
455
}
456
457
my $gname = 0;
458
459
sub invent_filename {
460
2
2
1
6
my ($self, $ct) = @_;
461
2
14
require MIME::Types;
462
2
10
my $type = MIME::Types->new->type($ct);
463
2
33
110
my $ext = $type && (($type->extensions)[0]);
464
2
50
28
$ext ||= "dat";
465
2
20
return "attachment-$$-" . $gname++ . ".$ext";
466
}
467
468
164
164
1
8799
sub default_header_class { 'Email::MIME::Header' }
469
470
sub header_str {
471
26
26
0
10961
my $self = shift;
472
26
66
$self->header_obj->header_str(@_);
473
}
474
475
sub header_str_set {
476
20
20
1
12473
my $self = shift;
477
20
57
$self->header_obj->header_str_set(@_);
478
}
479
480
sub header_str_pairs {
481
1
1
1
2008
my $self = shift;
482
1
3
$self->header_obj->header_str_pairs(@_);
483
}
484
485
sub header_as_obj {
486
14
14
1
78
my $self = shift;
487
14
38
$self->header_obj->header_as_obj(@_);
488
}
489
490
#pod =method content_type_set
491
#pod
492
#pod $email->content_type_set( 'text/html' );
493
#pod
494
#pod Change the content type. All C header attributes
495
#pod will remain intact.
496
#pod
497
#pod =cut
498
499
sub content_type_set {
500
28
28
1
1487
my ($self, $ct) = @_;
501
28
82
my $ct_header = parse_content_type($self->header('Content-Type'));
502
28
2475
@{$ct_header}{qw[type subtype]} = split m[/], $ct;
28
72
503
28
93
$self->_compose_content_type($ct_header);
504
28
80
$self->_reset_cids;
505
28
127
return $ct;
506
}
507
508
#pod =method charset_set
509
#pod
510
#pod =method name_set
511
#pod
512
#pod =method format_set
513
#pod
514
#pod =method boundary_set
515
#pod
516
#pod $email->charset_set( 'UTF-8' );
517
#pod $email->name_set( 'some_filename.txt' );
518
#pod $email->format_set( 'flowed' );
519
#pod $email->boundary_set( undef ); # remove the boundary
520
#pod
521
#pod These four methods modify common C attributes. If set to
522
#pod C, the attribute is removed. All other C header
523
#pod information is preserved when modifying an attribute.
524
#pod
525
#pod =cut
526
527
BEGIN {
528
19
19
72
foreach my $attr (qw[charset name format]) {
529
my $code = sub {
530
16
16
4209
my ($self, $value) = @_;
531
16
54
my $ct_header = parse_content_type($self->header('Content-Type'));
532
16
100
1655
if ($value) {
533
15
44
$ct_header->{attributes}->{$attr} = $value;
534
} else {
535
1
4
delete $ct_header->{attributes}->{$attr};
536
}
537
16
62
$self->_compose_content_type($ct_header);
538
16
42
return $value;
539
57
307
};
540
541
19
19
166
no strict 'refs'; ## no critic strict
19
36
19
1027
542
57
112
*{"$attr\_set"} = $code;
57
37124
543
}
544
}
545
546
sub boundary_set {
547
1
1
1
2
my ($self, $value) = @_;
548
1
4
my $ct_header = parse_content_type($self->header('Content-Type'));
549
550
1
50
183
if (length $value) {
551
1
4
$ct_header->{attributes}->{boundary} = $value;
552
} else {
553
0
0
delete $ct_header->{attributes}->{boundary};
554
}
555
1
3
$self->_compose_content_type($ct_header);
556
557
1
50
4
$self->parts_set([ $self->parts ]) if $self->parts > 1;
558
}
559
560
sub content_type_attribute_set {
561
65
65
0
1123
my ($self, $key, $value) = @_;
562
65
117
$key = lc $key;
563
564
65
100
248
if ($CT_SETTER{$key}) {
565
62
136
my $method = "$key\_set";
566
62
173
return $self->$method($value);
567
}
568
569
3
10
my $ct_header = parse_content_type($self->header('Content-Type'));
570
3
359
my $attrs = $ct_header->{attributes};
571
572
3
11
for my $existing_key (keys %$attrs) {
573
3
50
9
delete $attrs->{$existing_key} if lc $existing_key eq $key;
574
}
575
576
3
50
10
if ($value) {
577
3
9
$ct_header->{attributes}->{$key} = $value;
578
} else {
579
0
0
delete $ct_header->{attributes}->{$key};
580
}
581
3
9
$self->_compose_content_type($ct_header);
582
}
583
584
#pod =method encode_check
585
#pod
586
#pod =method encode_check_set
587
#pod
588
#pod $email->encode_check;
589
#pod $email->encode_check_set(0);
590
#pod $email->encode_check_set(Encode::FB_DEFAULT);
591
#pod
592
#pod Gets/sets the current C setting (default: I).
593
#pod This is the parameter passed to L and L
594
#pod when C, C, and C are called.
595
#pod
596
#pod With the default setting, Email::MIME may crash if the claimed charset
597
#pod of a body does not match its contents (for example - utf8 data in a
598
#pod text/plain; charset=us-ascii message).
599
#pod
600
#pod With an C of 0, the unrecognized bytes will instead be
601
#pod replaced with the C (U+0FFFD), and may end up
602
#pod as either that or question marks (?).
603
#pod
604
#pod See L for more information.
605
#pod
606
#pod =cut
607
608
sub encode_check {
609
102
102
1
189
my ($self) = @_;
610
611
102
452
return $self->{encode_check};
612
}
613
614
sub encode_check_set {
615
164
164
1
280
my ($self, $val) = @_;
616
617
164
292
return $self->{encode_check} = $val;
618
}
619
620
#pod =method encoding_set
621
#pod
622
#pod $email->encoding_set( 'base64' );
623
#pod $email->encoding_set( 'quoted-printable' );
624
#pod $email->encoding_set( '8bit' );
625
#pod
626
#pod Convert the message body and alter the C
627
#pod header using this method. Your message body, the output of the C
628
#pod method, will remain the same. The raw body, output with the C
629
#pod method, will be changed to reflect the new encoding.
630
#pod
631
#pod =cut
632
633
sub encoding_set {
634
59
59
1
126
my ($self, $enc) = @_;
635
59
100
158
$enc ||= '7bit';
636
59
128
my $body = $self->body;
637
59
178
$self->header_raw_set('Content-Transfer-Encoding' => $enc);
638
59
2444
$self->body_set($body);
639
}
640
641
#pod =method body_set
642
#pod
643
#pod $email->body_set( $unencoded_body_string );
644
#pod
645
#pod This method will encode the new body you send using the encoding
646
#pod specified in the C header, then set
647
#pod the body to the new encoded body.
648
#pod
649
#pod =cut
650
651
sub body_set {
652
295
295
1
14562
my ($self, $body) = @_;
653
295
417
my $body_ref;
654
655
295
100
606
if (ref $body) {
656
165
50
667
Carp::croak("provided body reference is not a scalar reference")
657
unless reftype($body) eq 'SCALAR';
658
165
272
$body_ref = $body;
659
} else {
660
130
205
$body_ref = \$body;
661
}
662
295
708
my $enc = $self->header('Content-Transfer-Encoding');
663
664
# XXX: This is a disgusting hack and needs to be fixed, probably by a
665
# clearer definition and reengineering of Simple construction. The bug
666
# this fixes is an indirect result of the previous behavior in which all
667
# Simple subclasses were free to alter the guts of the Email::Simple
668
# object. -- rjbs, 2007-07-16
669
295
100
100
2263
unless (((caller(1))[3] || '') eq 'Email::Simple::new') {
670
131
100
100
1211
$$body_ref = Email::MIME::Encodings::encode($enc, $$body_ref)
671
unless !$enc || $enc =~ $NO_ENCODE_RE;
672
}
673
674
295
2215
$self->{body_raw} = $$body_ref;
675
295
868
$self->SUPER::body_set($body_ref);
676
}
677
678
#pod =method body_str_set
679
#pod
680
#pod $email->body_str_set($unicode_str);
681
#pod
682
#pod This method behaves like C, but assumes that the given value is a
683
#pod Unicode string that should be encoded into the message's charset
684
#pod before being set.
685
#pod
686
#pod The charset must already be set, either manually (via the C
687
#pod argument to C or C) or through the C of a
688
#pod parsed message. If the charset can't be determined, an exception is thrown.
689
#pod
690
#pod =cut
691
692
sub body_str_set {
693
0
0
1
0
my ($self, $body_str) = @_;
694
695
0
0
my $ct = parse_content_type($self->content_type);
696
Carp::confess("body_str was given, but no charset is defined")
697
0
0
0
unless my $charset = $ct->{attributes}{charset};
698
699
0
0
my $body_octets = Encode::encode($charset, $body_str, $self->encode_check);
700
0
0
$self->body_set($body_octets);
701
}
702
703
#pod =method disposition_set
704
#pod
705
#pod $email->disposition_set( 'attachment' );
706
#pod
707
#pod Alter the C of a message. All header attributes
708
#pod will remain intact.
709
#pod
710
#pod =cut
711
712
sub disposition_set {
713
8
8
1
541
my ($self, $dis) = @_;
714
8
50
23
$dis ||= 'inline';
715
8
33
my $dis_header = $self->header('Content-Disposition');
716
8
100
37
$dis_header
717
? ($dis_header =~ s/^([^;]+)/$dis/)
718
: ($dis_header = $dis);
719
8
30
$self->header_raw_set('Content-Disposition' => $dis_header);
720
}
721
722
#pod =method filename_set
723
#pod
724
#pod $email->filename_set( 'boo.pdf' );
725
#pod
726
#pod Sets the filename attribute in the C header. All other
727
#pod header information is preserved when setting this attribute.
728
#pod
729
#pod =cut
730
731
sub filename_set {
732
4
4
1
9
my ($self, $filename) = @_;
733
4
9
my $dis_header = $self->header('Content-Disposition');
734
4
9
my ($disposition, $attrs) = ('inline', {});
735
4
50
9
if ($dis_header) {
736
4
11
my $struct = parse_content_disposition($dis_header);
737
4
444
$disposition = $struct->{type};
738
4
8
$attrs = $struct->{attributes};
739
}
740
4
100
12
$filename ? $attrs->{filename} = $filename : delete $attrs->{filename};
741
4
12
my $dis = build_content_disposition({type => $disposition, attributes => $attrs});
742
4
2185
$self->header_raw_set('Content-Disposition' => $dis);
743
}
744
745
#pod =method parts_set
746
#pod
747
#pod $email->parts_set( \@new_parts );
748
#pod
749
#pod Replaces the parts for an object. Accepts a reference to a list of
750
#pod C objects, representing the new parts. If this message was
751
#pod originally a single part, the C header will be changed to
752
#pod C, and given a new boundary attribute.
753
#pod
754
#pod =cut
755
756
sub parts_set {
757
29
29
1
123
my ($self, $parts) = @_;
758
29
45
my $body = q{};
759
760
29
72
my $ct_header = parse_content_type($self->header('Content-Type'));
761
762
29
100
100
3520
if (@{$parts} > 1 or $ct_header->{type} eq 'multipart') {
29
50
197
763
764
# setup multipart
765
$ct_header->{attributes}->{boundary} = Email::MessageID->new->user
766
25
100
155
unless length $ct_header->{attributes}->{boundary};
767
25
17491
my $bound = $ct_header->{attributes}->{boundary};
768
25
46
foreach my $part (@{$parts}) {
25
64
769
51
142
$body .= "$self->{mycrlf}--$bound$self->{mycrlf}";
770
51
113
$body .= $part->as_string;
771
}
772
25
88
$body .= "$self->{mycrlf}--$bound--$self->{mycrlf}";
773
774
25
100
55
unless (grep { $ct_header->{type} eq $_ } qw[multipart message]) {
50
153
775
10
50
44
if (scalar $self->header('Content-Type')) {
776
0
0
Carp::carp("replacing non-multipart type ($ct_header->{type}/$ct_header->{subtype}) with multipart/mixed");
777
}
778
10
33
@{$ct_header}{qw[type subtype]} = qw[multipart mixed];
10
29
779
}
780
781
25
83
$self->encoding_set('7bit');
782
25
224
delete $ct_header->{attributes}{charset};
783
} elsif (@$parts == 1) { # setup singlepart
784
4
19
$body .= $parts->[0]->body;
785
786
4
18
my $from_ct = parse_content_type($parts->[0]->header('Content-Type'));
787
4
382
@{$ct_header}{qw[type subtype]} = @{ $from_ct }{qw[type subtype]};
4
9
4
10
788
789
4
100
17
if (exists $from_ct->{attributes}{charset}) {
790
2
6
$ct_header->{attributes}{charset} = $from_ct->{attributes}{charset};
791
} else {
792
2
4
delete $ct_header->{attributes}{charset};
793
}
794
795
4
17
$self->encoding_set($parts->[0]->header('Content-Transfer-Encoding'));
796
4
42
delete $ct_header->{attributes}->{boundary};
797
}
798
799
29
103
$self->_compose_content_type($ct_header);
800
29
88
$self->body_set($body);
801
29
264
$self->fill_parts;
802
29
80
$self->_reset_cids;
803
}
804
805
#pod =method parts_add
806
#pod
807
#pod $email->parts_add( \@more_parts );
808
#pod
809
#pod Adds MIME parts onto the current MIME part. This is a simple extension
810
#pod of C to make our lives easier. It accepts an array reference
811
#pod of additional parts.
812
#pod
813
#pod =cut
814
815
sub parts_add {
816
3
3
1
1498
my ($self, $parts) = @_;
817
3
10
$self->parts_set([ $self->parts, @{$parts}, ]);
3
11
818
}
819
820
#pod =method walk_parts
821
#pod
822
#pod $email->walk_parts(sub {
823
#pod my ($part) = @_;
824
#pod return if $part->subparts; # multipart
825
#pod
826
#pod if ( $part->content_type =~ m[text/html]i ) {
827
#pod my $body = $part->body;
828
#pod $body =~ s/ ]+>//; # simple filter example
829
#pod $part->body_set( $body );
830
#pod }
831
#pod });
832
#pod
833
#pod Walks through all the MIME parts in a message and applies a callback to
834
#pod each. Accepts a code reference as its only argument. The code reference
835
#pod will be passed a single argument, the current MIME part within the
836
#pod top-level MIME object. All changes will be applied in place.
837
#pod
838
#pod =cut
839
840
sub walk_parts {
841
10
10
1
1996
my ($self, $callback) = @_;
842
843
10
22
my %changed;
844
845
my $walk_weak;
846
my $walk = sub {
847
40
40
79
my ($part) = @_;
848
40
108
$callback->($part);
849
850
40
100
3943
if (my @orig_subparts = $part->subparts) {
851
14
25
my $differ;
852
my @subparts;
853
854
14
105
for my $part (@orig_subparts) {
855
30
76
my $str = $part->as_string;
856
30
50
105
next unless my $new = $walk_weak->($part);
857
30
100
66
$differ = 1 if $str ne $new->as_string;
858
30
76
push @subparts, $new;
859
}
860
861
$differ
862
||= (@subparts != @orig_subparts)
863
|| (grep { $subparts[$_] != $orig_subparts[$_] } (0 .. $#subparts))
864
14
33
84
|| (grep { $changed{ 0+$subparts[$_] } } (0 .. $#subparts));
66
865
866
14
100
35
if ($differ) {
867
6
20
$part->parts_set(\@subparts);
868
6
125
$changed{ 0+$part }++;
869
}
870
}
871
872
40
185
return $part;
873
10
46
};
874
875
10
20
$walk_weak = $walk;
876
10
37
weaken $walk_weak;
877
878
10
23
my $rv = $walk->($self);
879
880
10
109
undef $walk;
881
882
10
40
return $rv;
883
}
884
885
sub _compose_content_type {
886
77
77
149
my ($self, $ct_header) = @_;
887
77
372
my $ct = build_content_type({type => $ct_header->{type}, subtype => $ct_header->{subtype}, attributes => $ct_header->{attributes}});
888
77
8408
$self->header_raw_set('Content-Type' => $ct);
889
77
3266
$self->{ct} = $ct_header;
890
}
891
892
sub _get_cid {
893
39
39
115
Email::MessageID->new->address;
894
}
895
896
sub _reset_cids {
897
57
57
104
my ($self) = @_;
898
899
57
147
my $ct_header = parse_content_type($self->header('Content-Type'));
900
901
57
100
5828
if ($self->parts > 1) {
902
19
100
70
if ($ct_header->{subtype} eq 'alternative') {
903
4
7
my %cids;
904
4
10
for my $part ($self->parts) {
905
9
100
24
my $cid = $part->header('Content-ID') // q{};
906
9
25
$cids{$cid}++;
907
}
908
4
100
24
return if keys(%cids) == 1;
909
910
1
3
my $cid = $self->_get_cid;
911
1
42
$_->header_raw_set('Content-ID' => "<$cid>") for $self->parts;
912
} else {
913
15
39
foreach ($self->parts) {
914
38
750
my $cid = $self->_get_cid;
915
38
100
1749
$_->header_raw_set('Content-ID' => "<$cid>")
916
unless $_->header('Content-ID');
917
}
918
}
919
}
920
}
921
922
1;
923
924
=pod
925
926
=encoding UTF-8
927
928
=head1 NAME
929
930
Email::MIME - easy MIME message handling
931
932
=head1 VERSION
933
934
version 1.953
935
936
=head1 SYNOPSIS
937
938
B Before you read this, maybe you just need L, which is
939
a much easier-to-use tool for building simple email messages that might have
940
attachments or both plain text and HTML. If that doesn't do it for you, then
941
by all means keep reading.
942
943
use Email::MIME;
944
my $parsed = Email::MIME->new($message);
945
946
my @parts = $parsed->parts; # These will be Email::MIME objects, too.
947
my $decoded = $parsed->body;
948
my $non_decoded = $parsed->body_raw;
949
950
my $content_type = $parsed->content_type;
951
952
...or...
953
954
use Email::MIME;
955
use IO::All;
956
957
# multipart message
958
my @parts = (
959
Email::MIME->create(
960
attributes => {
961
filename => "report.pdf",
962
content_type => "application/pdf",
963
encoding => "quoted-printable",
964
name => "2004-financials.pdf",
965
},
966
body => io( "2004-financials.pdf" )->binary->all,
967
),
968
Email::MIME->create(
969
attributes => {
970
content_type => "text/plain",
971
disposition => "attachment",
972
charset => "US-ASCII",
973
},
974
body_str => "Hello there!",
975
),
976
);
977
978
my $email = Email::MIME->create(
979
header_str => [
980
From => 'casey@geeknest.com',
981
To => [ 'user1@host.com', 'Name ' ],
982
Cc => Email::Address::XS->new("Display Name \N{U+1F600}", 'user@example.com'),
983
],
984
parts => [ @parts ],
985
);
986
987
# nesting parts
988
$email->parts_set(
989
[
990
$email->parts,
991
Email::MIME->create( parts => [ @parts ] ),
992
],
993
);
994
995
# standard modifications
996
$email->header_str_set( 'X-PoweredBy' => 'RT v3.0' );
997
$email->header_str_set( To => rcpts() );
998
$email->header_str_set( Cc => aux_rcpts() );
999
$email->header_str_set( Bcc => sekrit_rcpts() );
1000
1001
# more advanced
1002
$_->encoding_set( 'base64' ) for $email->parts;
1003
1004
# Quick multipart creation
1005
my $email = Email::MIME->create(
1006
header_str => [
1007
From => 'my@address',
1008
To => 'your@address',
1009
],
1010
parts => [
1011
q[This is part one],
1012
q[This is part two],
1013
q[These could be binary too],
1014
],
1015
);
1016
1017
print $email->as_string;
1018
1019
=head1 DESCRIPTION
1020
1021
This is an extension of the L module, to handle MIME
1022
encoded messages. It takes a message as a string, splits it up into its
1023
constituent parts, and allows you access to various parts of the
1024
message. Headers are decoded from MIME encoding.
1025
1026
=head1 PERL VERSION
1027
1028
This library should run on perls released even a long time ago. It should work
1029
on any version of perl released in the last five years.
1030
1031
Although it may work on older versions of perl, no guarantee is made that the
1032
minimum required version will not be increased. The version may be increased
1033
for any reason, and there is no promise that patches will be accepted to lower
1034
the minimum required perl.
1035
1036
=head1 METHODS
1037
1038
Please see L for the base set of methods. It won't take
1039
very long. Added to that, you have:
1040
1041
=head2 create
1042
1043
my $single = Email::MIME->create(
1044
header_str => [ ... ],
1045
body_str => '...',
1046
attributes => { ... },
1047
);
1048
1049
my $multi = Email::MIME->create(
1050
header_str => [ ... ],
1051
parts => [ ... ],
1052
attributes => { ... },
1053
);
1054
1055
This method creates a new MIME part. The C parameter is a list of
1056
headers pairs to include in the message. The value for each pair is expected to
1057
be a text string that will be MIME-encoded as needed. Alternatively it can be
1058
an object with C method which implements conversion of that
1059
object to MIME-encoded string. That object method is called with two named
1060
input parameters: C and C. It should return
1061
MIME-encoded representation of the object. As of 2017-07-25, the
1062
header-value-as-object code is very young, and may yet change.
1063
1064
In case header name is registered in C<%Email::MIME::Header::header_to_class_map>
1065
hash then registered class is used for conversion from Unicode string to 8bit
1066
MIME encoding. Value can be either string or array reference to strings.
1067
Object is constructed via method C with string value (or values
1068
in case of array reference) and converted to MIME-encoded string via
1069
C method.
1070
1071
A similar C parameter can be provided in addition to or instead of
1072
C. Its values will be used verbatim.
1073
1074
C is a hash of MIME attributes to assign to the part, and may
1075
override portions of the header set in the C
1076
correspond directly to methods for modifying a message. The allowed keys are:
1077
content_type, charset, name, format, boundary, encoding, disposition, and
1078
filename. They will be mapped to C<"$attr\_set"> for message modification.
1079
1080
The C parameter is a list reference containing C
1081
objects. Elements of the C list can also be a non-reference
1082
string of data. In that case, an C object will be created
1083
for you. Simple checks will determine if the part is binary or not, and
1084
all parts created in this fashion are encoded with C, just in case.
1085
1086
If C is given instead of C, it specifies the body to be used for a
1087
flat (subpart-less) MIME message. It is assumed to be a sequence of octets.
1088
1089
If C is given instead of C or C, it is assumed to be a
1090
character string to be used as the body. If you provide a C
1091
parameter, you B provide C and C attributes.
1092
1093
=head2 content_type_set
1094
1095
$email->content_type_set( 'text/html' );
1096
1097
Change the content type. All C header attributes
1098
will remain intact.
1099
1100
=head2 charset_set
1101
1102
=head2 name_set
1103
1104
=head2 format_set
1105
1106
=head2 boundary_set
1107
1108
$email->charset_set( 'UTF-8' );
1109
$email->name_set( 'some_filename.txt' );
1110
$email->format_set( 'flowed' );
1111
$email->boundary_set( undef ); # remove the boundary
1112
1113
These four methods modify common C attributes. If set to
1114
C, the attribute is removed. All other C header
1115
information is preserved when modifying an attribute.
1116
1117
=head2 encode_check
1118
1119
=head2 encode_check_set
1120
1121
$email->encode_check;
1122
$email->encode_check_set(0);
1123
$email->encode_check_set(Encode::FB_DEFAULT);
1124
1125
Gets/sets the current C setting (default: I).
1126
This is the parameter passed to L and L
1127
when C, C, and C are called.
1128
1129
With the default setting, Email::MIME may crash if the claimed charset
1130
of a body does not match its contents (for example - utf8 data in a
1131
text/plain; charset=us-ascii message).
1132
1133
With an C of 0, the unrecognized bytes will instead be
1134
replaced with the C (U+0FFFD), and may end up
1135
as either that or question marks (?).
1136
1137
See L for more information.
1138
1139
=head2 encoding_set
1140
1141
$email->encoding_set( 'base64' );
1142
$email->encoding_set( 'quoted-printable' );
1143
$email->encoding_set( '8bit' );
1144
1145
Convert the message body and alter the C
1146
header using this method. Your message body, the output of the C
1147
method, will remain the same. The raw body, output with the C
1148
method, will be changed to reflect the new encoding.
1149
1150
=head2 body_set
1151
1152
$email->body_set( $unencoded_body_string );
1153
1154
This method will encode the new body you send using the encoding
1155
specified in the C header, then set
1156
the body to the new encoded body.
1157
1158
=head2 body_str_set
1159
1160
$email->body_str_set($unicode_str);
1161
1162
This method behaves like C, but assumes that the given value is a
1163
Unicode string that should be encoded into the message's charset
1164
before being set.
1165
1166
The charset must already be set, either manually (via the C
1167
argument to C or C) or through the C of a
1168
parsed message. If the charset can't be determined, an exception is thrown.
1169
1170
=head2 disposition_set
1171
1172
$email->disposition_set( 'attachment' );
1173
1174
Alter the C of a message. All header attributes
1175
will remain intact.
1176
1177
=head2 filename_set
1178
1179
$email->filename_set( 'boo.pdf' );
1180
1181
Sets the filename attribute in the C header. All other
1182
header information is preserved when setting this attribute.
1183
1184
=head2 parts_set
1185
1186
$email->parts_set( \@new_parts );
1187
1188
Replaces the parts for an object. Accepts a reference to a list of
1189
C objects, representing the new parts. If this message was
1190
originally a single part, the C header will be changed to
1191
C, and given a new boundary attribute.
1192
1193
=head2 parts_add
1194
1195
$email->parts_add( \@more_parts );
1196
1197
Adds MIME parts onto the current MIME part. This is a simple extension
1198
of C to make our lives easier. It accepts an array reference
1199
of additional parts.
1200
1201
=head2 walk_parts
1202
1203
$email->walk_parts(sub {
1204
my ($part) = @_;
1205
return if $part->subparts; # multipart
1206
1207
if ( $part->content_type =~ m[text/html]i ) {
1208
my $body = $part->body;
1209
$body =~ s/ ]+>//; # simple filter example
1210
$part->body_set( $body );
1211
}
1212
});
1213
1214
Walks through all the MIME parts in a message and applies a callback to
1215
each. Accepts a code reference as its only argument. The code reference
1216
will be passed a single argument, the current MIME part within the
1217
top-level MIME object. All changes will be applied in place.
1218
1219
=head2 header
1220
1221
B Beware this method! In Email::MIME, it means the same as
1222
C, but on an Email::Simple object, it means C. Unless
1223
you always know what kind of object you have, you could get one of two
1224
significantly different behaviors.
1225
1226
Try to use either C or C as appropriate.
1227
1228
=head2 header_str_set
1229
1230
$email->header_str_set($header_name => @value_strings);
1231
1232
This behaves like C, but expects Unicode (character) strings as
1233
the values to set, rather than pre-encoded byte strings. It will encode them
1234
as MIME encoded-words if they contain any control or 8-bit characters.
1235
1236
Alternatively, values can be objects with C method. Same as in
1237
method C.
1238
1239
=head2 header_str_pairs
1240
1241
my @pairs = $email->header_str_pairs;
1242
1243
This method behaves like C, returning a list of field
1244
name/value pairs, but the values have been decoded to character strings, when
1245
possible.
1246
1247
=head2 header_as_obj
1248
1249
my $first_obj = $email->header_as_obj($field);
1250
my $nth_obj = $email->header_as_obj($field, $index);
1251
my @all_objs = $email->header_as_obj($field);
1252
1253
my $nth_obj_of_class = $email->header_as_obj($field, $index, $class);
1254
my @all_objs_of_class = $email->header_as_obj($field, undef, $class);
1255
1256
This method returns an object representation of the header value. It instances
1257
new object via method C of specified class. Input argument
1258
for that class method is list of the raw MIME-encoded values. If class argument
1259
is not specified then class name is taken from the hash
1260
C<%Email::MIME::Header::header_to_class_map> via key field. Use class method
1261
C<< Email::MIME::Header->set_class_for_header($class, $field) >> for adding new
1262
mapping.
1263
1264
=head2 parts
1265
1266
This returns a list of C objects reflecting the parts of the
1267
message. If it's a single-part message, you get the original object back.
1268
1269
In scalar context, this method returns the number of parts.
1270
1271
This is a stupid method. Don't use it.
1272
1273
=head2 subparts
1274
1275
This returns a list of C objects reflecting the parts of the
1276
message. If it's a single-part message, this method returns an empty list.
1277
1278
In scalar context, this method returns the number of subparts.
1279
1280
=head2 body
1281
1282
This decodes and returns the body of the object I. For
1283
top-level objects in multi-part messages, this is highly likely to be something
1284
like "This is a multi-part message in MIME format."
1285
1286
=head2 body_str
1287
1288
This decodes both the Content-Transfer-Encoding layer of the body (like the
1289
C method) as well as the charset encoding of the body (unlike the C
1290
method), returning a Unicode string.
1291
1292
If the charset is known, it is used. If there is no charset but the content
1293
type is either C or C, us-ascii is assumed. Otherwise,
1294
an exception is thrown.
1295
1296
=head2 body_raw
1297
1298
This returns the body of the object, but doesn't decode the transfer encoding.
1299
1300
=head2 decode_hook
1301
1302
This method is called before the L C method, to
1303
decode the body of non-binary messages (or binary messages, if the
1304
C method returns true). By default, this method does
1305
nothing, but subclasses may define behavior.
1306
1307
This method could be used to implement the decryption of content in secure
1308
email, for example.
1309
1310
=head2 content_type
1311
1312
This is a shortcut for access to the content type header.
1313
1314
=head2 filename
1315
1316
This provides the suggested filename for the attachment part. Normally
1317
it will return the filename from the headers, but if C is
1318
passed a true parameter, it will generate an appropriate "stable"
1319
filename if one is not found in the MIME headers.
1320
1321
=head2 invent_filename
1322
1323
my $filename = Email::MIME->invent_filename($content_type);
1324
1325
This routine is used by C to generate filenames for attached files.
1326
It will attempt to choose a reasonable extension, falling back to F.
1327
1328
=head2 debug_structure
1329
1330
my $description = $email->debug_structure;
1331
1332
This method returns a string that describes the structure of the MIME entity.
1333
For example:
1334
1335
+ multipart/alternative; boundary="=_NextPart_2"; charset="BIG-5"
1336
+ text/plain
1337
+ text/html
1338
1339
=head1 CONFIGURATION
1340
1341
The variable C<$Email::MIME::MAX_DEPTH> is the maximum depth of parts that will
1342
be processed. It defaults to 10, already higher than legitimate mail is ever
1343
likely to be. This value may go up over time as the parser is improved.
1344
1345
=head1 SEE ALSO
1346
1347
L
1348
1349
=head1 THANKS
1350
1351
This module was generously sponsored by Best Practical
1352
(http://www.bestpractical.com/), Pete Sergeant, and Pobox.com.
1353
1354
=head1 AUTHORS
1355
1356
=over 4
1357
1358
=item *
1359
1360
Ricardo SIGNES
1361
1362
=item *
1363
1364
Casey West
1365
1366
=item *
1367
1368
Simon Cozens
1369
1370
=back
1371
1372
=head1 CONTRIBUTORS
1373
1374
=for stopwords Alex Vandiver Anirvan Chatterjee Arthur Axel 'fREW' Schmidt Brian Cassidy Damian Lukowski Dan Book David Steinbrunner Dotan Dimet dxdc Eric Wong Geraint Edwards ivulfson Jesse Luehrs Kurt Anderson Lance A. Brown Matthew Horsfall memememomo Michael McClimon Mishrakk Pali Ricardo Signes Shawn Sorichetti Tomohiro Hosaka
1375
1376
=over 4
1377
1378
=item *
1379
1380
Alex Vandiver
1381
1382
=item *
1383
1384
Anirvan Chatterjee
1385
1386
=item *
1387
1388
Arthur Axel 'fREW' Schmidt
1389
1390
=item *
1391
1392
Brian Cassidy
1393
1394
=item *
1395
1396
Damian Lukowski
1397
1398
=item *
1399
1400
Dan Book
1401
1402
=item *
1403
1404
David Steinbrunner
1405
1406
=item *
1407
1408
Dotan Dimet
1409
1410
=item *
1411
1412
dxdc
1413
1414
=item *
1415
1416
Eric Wong
1417
1418
=item *
1419
1420
Geraint Edwards
1421
1422
=item *
1423
1424
ivulfson <9122139+ivulfson@users.noreply.github.com>
1425
1426
=item *
1427
1428
Jesse Luehrs
1429
1430
=item *
1431
1432
Kurt Anderson
1433
1434
=item *
1435
1436
Lance A. Brown
1437
1438
=item *
1439
1440
Matthew Horsfall
1441
1442
=item *
1443
1444
memememomo
1445
1446
=item *
1447
1448
Michael McClimon
1449
1450
=item *
1451
1452
Mishrakk <48946018+Mishrakk@users.noreply.github.com>
1453
1454
=item *
1455
1456
Pali
1457
1458
=item *
1459
1460
Ricardo Signes
1461
1462
=item *
1463
1464
Shawn Sorichetti
1465
1466
=item *
1467
1468
Tomohiro Hosaka
1469
1470
=back
1471
1472
=head1 COPYRIGHT AND LICENSE
1473
1474
This software is copyright (c) 2004 by Simon Cozens and Casey West.
1475
1476
This is free software; you can redistribute it and/or modify it under
1477
the same terms as the Perl 5 programming language system itself.
1478
1479
=cut
1480
1481
__END__