File Coverage

blib/lib/Mail/Qmail/Filter/Util.pm
Criterion Covered Total %
statement 25 25 100.0
branch 11 12 91.6
condition 3 5 60.0
subroutine 6 6 100.0
pod 3 3 100.0
total 48 51 94.1


line stmt bran cond sub pod time code
1 2     2   99980 use 5.014;
  2         16  
2 2     2   13 use warnings;
  2         4  
  2         99  
3              
4             package Mail::Qmail::Filter::Util;
5              
6             our $VERSION = '1.11';
7              
8 2     2   11 use base 'Exporter';
  2         3  
  2         739  
9              
10             our @EXPORT_OK = qw(addresses_to_hash match_address split_address);
11              
12             sub addresses_to_hash {
13 2     2 1 105 my $addrs = shift;
14 2         5 my %struct;
15 2 100       8 for ( ref $addrs ? @$addrs : $addrs ) {
16 4         9 my ( $localpart, $domain ) = split_address($_);
17 4 100       11 unless ( length $localpart ) {
18 1         4 $struct{$domain} = ''; # match for whole domain
19             }
20             else {
21 3   50     15 my $slot = $struct{$domain} //= {};
22 3 50       11 $slot->{$localpart} = '' if ref $slot;
23             }
24             }
25 2         12 \%struct;
26             }
27              
28             sub match_address {
29 4     4 1 13 my ( $struct, $addr ) = @_;
30 4         8 my ( $localpart, $domain ) = split_address($addr);
31 4 100       38 defined( my $slot = $struct->{$domain} ) or return;
32 3 100 66     25 !ref $slot || !length $localpart || defined $slot->{$localpart};
33             }
34              
35             sub split_address {
36 8     8 1 21 my $lc_addr = lc shift;
37 8 100       25 if ( $lc_addr =~ /\@/ ) {
38 7         27 split /\@/, $lc_addr, 2;
39             }
40             else {
41 1         3 undef, $lc_addr;
42             }
43             }
44              
45             1;
46              
47             =head1 NAME
48              
49             Mail::Qmail::Filter::Util -
50             utility functions for Mail::Qmail::Filter modules
51              
52             =head1 SYNOPSIS
53              
54             use Mail::Qmail::Filter::Util qw(addresses_to_hash match_address);
55             use Mo qw(coerce default);
56              
57             has addresses => coerce => \&addresses_to_hash;
58              
59             sub filter {
60             ...
61             if ( match_address( $self->addresses, $address ) ) {
62             ...
63             }
64             ...
65             }
66              
67             =head1 DESCRIPTION
68              
69             This module is not a filter itself, but provides utility functions
70             for other filters, possibly your own.
71              
72             =head1 EXPORTABLE FUNCTIONS
73              
74             =head2 addresses_to_hash
75              
76             Takes a single e-mail address or domain name as string or an array of such
77             strings and turns it into a data structure you can later pass to
78             L</match_address>.
79             Returns a reference to this data structure.
80              
81             =head2 match_address
82              
83             Expects two arguments:
84              
85             =over 4
86              
87             =item 1.
88              
89             the reference returned by L</addresses_to_hash>
90              
91             =item 2.
92              
93             an e-mail address (as a string)
94              
95             =back
96              
97             Will return a true value if the e-mail address given is one of the
98             addresses you had given to L</addresses_to_hash> or if its domain name
99             is one of the domain names you had given to L</addresses_to_hash>.
100              
101             Everything will be compared case-insensitively, because domain names are
102             not case-sensitive anyway, and presumably no-one uses case-sensitive
103             localparts.
104              
105             =head2 split_address
106              
107             Expects a domain name or an e-mail address as its only argument.
108              
109             Returns two values:
110              
111             =over 4
112              
113             =item 1.
114              
115             the local-part of the e-mail address, or L<undef|perlfunc/undef> for
116             domains
117              
118             =item 2.
119              
120             the domain part, converted to lowercase
121              
122             =back
123              
124             =head1 SEE ALSO
125              
126             L<Mail::Qmail::Filter>
127              
128             =head1 LICENSE AND COPYRIGHT
129              
130             Copyright 2019 Martin Sluka.
131              
132             This module is free software; you can redistribute it and/or modify it
133             under the terms of the the Artistic License (2.0). You may obtain a
134             copy of the full license at:
135              
136             L<http://www.perlfoundation.org/artistic_license_2_0>
137              
138             Any use, modification, and distribution of the Standard or Modified
139             Versions is governed by this Artistic License. By using, modifying or
140             distributing the Package, you accept this license. Do not use, modify,
141             or distribute the Package, if you do not accept this license.
142              
143             If your Modified Version has been derived from a Modified Version made
144             by someone other than you, you are nevertheless required to ensure that
145             your Modified Version complies with the requirements of this license.
146              
147             This license does not grant you the right to use any trademark, service
148             mark, tradename, or logo of the Copyright Holder.
149              
150             This license includes the non-exclusive, worldwide, free-of-charge
151             patent license to make, have made, use, offer to sell, sell, import and
152             otherwise transfer the Package with respect to any patent claims
153             licensable by the Copyright Holder that are necessarily infringed by the
154             Package. If you institute patent litigation (including a cross-claim or
155             counterclaim) against any party alleging that the Package constitutes
156             direct or contributory patent infringement, then this Artistic License
157             to you shall terminate on the date that such litigation is filed.
158              
159             Disclaimer of Warranty: THE PACKAGE IS PROVIDED BY THE COPYRIGHT HOLDER
160             AND CONTRIBUTORS "AS IS' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES.
161             THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
162             PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED TO THE EXTENT PERMITTED BY
163             YOUR LOCAL LAW. UNLESS REQUIRED BY LAW, NO COPYRIGHT HOLDER OR
164             CONTRIBUTOR WILL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, OR
165             CONSEQUENTIAL DAMAGES ARISING IN ANY WAY OUT OF THE USE OF THE PACKAGE,
166             EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
167              
168             =cut