File Coverage

blib/lib/Mail/SPF/Server.pm
Criterion Covered Total %
statement 82 164 50.0
branch 15 48 31.2
condition 4 30 13.3
subroutine 25 47 53.1
pod 10 13 76.9
total 136 302 45.0


line stmt bran cond sub pod time code
1             #
2             # Mail::SPF::Server
3             # Server class for processing SPF requests.
4             #
5             # (C) 2005-2012 Julian Mehnle
6             # 2005 Shevek
7             # $Id: Server.pm 61 2013-07-22 03:45:15Z julian $
8             #
9             ##############################################################################
10              
11             package Mail::SPF::Server;
12              
13             =head1 NAME
14              
15             Mail::SPF::Server - Server class for processing SPF requests
16              
17             =head1 VERSION
18              
19             version 3.20250505
20              
21             =cut
22              
23 3     3   502771 use warnings;
  3         8  
  3         280  
24 3     3   22 use strict;
  3         7  
  3         115  
25              
26 3     3   18 use base 'Mail::SPF::Base';
  3         7  
  3         1577  
27              
28 3     3   24 use Error ':try';
  3         7  
  3         24  
29 3     3   1373 use Net::DNS::Resolver;
  3         109758  
  3         207  
30              
31 3     3   1338 use Mail::SPF::MacroString;
  3         15  
  3         135  
32 3     3   1652 use Mail::SPF::Record;
  3         12  
  3         106  
33 3     3   1944 use Mail::SPF::Result;
  3         13  
  3         21  
34              
35 3     3   247 use constant TRUE => (0 == 0);
  3         6  
  3         188  
36 3     3   19 use constant FALSE => not TRUE;
  3         7  
  3         158  
37              
38 3         242 use constant record_classes_by_version => {
39             1 => 'Mail::SPF::v1::Record',
40             2 => 'Mail::SPF::v2::Record'
41 3     3   18 };
  3         6  
42              
43 3     3   21 use constant result_base_class => 'Mail::SPF::Result';
  3         7  
  3         241  
44              
45 3     3   21 use constant query_rr_type_all => 0;
  3         5  
  3         138  
46 3     3   15 use constant query_rr_type_txt => 1;
  3         7  
  3         158  
47 3     3   16 use constant query_rr_type_spf => 2;
  3         5  
  3         171  
48              
49 3         218 use constant default_default_authority_explanation =>
50 3     3   20 'Rejected by SPF record.';
  3         5  
51              
52 7     7 0 34 sub default_query_rr_types { shift->query_rr_type_txt };
53              
54 3     3   20 use constant default_max_dns_interactive_terms => 10; # RFC 4408, 10.1/6
  3         5  
  3         266  
55 3     3   17 use constant default_max_name_lookups_per_term => 10; # RFC 4408, 10.1/7
  3         154  
  3         269  
56 6     6 0 23 sub default_max_name_lookups_per_mx_mech { shift->max_name_lookups_per_term };
57 7     7 0 25 sub default_max_name_lookups_per_ptr_mech { shift->max_name_lookups_per_term };
58              
59 3     3   18 use constant default_max_void_dns_lookups => 2;
  3         7  
  3         12111  
60              
61             # Interface:
62             ##############################################################################
63              
64             =head1 SYNOPSIS
65              
66             use Mail::SPF;
67              
68             my $spf_server = Mail::SPF::Server->new(
69             # Optional custom default for authority explanation:
70             default_authority_explanation =>
71             'See http://www.%{d}/why/id=%{S};ip=%{I};r=%{R}'
72             );
73              
74             my $result = $spf_server->process($request);
75              
76             =cut
77              
78             # Implementation:
79             ##############################################################################
80              
81             =head1 DESCRIPTION
82              
83             B is a server class for processing SPF requests. Each
84             server instance can be configured with specific processing parameters. Also,
85             the default I DNS resolver used for making DNS look-ups can
86             be overridden with a custom resolver object.
87              
88             =head2 Constructor
89              
90             The following constructor is provided:
91              
92             =over
93              
94             =item B: returns I
95              
96             Creates a new server object for processing SPF requests.
97              
98             %options is a list of key/value pairs representing any of the following
99             options:
100              
101             =over
102              
103             =item B
104              
105             A I denoting the default (not macro-expanded) authority explanation
106             string to use if the authority domain does not specify an explanation string of
107             its own. Defaults to:
108              
109             'Rejected by SPF record.'
110              
111             As can be seen from the default, a non-standard C<_scope> pseudo macro is
112             supported that expands to the name of the identity's scope. (Note: Do I
113             use any non-standard macros in explanation strings published in DNS.)
114              
115             =item B
116              
117             A I denoting the local system's fully qualified host name that should
118             be used for expanding the C macro in explanation strings. Defaults to the
119             system's configured host name.
120              
121             =item B
122              
123             An optional DNS resolver object. If none is specified, a new I
124             object is used. The resolver object may be of a different class, but it must
125             provide an interface similar to I -- at least the C
126             and C methods must be supported, and the C method must
127             return either an object of class I, or, in the case of an
128             error, B.
129              
130             =item B
131              
132             For which RR types to query when looking up and selecting SPF records. The
133             following values are supported:
134              
135             =over
136              
137             =item B<< Mail::SPF::Server->query_rr_type_all >>
138              
139             Both C and C type RRs.
140              
141             =item B<< Mail::SPF::Server->query_rr_type_txt >> (default)
142              
143             C type RRs only.
144              
145             =item B<< Mail::SPF::Server->query_rr_type_spf >>
146              
147             C type RRs only.
148              
149             =back
150              
151             For years B has defaulted to looking up both C and C type
152             RRs as recommended by RFC 4408. Experience has shown, however, that a
153             significant portion of name servers suffer from serious brain damage with
154             regard to the handling of queries for RR types that are unknown to them, such
155             as the C RR type. Consequently B now defaults to looking up
156             only C type RRs. This may be overridden by setting the B
157             option.
158              
159             See RFC 4408, 3.1.1, for a discussion of the topic, as well as the description
160             of the L method.
161              
162             =item B
163              
164             An I denoting the maximum number of terms (mechanisms and modifiers)
165             per SPF check that perform DNS look-ups, as defined in RFC 4408, 10.1,
166             paragraph 6. If B is specified, there is no limit on the number of such
167             terms. Defaults to B<10>, which is the value defined in RFC 4408.
168              
169             A value above the default is I for security reasons. A
170             value below the default has implications with regard to the predictability of
171             SPF results. Only deviate from the default if you know what you are doing!
172              
173             =item B
174              
175             An I denoting the maximum number of DNS name look-ups per term
176             (mechanism or modifier), as defined in RFC 4408, 10.1, paragraph 7. If
177             B is specified, there is no limit on the number of look-ups performed.
178             Defaults to B<10>, which is the value defined in RFC 4408.
179              
180             A value above the default is I for security reasons. A
181             value below the default has implications with regard to the predictability of
182             SPF results. Only deviate from the default if you know what you are doing!
183              
184             =item B
185              
186             =item B
187              
188             An I denoting the maximum number of DNS name look-ups per B or B
189             mechanism, respectively. Defaults to the value of the C
190             option. See there for additional information and security notes.
191              
192             =item B
193              
194             An I denoting the maximum number of "void" DNS look-ups per SPF check,
195             i.e. the number of DNS look-ups that were caused by DNS-interactive terms and
196             macros (as defined in RFC 4408, 10.1, paragraphs 6 and 7) and that are allowed
197             to return an empty answer with RCODE 0 or RCODE 3 (C) before
198             processing is aborted with a C result. If B is specified,
199             there is no stricter limit on the number of void DNS look-ups beyond the usual
200             processing limits. Defaults to B<2>.
201              
202             Specifically, the DNS look-ups that are subject to this limit are those caused
203             by the C, C, C, and C mechanisms and the C

macro.

204              
205             A value of B<2> is likely to prevent effective DoS attacks against third-party
206             victim domains. However, a definite limit may cause C results even
207             with certain (overly complex) innocent sender policies where useful results
208             would normally be returned.
209              
210             =back
211              
212             =cut
213              
214             sub new {
215 7     7 1 653706 my ($self, %options) = @_;
216 7         61 $self = $self->SUPER::new(%options);
217              
218             # Do not cache a Mail::SPF::MacroString instance with
219             # context provided, this causes a circular reference that leaks
220             # both objects.
221             $self->{default_authority_explanation} = $self->default_default_authority_explanation
222 7 50       57 if not defined($self->{default_authority_explanation});
223              
224 7   33     74 $self->{hostname} ||= Mail::SPF::Util->hostname;
225              
226 7   66     524 $self->{dns_resolver} ||= Net::DNS::Resolver->new();
227              
228             $self->{query_rr_types} = $self->default_query_rr_types
229 7 50       136 if not defined($self->{query_rr_types});
230              
231             $self->{max_dns_interactive_terms} = $self->default_max_dns_interactive_terms
232 7 100       38 if not exists($self->{max_dns_interactive_terms});
233             $self->{max_name_lookups_per_term} = $self->default_max_name_lookups_per_term
234 7 100       44 if not exists($self->{max_name_lookups_per_term});
235             $self->{max_name_lookups_per_mx_mech} = $self->default_max_name_lookups_per_mx_mech
236 7 100       31 if not exists($self->{max_name_lookups_per_mx_mech});
237             $self->{max_name_lookups_per_ptr_mech} = $self->default_max_name_lookups_per_ptr_mech
238 7 50       33 if not exists($self->{max_name_lookups_per_ptr_mech});
239              
240             $self->{max_void_dns_lookups} = $self->default_max_void_dns_lookups
241 7 50       42 if not exists($self->{max_void_dns_lookups});
242              
243 7         32 return $self;
244             }
245              
246             =back
247              
248             =head2 Class methods
249              
250             The following class methods are provided:
251              
252             =over
253              
254             =item B: returns I
255              
256             =item B: returns I
257              
258             Returns a I descendent class determined from the given
259             result name via the server's inherent result base class, or returns the
260             server's inherent result base class if no result name is given. This method
261             may also be used as an instance method.
262              
263             I: Do not write code invoking class methods on I result class
264             names as this would ignore any derivative result classes provided by
265             B extension modules.
266              
267             =cut
268              
269             sub result_class {
270 0     0 1 0 my ($self, $name) = @_;
271             return
272             defined($name) ?
273 0 0       0 $self->result_base_class->result_classes->{$name}
274             : $self->result_base_class;
275             }
276              
277             =item B: throws I
278              
279             =item B: throws I
280              
281             Throws a I descendant determined from the given result name
282             via the server's inherent result base class, passing an optional result text
283             and associating the given I object with the result object.
284             This method may also be used as an instance method.
285              
286             I: Do not write code invoking C on I result class names
287             as this would ignore any derivative result classes provided by B
288             extension modules.
289              
290             =cut
291              
292             sub throw_result {
293 0     0 1 0 my ($self, $name, $request, @text) = @_;
294 0         0 $self->result_class($name)->throw($self, $request, @text);
295             }
296              
297             =back
298              
299             =head2 Instance methods
300              
301             The following instance methods are provided:
302              
303             =over
304              
305             =item B: returns I
306              
307             Processes the given I object, queries the authoritative
308             domain for an SPF sender policy (see the description of the L
309             method), evaluates the policy with regard to the given identity and other
310             request parameters, and returns a I object denoting the
311             result of the policy evaluation. See RFC 4408, 4, and RFC 4406, 4, for
312             details.
313              
314             =cut
315              
316             sub process {
317 0     0 1 0 my ($self, $request) = @_;
318              
319 0         0 $request->state('authority_explanation', undef);
320 0         0 $request->state('dns_interactive_terms_count', 0);
321 0         0 $request->state('void_dns_lookups_count', 0);
322              
323 0         0 my $result;
324             try {
325 0     0   0 my $record = $self->select_record($request);
326 0         0 $request->record($record);
327 0         0 $record->eval($self, $request);
328             }
329             catch Mail::SPF::Result with {
330 0     0   0 $result = shift;
331             }
332             catch Mail::SPF::EDNSError with {
333 0     0   0 $result = $self->result_class('temperror')->new($self, $request, shift->text);
334             }
335             catch Mail::SPF::ENoAcceptableRecord with {
336 0 0 0 0   0 if((not defined $request->{record}->{terms}[0]->{domain_spec}->{text}) or ($request->{record}->{terms}[0]->{domain_spec}->{text} !~ /\.\./)) {
337             # remove empty record structure in order to stringify it correctly
338 0         0 undef $request->{record};
339 0         0 $result = $self->result_class('none' )->new($self, $request, shift->text);
340             } else {
341 0         0 $result = $self->result_class('permerror')->new($self, $request, shift->text);
342             }
343             }
344             catch Mail::SPF::ERedundantAcceptableRecords with {
345 0     0   0 $result = $self->result_class('permerror')->new($self, $request, shift->text);
346             }
347             catch Mail::SPF::ESyntaxError with {
348 0     0   0 $result = $self->result_class('permerror')->new($self, $request, shift->text);
349             }
350             catch Mail::SPF::EProcessingLimitExceeded with {
351 0     0   0 $result = $self->result_class('permerror')->new($self, $request, shift->text);
352 0         0 };
353             # Propagate other, unknown errors.
354             # This should not happen, but if it does, it helps exposing the bug!
355              
356 0         0 return $result;
357             }
358              
359             =item B: returns I;
360             throws I,
361             I, I,
362             I
363              
364             Queries the authority domain of the given I object for SPF
365             sender policy records and, if multiple records are available, selects the
366             record of the highest acceptable record version that covers the requested
367             scope.
368              
369             More precisely, the following algorithm is performed (assuming that both C
370             and C RR types are being queried):
371              
372             =over
373              
374             =item 1.
375              
376             Determine the authority domain, the set of acceptable SPF record versions, and
377             the identity scope from the given request object.
378              
379             =item 2.
380              
381             Query the authority domain for SPF records of the C DNS RR type,
382             discarding any records that are of an inacceptable version or do not cover the
383             desired scope.
384              
385             If this yields no SPF records, query the authority domain for SPF records of
386             the C DNS RR type, discarding any records that are of an inacceptable
387             version or do not cover the desired scope.
388              
389             If still no acceptable SPF records could be found, throw a
390             I exception.
391              
392             =item 3.
393              
394             Discard all records but those of the highest acceptable version found.
395              
396             If exactly one record remains, return it. Otherwise, throw a
397             I exception.
398              
399             =back
400              
401             If the querying of either RR type has been disabled via the L
402             constructor's C option, the respective part in step 2 will
403             be skipped.
404              
405             I exceptions due to DNS look-ups and
406             I exceptions due to invalid acceptable records may
407             also be thrown.
408              
409             =cut
410              
411             sub select_record {
412 0     0 1 0 my ($self, $request) = @_;
413              
414 0         0 my $domain = $request->authority_domain;
415 0         0 my @versions = $request->versions;
416 0         0 my $scope = $request->scope;
417              
418             # Employ identical behavior for 'v=spf1' and 'spf2.0' records, both of
419             # which support SPF (code 99) and TXT type records (this may be different
420             # in future revisions of SPF):
421             # Query for SPF type records first, then fall back to TXT type records.
422              
423 0         0 my @records;
424 0         0 my $query_count = 0;
425 0         0 my @dns_errors;
426              
427             # Query for SPF-type RRs first:
428 0 0 0     0 if (
429             $self->query_rr_types == $self->query_rr_type_all or
430             $self->query_rr_types & $self->query_rr_type_spf
431             ) {
432             try {
433 0     0   0 $query_count++;
434 0         0 my $packet = $self->dns_lookup($domain, 'SPF');
435 0         0 push(
436             @records,
437             $self->get_acceptable_records_from_packet(
438             $packet, 'SPF', \@versions, $scope, $domain)
439             );
440             }
441             catch Mail::SPF::EDNSError with {
442 0     0   0 push(@dns_errors, shift);
443 0         0 };
444             #catch Mail::SPF::EDNSTimeout with {
445             # # FIXME Ignore DNS time-outs on SPF type lookups?
446             # # Apparrently some brain-dead DNS servers time out on SPF-type queries.
447             #};
448             }
449              
450             # If no usable SPF-type RRs, try TXT-type RRs:
451 0 0 0     0 if (
      0        
452             not @records and
453             (
454             $self->query_rr_types == $self->query_rr_type_all or
455             $self->query_rr_types & $self->query_rr_type_txt
456             )
457             ) {
458             # NOTE:
459             # This deliberately violates RFC 4406 (Sender ID), 4.4/3 (4.4.1):
460             # TXT-type RRs are still tried if there _are_ SPF-type RRs but all of
461             # them are inapplicable (i.e. "Hi!", or even "spf2.0/pra" for an
462             # 'mfrom' scope request). This conforms to the spirit of the more
463             # sensible algorithm in RFC 4408 (SPF), 4.5.
464             # Implication: Sender ID processing may make use of existing TXT-
465             # type records where a result of "None" would normally be returned
466             # under a strict interpretation of RFC 4406.
467              
468             try {
469 0     0   0 $query_count++;
470 0         0 my $packet = $self->dns_lookup($domain, 'TXT');
471 0         0 push(
472             @records,
473             $self->get_acceptable_records_from_packet(
474             $packet, 'TXT', \@versions, $scope, $domain)
475             );
476             }
477             catch Mail::SPF::EDNSError with {
478 0     0   0 push(@dns_errors, shift);
479 0         0 };
480             }
481              
482 0 0       0 @dns_errors < $query_count
483             or $dns_errors[0]->throw;
484             # Unless at least one query succeeded, re-throw the first DNS error that occurred.
485              
486             @records
487 0 0       0 or throw Mail::SPF::ENoAcceptableRecord(
488             "No applicable sender policy available"); # RFC 4408, 4.5/7
489              
490             # Discard all records but the highest acceptable version:
491 0         0 my $preferred_record_class = $records[0]->class;
492 0         0 @records = grep($_->isa($preferred_record_class), @records);
493              
494 0 0       0 @records == 1
495             or throw Mail::SPF::ERedundantAcceptableRecords(
496             "Redundant applicable '" . $preferred_record_class->version_tag . "' " .
497             "sender policies found"); # RFC 4408, 4.5/6
498              
499 0         0 return $records[0];
500             }
501              
502             =item B:
503             returns I of I
504              
505             Filters from the given I object all resource records of the
506             given RR type and for the given domain name, discarding any records that are
507             not SPF records at all, that are of an inacceptable SPF record version, or that
508             do not cover the given scope. Returns a list of acceptable records.
509              
510             =cut
511              
512             sub get_acceptable_records_from_packet {
513 0     0 1 0 my ($self, $packet, $rr_type, $versions, $scope, $domain) = @_;
514              
515 0         0 my @versions = sort { $b <=> $a } @$versions;
  0         0  
516             # Try higher record versions first.
517             # (This may be too simplistic for future revisions of SPF.)
518              
519 0         0 my @records;
520              
521 0         0 foreach my $rr ($packet->answer) {
522 0 0       0 next if $rr->type ne $rr_type; # Ignore RRs of unexpected type.
523              
524             # char_str_list method is 'historical', use as a fallback for Net::DNS prior to 0.69
525             # where txtdata is not available.
526             # join with no intervening spaces, RFC 6376
527             # must call txtdata() in a list context
528 0 0       0 my $text = $rr->can('txtdata')
529             ? join('', $rr->txtdata)
530             : join('', $rr->char_str_list);
531 0         0 my $record;
532              
533             # Try to parse RR as each of the requested record versions,
534             # starting from the highest version:
535             VERSION:
536 0         0 foreach my $version (@versions) {
537 0         0 my $class = $self->record_classes_by_version->{$version};
538 0         0 eval("require $class");
539             try {
540 0     0   0 $record = $class->new_from_string($text);
541             }
542 0     0   0 catch Mail::SPF::EInvalidRecordVersion with {};
543             # Ignore non-SPF and unknown-version records.
544             # Propagate other errors (including syntax errors), though.
545 0 0       0 last VERSION if defined($record);
546             }
547              
548 0 0 0     0 push(@records, $record)
549             if defined($record)
550             and grep($scope eq $_, $record->scopes); # record covers requested scope?
551             }
552 0         0 return @records;
553             }
554              
555             =item B: returns I;
556             throws I, I
557              
558             Queries the DNS using the configured resolver for resource records of the
559             desired type at the specified domain and returns a I object
560             if an answer packet was received. Throws a I exception
561             if a DNS time-out occurred. Throws a I exception if an
562             error (other than RCODE 3 AKA C) occurred.
563              
564             =cut
565              
566             sub dns_lookup {
567 4     4 1 30 my ($self, $domain, $rr_type) = @_;
568              
569 4         9 my $packet;
570              
571 4 50       29 if (UNIVERSAL::isa($domain, 'Mail::SPF::MacroString')) {
572 0         0 $domain = $domain->expand;
573             # Truncate overlong labels at 63 bytes (RFC 4408, 8.1/27):
574 0         0 $domain =~ s/([^.]{63})[^.]+/$1/g;
575             # Drop labels from the head of domain if longer than 253 bytes (RFC 4408, 8.1/25):
576 0         0 $domain =~ s/^[^.]+\.(.*)$/$1/
577             while length($domain) > 253;
578             }
579              
580 4         1291 $domain =~ s/^(.*?)\.?$/\L$1/; # Normalize domain.
581              
582             try {
583 4     4   155 $packet = $self->dns_resolver->send($domain, $rr_type);
584             }
585             otherwise {
586 0     0   0 throw Mail::SPF::ENoAcceptableRecord($self->dns_resolver->errorstring);
587 4         63 };
588              
589             # Throw DNS exception unless an answer packet with RCODE 0 or 3 (NXDOMAIN)
590             # was received (thereby treating NXDOMAIN as an acceptable but empty answer packet):
591 4 50 33     27991 throw Mail::SPF::EDNSTimeout("Time-out on DNS '$rr_type' lookup of '$domain'")
592             if defined $self->dns_resolver->errorstring && $self->dns_resolver->errorstring =~ /^(timeout|query timed out)$/;
593 4 50       65 throw Mail::SPF::EDNSError("Unknown error on DNS '$rr_type' lookup of '$domain'")
594             unless defined $packet;
595 4 100       17 throw Mail::SPF::EDNSError("'" . $packet->header->rcode . "' error on DNS '$rr_type' lookup of '$domain'")
596             unless $packet->header->rcode =~ /^(NOERROR|NXDOMAIN)$/;
597              
598 3         234 return $packet;
599             }
600              
601             =item B: throws I
602              
603             Increments by one the count of DNS-interactive mechanisms and modifiers that
604             have been processed so far during the evaluation of the given
605             I object. If this exceeds the configured limit (see the
606             L constructor's C option), throws a
607             I exception.
608              
609             This method is supposed to be called by the C and C methods of
610             I and I sub-classes before (and only if) they
611             do any DNS look-ups.
612              
613             =cut
614              
615             sub count_dns_interactive_term {
616 0     0 1   my ($self, $request) = @_;
617 0           my $dns_interactive_terms_count = ++$request->root_request->state('dns_interactive_terms_count');
618 0           my $max_dns_interactive_terms = $self->max_dns_interactive_terms;
619 0 0 0       if (
620             defined($max_dns_interactive_terms) and
621             $dns_interactive_terms_count > $max_dns_interactive_terms
622             ) {
623 0           throw Mail::SPF::EProcessingLimitExceeded(
624             "Maximum DNS-interactive terms limit ($max_dns_interactive_terms) exceeded");
625             }
626 0           return;
627             }
628              
629             =item B: throws I
630              
631             Increments by one the count of "void" DNS look-ups that have occurred so far
632             during the evaluation of the given I object. If this
633             exceeds the configured limit (see the L constructor's C
634             option), throws a I exception.
635              
636             This method is supposed to be called by any code after any calls to the
637             L method whenever (i) no answer records were returned, and (ii)
638             this fact is a possible indication of a DoS attack against a third-party victim
639             domain, and (iii) the number of "void" look-ups is not already constrained
640             otherwise (as for example is the case with the C mechanism and the
641             C modifier). Specifically, this applies to look-ups performed by the
642             C, C, C, and C mechanisms and the C

macro.

643              
644             =cut
645              
646             sub count_void_dns_lookup {
647 0     0 1   my ($self, $request) = @_;
648 0           my $void_dns_lookups_count = ++$request->root_request->state('void_dns_lookups_count');
649 0           my $max_void_dns_lookups = $self->max_void_dns_lookups;
650 0 0 0       if (
651             defined($max_void_dns_lookups) and
652             $void_dns_lookups_count > $max_void_dns_lookups
653             ) {
654 0           throw Mail::SPF::EProcessingLimitExceeded(
655             "Maximum void DNS look-ups limit ($max_void_dns_lookups) exceeded");
656             }
657 0           return;
658             }
659              
660             =item B: returns I
661              
662             Returns the default authority explanation as a I object. See the
663             description of the L constructor's C
664             option.
665              
666             =cut
667              
668             sub default_authority_explanation {
669 0     0 1   my ($self) = @_;
670              
671             return Mail::SPF::MacroString->new(
672             text => $self->{default_authority_explanation},
673 0           server => $self,
674             is_explanation => TRUE
675             );
676             }
677              
678             =item B: returns I
679              
680             Returns the local system's host name. See the description of the L
681             constructor's C option.
682              
683             =item B: returns I or compatible object
684              
685             Returns the DNS resolver object of the server object. See the description of
686             the L constructor's C option.
687              
688             =item B: returns I
689              
690             Returns a value denoting the RR types for which to query when looking up and
691             selecting SPF records. See the description of the L constructor's
692             C option.
693              
694             =item B: returns I
695              
696             =item B: returns I
697              
698             =item B: returns I
699              
700             =item B: returns I
701              
702             =item B: returns I
703              
704             Return the limit values of the server object. See the description of the
705             L constructor's corresponding options.
706              
707             =cut
708              
709             # Make read-only accessors:
710             __PACKAGE__->make_accessor($_, TRUE)
711             foreach qw(
712             hostname
713              
714             dns_resolver
715             query_rr_types
716              
717             max_dns_interactive_terms
718             max_name_lookups_per_term
719             max_name_lookups_per_mx_mech
720             max_name_lookups_per_ptr_mech
721              
722             max_void_dns_lookups
723             );
724              
725             =back
726              
727             =head1 SEE ALSO
728              
729             L, L, L
730              
731             L
732              
733             For availability, support, and license information, see the README file
734             included with Mail::SPF.
735              
736             =head1 AUTHORS
737              
738             Julian Mehnle , Shevek
739              
740             =cut
741              
742             TRUE;