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-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;