File Coverage

blib/lib/Mail/DKIM/AuthorDomainPolicy.pm
Criterion Covered Total %
statement 28 77 36.3
branch 5 28 17.8
condition 2 27 7.4
subroutine 8 16 50.0
pod 8 12 66.6
total 51 160 31.8


line stmt bran cond sub pod time code
1             package Mail::DKIM::AuthorDomainPolicy;
2 6     6   792 use strict;
  6         16  
  6         219  
3 6     6   36 use warnings;
  6         16  
  6         280  
4             our $VERSION = '1.20230212'; # VERSION
5             # ABSTRACT: represents an Author Domain Signing Practices (ADSP) record
6              
7             # Copyright 2005-2009 Messiah College.
8             # Jason Long
9              
10             # Copyright (c) 2004 Anthony D. Urso. All rights reserved.
11             # This program is free software; you can redistribute it and/or
12             # modify it under the same terms as Perl itself.
13              
14 6     6   40 use base 'Mail::DKIM::Policy';
  6         14  
  6         6377  
15              
16             # base class is used for parse(), as_string()
17              
18 6     6   47 use Mail::DKIM::DNS;
  6         25  
  6         5575  
19              
20              
21             sub fetch {
22 0     0 1 0 my $class = shift;
23 0         0 my %prms = @_;
24              
25 0         0 my $self;
26 0         0 my $had_error= not eval {
27 0         0 local $SIG{__DIE__};
28 0         0 $self= $class->SUPER::fetch(%prms);
29 0         0 1
30             };
31 0         0 my $E = $@;
32              
33 0 0 0     0 if ( $self && !$self->is_implied_default_policy ) {
34 0         0 return $self;
35             }
36              
37             # didn't find a policy; check the domain itself
38             {
39             #FIXME- not good to have this code duplicated between
40             #here and get_lookup_name()
41             #
42 0 0 0     0 if ( $prms{Author} && !$prms{Domain} ) {
  0         0  
43 0   0     0 $prms{Domain} = ( $prms{Author} =~ /\@([^@]*)$/ and $1 );
44             }
45              
46 0 0       0 unless ( $prms{Domain} ) {
47 0         0 die "no domain to fetch policy for\n";
48             }
49              
50 0         0 my @resp = Mail::DKIM::DNS::query( $prms{Domain}, 'MX' );
51 0 0 0     0 if ( !@resp && $@ eq 'NXDOMAIN' ) {
52 0         0 return $class->nxdomain_policy;
53             }
54             }
55              
56 0 0       0 die $E if $had_error;
57 0         0 return $self;
58             }
59              
60             # get_lookup_name() - determine name of record to fetch
61             #
62             sub get_lookup_name {
63 0     0 0 0 my $self = shift;
64 0         0 my ($prms) = @_;
65              
66             # in ADSP, the record to fetch is determined based on the From header
67              
68 0 0 0     0 if ( $prms->{Author} && !$prms->{Domain} ) {
69 0   0     0 $prms->{Domain} = ( $prms->{Author} =~ /\@([^@]*)$/ and $1 );
70             }
71              
72 0 0       0 unless ( $prms->{Domain} ) {
73 0         0 die "no domain to fetch policy for\n";
74             }
75              
76             # IETF seems poised to create policy records this way
77 0         0 return '_adsp._domainkey.' . $prms->{Domain};
78             }
79              
80              
81             sub new {
82 1     1 1 630 my $class = shift;
83 1         11 return $class->parse( String => '' );
84             }
85              
86              
87             #undocumented private class method
88             our $DEFAULT_POLICY;
89              
90             sub default {
91 0     0 0 0 my $class = shift;
92 0   0     0 $DEFAULT_POLICY ||= $class->new;
93 0         0 return $DEFAULT_POLICY;
94             }
95              
96             #undocumented private class method
97             our $NXDOMAIN_POLICY;
98              
99             sub nxdomain_policy {
100 0     0 0 0 my $class = shift;
101 0 0       0 if ( !$NXDOMAIN_POLICY ) {
102 0         0 $NXDOMAIN_POLICY = $class->new;
103 0         0 $NXDOMAIN_POLICY->policy('NXDOMAIN');
104             }
105 0         0 return $NXDOMAIN_POLICY;
106             }
107              
108              
109             sub apply {
110 2     2 1 580 my $self = shift;
111 2         5 my ($dkim) = @_;
112              
113             # first_party indicates whether there is a DKIM signature with
114             # a d= tag matching the address in the From: header
115 2         3 my $first_party;
116              
117             my @passing_signatures =
118 2 0       8 grep { $_->result && $_->result eq 'pass' } $dkim->signatures;
  0         0  
119              
120 2         6 foreach my $signature (@passing_signatures) {
121 0         0 my $author_domain = $dkim->message_originator->host;
122 0 0       0 if ( lc $author_domain eq lc $signature->domain ) {
123              
124             # found a first party signature
125 0         0 $first_party = 1;
126 0         0 last;
127             }
128             }
129              
130 2 50       5 return 'accept' if $first_party;
131 2 100       5 return 'reject' if ( $self->signall_strict );
132              
133 1         13 return 'neutral';
134             }
135              
136              
137             sub is_implied_default_policy {
138 0     0 1 0 my $self = shift;
139 0         0 my $default_policy = ref($self)->default;
140 0         0 return ( $self == $default_policy );
141             }
142              
143              
144             sub location {
145 0     0 1 0 my $self = shift;
146 0         0 return $self->{Domain};
147             }
148              
149             sub name {
150 0     0 1 0 return 'ADSP';
151             }
152              
153              
154             sub policy {
155 4     4 1 8 my $self = shift;
156              
157             (@_)
158 4 50       10 and $self->{tags}->{dkim} = shift;
159              
160 4 50       10 if ( defined $self->{tags}->{dkim} ) {
161 4         22 return $self->{tags}->{dkim};
162             }
163             else {
164 0         0 return 'unknown';
165             }
166             }
167              
168              
169             sub signall {
170 0     0 1 0 my $self = shift;
171              
172 0   0     0 return $self->policy
173             && ( $self->policy =~ /all/i );
174             }
175              
176              
177             sub signall_strict {
178 2     2 0 3 my $self = shift;
179              
180 2   66     6 return $self->policy
181             && ( $self->policy =~ /discardable/i );
182             }
183              
184             1;
185              
186             __END__