File Coverage

blib/lib/Mail/Qmail/Filter/Util.pm
Criterion Covered Total %
statement 26 26 100.0
branch 12 14 85.7
condition 3 5 60.0
subroutine 6 6 100.0
pod 3 3 100.0
total 50 54 92.5


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