3.20261105 2026-11-06 Australia/Melbourne

  ** Thanks to Giovanni <g.bechis@snb.it> for these changes:
  - RFC 7208 says there MUST be a limit of no more than 10 MX records
    looked up and checked; throw a permerror when the limit is exceeded
    instead of silently truncating the list
  - RFC 7208 says implementations SHOULD limit "void lookups" to two;
    enable the corresponding regression tests

  - Ensure every module's $VERSION is set by Dist::Zilla at release time,
    and manage the version number in README the same way

  - Security: escape untrusted text in the Received-SPF header to
    prevent header field injection:
    - escape parentheses and backslashes in the explanation comment,
      so text from a malformed SPF record or the sender identity can
      no longer close the comment early and inject forged fields such
      as client-ip=
    - escape control characters (e.g. CR/LF) in the envelope-from and
      helo fields
  - Fix macro expansion stopping at the first line break in a macro
    string, leaving later macros unexpanded
  - Security: authority_explanation now escapes control and non-ASCII
    characters in the explanation string (exp= TXT record) published in
    DNS, and document that the result text() may contain untrusted data
  - Remove the check for includes of the same domain through CNAME
    aliases. Including a domain and a CNAME alias of it is legal in
    RFC 7208, but the check tried to throw a hard fail for it. With
    a real resolver it read an unpopulated Net::DNS internal field and
    so in practice did nothing, but where it did take effect (e.g.
    with Net::DNS::Resolver::Programmable) it could wrongly fail
    authorized senders, and it used CNAME targets from DNS as
    unescaped regular expressions, which could make process() die.
    It also made an extra CNAME lookup per include that was not
    counted towards the RFC 7208 DNS lookup and void lookup limits.
    The test suite's resolver now follows CNAMEs, which is what the
    RFC 7208 cname-aliasing test case needed
  - Security: an exception thrown by the DNS resolver, including
    Net::DNS refusing to compose a query for an invalid domain name,
    made the SPF result none, i.e. no policy, rather than temperror.
    As invalid names can come from macros expanded with the sender's
    local part or HELO name, a sender could turn a domain's -all
    policy into none. Invalid domain names (empty label, label longer
    than 63 bytes, or name longer than 253 bytes, counted the way
    Net::DNS does, i.e. in bytes of UTF-8 and reading escapes such as
    "\.") are now treated as non-existent without querying the
    resolver, per RFC 7208, and other resolver exceptions result in
    temperror
  - Check the IP address version in the ip6 mechanism using the public
    NetAddr::IP API, rather than enumerating the request's address via
    an overloaded array dereference and reading an internal field,
    which died if the request's IP address was a large network
  - Allow Mail::SPF::Server->process() to evaluate a proposed SPF record
    passed in via a new 'record' option, instead of querying DNS for the
    authority domain's record, so a not-yet-published record can be tested
    against real DNS state

  - Prefer SPF1 over SPF2 (Sender ID, which is deprecated) when a record
    could be parsed as either

  - When a domain publishes both "v=spf1" and "spf2.0" records, always
    select the "v=spf1" record. Previously the record was chosen by the
    order of the records in the DNS answer, so the result could vary
    between queries, although the documentation and RFC 4406 said
    "spf2.0" records were preferred. Sender ID is historic (RFC 6686),
    so "v=spf1" is now deliberately preferred
  - Security: a "p" macro in an explanation string (exp= TXT record)
    made a PTR look-up and up to 10 A/AAAA look-ups for every
    occurrence, not limited by the RFC 7208 DNS look-up limits, so a
    sender could make a single SPF check send thousands of DNS
    queries. The "p" macro value is now looked up at most once per SPF
    check and authority domain. Also, exceeding the void look-up limit
    while expanding the explanation made authority_explanation() die;
    it now falls back to the default explanation
  - Reject a network (e.g. '10.0.0.0/8') as a request's ip_address
    with an EInvalidOptionValue exception. NetAddr::IP accepted it,
    which made no sense for SPF and changed the meaning of the
    mechanisms' address checks
  - Ignore an explanation string (exp= TXT record) that contains
    anything other than printable ASCII characters and spaces, as
    RFC 7208 requires, and use the default explanation instead.
    Control characters were already escaped, but an MTA using the
    explanation in an SMTP reply would still have sent the escaped
    text of a malicious explanation
  - Return none without querying DNS when the identity's domain is
    empty (e.g. "MAIL FROM:<a@>", which queried the root zone) or a
    single-label name (e.g. "HELO mailhost", which the resolver may
    expand with its search list and so query the receiver's internal
    domains), as RFC 7208 requires
  - Security: spfd now escapes control characters in the values of
    its response, so text from DNS or the client cannot add lines to
    the response, and in its debug output
  - Security: fix spfd's privilege dropping with --set-user and
    --set-group. An unknown user or group name was not reported (due to
    an operator precedence bug) and could leave spfd running as root,
    the invoking user's supplementary groups (e.g. root's) were kept,
    and --set-user without --set-group kept group ID 0. spfd now dies on
    unknown names, drops the supplementary groups when started as root,
    and changes to the user's primary group if no group is given
  - Security: limit spfd to 64 concurrent connections, 60 seconds per
    connection, and 32 request lines of at most 1024 bytes, so a local
    client can no longer exhaust the process table or memory with idle,
    slow or overlong requests. A request still being processed after 60
    seconds (e.g. because DNS servers are unreachable) gets a temperror
    result. spfd now also logs non-Mail::SPF errors
    for a request, and no longer runs the child's code in the listening
    process if fork() fails
  - Security: spfd now creates its UNIX socket accessible to its owner
    only until --socket-user, --socket-group and --socket-perms have
    been applied, so other users can't connect to it in the meantime.
    Fix --socket-group being ignored unless --socket-user was also
    given (a typo compared the socket path instead of the group), and
    die with a clear message if the listening socket can't be created
  - Security: spfquery now opens the --file argument in explicit read
    mode. A file name ending in "|" was run as a shell command, and one
    starting with ">" truncated the file

3.20260331 2026-04-01 Australia/Melbourne
  ** Thanks to Giovanni <g.bechis@snb.it> for this change: 
  - Do not check for multiple CNAMEs if the included domain is a macro

3.20250505 2025-05-05 Australia/Sydney

  ** Thanks to Giovanni <g.bechis@snb.it> for these changes: 
  - avoid a 'Attempt to reload Mail/SPF/Mech.pm aborted.' error
  - remove empty record structure in order to stringify it correctly
  
  ** Thanks to Keith <kealanta@fastmailteam.com> for these changes, based on Debian patches: 
  - Redirecting all references to openspf.org to open-spf.org
  - fix pod test errors

3.20240923 2024-09-23 Australia/Melbourne

  - Fix issue where certain DNS results would cause an exception to be thrown

3.20240827 2024-08-27 Australia/Melbourne

  ** Thanks to Giovanni <g.bechis@snb.it> for the changes in this release.

  - Do not try to parse an IPv4 address unnecessarily

  - Import RFC7208 Tests

  - referencing the same TXT record through multiple CNAME aliases is not permitted
    by RFC7208

  - Make it clear that BlackMagic module is not available

  - Fix checks for IPv4-mapped IPv6 connections

  - Cache DNS results

  - Misc dzil/build/ci improvements

  - SPF explanation text is restricted to 7-bit ascii

3.20240617 2024-06-17 Australia/Melbourne
 
  - Update INSTALL file for Dist::Zilla changes
    Thanks to Giovanni <g.bechis@snb.it>
 
  - Fix memory leak in Mail::SPF::Server when cacheing a Mail::SPF::MacroString
    Thanks to Giovanni <g.bechis@snb.it> and Felipe Gasper
 
  - When mfrom is empty, create a synthetic mfrom (postmaster@helo) and check
    that identity using the mfrom scope as specified in RFC7208
    Thanks to Giovanni <g.bechis@snb.it>
 
  - Fix missing declare in Mail::SPF::Server
    Thanks to Giovanni <g.bechis@snb.it>
 
  - require Mail::SPF::Mech when needed
    Thanks to Giovanni <g.bechis@snb.it>
 
  - correctly handle empty labels
    Thanks to Giovanni <g.bechis@snb.it>
 
  - use "try" instead of "eval"
    Thanks to Giovanni <g.bechis@snb.it>
 
  - error out if the lookup fails
    Thanks to Giovanni <g.bechis@snb.it>

3.20240206 2024-02-06 UTC

  - Remove signature file from distribution

3.20240205 2024-02-05 UTC

  - Fix pod in Mail::SPF::Util (RT#93241)
    Thanks to rwfranks@acm.org and GBECHIS@cpan.org

  - Fixes char_str_list is not a valid sub in new Net::DNS (RT#149825)
    Reworked from patch supplied with thanks by GBECHIS@cpan.org

  - BREAKING CHANGE: spfd is now installed in /bin instead of /sbin
    As a result Mail::SPF now respects an install prefix and may be
    more easily installed in a non root and/or local lib environment.

--- 2.009 (2013-07-21 03:30)

  Mail::SPF:
  * Default to querying only TXT type RRs (query_rr_types = Mail::SPF::Server->
    query_rr_type_txt).  Experience has shown that querying SPF type RRs is
    impractical.

--- 2.008 (2012-01-30 08:15)

  Mail::SPF:
  * Sanitize result local_explanation (as well as result object string
    representation) by replacing all non-printable or non-ascii characters
    with their hex-escaped representation (e.g., "\x00").
    (Addresses: bugs.launchpad.net #806926)

  Miscellaneous:
  * Change openspf.org URLs to openspf.net because openspf.org is unreachable
    indefinitely.
  * Change <http://www.ietf.org/rfc/….txt> URLs
    to <http://tools.ietf.org/html/…>.
  * META.yml: configure_requires: Module::Build 0.2805
  * META.yml: requires: Net::DNS 0.62 (was: 0.52) (Closes: rt.cpan.org #28545)
  * META.yml: Revert to flat version numbers for perl and Net::DNS::Resolver::
    Programmable build requirements to avoid Module::Build::Compat/Makefile.PL
    incompatibilities. (Closes: rt.cpan.org #53231)
  * Attempt to prevent a cascading failure in t/00.03-class-result.t that seems
    to happen under rare, unknown circumstances. (Closes: rt.cpan.org #39099)

  Debian:
  * Declare Debian source package format as 3.0.
  * Standards-Version: 3.9.2 (was: 3.8.3)
  * Bump debhelper compatibility level to 7 (was: 5) and simplify debian/rules
    using debhelper 7 features.
  * debian/control: Simplify depdendencies under the assumption that package
    will be installed on Debian Lenny (oldstable at the time of writing) or
    later (or the Ubuntu equivalent).
  * debian/watch: Use dist-based URL.

--- 2.007 (2009-10-31 21:00)

  Mail::SPF:
  * Macro expansion:
    * Distinguish between split and join delimiters; they are not necessarily
      the same.
    * Support multiple split delimiters rather than at most one.

  Miscellaneous:
  * We ship and pass the 2009.10 release of the official RFC 4408 test suite.
  * Give advice in INSTALL on how to install without root privileges.

  Debian:
  * Standards-Version: 3.8.3 (was: 3.8.0)
  * Build-Depends-Indep: perl-modules (>= 5.10.0) | libmodule-build-perl (>= 0.26)
    (was: libmodule-build-perl (>= 0.26))

--- 2.006 (2008-08-17 22:00)

  Mail::SPF:
  + Added result object factory facility to Mail::SPF::Server in order to
    support the sub-classing of Mail::SPF::Server and Mail::SPF::Result.
    See README for details.
    Any code throwing Mail::SPF::Result(::*) objects directly should stop doing
    so and use Mail::SPF::Server::throw_result() instead.
  + Added a "query_rr_types" option to Mail::SPF::Server's constructor as a
    way to disable the retrieval of either "SPF" or "TXT" type RRs.
    I wouldn't make use of it if I was you!
  ! Changed the "max_void_dns_lookups" option's default value from undef (i.e.,
    no limit) to a limit of 2.  This should not cause any problems in practice,
    however see the "max_void_dns_lookups" option's description for specifics
    on what this entails.
  * Match <toplabel> patterns greedily by reversing the order of the <toplabel>
    regexp alternatives from RFC 4408.  Thus TLDs with dashes (e.g.,
    ".xn--wgv71a") are now correctly matched.
  * In macro strings, expand '%-' to '%20' rather than '-'.
    Thanks to Frank Ellermann for providing a test case for the RFC 4408 test
    suite that inadvertently exposed this bug.
  > Mail::SPF::Result:
    + Added new received_spf_header_name() constant specifying the "Received-
      SPF" header field name, which may (and usually should) be overridden by
      custom result sub-classes; see the documentation.
    * Generate "identity=mailfrom" rather than "identity=mfrom" in
      "Received-SPF" header field.
    * name() now returns a symbolic result name instead of the trailing part of
      the result class name.  This should have no impact on 3rd-party code.
    * Added new isa_by_name() method as an equivalent to the built-in isa(),
      taking a result name instead of a class name.  Provides a superset of the
      is_code() method's functionality.
  * Substituted ";"s for "&" parameter separators in the openspf.org "Why?"
    page URL in the default authority explanation string.  This change is
    purely cosmetic.
  * Minor documentation fixes and improvements.

  Miscellaneous:
  * We ship and pass the 2008.08 release of the official RFC 4408 test suite.
  * While officially declaring a build-requirement of Module::Build >= 0.2805
    (which, if not satisfied, Module::Build itself will warn about, but not
    abort), do not strictly require it.  If the META.yml file generated during
    package building is irrelevant, e.g., if we are being built by a package
    management/build system such as Debian's, then 0.26 is sufficient.
  * Recommend NetAddr::IP >= 4.007, as it has all $& and $` removed for better
    performance;
    see <http://issues.apache.org/SpamAssassin/show_bug.cgi?id=5312>.

--- 2.005 (2007-05-30 23:00)

  Mail::SPF:
  + Added a "max_void_dns_lookups" option to Mail::SPF::Server's constructor,
    allowing the number of potentially abusive lookups induced by DoS attacks
    to be limited.  See the documentation of the Mail::SPF::Server class.
  + Added a "precedence" class property to Mail::SPF::GlobalMod and sub-classes
    that defines the order in which global modifiers are to be processed
    (0: first, 1: last).  See Mail::SPF::Mod.
    Mail::SPF::Mod::Exp has precedence 0.2, Mail::SPF::Mod::Redirect has 0.8.
    Also, Mail::SPF::Record::global_mods() now returns modifiers ordered by
    precedence.
  + Added support for a non-standard %{_scope} pseudo macro that expands to the
    request's identity scope.  Note: Do NOT use any such non-standard macros in
    explanation strings published in DNS!
  ! Mail::SPF::Util::valid_domain_for_ip_address() now requires a Mail::SPF::
    Request object to be passed as a new second argument.  This is actually
    consistent with many of Mail::SPF's methods.  Please excuse the late API
    change (but who uses Mail::SPF::Util directly anyway?).
  * Updated default authority explanation string to include identity scope in
    the openspf.org "Why?" page URL in order to avoid misleading result
    explanations.
  * Truncate labels resulting from macro expansions to 63 bytes.  This is not
    strictly required by RFC 4408, 8.1/27, but is merely meant as a precaution.
  * Minor documentation fixes and improvements.

  Miscellaneous:
  * We ship and pass the 2007.05 release of the official RFC 4408 test suite
    (no changes were required).
  ! Build-require Module::Build >= 0.2805 (was: >= 0.26), hopefully fixing a
    version.pm/CPAN.pm compatibility issue (closes: rt.cpan.org #26784).
    (Debian packaging is not affected because it does not rely on META.yml.)

  Debian:
  * Conflicts: spfquery (<< 1.2.5.dfsg-1) (was unversioned)

--- 2.004 (2007-01-20 02:00)

  Mail::SPF:
  * Correctly fall back to default authority explanation if the authority
    domain does specify an explanation string but it cannot be expanded (e.g.
    due to syntax errors).
  * In Mail::SPF::Result::received_spf_header(), gracefully fall back to a
    hostname of "unknown" if a fully qualified hostname can not be determined.
    Some (misconfigured) systems simply will not reveal one.
  * Minor documentation improvements and fixes.

  Miscellaneous:
  * Note in the README file that we pass the 2006.11 release of the official
    RFC 4408 test-suite.

  Tests:
  * Do not test Mail::SPF::Util::hostname(), as some (misconfigured) systems
    simply will not reveal a fully qualified hostname (see CPANTS tests for
    2.003).
  * Minor code clean-up.

--- 2.003 (2007-01-10 00:00)

  Mail::SPF:
  * Fixed two Perl 5.6 incompatibilities:
    * Added `use utf8` statements in several modules to keep Perl 5.6 from
      whining about /[\p{}]/.
    * Do not use the `use constant { a=>1, b=>2 }` multiple-constants idiom,
      as it was introduced only in constant 1.03 (Perl 5.7.2).
  * Fixed a very minor bug where a "TempError" result would incorrectly be
    returned in the very rare case when the SPF-type look-up succeeded but
    returned 0 records, and the following TXT-type look-up errored or timed
    out.  Now a "None" result is correctly returned in that case as demanded
    by RFC 4408.

  spfquery:
  * Minor documentation fixes.

--- 2.002 (2006-12-14 00:00)

  Mail::SPF:
  * Updated default authority explanation string to the SPF website's new
    "Why?" page URL parameters scheme:
    <http://www.openspf.org/Why?id=%{S}&ip=%{I}&receiver=%{R}>

  spfquery:
  * Updated the '--help' text and man-page with regard to the black magic
    options (which require the yet unreleased Mail::SPF::BlackMagic module).

--- 2.001 (gold release) (2006-12-09 20:00)

  Gold Release!

  Major overhaul:
  ! Major code refactoring, achieving full RFC 4408/4406 compliance, and
    breaking API compatibility with 2.000.
  ! Switched from ExtUtils::MakeMaker to Module::Build.
  + Added complete rewrites of spfquery (2.500) and spfd (2.000).
  + Added complete documentation.
  + Added unit tests and the RFC 4408 test-suite.
  + Added Debian package control files.
  + And more... (closes: rt.cpan.org #20821, #20822, #21922, #21925)

--- 2.000 (initial release) (2005-06-23 00:00)

# $Id: CHANGES 61 2013-07-22 03:45:15Z julian $
# vim:syn= tw=79 sts=2 sw=2
