| 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
|
|
|
|
|
|
|
#XXX Do the list still exist? |
|
13
|
|
|
|
|
|
|
#XXX Add Simplelists |
|
14
|
|
|
|
|
|
|
|
|
15
|
|
|
|
|
|
|
package Mail::Message::Head::ListGroup;{ |
|
16
|
|
|
|
|
|
|
our $VERSION = '4.04'; |
|
17
|
|
|
|
|
|
|
} |
|
18
|
|
|
|
|
|
|
|
|
19
|
2
|
|
|
2
|
|
2313
|
use parent 'Mail::Message::Head::FieldGroup'; |
|
|
2
|
|
|
|
|
5
|
|
|
|
2
|
|
|
|
|
19
|
|
|
20
|
|
|
|
|
|
|
|
|
21
|
2
|
|
|
2
|
|
146
|
use strict; |
|
|
2
|
|
|
|
|
6
|
|
|
|
2
|
|
|
|
|
53
|
|
|
22
|
2
|
|
|
2
|
|
12
|
use warnings; |
|
|
2
|
|
|
|
|
5
|
|
|
|
2
|
|
|
|
|
127
|
|
|
23
|
|
|
|
|
|
|
|
|
24
|
2
|
|
|
2
|
|
34
|
use Log::Report 'mail-message', import => [ qw/__x error/ ]; |
|
|
2
|
|
|
|
|
6
|
|
|
|
2
|
|
|
|
|
14
|
|
|
25
|
|
|
|
|
|
|
|
|
26
|
2
|
|
|
2
|
|
435
|
use List::Util qw/first/; |
|
|
2
|
|
|
|
|
7
|
|
|
|
2
|
|
|
|
|
155
|
|
|
27
|
2
|
|
|
2
|
|
15
|
use Scalar::Util qw/blessed/; |
|
|
2
|
|
|
|
|
21
|
|
|
|
2
|
|
|
|
|
10447
|
|
|
28
|
|
|
|
|
|
|
|
|
29
|
|
|
|
|
|
|
#-------------------- |
|
30
|
|
|
|
|
|
|
|
|
31
|
|
|
|
|
|
|
sub init($$) |
|
32
|
20
|
|
|
20
|
0
|
50
|
{ my ($self, $args) = @_; |
|
33
|
20
|
|
|
|
|
98
|
$self->SUPER::init($args); |
|
34
|
|
|
|
|
|
|
|
|
35
|
20
|
|
|
|
|
40
|
my $address = $args->{address}; |
|
36
|
20
|
100
|
33
|
|
|
69
|
if(!defined $address) { ; } |
|
|
|
50
|
|
|
|
|
|
|
37
|
|
|
|
|
|
|
elsif(!ref $address || !$address->isa('Mail::Message::Field::Address')) |
|
38
|
1
|
|
|
|
|
809
|
{ require Mail::Message::Field::Address; |
|
39
|
1
|
50
|
|
|
|
11
|
my $mi = Mail::Message::Field::Address->coerce($address) |
|
40
|
|
|
|
|
|
|
or error __x"cannot convert '{address}' into an address object.", address => $address; |
|
41
|
|
|
|
|
|
|
|
|
42
|
1
|
|
|
|
|
3
|
$address = $mi; |
|
43
|
|
|
|
|
|
|
} |
|
44
|
|
|
|
|
|
|
|
|
45
|
20
|
100
|
|
|
|
76
|
$self->{MMHL_address} = $address if defined $args->{address}; |
|
46
|
20
|
50
|
|
|
|
62
|
$self->{MMHL_listname} = $args->{listname} if defined $args->{listname}; |
|
47
|
20
|
50
|
|
|
|
51
|
$self->{MMHL_rfc} = $args->{rfc} if defined $args->{rfc}; |
|
48
|
20
|
|
|
|
|
59
|
$self->{MMHL_fns} = []; |
|
49
|
20
|
|
|
|
|
822
|
$self; |
|
50
|
|
|
|
|
|
|
} |
|
51
|
|
|
|
|
|
|
|
|
52
|
|
|
|
|
|
|
|
|
53
|
|
|
|
|
|
|
sub from($) |
|
54
|
19
|
|
|
19
|
1
|
455
|
{ my ($class, $from) = @_; |
|
55
|
19
|
50
|
|
|
|
122
|
my $head = $from->isa('Mail::Message::Head') ? $from : $from->head; |
|
56
|
19
|
|
|
|
|
107
|
my $self = $class->new(head => $head); |
|
57
|
19
|
100
|
|
|
|
87
|
$self->collectFields or return (); |
|
58
|
|
|
|
|
|
|
|
|
59
|
17
|
|
|
|
|
43
|
my ($type, $software, $version, $field); |
|
60
|
17
|
100
|
100
|
|
|
73
|
if(my $communigate = $head->get('X-ListServer')) |
|
|
|
100
|
66
|
|
|
|
|
|
|
|
50
|
100
|
|
|
|
|
|
|
|
100
|
66
|
|
|
|
|
|
|
|
100
|
66
|
|
|
|
|
|
|
|
100
|
100
|
|
|
|
|
|
|
|
100
|
33
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
61
|
2
|
|
|
|
|
7
|
{ ($software, $version) = $communigate =~ m/^(.*)\s+LIST\s*([\d.]+)\s*$/i; |
|
62
|
2
|
100
|
|
|
|
15
|
$type = ($software =~ m/Pro/ ? 'CommuniGatePro' : 'CommuniGate'); |
|
63
|
|
|
|
|
|
|
} |
|
64
|
|
|
|
|
|
|
elsif(my $mailman = $head->get('X-Mailman-Version')) |
|
65
|
2
|
|
|
|
|
6
|
{ $version = "$mailman"; |
|
66
|
2
|
|
|
|
|
6
|
$type = 'Mailman'; |
|
67
|
|
|
|
|
|
|
} |
|
68
|
|
|
|
|
|
|
elsif(my $majordomo = $head->get('X-Majordomo-Version')) |
|
69
|
0
|
|
|
|
|
0
|
{ $version = "$majordomo"; |
|
70
|
0
|
|
|
|
|
0
|
$type = 'Majordomo'; |
|
71
|
|
|
|
|
|
|
} |
|
72
|
|
|
|
|
|
|
elsif(my $ecartis = $head->get('X-Ecartis-Version')) |
|
73
|
1
|
|
|
|
|
3
|
{ ($software, $version) = $ecartis =~ m/^(.*)\s+(v[\d.]+)/; |
|
74
|
1
|
|
|
|
|
3
|
$type = 'Ecartis'; |
|
75
|
|
|
|
|
|
|
} |
|
76
|
|
|
|
|
|
|
elsif(my $listar = $head->get('X-Listar-Version')) |
|
77
|
1
|
|
|
|
|
5
|
{ ($software, $version) = $listar =~ m/^(.*?)\s+(v[\w.]+)/; |
|
78
|
1
|
|
|
|
|
4
|
$type = 'Listar'; |
|
79
|
|
|
|
|
|
|
} |
|
80
|
|
|
|
|
|
|
elsif(defined($field = $head->get('List-Software')) && $field =~ m/listbox/i) |
|
81
|
1
|
|
|
|
|
4
|
{ ($software, $version) = $field =~ m/^(\S*)\s*(v[\d.]+)\s*$/; |
|
82
|
1
|
|
|
|
|
4
|
$type = 'Listbox'; |
|
83
|
|
|
|
|
|
|
} |
|
84
|
42
|
|
|
42
|
|
128
|
elsif($field = first { m!LISTSERV-TCP/IP!s } $head->get('Received')) |
|
85
|
|
|
|
|
|
|
{ # Listserv is hard to recognise |
|
86
|
2
|
|
|
|
|
5
|
($software, $version) = $field =~ |
|
87
|
|
|
|
|
|
|
m!\( (LISTSERV-TCP/IP) \s+ release \s+ (\S+) \)!xs; |
|
88
|
2
|
|
|
|
|
7
|
$type = 'Listserv'; |
|
89
|
|
|
|
|
|
|
} |
|
90
|
|
|
|
|
|
|
elsif(defined($field = $head->get('X-Mailing-List')) && $field =~ m[archive/latest]) |
|
91
|
1
|
|
|
|
|
3
|
{ $type = 'Smartlist' } |
|
92
|
|
|
|
|
|
|
elsif(defined($field = $head->get('Mailing-List')) && $field =~ m/yahoo/i ) |
|
93
|
1
|
|
|
|
|
3
|
{ $type = 'YahooGroups' } |
|
94
|
|
|
|
|
|
|
elsif(defined($field) && $field =~ m/(ezmlm)/i ) |
|
95
|
1
|
|
|
|
|
4
|
{ $type = 'Ezmlm' } |
|
96
|
|
|
|
|
|
|
elsif(my $fml = $head->get('X-MLServer')) |
|
97
|
2
|
|
|
|
|
7
|
{ ($software, $version) = $fml =~ m/^\s*(\S+)\s*\[\S*\s*([^\]]*?)\s*\]/; |
|
98
|
2
|
|
|
|
|
5
|
$type = 'FML'; |
|
99
|
|
|
|
|
|
|
} |
|
100
|
|
|
|
|
|
|
elsif(defined($field = $head->get('List-Subscribe') || $head->get('List-Unsubscribe')) && $field =~ m/sympa/i) |
|
101
|
1
|
|
|
|
|
3
|
{ $type = 'Sympa' } |
|
102
|
7
|
|
|
7
|
|
21
|
elsif(first { m/majordom/i } $head->get('Received')) |
|
103
|
|
|
|
|
|
|
{ # Majordomo is hard to recognize |
|
104
|
1
|
|
|
|
|
3
|
$type = "Majordomo"; |
|
105
|
|
|
|
|
|
|
} |
|
106
|
|
|
|
|
|
|
elsif(defined($field = $head->get('List-ID')) && $field =~ m/listbox\.com/i) |
|
107
|
1
|
|
|
|
|
3
|
{ $type = "Listbox" } |
|
108
|
|
|
|
|
|
|
|
|
109
|
17
|
|
|
|
|
151
|
$self->detected($type, $software, $version); |
|
110
|
17
|
|
|
|
|
91
|
$self; |
|
111
|
|
|
|
|
|
|
} |
|
112
|
|
|
|
|
|
|
|
|
113
|
|
|
|
|
|
|
|
|
114
|
|
|
|
|
|
|
sub rfc() |
|
115
|
18
|
|
|
18
|
1
|
50
|
{ my $self = shift; |
|
116
|
18
|
50
|
|
|
|
76
|
return $self->{MMHL_rfc} if defined $self->{MMHL_rfc}; |
|
117
|
|
|
|
|
|
|
|
|
118
|
18
|
|
|
|
|
105
|
my $head = $self->head; |
|
119
|
18
|
100
|
|
|
|
73
|
defined $head->get('List-Post') ? 'rfc2369' |
|
|
|
100
|
|
|
|
|
|
|
120
|
|
|
|
|
|
|
: defined $head->get('List-Id') ? 'rfc2919' |
|
121
|
|
|
|
|
|
|
: undef; |
|
122
|
|
|
|
|
|
|
} |
|
123
|
|
|
|
|
|
|
|
|
124
|
|
|
|
|
|
|
|
|
125
|
|
|
|
|
|
|
sub address() |
|
126
|
20
|
|
|
20
|
1
|
817
|
{ my $self = shift; |
|
127
|
20
|
100
|
|
|
|
79
|
return $self->{MMHL_address} if exists $self->{MMHL_address}; |
|
128
|
|
|
|
|
|
|
|
|
129
|
17
|
|
50
|
|
|
60
|
my $type = $self->type || 'Unknown'; |
|
130
|
17
|
|
|
|
|
46
|
my $head = $self->head; |
|
131
|
|
|
|
|
|
|
|
|
132
|
17
|
|
|
|
|
33
|
my ($field, $address); |
|
133
|
17
|
100
|
66
|
|
|
91
|
if($type eq 'Smartlist' && defined($field = $head->get('X-Mailing-List'))) |
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
134
|
1
|
50
|
|
|
|
5
|
{ $address = $1 if $field =~ m/\<([^>]+)\>/ } |
|
135
|
|
|
|
|
|
|
elsif($type eq 'YahooGroups') |
|
136
|
1
|
|
|
|
|
5
|
{ $address = $head->get('X-Apparently-To')->unfoldedBody } |
|
137
|
|
|
|
|
|
|
elsif($type eq 'Listserv') |
|
138
|
2
|
|
|
|
|
10
|
{ $address = $head->get('Sender') } |
|
139
|
|
|
|
|
|
|
|
|
140
|
17
|
|
33
|
|
|
126
|
$address ||= $head->get('List-Post') || $head->get('Reply-To') || $head->get('Sender'); |
|
|
|
|
66
|
|
|
|
|
|
141
|
17
|
100
|
|
|
|
99
|
$address = $address->study if blessed $address; |
|
142
|
|
|
|
|
|
|
|
|
143
|
17
|
50
|
|
|
|
222
|
if(!defined $address) { ; } |
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
144
|
|
|
|
|
|
|
elsif(!ref $address) |
|
145
|
2
|
|
|
|
|
17
|
{ $address =~ s/\bowner-|-(?:owner|bounce|admin)\@//i; |
|
146
|
2
|
|
|
|
|
14
|
$address = Mail::Message::Field::Address->new(address => $address); |
|
147
|
|
|
|
|
|
|
} |
|
148
|
|
|
|
|
|
|
elsif($address->isa('Mail::Message::Field::Addresses')) |
|
149
|
|
|
|
|
|
|
{ # beautify |
|
150
|
11
|
|
|
|
|
39
|
$address = ($address->addresses)[0]; |
|
151
|
11
|
50
|
|
|
|
454
|
my $username = defined $address ? $address->username : ''; |
|
152
|
11
|
50
|
|
|
|
178
|
if($username =~ s/^owner-|-(owner|bounce|admin)$//i) |
|
153
|
0
|
|
|
|
|
0
|
{ $address = Mail::Message::Field::Address->new(username => $username, domain => $address->domain); |
|
154
|
|
|
|
|
|
|
} |
|
155
|
|
|
|
|
|
|
} |
|
156
|
|
|
|
|
|
|
elsif($address->isa('Mail::Message::Field::URIs')) |
|
157
|
4
|
|
|
4
|
|
37
|
{ my $uri = first { $_->scheme eq 'mailto' } $address->URIs; |
|
|
4
|
|
|
|
|
30
|
|
|
158
|
4
|
50
|
|
|
|
116
|
$address = defined $uri ? Mail::Message::Field::Address->new(address => $uri->to) : undef; |
|
159
|
|
|
|
|
|
|
} |
|
160
|
|
|
|
|
|
|
else # Don't understand life anymore :-( |
|
161
|
0
|
|
|
|
|
0
|
{ undef $address; |
|
162
|
|
|
|
|
|
|
} |
|
163
|
|
|
|
|
|
|
|
|
164
|
17
|
|
|
|
|
134
|
$self->{MMHL_address} = $address; |
|
165
|
|
|
|
|
|
|
} |
|
166
|
|
|
|
|
|
|
|
|
167
|
|
|
|
|
|
|
|
|
168
|
|
|
|
|
|
|
sub listname() |
|
169
|
1
|
|
|
1
|
1
|
1903
|
{ my $self = shift; |
|
170
|
1
|
50
|
|
|
|
9
|
exists $self->{MMHL_listname} and return $self->{MMHL_listname}; |
|
171
|
|
|
|
|
|
|
|
|
172
|
1
|
|
|
|
|
21
|
my $head = $self->head; |
|
173
|
|
|
|
|
|
|
|
|
174
|
|
|
|
|
|
|
# Some lists have a field with the name only |
|
175
|
1
|
|
33
|
|
|
17
|
my $list = $head->get('List-ID') || $head->get('X-List') || $head->get('X-ML-Name'); |
|
176
|
|
|
|
|
|
|
|
|
177
|
1
|
|
|
|
|
3
|
my $listname; |
|
178
|
1
|
50
|
|
|
|
5
|
if(defined $list) |
|
|
|
50
|
|
|
|
|
|
|
179
|
0
|
|
|
|
|
0
|
{ $listname = $list->study->decodedBody; |
|
180
|
|
|
|
|
|
|
} |
|
181
|
|
|
|
|
|
|
elsif(my $address = $self->address) |
|
182
|
1
|
|
33
|
|
|
5
|
{ $listname = $address->phrase || $address->address; |
|
183
|
|
|
|
|
|
|
} |
|
184
|
|
|
|
|
|
|
|
|
185
|
1
|
|
|
|
|
12
|
$self->{MMHL_listname} = $listname; |
|
186
|
|
|
|
|
|
|
} |
|
187
|
|
|
|
|
|
|
|
|
188
|
|
|
|
|
|
|
#-------------------- |
|
189
|
|
|
|
|
|
|
|
|
190
|
|
|
|
|
|
|
my $list_field_names = qr/ |
|
191
|
|
|
|
|
|
|
^ (?: List|X-Envelope|X-Original ) - |
|
192
|
|
|
|
|
|
|
| ^ (?: Precedence|Mailing-List|Approved-By ) $ |
|
193
|
|
|
|
|
|
|
| ^ X-(?: Loop|BeenThere|Sequence|List|Sender|MLServer ) $ |
|
194
|
|
|
|
|
|
|
| ^ X-(?: Mailman|Listar|Egroups|Encartis|ML ) - |
|
195
|
|
|
|
|
|
|
| ^ X-(?: Archive|Mailing|Original|Mail|ListServer ) - |
|
196
|
|
|
|
|
|
|
| ^ (?: Mail-Followup|Delivered|Errors|X-Apperently ) -To $ |
|
197
|
|
|
|
|
|
|
/xi; |
|
198
|
|
|
|
|
|
|
|
|
199
|
0
|
|
|
0
|
1
|
0
|
sub isListGroupFieldName($) { $_[1] =~ $list_field_names } |
|
200
|
|
|
|
|
|
|
|
|
201
|
|
|
|
|
|
|
#-------------------- |
|
202
|
|
|
|
|
|
|
|
|
203
|
|
|
|
|
|
|
sub collectFields() |
|
204
|
19
|
|
|
19
|
1
|
40
|
{ my $self = shift; |
|
205
|
19
|
|
|
|
|
68
|
my @names = map $_->name, $self->head->grepNames($list_field_names); |
|
206
|
19
|
|
|
|
|
135
|
$self->addFields(@names); |
|
207
|
19
|
|
|
|
|
96
|
@names; |
|
208
|
|
|
|
|
|
|
} |
|
209
|
|
|
|
|
|
|
|
|
210
|
|
|
|
|
|
|
#-------------------- |
|
211
|
|
|
|
|
|
|
|
|
212
|
|
|
|
|
|
|
sub details() |
|
213
|
17
|
|
|
17
|
1
|
10618
|
{ my $self = shift; |
|
214
|
17
|
|
50
|
|
|
93
|
my $type = $self->type || 'Unknown'; |
|
215
|
17
|
|
|
|
|
57
|
my $software = $self->software; |
|
216
|
17
|
|
|
|
|
77
|
my $version = $self->version; |
|
217
|
|
|
|
|
|
|
|
|
218
|
17
|
100
|
100
|
|
|
105
|
undef $software if defined $software && $type eq $software; |
|
219
|
|
|
|
|
|
|
|
|
220
|
17
|
50
|
|
|
|
75
|
my $release |
|
|
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
221
|
|
|
|
|
|
|
= defined $software |
|
222
|
|
|
|
|
|
|
? (defined $version ? " ($software $version)" : " ($software)") |
|
223
|
|
|
|
|
|
|
: (defined $version ? " ($version)" : ''); |
|
224
|
|
|
|
|
|
|
|
|
225
|
17
|
|
50
|
|
|
54
|
my $address = $self->address || 'unknown address'; |
|
226
|
17
|
|
|
|
|
92
|
my $fields = scalar $self->fields; |
|
227
|
17
|
|
|
|
|
111
|
"$type at $address$release, $fields fields"; |
|
228
|
|
|
|
|
|
|
} |
|
229
|
|
|
|
|
|
|
|
|
230
|
|
|
|
|
|
|
#-------------------- |
|
231
|
|
|
|
|
|
|
|
|
232
|
|
|
|
|
|
|
1; |