File Coverage

blib/lib/Mail/Message/Head/ListGroup.pm
Criterion Covered Total %
statement 15 111 13.5
branch 0 92 0.0
condition 0 48 0.0
subroutine 5 16 31.2
pod 7 8 87.5
total 27 275 9.8


line stmt bran cond sub pod time code
1             # Copyrights 2001-2021 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.02.
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   1772 use vars '$VERSION';
  2         6  
  2         127  
11             $VERSION = '3.011';
12              
13 2     2   14 use base 'Mail::Message::Head::FieldGroup';
  2         4  
  2         595  
14              
15 2     2   31 use strict;
  2         4  
  2         45  
16 2     2   11 use warnings;
  2         4  
  2         54  
17              
18 2     2   12 use List::Util 'first';
  2         5  
  2         4199  
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;