File Coverage

blib/lib/Mail/SPF/Mech/MX.pm
Criterion Covered Total %
statement 22 42 52.3
branch 0 14 0.0
condition 0 6 0.0
subroutine 7 10 70.0
pod 2 3 66.6
total 31 75 41.3


line stmt bran cond sub pod time code
1             #
2             # Mail::SPF::Mech::MX
3             # SPF record "mx" mechanism class.
4             #
5             # (C) 2005-2012 Julian Mehnle
6             # 2005 Shevek
7             # $Id: MX.pm 57 2012-01-30 08:15:31Z julian $
8             #
9             ##############################################################################
10              
11             package Mail::SPF::Mech::MX;
12              
13             =head1 NAME
14              
15             Mail::SPF::Mech::MX - SPF record C mechanism class
16              
17             =cut
18              
19 1     1   1139 use warnings;
  1         2  
  1         28  
20 1     1   5 use strict;
  1         2  
  1         29  
21              
22 1     1   5 use base 'Mail::SPF::SenderIPAddrMech';
  1         2  
  1         73  
23              
24 1     1   5 use constant TRUE => (0 == 0);
  1         1  
  1         59  
25 1     1   6 use constant FALSE => not TRUE;
  1         2  
  1         50  
26              
27 1     1   5 use constant name => 'mx';
  1         1  
  1         63  
28 1     1   6 use constant name_pattern => qr/${\name}/i;
  1         2  
  1         2  
  1         396  
29              
30             =head1 DESCRIPTION
31              
32             An object of class B represents an SPF record mechanism of
33             type C.
34              
35             =head2 Constructors
36              
37             The following constructors are provided:
38              
39             =over
40              
41             =item B: returns I
42              
43             Creates a new SPF record C mechanism object.
44              
45             %options is a list of key/value pairs representing any of the following
46             options:
47              
48             =over
49              
50             =item B
51              
52             =item B
53              
54             =item B
55              
56             =item B
57              
58             See L.
59              
60             =back
61              
62             =item B: returns I;
63             throws I, I
64              
65             Creates a new SPF record C mechanism object by parsing the string and
66             any options given.
67              
68             =back
69              
70             =head2 Class methods
71              
72             The following class methods are provided:
73              
74             =over
75              
76             =item B
77              
78             =item B
79              
80             =item B
81              
82             =item B
83              
84             See L.
85              
86             =item B: returns I
87              
88             Returns B<'mx'>.
89              
90             =item B: returns I
91              
92             Returns a regular expression that matches a mechanism name of B<'mx'>.
93              
94             =back
95              
96             =head2 Instance methods
97              
98             The following instance methods are provided:
99              
100             =over
101              
102             =cut
103              
104             sub parse_params {
105 0     0 0   my ($self) = @_;
106 0           $self->parse_domain_spec();
107 0           $self->parse_ipv4_ipv6_prefix_lengths();
108 0           return;
109             }
110              
111             =item B
112              
113             =item B
114              
115             =item B
116              
117             =cut
118              
119             sub params {
120 0     0 1   my ($self) = @_;
121 0           my $params;
122 0 0         $params .= ':' . $self->{domain_spec}
123             if defined($self->{domain_spec});
124 0 0 0       $params .= '/' . $self->{ipv4_prefix_length}
125             if defined($self->{ipv4_prefix_length})
126             and $self->{ipv4_prefix_length} != $self->default_ipv4_prefix_length;
127 0 0 0       $params .= '//' . $self->{ipv6_prefix_length}
128             if defined($self->{ipv6_prefix_length})
129             and $self->{ipv6_prefix_length} != $self->default_ipv6_prefix_length;
130 0           return $params;
131             }
132              
133             =item B
134              
135             =item B
136              
137             =item B
138              
139             See L.
140              
141             =item B: returns I
142              
143             Returns the C parameter of the mechanism.
144              
145             =item B: returns I
146              
147             Returns the IPv4 network prefix length of the mechanism.
148              
149             =item B: returns I
150              
151             Returns the IPv6 network prefix length of the mechanism.
152              
153             =cut
154              
155             # Make read-only accessors:
156             __PACKAGE__->make_accessor($_, TRUE)
157             foreach qw(domain_spec ipv4_prefix_length ipv6_prefix_length);
158              
159             =item B: returns I
160              
161             Checks whether any MX hosts of the mechanism's target domain name (that is, any
162             of the host addresses of its DNS C records) matches the given request's IP
163             address (see L), and returns B if it does,
164             or B otherwise. The mechanism's IP network prefix lengths are respected
165             when matching address records against the request's IP address. See RFC 4408,
166             5 and 5.4, for the exact algorithm used.
167              
168             =cut
169              
170             sub match {
171 0     0 1   my ($self, $server, $request) = @_;
172              
173 0           $server->count_dns_interactive_term($request);
174              
175 0           my $target_domain = $self->domain($server, $request);
176 0           my $mx_packet = $server->dns_lookup($target_domain, 'MX');
177 0 0         my @mx_rrs = $mx_packet->answer
178             or $server->count_void_dns_lookup($request);
179              
180             # Respect the MX mechanism lookups limit (RFC 4408, 5.4/3/4):
181 0 0         @mx_rrs = splice(@mx_rrs, 0, $server->max_name_lookups_per_mx_mech)
182             if defined($server->max_name_lookups_per_mx_mech);
183              
184             # TODO Use A records from packet's "additional" section? Probably not.
185              
186             # Check MX records:
187 0           foreach my $rr (@mx_rrs) {
188 0 0         if ($rr->type eq 'MX') {
189 0 0         return TRUE
190             if $self->match_in_domain($server, $request, $rr->exchange);
191             }
192             else {
193             # Unexpected RR type.
194             # TODO Generate debug info or ignore silently.
195             }
196             }
197              
198 0           return FALSE;
199             }
200              
201             =back
202              
203             =head1 SEE ALSO
204              
205             L, L, L, L
206              
207             L
208              
209             For availability, support, and license information, see the README file
210             included with Mail::SPF.
211              
212             =head1 AUTHORS
213              
214             Julian Mehnle , Shevek
215              
216             =cut
217              
218             TRUE;