File Coverage

blib/lib/Mail/SPF/v2/Record.pm
Criterion Covered Total %
statement 27 49 55.1
branch 0 14 0.0
condition 0 8 0.0
subroutine 9 12 75.0
pod 1 3 33.3
total 37 86 43.0


line stmt bran cond sub pod time code
1             #
2             # Mail::SPF::v2::Record
3             # Sender ID ("spf2.0") record class.
4             #
5             # (C) 2005-2012 Julian Mehnle
6             # 2005 Shevek
7             # $Id: Record.pm 57 2012-01-30 08:15:31Z julian $
8             #
9             ##############################################################################
10              
11             package Mail::SPF::v2::Record;
12              
13             =head1 NAME
14              
15             Mail::SPF::v2::Record - Sender ID ("spf2.0") record class
16              
17             =head1 VERSION
18              
19             version 3.20250505
20              
21             =cut
22              
23 1     1   1635 use warnings;
  1         3  
  1         95  
24 1     1   8 use strict;
  1         2  
  1         34  
25              
26 1     1   6 use base 'Mail::SPF::Record';
  1         2  
  1         246  
27              
28 1     1   8 use constant TRUE => (0 == 0);
  1         3  
  1         101  
29 1     1   15 use constant FALSE => not TRUE;
  1         3  
  1         97  
30              
31 1         113 use constant mech_classes => {
32             all => 'Mail::SPF::Mech::All',
33             ip4 => 'Mail::SPF::Mech::IP4',
34             ip6 => 'Mail::SPF::Mech::IP6',
35             a => 'Mail::SPF::Mech::A',
36             mx => 'Mail::SPF::Mech::MX',
37             ptr => 'Mail::SPF::Mech::PTR',
38             'exists' => 'Mail::SPF::Mech::Exists',
39             include => 'Mail::SPF::Mech::Include'
40 1     1   7 };
  1         2  
41              
42 1         196 use constant mod_classes => {
43             redirect => 'Mail::SPF::Mod::Redirect',
44             'exp' => 'Mail::SPF::Mod::Exp'
45 1     1   7 };
  1         3  
46              
47             eval("require $_")
48             foreach values(%{mech_classes()}), values(%{mod_classes()});
49              
50 1     1   8 use constant valid_scope => qr/^(?: mfrom | pra )$/x;
  1         3  
  1         169  
51 1         970 use constant version_tag_pattern => qr{
52             spf(2\.0)
53             /
54             ( (?: mfrom | pra ) (?: , (?: mfrom | pra ) )* )
55             (?= \x20 | $ )
56 1     1   7 }ix;
  1         4  
57              
58             =head1 SYNOPSIS
59              
60             See L.
61              
62             =head1 DESCRIPTION
63              
64             An object of class B represents a B
65             (C) record.
66              
67             =head2 Constructors
68              
69             The following constructors are provided:
70              
71             =over
72              
73             =item B: returns I
74              
75             Creates a new Sender ID ("spf2.0") record object.
76              
77             %options is a list of key/value pairs representing any of the following
78             options:
79              
80             =over
81              
82             =item B
83              
84             =item B
85              
86             =item B
87              
88             See L.
89              
90             =item B
91              
92             I. See L. The B<'mfrom'> and B<'pra'> scopes
93             are supported. There is no default.
94              
95             =back
96              
97             =cut
98              
99             sub new {
100 0     0 1   my ($self, %options) = @_;
101 0           $self = $self->SUPER::new(%options);
102              
103 0 0         if (not defined($self->{parse_text})) {
104             # No parsing is intended, so scopes should have been specified:
105 0   0       my $scopes = $self->{scopes} || [];
106 0 0         @$scopes > 0
107             or throw Mail::SPF::EInvalidScope('No scopes for spf2.0 record');
108 0           foreach my $scope (@$scopes) {
109 0 0         $scope =~ $self->valid_scope
110             or throw Mail::SPF::EInvalidScope("Invalid scope '$scope' for spf2.0 record");
111             }
112             }
113              
114 0           return $self;
115             }
116              
117             =item B: returns I;
118             throws I, I,
119             I
120              
121             Creates a new Sender ID ("spf2.0") record object by parsing the string and
122             any options given.
123              
124             =back
125              
126             =head2 Class methods
127              
128             The following class methods are provided:
129              
130             =over
131              
132             =item B: returns I
133              
134             Returns a regular expression that matches a version tag of B<'spf2.0/'> plus a
135             comma-separated list of any of the B<'mfrom'> and B<'pra'> scopes. The
136             following are valid version tags:
137              
138             spf2.0/mfrom
139             spf2.0/pra
140             spf2.0/mfrom,pra
141             spf2.0/pra,mfrom
142              
143             =item B
144              
145             =item B
146              
147             See L.
148              
149             =back
150              
151             =head2 Instance methods
152              
153             The following instance methods are provided:
154              
155             =over
156              
157             =cut
158              
159             sub parse_version_tag {
160 0     0 0   my ($self) = @_;
161 0 0         if ($self->{parse_text} =~ s/^${\$self->version_tag_pattern}(?:\x20+|$)//) {
  0            
162 0           my $scopes = $self->{scopes} = [ split(/,/, $2) ];
163 0 0         @$scopes > 0
164             or throw Mail::SPF::EInvalidScope('No scopes for spf2.0 record');
165 0           foreach my $scope (@$scopes) {
166 0 0         $scope =~ $self->valid_scope
167             or throw Mail::SPF::EInvalidScope("Invalid scope '$scope' for spf2.0 record");
168             }
169             }
170             else {
171 0           throw Mail::SPF::EInvalidRecordVersion(
172             "Not a 'spf2.0' record: '" . $self->text . "'");
173             }
174 0           return;
175             }
176              
177             =item B
178              
179             =item B
180              
181             =item B
182              
183             =item B
184              
185             =item B
186              
187             =item B
188              
189             =item B
190              
191             See L.
192              
193             =item B: returns I
194              
195             Returns B<'spf2.0/'> plus a comma-separated list of the scopes of the record.
196             See L for a list of possible return values.
197              
198             =cut
199              
200             sub version_tag {
201 0     0 0   my ($self) = @_;
202             return 'spf2.0'
203             if not ref($self) # called as class method
204             or not defined($self->{scopes}) # no scopes parsed
205 0 0 0       or not @{$self->{scopes}}; # no scopes specified in record
  0   0        
206 0           return 'spf2.0/' . join(',', @{$self->{scopes}});
  0            
207             }
208              
209             =back
210              
211             =head1 SEE ALSO
212              
213             L, L, L, L,
214             L
215              
216             L
217              
218             For availability, support, and license information, see the README file
219             included with Mail::SPF.
220              
221             =head1 AUTHORS
222              
223             Julian Mehnle , Shevek
224              
225             =cut
226              
227             TRUE;