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