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