Mailing List Archive

svn commit: mail-spf-query-perl: r117 - trunk
Author: julian
Date: 2005-12-07 17:48:47 -0600 (Wed, 07 Dec 2005)
New Revision: 117

Modified:
trunk/Query.pm
trunk/README
Log:
trunk/Query.pm
* Marked best guess processing, trusted forwarder accreditation checking, and
a few other things as non-standard features.
* Added a "NON-STANDARD FEATURES" POD section.
* Say "trusted=>0, guess=>0" in the sample code in the "SYNOPSIS" POD section.
* Consistently made method POD documentation into proper "=head2" sections.
* Cleaned up (and rewrapped) the formatting of most of the POD documentation.
* Removed superfluous "EXPORT" POD section.
* Added link to the SPF specification in the "SEE ALSO" POD section.
* Minor wording improvements.

trunk/README
* Reordered the result codes in a more sensical way.


Modified: trunk/Query.pm
===================================================================
--- trunk/Query.pm 2005-12-05 20:59:08 UTC (rev 116)
+++ trunk/Query.pm 2005-12-07 23:48:47 UTC (rev 117)
@@ -17,11 +17,11 @@
#
# The result of evaluating a SPF record associated with a domain is one of:
#
-# none The domain does not have an SPF record.
-# neutral Domain explicitly wishes you to pretend it had no SPF record.
# pass Explicit pass -- message is not a forgery.
+# fail Explicit fail -- MTA may reject, MUA may discard.
# softfail Explicit softfail -- please apply strict antispam checks.
-# fail Explicit fail -- MTA may reject, MUA may discard.
+# neutral Domain explicitly wishes you to pretend it had no SPF record.
+# none The domain does not have an SPF record.
# error Some type of temporary failure, usually DNS-related.
# unknown A permanent error, such as missing SPF record during "include"
# or "redirect", parse error, unknown mechanism, or record loop.
@@ -56,7 +56,9 @@
# ----------------------------------------------------------

my $GUESS_MECHS = "a/24 mx/24 ptr";
+
my $TRUSTED_FORWARDER = "include:spf.trusted-forwarder.org";
+
my $DEFAULT_EXPLANATION = "Please see http://www.openspf.org/why.html?sender=%{S}&ip=%{I}&receiver=%{R}";
my @KNOWN_MECHANISMS = qw( a mx ptr include ip4 ip6 exists all );
my $MAX_LOOKUP_COUNT = 20;
@@ -82,116 +84,130 @@

=head1 SYNOPSIS

- my $query = new Mail::SPF::Query (ip => "127.0.0.1", sender=>'foo@example.com', helo=>"somehost.example.com", trusted=>1, guess=>1);
- my ($result, # pass | fail | softfail | neutral | none | error | unknown [mechanism]
- $smtp_comment, # "please see http://www.openspf.org/why.html?..." when rejecting, return this string to the SMTP client
- $header_comment, # prepend_header("Received-SPF" => "$result ($header_comment)")
- $spf_record, # "v=spf1 ..." original SPF record for the domain
- ) = $query->result();
+ my $query = new Mail::SPF::Query (ip => "127.0.0.1", sender=>'foo@example.com', helo=>"somehost.example.com", trusted=>0, guess=>0);
+ my ($result, # pass | fail | softfail | neutral | none | error | unknown [mechanism]
+ $smtp_comment, # "please see http://www.openspf.org/why.html?..." when rejecting, return this string to the SMTP client
+ $header_comment, # prepend_header("Received-SPF" => "$result ($header_comment)")
+ $spf_record, # "v=spf1 ..." original SPF record for the domain
+ ) = $query->result();

- if ($result eq "pass") { "domain is (probably) not forged. apply RHSBL and content filters" }
- elsif ($result eq "fail") { "domain is forged. reject or save to spambox" }
+ if ($result eq "pass") { "domain is (probably) not forged. apply RHSBL and content filters" }
+ elsif ($result eq "fail") { "domain is forged. reject or save to spambox" }

- The default mechanism for trusted=>1 is "include:spf.trusted-forwarder.org".
- The default mechanisms for guess=>1 are "a/24 mx/24 ptr".
+ # NOTE: Trusted forwarder accreditation checking (trusted=>1) and best guess
+ # processing (guess=>1) are non-standard features.
+ # The default mechanism for trusted=>1 is "include:spf.trusted-forwarder.org".
+ # The default mechanisms for guess=>1 are "a/24 mx/24 ptr".

=head1 ABSTRACT

-The SPF protocol relies on sender domains to describe their
-designated outbound mailers in DNS. Given an email address,
-Mail::SPF::Query determines the legitimacy of an SMTP client
-IP.
+The SPF protocol relies on sender domains to describe their designated outbound
+mailers in DNS. Given an email address, Mail::SPF::Query determines the
+legitimacy of an SMTP client IP address.

=head1 DESCRIPTION

-There are two ways to use Mail::SPF::Query. Your choice
-depends on whether the domains your server is an MX for have
-secondary MXes which your server doesn't know about.
+There are two ways to use Mail::SPF::Query. Your choice depends on whether the
+domains your server is an MX for have secondary MXes which your server doesn't
+know about.

-The first and more common style, calling ->result(), is
-suitable when all mail is received directly from the
-originator's MTA. If the domains you receive do not have
-secondary MX entries, this is appropriate. This style of
-use is outlined in the SYNOPSIS above. This is the common
-case.
+The first and more common style, calling ->result(), is suitable when all mail
+is received directly from the originator's MTA. If the domains you receive do
+not have secondary MX entries, this is appropriate. This style of use is
+outlined in the SYNOPSIS above. This is the common case.

-The second style is more complex, but works when your server
-receives mail from secondary MXes. This performs checks as
-each recipient is handled. If the message is coming from a
-valid MX secondary for a recipient, then the SPF check is
-not performed, and a "pass" response is returned right away.
-To do this, call C<result2()> and C<message_result2()>
-instead of C<result()>.
+The second style is more complex, but works when your server receives mail from
+secondary MXes. This performs checks as each recipient is handled. If the
+message is coming from a valid MX secondary for a recipient, then the SPF check
+is not performed, and a "pass" response is returned right away. To do this,
+call C<result2()> and C<message_result2()> instead of C<result()>.

-If you do not know what a secondary MX is, you probably
-don't have one. Use the first style.
+If you do not know what a secondary MX is, you probably don't have one. Use
+the first style.

-You can try out Mail::SPF::Query on the command line with
-the following command:
+You can try out Mail::SPF::Query on the command line with the following
+command:

- perl -MMail::SPF::Query -le 'print for Mail::SPF::Query->new(helo=>shift, ipv4=>shift, sender=>shift)->result' helohost.example.com 1.2.3.4 user@example.com
+ perl -MMail::SPF::Query -le 'print for Mail::SPF::Query->new(helo=>shift, ipv4=>shift, sender=>shift)->result' helohost.example.com 1.2.3.4 user@example.com

+=head1 NON-STANDARD FEATURES

+Mail::SPF::Query tries to implement the SPF specification (see L</"SEE ALSO">)
+as close as reasonably possible given that M:S:Q has been the very first SPF
+implementation and has changed with the SPF specification over time.
+
+As such, M:S:Q does have some legacy features that are not parts of the
+official SPF specification, most notably I<best guess processing> and I<trusted
+forwarder accreditation checking>. Please be careful when using these
+I<non-standard> features or when reproducing them in your own SPF
+implementation, as they may cause unexpected results.
+
=head1 METHODS

-=over
+=head2 C<< Mail::SPF::Query->new() >>

-=item C<< Mail::SPF::Query->new() >>
+ my $query = eval { new Mail::SPF::Query (
+ ip =>"127.0.0.1",
+ sender =>'foo@example.com',
+ helo =>"host.example.com",

- my $query = eval { new Mail::SPF::Query (ip =>"127.0.0.1",
- sender=>'foo@example.com',
- helo =>"host.example.com") };
+ # optional parameters:
+ debug => 1, debuglog => sub { print STDERR "@_\n" },
+ local => 'extra mechanisms',
+ trusted => 1, # do trusted forwarder processing
+ guess => 1, # do best_guess if no SPF record
+ default_explanation => 'Please see http://spf.my.isp/spferror.html for details',
+ max_lookup_count => 20, # total number of SPF include/redirect queries
+ sanitize => 0, # do not sanitize all returned strings
+ myhostname => "foo.example.com", # prepended to header_comment
+ fallback => { "foo.com" => { record => "v=spf1 a mx -all", OPTION => VALUE },
+ "*.foo.com" => { record => "v=spf1 a mx -all", OPTION => VAULE }, },
+ override => { "bar.com" => { record => "v=spf1 a mx -all", OPTION => VALUE },
+ "*.bar.com" => { record => "v=spf1 a mx -all", OPTION => VAULE }, }
+ ) };

- optional parameters:
- debug => 1, debuglog => sub { print STDERR "@_\n" },
- local => 'extra mechanisms',
- trusted => 1, # do trusted forwarder processing
- guess => 1, # do best_guess if no SPF record
- default_explanation => 'Please see http://spf.my.isp/spferror.html for details',
- max_lookup_count => 20, # total number of SPF include/redirect queries
- sanitize => 0, # do not sanitize all returned strings
- myhostname => "foo.example.com", # prepended to header_comment
- fallback => { "foo.com" => { record => "v=spf1 a mx -all", OPTION => VALUE },
- "*.foo.com" => { record => "v=spf1 a mx -all", OPTION => VAULE }, },
- override => { "bar.com" => { record => "v=spf1 a mx -all", OPTION => VALUE },
- "*.bar.com" => { record => "v=spf1 a mx -all", OPTION => VAULE }, },
- },
+ if ($@) { warn "bad input to Mail::SPF::Query: $@" }

- if ($@) { warn "bad input to Mail::SPF::Query: $@" }
+Set C<trusted=E<gt>1> to turned on C<trusted-forwarder.org> accreditation
+checking. The mechanism C<include:spf.trusted-forwarder.org> is used just
+before a C<-all> or C<?all>. The precise circumstances are somewhat more
+complicated, but it does get the case of C<v=spf1 -all> right -- i.e.
+C<trusted-forwarder.org> is not checked. B<This is a non-standard feature.>

-Set C<trusted=E<gt>1> to turned on automatic trusted_forwarder processing.
-The mechanism C<include:spf.trusted-forwarder.org> is used just before a C<-all> or C<?all>.
-The precise circumstances are somewhat more complicated, but it does get the case of C<v=spf1 -all>
-right -- i.e. spf.trusted-forwarder.org is not checked.
+Set C<guess=E<gt>1> to turned on automatic best guess processing. This will
+use the best_guess SPF record when one cannot be found in the DNS. Note that
+this can only return C<pass> or C<neutral>. The C<trusted> and C<local> flags
+also operate when the best_guess is being used. B<This is a non-standard
+feature.>

-Set C<guess=E<gt>1> to turned on automatic best_guess processing.
-This will use the best_guess SPF record when one cannot be found
-in the DNS. Note that this can only return C<pass> or C<neutral>.
-The C<trusted> and C<local> flags also operate when the best_guess is being used.
+Set C<local=E<gt>'include:local.domain'> to include some extra processing just
+before a C<-all> or C<?all>. The local processing happens just before the
+trusted forwarder processing. B<This is a non-standard feature.>

-Set C<local=E<gt>'include:local.domain'> to include some extra processing just before a C<-all> or C<?all>.
-The local processing happens just before the trusted processing.
+Set C<default_explanation> to a string to be used if the SPF record does not
+provide a specific explanation. The default value will direct the user to a
+page at www.openspf.org with the following message:

-Set C<default_explanation> to a string to be used if the SPF record does not provide
-a specific explanation. The default value will direct the user to a page at www.openspf.org with
-"Please see http://www.openspf.org/why.html?sender=%{S}&ip=%{I}&receiver=%{R}". Note that the
-string has macro substitution performed.
+ Please see http://www.openspf.org/why.html?sender=%{S}&ip=%{I}&receiver=%{R}

-Set C<sanitize> to 0 to get all the returned strings unsanitized. Alternatively, pass a function reference
-and this function will be used to sanitize the returned values. The function must take a single string
-argument and return a single string which contains the sanitized result.
+Note that the string has macro substitution performed.

+Set C<sanitize> to 0 to get all the returned strings unsanitized.
+Alternatively, pass a function reference and this function will be used to
+sanitize the returned values. The function must take a single string argument
+and return a single string which contains the sanitized result.
+
Set C<debug=E<gt>1> to watch the queries happen.

-Set C<fallback> to define "pretend" SPF records for domains
-that don't publish them yet. Wildcards are supported.
+Set C<fallback> to define "pretend" SPF records for domains that don't publish
+them yet. Wildcards are supported. B<This is a non-standard feature.>

-Set C<override> to define SPF records for domains that do
-publish but which you want to override anyway. Wildcards
-are supported.
+Set C<override> to define SPF records for domains that do publish but which you
+want to override anyway. Wildcards are supported. B<This is a non-standard
+feature.>

-NOTE: domain name arguments to fallback and override
-need to be in all lowercase.
+Note: domain name arguments to fallback and override need to be in all
+lowercase.

=cut

@@ -279,93 +295,97 @@
return $query;
}

-=head2 $query->result()
+=head2 C<< $query->result() >>

- my ($result, $smtp_comment, $header_comment, $spf_record, $detail) = $query->result();
+ my ($result, $smtp_comment, $header_comment, $spf_record, $detail) = $query->result();

-C<$result> will be one of C<pass>, C<fail>, C<softfail>, C<neutral>, C<none>, C<error> or C<unknown [...]>.
+C<$result> will be one of C<pass>, C<fail>, C<softfail>, C<neutral>, C<none>,
+C<error> or C<unknown [...]>:

-C<pass> means the client IP is a designated mailer for the
-sender. The mail should be accepted subject to local policy
-regarding the sender.
+=over

-C<fail> means the client IP is not a designated mailer, and
-the sender wants you to reject the transaction for fear of
-forgery.
+=item C<pass>

-C<softfail> means the client IP is not a designated mailer,
-but the sender prefers that you accept the transaction
-because it isn't absolutely sure all its users are mailing
-through approved servers. The C<softfail> status is often
-used during initial deployment of SPF records by a domain.
+The client IP address is an authorized mailer for the sender. The mail should
+be accepted subject to local policy regarding the sender.

-C<neutral> means that the sender makes no assertion about the
-status of the client IP.
+=item C<fail>

-C<none> means that there is no SPF record for this domain.
+The client IP address is not an authorized mailer, and the sender wants you to
+reject the transaction for fear of forgery.

-C<unknown [...]> means the domain has a configuration error in
-the published data or defines a mechanism which this library
-does not understand. If the data contained an unrecognized
-mechanism, it will be presented following "unknown". You
-should test for unknown using a regexp C</^unknown/> rather
-than C<eq "unknown">.
+=item C<softfail>

-C<error> means the DNS lookup encountered a temporary error
-during processing.
+The client IP address is not an authorized mailer, but the sender prefers that
+you accept the transaction because it isn't absolutely sure all its users are
+mailing through approved servers. The C<softfail> status is often used during
+initial deployment of SPF records by a domain.

-Results are cached internally for a default of 120 seconds.
-You can call C<-E<gt>result()> repeatedly; subsequent
-lookups won't hit your DNS.
+=item C<neutral>

-The smtp_comment should be displayed to the SMTP client.
+The sender makes no assertion about the status of the client IP.

-The header_comment goes into a Received-SPF header, like so: C<Received-SPF: $result ($header_comment)>
+=item C<none>

-The spf_record shows the original SPF record fetched for the
-query. If there is no SPF record, it is blank. Otherwise,
-it will start with "v=spf1" and contain the SPF mechanisms
-and such that describe the domain.
+There is no SPF record for this domain.

+=item C<error>
+
+The DNS lookup encountered a temporary error during processing.
+
+=item C<unknown [...]>
+
+The domain has a configuration error in the published data or defines a
+mechanism that this library does not understand. If the data contained an
+unrecognized mechanism, it will be presented following "unknown". You should
+test for unknown using a regexp C</^unknown/> rather than C<eq "unknown">.
+
+=back
+
+Results are cached internally for a default of 120 seconds. You can call
+C<-E<gt>result()> repeatedly; subsequent lookups won't hit your DNS.
+
+C<smtp_comment> should be displayed to the SMTP client.
+
+C<header_comment> goes into a C<Received-SPF> header, like so:
+
+ Received-SPF: $result ($header_comment)
+
+C<spf_record> shows the original SPF record fetched for the query. If there is
+no SPF record, it is blank. Otherwise, it will start with C<v=spf1> and
+contain the SPF mechanisms and such that describe the domain.
+
Note that the strings returned by this method (and most of the other methods)
-are (at least partially) under the control of the sender's
-domain. This means that, if the sender is an attacker,
-the contents can be assumed to be hostile.
-The various methods that return these strings make sure
-that (by default) the strings returned contain only
-characters in the range 32 - 126. This behavior can
-be changed by setting C<sanitize> to 0 to turn off sanitization
-entirely. You can also set C<sanitize> to a function reference to
-perform custom sanitization.
-In particular, assume that the C<smtp_comment> might
-contain a newline character.
+are (at least partially) under the control of the sender's domain. This means
+that, if the sender is an attacker, the contents can be assumed to be hostile.
+The various methods that return these strings make sure that (by default) the
+strings returned contain only characters in the range 32 - 126. This behavior
+can be changed by setting C<sanitize> to 0 to turn off sanitization entirely.
+You can also set C<sanitize> to a function reference to perform custom
+sanitization. In particular, assume that C<smtp_comment> might contain a
+newline character.

-The C<detail> element is a hash of all the foregoing
-elements, plus extra data returned by the SPF result.
+C<detail> is a hash of all the foregoing result elements, plus extra data
+returned by the SPF result.

-Why the weird duplication? In the beginning, C<result()>
-returned only one value, the C<$result>. Then
-C<$smtp_comment> and C<$header_comment> came along. Then
-C<$spf_record>. Past a certain number of positional
-results, it makes more sense to have a hash. But we didn't
-want to break backwards compatibility, so we just declared
-that the fifth result would be a hash and future return
-value would go in there.
+I<Why the weird duplication?> In the beginning, C<result()> returned only one
+value, the C<$result>. Then C<$smtp_comment> and C<$header_comment> came
+along. Then C<$spf_record>. Past a certain number of positional results, it
+makes more sense to have a hash. But we didn't want to break backwards
+compatibility, so we just declared that the fifth result would be a hash and
+future return value would go in there.

The keys of the hash are:

- result
- smtp_comment
- header_comment
- header_pairs
- spf_record
- modifiers
+ result
+ smtp_comment
+ header_comment
+ header_pairs
+ spf_record
+ modifiers

-$query->result();
-
=cut

-
# ----------------------------------------------------------
# result
# ----------------------------------------------------------
@@ -470,58 +490,51 @@
return join " ", @pair_text;
}

-=item C<< $query->result2() >>
+=head2 C<< $query->result2() >>

- my ($result, $smtp_comment, $header_comment, $spf_record) = $query->result2('recipient@domain', 'recipient2@domain');
+ my ($result, $smtp_comment, $header_comment, $spf_record) = $query->result2('recipient@domain', 'recipient2@domain');

-C<result2> does everything that C<result> does, but it first
-checks to see if the sending system is a recognized MX
-secondary for the recipient(s). If so, then it returns C<pass>
-and does not perform the SPF query. Note that the sending
-system may be a MX secondary for some (but not all) of the
-recipients for a multi-recipient message, which is why
-result2 takes an argument list. See also C<message_result2()>.
+C<result2()> does everything that C<result()> does, but it first checks to see if
+the sending system is a recognized MX secondary for the recipient(s). If so,
+then it returns C<pass> and does not perform the SPF query. Note that the
+sending system may be a MX secondary for some (but not all) of the recipients
+for a multi-recipient message, which is why result2 takes an argument list.
+See also C<message_result2()>.

+B<This is a non-standard feature.> B<This feature is also deprecated, because
+exemption of trusted relays, such as secondary MXes, should really be performed
+by the software that uses this library before doing an SPF check.>
+
C<$result> will be one of C<pass>, C<fail>, C<neutral [...]>, or C<unknown>.
See C<result()> above for meanings.

-If you have MX secondaries and if you are unable to
-explicitly whitelist those secondaries before SPF tests
-occur, you can use this method in place of C<result()>, calling
-it as many times as there are recipients, or just providing
-all the recipients at one time.
+If you have secondary MXes and if you are unable to explicitly white-list them
+before SPF tests occur, you can use this method in place of C<result()>,
+calling it as many times as there are recipients, or just providing all the
+recipients at one time.

-The smtp_comment can be displayed to the SMTP client.
+C<smtp_comment> can be displayed to the SMTP client.

For example:

- my $query = new Mail::SPF::Query (ip => "127.0.0.1",
- sender=>'foo@example.com',
- helo=>"somehost.example.com");
+ my $query = new Mail::SPF::Query (ip => "127.0.0.1",
+ sender=>'foo@example.com',
+ helo=>"somehost.example.com");

- ...
+ ...

- my ($result, $smtp_comment, $header_comment);
+ my ($result, $smtp_comment, $header_comment);

- ($result, $smtp_comment, $header_comment) = $query->result2('recip1@example.com');
- # return suitable error code based on $result eq 'fail' or not
+ ($result, $smtp_comment, $header_comment) = $query->result2('recip1@example.com');
+ # return suitable error code based on $result eq 'fail' or not

- ($result, $smtp_comment, $header_comment) = $query->result2('recip2@example.org');
- # return suitable error code based on $result eq 'fail' or not
+ ($result, $smtp_comment, $header_comment) = $query->result2('recip2@example.org');
+ # return suitable error code based on $result eq 'fail' or not

- ($result, $smtp_comment, $header_comment) = $query->message_result2();
- # return suitable error if $result eq 'fail'
- # prefix message with "Received-SPF: $result ($header_comment)"
+ ($result, $smtp_comment, $header_comment) = $query->message_result2();
+ # return suitable error if $result eq 'fail'
+ # prefix message with "Received-SPF: $result ($header_comment)"

-This feature is relatively new to the module. You can get
-support on the mailing list spf-devel@listbox.com.
-
-The methods C<result2()> and C<message_result2()> use "2" because they
-work for secondary MXes. C<result2()> takes care to minimize the number of DNS operations
-so that there is little performance penalty from using it in place of C<result()>.
-In particular, if no arguments are supplied, then it just calls C<result()> and
-returns the method response.
-
=cut

# ----------------------------------------------------------
@@ -604,17 +617,17 @@
return undef;
}

-=item C<< $query->message_result2() >>
+=head2 C<< $query->message_result2() >>

- my ($result, $smtp_comment, $header_comment, $spf_record) = $query->message_result2();
+ my ($result, $smtp_comment, $header_comment, $spf_record) = $query->message_result2();

-C<message_result2()> returns an overall status for the message
-after zero or more calls to C<result2()>. It will always be the last
-status returned by C<result2()>, or the status returned by C<result()> if
-C<result2()> was never called.
+C<message_result2()> returns an overall status for the message after zero or
+more calls to C<result2()>. It will always be the last status returned by
+C<result2()>, or the status returned by C<result()> if C<result2()> was never
+called.

-C<$result> will be one of C<pass>, C<fail>, C<neutral [...]>, or C<error>.
-See C<result()> above for meanings.
+C<$result> will be one of C<pass>, C<fail>, C<neutral [...]>, or C<error>. See
+C<result()> above for meanings.

=cut

@@ -642,48 +655,45 @@
return $query->{result2}->[0];
}

-=item C<< $query->best_guess() >>
+=head2 C<< $query->best_guess() >>

- my ($result, $smtp_comment, $header_comment) = $query->best_guess();
+ my ($result, $smtp_comment, $header_comment) = $query->best_guess();

-When a domain does not publish SPF records, this library can
-produce an educated guess anyway.
+When a domain does not publish an SPF record, this library can produce an
+educated guess anyway.

-It pretends the domain defined A, MX, and PTR mechanisms,
-plus a few others. The default set of directives is
+It pretends the domain defined A, MX, and PTR mechanisms, plus a few others.
+The default set of directives is

- "a/24 mx/24 ptr"
+ a/24 mx/24 ptr

That default set will return either "pass" or "neutral".

-If you want to experiment with a different default, you can
-pass it as an argument: C<< $query->best_guess("a mx ptr") >>
+If you want to experiment with a different default, you can pass it as an
+argument: C<< $query->best_guess("a mx ptr") >>

-Note that this method is deprecated. You should set C<guess=E<gt>1>
-on the C<new> method instead.
+B<This is a non-standard feature.> B<This method is also deprecated.> You
+should set C<guess=E<gt>1> on the C<new()> method instead.

-=item C<< $query->trusted_forwarder() >>
+=head2 C<< $query->trusted_forwarder() >>

- my ($result, $smtp_comment, $header_comment) = $query->best_guess();
+ my ($result, $smtp_comment, $header_comment) = $query->best_guess();

-It is possible that the message is coming through a
-known-good relay like acm.org or pobox.com. During the
-transitional period, many legitimate services may appear to
-forge a sender address: for example, a news website may have
-a "send me this article in email" link.
+It is possible that the message is coming through a known-good relay like
+C<acm.org> or C<pobox.com>. During the transitional period, many legitimate
+services may appear to forge a sender address: for example, a news website may
+have a "send me this article in email" link.

-The trusted-forwarder.org domain is a whitelist of
-known-good hosts that either forward mail or perform
-legitimate envelope sender forgery.
+The C<trusted-forwarder.org> domain is a white-list of known-good hosts that
+either forward mail or perform benign envelope sender forgery:

- "include:spf.trusted-forwarder.org"
+ include:spf.trusted-forwarder.org

This will return either "pass" or "neutral".

-Note that this method is deprecated. You should set C<trusted=E<gt>1>
-on the C<new> method instead.
+B<This is a non-standard feature.> B<This method is also deprecated.> You
+should set C<trusted=E<gt>1> on the C<new()> method instead.

-
=cut

sub clone {
@@ -758,11 +768,10 @@

# ----------------------------------------------------------

-=item C<< $query->sanitize('string') >>
+=head2 C<< $query->sanitize('string') >>

-This applies the sanitization rules for the particular query
-object. These rules are controlled by the C<sanitize> parameter
-to the Mail::SPF::Query new method.
+This applies the sanitization rules for the particular query object. These
+rules are controlled by the C<sanitize> parameter to the c<new()> method.

=cut

@@ -779,17 +788,17 @@

# ----------------------------------------------------------

-=item C<< strict_sanitize('string') >>
+=head2 C<< strict_sanitize('string') >>

-This ensures that all the characters in the returned string are printable.
-All whitespace is converted into spaces, and all other non-printable
-characters are converted into question marks. This is probably
-over aggressive for many applications.
+This ensures that all the characters in the returned string are printable. All
+whitespace is converted into spaces, and all other non-printable characters are
+converted into question marks. This is probably over-aggressive for many
+applications.

-This function is used by default when the C<sanitize> option is passed to
-the new method of Mail::SPF::Query.
+This function is used by default when the C<sanitize> option is passed to the
+C<new()> method.

-Note that this function is not a class method.
+B<This function is not a class method.>

=cut

@@ -804,14 +813,13 @@

# ----------------------------------------------------------

-=item C<< $query->debuglog() >>
+=head2 C<< $query->debuglog() >>

-Subclasses may override this with their own debug logger.
-I recommend Log::Dispatch.
+Subclasses may override this with their own debug logger. C<Log::Dispatch> is
+recommended.

-Alternatively, pass the C<new()> constructor a
-C<debuglog => sub { ... }> callback, and we'll pass
-debugging lines to that.
+Alternatively, pass the C<new()> constructor a C<< debuglog => sub { ... } >>
+callback, and we'll pass debugging lines to that.

=cut

@@ -1776,19 +1784,14 @@

1;

-=item EXPORT
-
-None by default.
-
-=back
-
=head1 WARNINGS

-Mail::Query::SPF should only be used at the point where messages are received from the Internet.
-The underlying assumption is that the sender of the email is sending the message directly to you
-or one of your secondaries. If your MTA does not have an exhaustive list of secondaries, then
-the C<result2()> and C<message_result2()> methods should be used. These methods take care to
-permit mail from secondaries.
+Mail::Query::SPF should only be used at the point where messages are received
+from the Internet. The underlying assumption is that the sender of the e-mail
+is sending the message directly to you or one of your secondary MXes. If your
+MTA does not have an exhaustive list of secondary MXes, then the C<result2()>
+and C<message_result2()> methods can be used. These methods take care to permit
+mail from secondary MXes.

=head1 AUTHORS

@@ -1806,6 +1809,8 @@

Mail::SPF::Query: L<http://search.cpan.org/dist/Mail-SPF-Query>

+The latest release of the SPF specification: L<http://www.openspf.org/spf-classic-current.txt>
+
=cut

# vim:et sts=4 sw=4

Modified: trunk/README
===================================================================
--- trunk/README 2005-12-05 20:59:08 UTC (rev 116)
+++ trunk/README 2005-12-07 23:48:47 UTC (rev 117)
@@ -14,11 +14,11 @@
'print for Mail::SPF::Query->new( helo=>shift, ipv4=>shift, sender=>shift )->result' \
helohost.example.com 1.2.3.4 user@example.com

- none (sender domain example.com does not designate sender policy)
- neutral (client 1.2.3.4 is neither authorized nor denied by sender domain example.com)
pass (client 1.2.3.4 is an authorized mailer for sender domain example.com)
+ fail (client 1.2.3.4 is not an authorized mailer for sender domain example.com)
softfail (client 1.2.3.4 is not an authorized mailer for transitioning sender domain example.com)
- fail (client 1.2.3.4 is not an authorized mailer for sender domain example.com)
+ neutral (client 1.2.3.4 is neither authorized nor denied by sender domain example.com)
+ none (sender domain example.com does not designate sender policy)
error (temporary failure while resolving sender policy for sender domain example.com)
unknown (sender domain example.com has an invalid sender policy)


-------
To unsubscribe, change your address, or temporarily deactivate your subscription,
please go to http://v2.listbox.com/member/?listname=spf-devel@v2.listbox.com