# Revision 1.108.2.150  2015/08/05 13:49:45  customdesigned
# Forgot tabnanny
#
# Revision 1.108.2.149  2015/08/05 13:07:09  customdesigned
# Release 2.0.12
#
# Revision 1.108.2.148  2015/08/05 04:49:48  customdesigned
# Reset void_lookups at top of check()
#
# Revision 1.108.2.147  2015/08/05 03:36:59  customdesigned
# Ignore permerror for best_guess
#
# Revision 1.108.2.146  2015/06/05 15:58:18  customdesigned
# Don't crash on null TXT record.
#
# Revision 1.108.2.145  2015/01/14 20:27:42  customdesigned
# Fix list feature
#
# Revision 1.108.2.144  2015/01/13 04:40:07  customdesigned
# Trailing spaces *are* allowed by 4.5/2
#
# Revision 1.108.2.143  2015/01/12 22:51:56  customdesigned
# Trailing space is PermError, but strip for extended result in lax mode.
#
# Revision 1.108.2.142  2015/01/06 14:13:50  customdesigned
# Make CNAME loop result in unknown host.
#
# Revision 1.108.2.141  2015/01/02 01:08:18  customdesigned
# Test case and fix for mixed case CNAME loop.
#
# Revision 1.108.2.140  2015/01/02 00:26:08  customdesigned
# Make CNAME loop check case insensitive.
#
# Revision 1.108.2.139  2014/12/19 00:16:12  kitterma
# Missed a spot bumping to 2.0.12.
#
# Revision 1.108.2.138  2014/12/19 00:15:12  kitterma
# Bump versions, etc. to start 2.0.12 development.
#
# Revision 1.108.2.137  2014/12/13 15:39:27  customdesigned
# Require ipaddress/ipaddr backport with Bytes for python2.
#
# Revision 1.108.2.136  2014/12/05 16:20:07  customdesigned
# Release 2.0.11
#
# Revision 1.108.2.135  2014/12/03 01:11:09  customdesigned
# Fold case of domain for all cache entries.
#
# Revision 1.108.2.134  2014/12/03 01:01:24  customdesigned
# PTR case change fix with test case
#
# Revision 1.108.2.133  2014/10/06 11:54:11  kitterma
# *** empty log message ***
#
# Revision 1.108.2.132  2014/10/06 11:51:03  kitterma
#   * Downcase IPv6 PTR results since case inconsistency can cause PTR match
#     failures (patch thanks to Joni Fieggen)
#
# Revision 1.108.2.131  2014/09/22 17:20:33  customdesigned
# Update comments
#
# Revision 1.108.2.130  2014/09/22 17:13:53  customdesigned
# Cleaner fix for multiple spaces.
#
# Revision 1.108.2.129  2014/09/21 21:11:47  kitterma
#  * Reset to start 2.0.11 development
#  * Fixed bug where multiple spaces between terms causes pyspf to think they
#    were unknown mechanisms
#
# Revision 1.108.2.128  2014/09/02 17:31:53  customdesigned
#
# Release 2.0.10
#
# Revision 1.108.2.127  2014/09/01 21:17:13  kitterma
# Fix TempError handling of errors from the DNS module.
#
# Revision 1.108.2.126  2014/08/02 18:35:50  customdesigned
# '~' is also an unreserved char in rfc7208.
#
# Revision 1.108.2.125  2014/08/02 04:36:48  kitterma
#   * Fix bug in SPF record parsing that caused all 'whitespace' characters to
#     be considered valid term separators and not just spaces
#
# Revision 1.108.2.124  2014/08/02 04:32:36  kitterma
# Archive previous commit messages for spf.py in pyspf_changelog.txt and bumpi
# version to 2.0.10 for start of follow on work.
#
# Revision 1.108.2.123  2014/07/30 18:41:18  customdesigned
# Fix flagging AAAA records in dns_a.  Add --strict option to CLI
#
# Revision 1.108.2.122  2014/04/29 22:56:48  customdesigned
# Release 2.0.9
#
# Revision 1.108.2.121  2014/04/28 21:57:08  customdesigned
# Ignore void lookups for explanation and type 99 lookup.
#
# Revision 1.108.2.120  2014/04/24 23:02:15  kitterma
# Remove redundant check of self.void_lookups.
#
# Revision 1.108.2.119  2014/04/22 23:03:42  kitterma
# Update CHANGELOG to prepare for release.
#
# Revision 1.108.2.118  2014/04/22 22:03:13  kitterma
# Add processing for new void lookups processing limit.
#
# Revision 1.108.2.117  2014/04/22 20:54:42  kitterma
# Adjust documentation of lookup limits to include RFC 7208
# Add constants and variables for new void lookup limit
#
# Revision 1.108.2.116  2014/04/22 17:10:54  kitterma
# Default SPF process timeout limit to 20 seconds per RFC 7208 4.6.4.
#
# Revision 1.108.2.115  2014/04/22 17:02:55  kitterma
# Change default DNS timeout to 20 seconds in DNSLookup to better match RFC
# 7208 4.6.4.
#
# Revision 1.108.2.114  2014/04/22 04:56:38  kitterma
# Add permerror to permitted mx-limit results for rfc4408 to fudge changes for
# RFC 7208.
#
# Revision 1.108.2.113  2014/04/22 04:46:58  kitterma
# Make mx > 10 a permerror per RFC 7208 and mx-limit test.
#
# Revision 1.108.2.112  2014/01/20 22:16:38  customdesigned
# Rename local var hiding str.
#
# Revision 1.108.2.111  2014/01/20 22:03:08  customdesigned
# Test case and fix for more thorough macro syntax error detection.
#
# Revision 1.108.2.110  2013/07/25 21:21:49  kitterma
# Archive previous commit messages for spf.py in pyspf_changelog.txt and bump version to 2.0.9 for start of follow on work.
#
# Revision 1.108.2.109  2013/07/25 01:51:24  customdesigned
# Forgot to convert to bytes in py3dns-3.0.2 workaround.
#
# Revision 1.108.2.108  2013/07/25 01:29:07  customdesigned
# The Final and Ultimate Solution to the String Problem for TXT records.
#
# Revision 1.108.2.107  2013/07/23 18:37:17  customdesigned
# Removed decode from dns_txt again, as it breaks python3, both with py3dns and test framework.
# Need to identify exact situation in which it is needed to put it back.
#
# Revision 1.108.2.106  2013/07/23 06:32:58  kitterma
# Post fix cleanup.
#
# Revision 1.108.2.105  2013/07/23 06:30:13  kitterma
# Fix compatibility with py3dns versions that return type bytes.
#
# Revision 1.108.2.104  2013/07/23 06:20:18  kitterma
# Consolidate code related to UnicodeDecodeError and UnicodeEncodeError into UnicodeError.
#
# Revision 1.108.2.103  2013/07/23 06:07:24  customdesigned
# Test case and fix for allowing non-ascii in non-spf TXT records.
#
# Revision 1.108.2.102  2013/07/23 05:22:54  customdesigned
# Check for non-ascii on explanation.
#
# Revision 1.108.2.101  2013/07/23 04:51:59  customdesigned
# Functional alias for __email__
#
# Revision 1.108.2.100  2013/07/23 04:07:38  customdesigned
# Sort unofficial keywords for consistent ordering.
#
# Revision 1.108.2.99  2013/07/23 02:40:54  customdesigned
# Update __email__ and __author__
#
# Revision 1.108.2.98  2013/07/23 02:35:33  customdesigned
# Release 2.0.8
#
# Revision 1.108.2.97  2013/07/23 02:04:59  customdesigned
# Release 2.0.8
#
# Revision 1.108.2.96  2013/07/22 22:59:58  kitterma
# Give another header test it's own variable names.
#
# Revision 1.108.2.95  2013/07/22 19:29:22  kitterma
# Fix dns_txt to work if DNS data is not pure bytes for python3 compatibility.
#
# Revision 1.108.2.94  2013/07/22 02:44:39  kitterma
# Add tests for cirdmatch.
#
# Revision 1.108.2.93  2013/07/21 23:56:51  kitterma
# Fix cidrmatch to work with both ipaddr and the python3.3 ipadrress versions of the module.
#
# Revision 1.108.2.91  2013/07/03 23:38:39  customdesigned
# Removed two more unused functions.
#
# Revision 1.108.2.90  2013/07/03 22:58:26  customdesigned
# Clean up use of ipaddress module.  make %{i} upper case to match test suite
# (test suite is incorrect requiring uppercase, but one thing at a time).
# Remove no longer used inet_pton substitute.  But what if someone was using it?
#
# Revision 1.108.2.89  2013/05/26 03:32:19  kitterma
# Syntax fix to maintain python2.6 compatibility.
#
# Revision 1.108.2.88  2013/05/26 00:30:12  kitterma
# Bump versions to 2.0.8 and add CHANGELOG entries.
#
# Revision 1.108.2.87  2013/05/26 00:23:52  kitterma
# Move old (pre-2.0.7) spf.py commit messages to pyspf_changelog.txt.
#
# Revision 1.108.2.86  2013/05/25 22:39:19  kitterma
# Use ipaddr/ipaddress instead of custome code.
#
# Revision 1.108.2.85  2013/05/25 00:06:03  kitterma
# Fix return type detection for bytes/string for python3 compatibility in dns_txt.
#
# Revision 1.108.2.84  2013/04/20 20:49:13  customdesigned
# Some dual-cidr doc tests
#
# Revision 1.108.2.83  2013/03/25 22:51:37  customdesigned
# Replace dns_99 method with dns_txt(type='SPF')
# Fix null CNAME in cache bug.
#
# Revision 1.108.2.82  2013/03/14 21:13:06  customdesigned
# Fix Non-ascii exception description.
#
# Revision 1.108.2.81  2013/03/14 21:03:25  customdesigned
# Fix dns_txt and dns_spf - should hopefully still be correct for python3.
#
# Revision 1.108.2.80  2012/06/14 20:09:56  kitterma
# Use the correct exception type to capture unicode in SPF records.
#
# Revision 1.108.2.79  2012/03/10 00:19:44  kitterma
# Add fixes for py3dns DNS return as type bytes - not complete.
#
# Revision 1.108.2.77  2012/02/09 22:13:42  kitterma
# Fix stray character in last commit.
# Start fixing python3 bytes issue - Now works, but fails the non-ASCII exp test.
#
# Revision 1.108.2.76  2012/02/05 05:50:39  kitterma
# Fix a few stray print -> print() changes for python3 compatbility.
#
# Revision 1.108.2.75  2012/02/03 01:44:58  customdesigned
# Fix CNAME duplicating DNS records.
# Fix handling non-ascii chars in TXT/SPF records.
#
# Revision 1.108.2.74  2012/01/19 06:40:24  kitterma
#   * Accounts for new py3dns error classes coming in py3dns 3.0.2 (but fully
#     backward compatible with earlier versions)
#
# Revision 1.108.2.73  2012/01/19 06:22:35  kitterma
#  * Accept TXT and SPF type records back from py(3)dns and deal with them regardless of type (string or bytes.
#  * Update README
#
# Revision 1.108.2.72  2012/01/16 15:37:47  kitterma
# Do away with default querytime, make it fully optional and by default completely backwards compatible.
#
# Revision 1.108.2.71  2012/01/16 06:19:31  kitterma
#  * Refactor timeout changes to improve backward comaptibility (see CHANGELOG).
#
# Revision 1.108.2.70  2012/01/13 04:21:19  kitterma
#   * Change timeouts to be global for all DNS lookups instead of per DNS lookup
#     to match processing limits recommendation in RFC 4408 10.1
#     - Default is 20 seconds for the global timer instead of 30 seconds per DNS
#       lookup
#     - This can be adjusted by changing spf.MAX_GLOBAL_TIME
#
# Revision 1.108.2.69  2012/01/10 06:13:18  kitterma
#   * Finish Python3 port - works with python2.6/2.7/3.2 and 2to3 is no longer
#     required.
#
# Revision 1.108.2.68  2012/01/10 05:56:16  kitterma
# Update copyright years and fix date.
#
# Revision 1.108.2.67  2012/01/10 04:42:03  kitterma
#   * Rework query.parse_header:
#     - Make query.parse_header automatically select Received-DPF or
#       Authentication Results header types and use them to collect SPF
#       results from trusted relays
#     - Add query.parse_header_spf and query.parse_header_ar functions for
#       header type specific processing
#   * Add 'Programming Language :: Python3' to setup.py
#   * Bump release dates
#
# Revision 1.108.2.66  2012/01/10 00:17:09  kitterma
# Fix authentication results support to provide similar comments as Received-SPF.
#   
# Revision 1.108.2.65  2011/11/08 07:38:37  kitterma
# Extend query.get_header to return either Received-SPF (still default) or
#     Authentication Results headers
#
# Revision 1.108.2.64  2011/11/08 05:11:56  kitterma
# Add tests for query.get_header.
#
# Revision 1.108.2.63  2011/11/08 04:36:33  kitterma
# Update CHANGELOG, setup.py, spf.py, and move old commit messages to
# pyspf_changelog.txt to start on new version (2.0.7).
#
# Revision 1.108.2.62  2011/11/05 19:07:53  customdesigned
# New website openspf.org -> openspf.net
#
# Revision 1.108.2.61  2011/10/27 16:29:38  customdesigned
# Move python version test to def time.
#
# Revision 1.108.2.60  2011/10/27 16:28:18  kitterma
# Use bytes in to_ascii to work in python and python3.
#
# Revision 1.108.2.59  2011/10/27 14:50:05  customdesigned
# Ensure entire SPF policy is ascii.
#
# Revision 1.108.2.58  2011/10/27 14:29:49  customdesigned
# Catch non-ascii domains.
#
# Revision 1.108.2.57  2011/10/27 10:32:06  kitterma
# Drop version from spf.py shebang.
#
# Revision 1.108.2.56  2011/10/27 04:58:03  kitterma
# Update CHANGELOG, adjust minimum version requirement in setup.py, and update dates for a release.
#
# Revision 1.108.2.55  2011/10/27 03:49:11  kitterma
# Fix doctests to raise ... as ... and print(x) as 2to3 doesn't fix these.
# Doctests all pass in 2.6, 2.7, and 3.2
#
# Revision 1.108.2.53  2011/10/18 02:56:32  kitterma
# Resolve local conflicts in spf.py changelog.
#
# Revision 1.108.2.52  2011/10/04 23:08:18  customdesigned
# verbose option
#
# Revision 1.108.2.51  2011/03/06 03:54:01  kitterma
# Update copyright years.
#
# Revision 1.108.2.50  2011/03/06 03:14:54  kitterma
# Wrangle types around so addr2bin tests pass with python2.4/2.6/3.2(with 2to3).
#
# Revision 1.108.2.49  2011/03/05 23:10:55  kitterma
# Fix one missed instance of reverting to the older doctest with error type.
#
# Revision 1.108.2.48  2011/03/05 18:00:46  kitterma
# Fix typo.
#
# Revision 1.108.2.47  2011/03/05 18:00:15  kitterma
# Try to import both email.message and email.Message for backward compatibility.
#
# Revision 1.108.2.46  2011/03/05 17:37:57  kitterma
# Revert to older doctest construct for python2.4/2.5 compatibility and set minimum version to 2.4.
#
# Revision 1.108.2.45  2011/03/03 04:14:31  kitterma
#  * Refactor spf.py to support python3 via 2to3 - Minimum Python version is now python2.6.
#  * Update README and CHANGELOG
#
# Revision 1.108.2.44  2011/02/11 18:25:31  kitterma
# Move older spf.py commit messages to pyspf_changelog.txt and update version numbers.
#
# Revision 1.108.2.43  2011/02/11 18:17:47  kitterma
# Ensure an error is raise for all DNS rcodes other than 0 and 3 per RFC 4408.
#
# Revision 1.108.2.42  2011/02/11 18:14:22  kitterma
# Make TCP fallback an AmbiguityWarning in strict mode rather than an
# error in harsh mode so we can retry and validate the TCP based record.
#
# Revision 1.108.2.41  2010/08/19 01:18:08  customdesigned
# Return extra keyword dict from parse_header, parse identity.
#
# Revision 1.108.2.40  2010/04/29 20:23:44  customdesigned
# Return result from parse_header
#
# Revision 1.108.2.39  2010/04/29 18:53:38  customdesigned
# Parse Received-SPF header
#
# Revision 1.108.2.38  2010/04/29 16:36:47  customdesigned
# report CIDR error only for valid mechanism
#
# Revision 1.108.2.37  2008/11/11 18:43:42  customdesigned
# Make doc tests run on 2.5.  Heuristic for missing IP4.
#
# Revision 1.108.2.36  2008/09/10 00:46:45  customdesigned
# Test case for handling invalid SPF on command line.
#
# Revision 1.108.2.35  2008/09/10 00:35:03  customdesigned
# Handle invalid SPF record on command line.
#
# Revision 1.108.2.34  2008/08/25 17:58:07  customdesigned
# Add timeout to check2.
#
# Revision 1.108.2.33  2008/04/23 21:00:42  customdesigned
# Quote nulls in Received-SPF.
#
# Revision 1.108.2.32  2008/04/23 20:03:53  customdesigned
# Add timeout keyword to query constructor and DNSLookup.
#
# Revision 1.108.2.31  2008/03/27 01:15:33  customdesigned
# Improve valid DNS name check.
#
# Revision 1.108.2.30  2008/03/27 00:58:15  customdesigned
# Check dns names before DNSLookup
#
# Revision 1.108.2.29  2008/03/26 15:08:20  kitterma
# Fix commit log typo.
#
# Revision 1.108.2.28  2008/03/26 14:45:37  kitterma
# Update built in tests for Python2.5 (addr2bin will now fail slightly with older
# Python versions). SF #1655736
#
# Revision 1.108.2.27  2008/03/26 14:34:35  kitterma
# Change shebangs to #!/usr/bin/python throughout.
#
# Revision 1.108.2.26  2008/03/26 14:31:04  kitterma
# Patch from Debian to avoid crash if command line SPF record request returns
# TempError or PermError.
#
# Revision 1.108.2.25  2008/03/26 14:26:19  kitterma
# Update for new version (working on 2.0.5) and year.
#
# Revision 1.108.2.24  2008/03/24 21:33:22  customdesigned
# Patch from Scott Kitterman to retry truncated results with TCP unless
# in harsh mode.
#
# Revision 1.108.2.23  2007/11/28 19:48:37  customdesigned
# Reflect decision on empty-exp errata.
#
# Revision 1.108.2.22  2007/06/23 20:17:09  customdesigned
# Don't try to include null (None) keyword values.
#
# Revision 1.108.2.21  2007/03/29 19:38:03  customdesigned
# Remove trailing ';' again, fix Received-SPF tests.
#
# Revision 1.108.2.20  2007/03/27 20:54:22  customdesigned
# Correct Received-SPF header format.
#
# Revision 1.108.2.19  2007/03/17 19:07:01  customdesigned
# For default modifier, return ambiguous in harsh mode, ignore in strict mode,
# follow in lax mode.
#
# Revision 1.108.2.18  2007/03/17 18:25:38  customdesigned
# Default modifier is obsolete.  Retab (expandtab) spf.py
#
# Revision 1.108.2.17  2007/03/13 20:13:16  customdesigned
# Missing parentheses.
#
# Revision 1.108.2.16  2007/01/25 20:50:13  kitterma
# Update versions to reflect working on 2.0.4 now.
#
# Revision 1.108.2.15  2007/01/19 23:23:50  customdesigned
# Fix validated_ptrs and best_guess
#
# Revision 1.108.2.14  2007/01/17 01:01:00  customdesigned
# Merge latest test suite fixes.
#
#
# Revision 1.108.2.13  2007/01/15 19:14:27  customdesigned
# Permerror for more than one exp= or redirect=
#
# Revision 1.132  2007/01/17 00:47:17  customdesigned
# Test for and fix illegal implicit mechanisms.
#
# Revision 1.131  2007/01/16 23:54:58  customdesigned
# Test and fix for invalid domain-spec.
#
# Revision 1.130  2007/01/15 02:21:10  customdesigned
# Forget op= on redirect.
#
# Revision 1.108.2.12  2007/01/13 18:45:33  customdesigned
# Record matching mechanism.
#
# Revision 1.108.2.11  2007/01/13 18:21:41  customdesigned
# Test for RFC4408 6.2/4, and fix spf.py to comply.
#
# Revision 1.123  2007/01/11 18:49:37  customdesigned
# Add mechanism to Received-SPF header.
#
# Revision 1.122  2007/01/11 18:25:54  customdesigned
# Record matching mechanism.
#
# Revision 1.108.2.10  2007/01/13 00:46:35  kitterma
# Update copyright statements for new year.
#
# Revision 1.108.2.9  2007/01/12 22:14:56  kitterma
# Change DNS queries to only check Type SPF in Harsh mode
#
# Revision 1.108.2.8  2007/01/06 22:58:21  kitterma
# Update changelogs and version to reflect 2.0.2 released and 2.0.3 started.
#
# Revision 1.108.2.7  2007/01/06 21:03:15  customdesigned
# Tested spf.py in python2.2.
#
# Version 2.0.2 released.
#
# Revision 1.108.2.6  2006/12/30 17:12:50  customdesigned
# Merge fixes from CVS HEAD.
#
# Revision 1.108.2.5  2006/12/24 19:10:38  kitterma
# Move spf.py changelog to CHANGELOG. Move spf.py cvs commits from previous
# releases to py_spfchangelog.txt. Update README to describe provided scripts.
# Add to README discussion of spf module interface.
#
# Revision 1.108.2.4  2006/12/23 06:35:37  customdesigned
# Fully quote structured values in Received-SPF.
#
# Revision 1.108.2.3  2006/12/23 04:44:05  customdesigned
# Fix key-value quoting in get_header.
#
# Revision 1.121  2006/12/30 17:01:52  customdesigned
# Missed a spot for new result names.
#
# Revision 1.120  2006/12/28 04:54:21  customdesigned
# Skip optional trailing ";" in Received-SPF
#
# Revision 1.118  2006/12/28 04:04:27  customdesigned
# Optimize get_header to remove useless key-value pairs.
#
# Revision 1.117  2006/12/23 06:31:16  customdesigned
# Fully quote values in key-value pairs.
#
# Revision 1.108.2.2  2006/12/22 20:27:24  customdesigned
# Index error reporting non-mech permerror.
#
# Revision 1.108.2.1  2006/12/22 04:59:40  customdesigned
# Merge comma heuristic.

# Revision 1.108  2006/11/08 01:27:00  customdesigned
# Return all key-value-pairs in Received-SPF header for all results.
#
# Revision 1.107  2006/11/04 21:58:12  customdesigned
# Prevent cache poisoning by bogus additional RRs in PTR DNS response.
#
# Revision 1.106  2006/10/16 20:48:24  customdesigned
# More DOS limit tests.
#
# Revision 1.105  2006/10/07 22:06:28  kitterma
# Pass strict status to DNSLookup - will be needed for TCP failover.
#
# Revision 1.104  2006/10/07 21:59:37  customdesigned
# long/empty label tests and fix.
#
# Revision 1.103  2006/10/07 18:16:20  customdesigned
# Add tests for and fix RE_TOPLAB.
#
# Revision 1.102  2006/10/05 13:57:15  customdesigned
# Remove isSPF and make missing space after version tag a warning.
#
# Revision 1.101  2006/10/05 13:39:11  customdesigned
# SPF version tag is case insensitive.
#
# Revision 1.100  2006/10/04 02:14:04  customdesigned
# Remove incomplete saving of result.  Was messing up bmsmilter.  Would
# be useful if done consistently - and disabled when passing spf= to check().
#
# Revision 1.99  2006/10/03 21:00:26  customdesigned
# Correct fat fingered merge error.
#
# Revision 1.98  2006/10/03 17:35:45  customdesigned
# Provide python inet_ntop and inet_pton when not socket.has_ipv6
#
# Revision 1.97  2006/10/02 17:10:13  customdesigned
# Test and fix for uppercase macros.
#
# Revision 1.96  2006/10/01 01:27:54  customdesigned
# Switch to pymilter lax processing convention:
# Always return strict result, extended result in q.perm_error.ext
#
# Revision 1.95  2006/09/30 22:53:44  customdesigned
# Fix getp to obey SHOULDs in RFC.
#
# Revision 1.94  2006/09/30 22:23:25  customdesigned
# p macro tests and fixes
#
# Revision 1.93  2006/09/30 20:57:06  customdesigned
# Remove generator expression for compatibility with python2.3.
#
# Revision 1.92  2006/09/30 19:52:52  customdesigned
# Removed redundant flag and unneeded global.
#
# Revision 1.91  2006/09/30 19:37:49  customdesigned
# Missing L
#
# Revision 1.90  2006/09/30 19:29:58  customdesigned
# pydns returns AAAA RR as binary string
#
# Revision 1.89  2006/09/29 20:23:11  customdesigned
# Optimize cidrmatch
#
# Revision 1.88  2006/09/29 19:44:10  customdesigned
# Fix ptr with ip6 for harsh mode.
#
# Revision 1.87  2006/09/29 19:26:53  customdesigned
# Add PTR tests and fix ip6 ptr
#
# Revision 1.86  2006/09/29 17:55:22  customdesigned
# Pass ip6 tests
#
# Revision 1.85  2006/09/29 15:58:02  customdesigned
# Pass self test on non IP6 python.
# PTR accepts no cidr.
#
# Revision 1.83  2006/09/27 18:09:40  kitterma
# Converted spf.check to return pre-MARID result codes for drop in
# compatibility with pySPF 1.6/1.7.  Added new procedure, spf.check2 to
# return RFC4408 results in a two part answer (result, explanation).
# This is the external API for pySPF 2.0.  No longer any need to branch
# for 'classic' and RFC compliant pySPF libraries.
#
# Revision 1.82  2006/09/27 18:02:21  kitterma
# Converted max MX limit to ambiguity warning for validator.
#
# Revision 1.81  2006/09/27 17:38:14  kitterma
# Updated initial comments and moved pre-1.7 changes to spf_changelog.
#
# Revision 1.80  2006/09/27 17:33:53  kitterma
# Fixed indentation error in check0.
#
# Revision 1.79  2006/09/26 18:05:44  kitterma
# Removed unused receiver policy definitions.
#
# Revision 1.78  2006/09/26 16:15:50  kitterma
# added additional IP4 and CIDR validation tests - no code changes.
#
# Revision 1.77  2006/09/25 19:42:32  customdesigned
# Fix unknown macro sentinel
#
# Revision 1.76  2006/09/25 19:10:40  customdesigned
# Fix exp= error and add another failing test.
#
# Revision 1.75  2006/09/25 02:02:30  kitterma
# Fixed redirect-cancels-exp test suite failure.
#
# Revision 1.74  2006/09/24 04:04:08  kitterma
# Implemented check for macro 'c' - Macro unimplimented.
#
# Revision 1.73  2006/09/24 02:08:35  kitterma
# Fixed invalid-macro-char test failure.
#
# Revision 1.72  2006/09/23 05:45:52  kitterma
# Fixed domain-name-truncation test failure
#
# Revision 1.71  2006/09/22 01:02:54  kitterma
# pySPF correction for nolocalpart in rfc4408-tests.yml failed, 4.3/2.
# Added comments to testspf.py on where to get YAML.
#
# Revision 1.70  2006/09/18 02:13:27  kitterma
# Worked through a large number of pylint issues - all 4 spaces, not a mix
# of 4 spaces, 2 spaces, and tabs. Caught a few minor errors in the process.
# All built in tests still pass.
#
# Revision 1.69  2006/09/17 18:44:25  kitterma
# Fixed validation mode only crash bug when rDNS check had no PTR record
#
# Revision 1.68  2006/09/01 23:56:43  customdesigned
# Fix improved RE_IP6
#
# Revision 1.67  2006/09/01 23:27:56  customdesigned
# Improved RE_IP6
#
# Revision 1.66  2006/09/01 22:16:41  customdesigned
# Parse IP6 for RFC conformance.
#
# Revision 1.65  2006/08/31 18:00:18  customdesigned
# Fix dual-cidr-length parsing.
#
# Revision 1.64  2006/08/30 17:54:23  customdesigned
# Fix dual-cidr.
#
# Revision 1.63  2006/07/28 01:53:03  customdesigned
# Localhost shouldn't get automatic pass
#
# Revision 1.62  2006/07/27 03:56:45  customdesigned
# Removed redundant trailing dot check.
#
# Revision 1.61  2006/07/26 21:40:19  customdesigned
# YAML test format.  Accept trailing dot on domains.
#
# Revision 1.60  2006/06/28 04:25:38  customdesigned
# Catch unexpected IO errors from pydns.
#
# Revision 1.59  2006/05/19 13:18:23  kitterma
# Fix to disallow ':' except between the mechanism and domain-spec.
#
# Revision 1.58  2006/05/19 02:04:58  kitterma
# Corrected validation bug where 'all' mechanism was not correctly checked,
# updated for RFC 4408 Auth 48 changes - trailing dot now allowed in domain
# name and Type TXT and Type SPF DNS records not identical raises a warning
# instead of a permanent error, and changed internet draft references to refer
# to RFC 4408.
#
# Revision 1.57  2006/05/12 16:38:12  customdesigned
# a:1.2.3.4 -> ip4:1.2.3.4 heuristic.
#
# Revision 1.56  2005/12/29 19:14:11  customdesigned
# Handle NULL MX and other A lookups of DNS root.
#
# Revision 1.55  2005/10/30 00:41:48  customdesigned
# Ignore SPF records missing space after version as required by RFC.
# FIXME: in "relaxed" mode, give permerror when there is exactly one
# such malformed record.
#
# Revision 1.54  2005/08/23 21:50:10  customdesigned
# Missing separator line in insert_libspf_local_policy self test.
#
# Revision 1.53  2005/08/23 20:37:19  customdesigned
# Simplify libspf_local further.  FIXME for possible specification error.
#
# Revision 1.52  2005/08/23 20:23:31  customdesigned
# Clean up libspf_local and add inline test cases.
# Repair try..finally in check1() broken when Ambiguity warning added.
#
# Revision 1.51  2005/08/19 19:06:49  customdesigned
# use note_error method for consistent extended processing.
# Return extended result, strict result in self.perm_error
#
# Revision 1.50  2005/08/19 18:13:31  customdesigned
# Still want to do strict tests in even stricter modes.
#
# Revision 1.49  2005/08/12 18:54:34  kitterma
# Consistently treat strict as a numeric for hard processing.
#
# Revision 1.48  2005/08/11 14:30:44  kitterma
# Restore all numeric TLD test from 1.44 that was inadvertently deleted.  Ugh.
#
# Revision 1.47  2005/08/10 13:31:34  kitterma
# Completed first part of local policy implementation.  Local policy will now be
# added before the last non-fail mechanism as in Libspf2 and Mail::SPF::Query.
# Still ToDo for local policy is: don't do local policy until after redirect=,
# modify explanation to indicate result is based on local policy, and an option
# for RFE [ 1224459 ] local policy API to execute local policy before public
# policy.  Will do the RFE after basic compatibility with the reference
# implementations.  Restored Unix line endings.  Changed Harsh mode check for
# ambiguity to exclude exists: mechanisms.
#
# Revision 1.46  2005/08/08 15:03:28  kitterma
# Added PermError for redirect= to a domain without an SPF record.
#
# Revision 1.45  2005/08/08 03:04:44  kitterma
# Added PermError for multiple SPF records per para 4.5 of schlitt-02
#
# Revision 1.44  2005/08/06 06:31:21  kitterma
# Added RFC 3696 test for all numeric TLD, new PermError.
#
# Revision 1.43  2005/08/02 12:57:02  kitterma
# Removed extraneous debugging print statement.
#
# Revision 1.42  2005/07/28 21:03:24  kitterma
# Added ambiguity check for no A records returned for a mechanism when harsh.
#
# Revision 1.41  2005/07/28 18:26:14  kitterma
# Added AmbiguityWarning error class for harsh processing (validator).
# Added ambiguous result tests for more than 10 MX or PTR returned.
# Added AmbiguityWarning for mx mechanisms that return no MX records.
# Created new result called ambiguous for use with harsh processing.
#
# Revision 1.40  2005/07/28 04:25:45  kitterma
# Clean up modifier RE to match current ABNF.  Added test example for this.
# Fixed missing space in one test/example.
#
# Revision 1.39  2005/07/28 03:56:13  kitterma
# Restore three part API (res, code, txt).
# Add dictionary to support local policy checks in future updates.
# Add record for trusted-forwarder.org - support future TFWL checks.
#
# Revision 1.38  2005/07/26 14:11:12  kitterma
# Added check to PermError if SPF record has no spaces
#
# Revision 1.37  2005/07/26 06:12:19  customdesigned
# Use ABNF derived RE for IP4.  IP6 RE is way ugly...
#
# Revision 1.36  2005/07/26 05:59:38  customdesigned
# Validate ip4 address format.
#
# Revision 1.35  2005/07/26 05:23:24  customdesigned
# Fix stupid typo in RE_CIDR
#
# Revision 1.34  2005/07/23 17:58:02  customdesigned
# Put new result codes in unit tests.
#
# Revision 1.33  2005/07/22 18:23:28  kitterma
# *** Breaks external API.  Only returns SPF result now.  Up to the calling
# module to determine the MTA result codes from that.  Also, internally support
# the newer PermError/TempError convention.
#
# Revision 1.32  2005/07/22 17:45:20  kitterma
# Converted TempError to look like PermError processing
#
# Revision 1.31  2005/07/22 02:11:50  customdesigned
# Use dictionary to check for CNAME loops.  Check limit independently for
# each top level name, just like for PTR.
#
# Revision 1.30  2005/07/21 20:07:31  customdesigned
# Translate DNS error in DNSLookup.  This completely isolates DNS
# dependencies to the DNSLookup method.
#
# Revision 1.29  2005/07/21 17:49:39  customdesigned
# My best guess at what RFC intended for limiting CNAME loops.
#
# Revision 1.28  2005/07/21 17:37:08  customdesigned
# Break out external DNSLookup method so that test suite can
# duplicate CNAME loop bug.  Test zone data dictionary now
# mirrors structure of real DNS.
#
# Revision 1.27  2005/07/21 15:26:06  customdesigned
# First cut at updating docs.  Test suite is obsolete.
#
# Revision 1.26  2005/07/20 03:12:40  customdesigned
# When not in strict mode, don't give PermErr for bad mechanism until
# encountered during evaluation.
#
# Revision 1.25  2005/07/19 23:24:42  customdesigned
# Validate all mechanisms before evaluating.
#
# Revision 1.24  2005/07/19 18:11:52  kitterma
# Fix to change that compares type TXT and type SPF records.  Bug in the change
# prevented records from being returned if it was published as TXT, but not SPF.
#
# Revision 1.23  2005/07/19 15:22:50  customdesigned
# MX and PTR limits are MUST NOT check limits, and do not result in PermErr.
# Also, check belongs in mx and ptr specific methods, not in dns() method.
#
# Revision 1.22  2005/07/19 05:02:29  customdesigned
# FQDN test was broken.  Added test case.  Move FQDN test to after
# macro expansion.
#
# Revision 1.21  2005/07/18 20:46:27  kitterma
# Fixed reference problem in 1.20
#
# Revision 1.20  2005/07/18 20:21:47  kitterma
# Change to dns_spf to go ahead and check for a type 99 (SPF) record even if a
# TXT record is found and make sure if type SPF is present that they are
# identical when using strict processing.
#
# Revision 1.19  2005/07/18 19:36:00  kitterma
# Change to require at least one dot in a domain name.  Added PermError
# description to indicate FQDN should be used.  This is a common error.
#
# Revision 1.18  2005/07/18 17:13:37  kitterma
# Change macro processing to raise PermError on an unknown macro.
# schlitt-spf-classic-02 para 8.1.  Change exp modifier processing to ignore
# exp strings with syntax errors.  schlitt-spf-classic-02 para 6.2.
#
# Revision 1.17  2005/07/18 14:35:34  customdesigned
# Remove debugging printf
#
# Revision 1.16  2005/07/18 14:34:14  customdesigned
# Forgot to remove debugging print
#
# Revision 1.15  2005/07/15 21:17:36  customdesigned
# Recursion limit raises AssertionError in strict mode, PermError otherwise.
#
# Revision 1.14  2005/07/15 20:34:11  customdesigned
# Check whether DNS package already supports SPF before patching
#
# Revision 1.13  2005/07/15 20:01:22  customdesigned
# Allow extended results for MX limit
#
# Revision 1.12  2005/07/15 19:12:09  customdesigned
# Official IANA SPF record (type 99) support.
#
# Revision 1.11  2005/07/15 18:03:02  customdesigned
# Fix unknown Received-SPF header broken by result changes
#
# Revision 1.10  2005/07/15 16:17:05  customdesigned
# Start type99 support.
# Make Scott's "/" support in parse_mechanism more elegant as requested.
# Add test case for "/" support.
#
# Revision 1.9  2005/07/15 03:33:14  kitterma
# Fix for bug 1238403 - Crash if non-CIDR / present.  Also added
# validation check for valid IPv4 CIDR range.
#
# Revision 1.8  2005/07/14 04:18:01  customdesigned
# Bring explanations and Received-SPF header into line with
# the unknown=PermErr and error=TempErr convention.
# Hope my case-sensitive mech fix doesn't clash with Scotts.
#
# Revision 1.7  2005/07/12 21:43:56  kitterma
# Added processing to clarify some cases of unknown
# qualifier errors (to distinguish between unknown qualifier and
# unknown mechanism).
# Also cleaned up comments from previous updates.
#
# Revision 1.6  2005/06/29 14:46:26  customdesigned
# Distinguish trivial recursion from missing arg for diagnostic purposes.
#
# Revision 1.5  2005/06/28 17:48:56  customdesigned
# Support extended processing results when a PermError should strictly occur.
#
# Revision 1.4  2005/06/22 15:54:54  customdesigned
# Correct spelling.
#
# Revision 1.3  2005/06/22 00:08:24  kitterma
# Changes from draft-mengwong overall DNS lookup and recursion
# depth limits to draft-schlitt-spf-classic-02 DNS lookup, MX lookup, and
# PTR lookup limits.  Recursion code is still present and functioning, but
# it should be impossible to trip it.
#
# Revision 1.2  2005/06/21 16:46:09  kitterma
# Updated definition of SPF, added reference to the sourceforge project site,
# and deleted obsolete Microsoft Caller ID for Email XML translation routine.
#
# Revision 1.1.1.1  2005/06/20 19:57:32  customdesigned
# Move Python SPF to its own module.
#
# Revision 1.5  2005/06/14 20:31:26  customdesigned
# fix pychecker nits
#
# Revision 1.4  2005/06/02 04:18:55  customdesigned
# Update copyright notices after reading article on /.
#
# Revision 1.3  2005/06/02 02:08:12  customdesigned
# Reject on PermErr
#
# Revision 1.2  2005/05/31 18:57:59  customdesigned
# Clear unknown mechanism list at proper time.
#
# Revision 1.24  2005/03/16 21:58:39  stuart
# Change Milter module to package.
#
# Revision 1.22  2005/02/09 17:52:59  stuart
# Report DNS errors as PermError rather than unknown.
#
# Revision 1.21  2004/11/20 16:37:03  stuart
# Handle multi-segment TXT records.
#
# Revision 1.20  2004/11/19 06:10:30  stuart
# Use PermError exception instead of reporting unknown.
#
# Revision 1.19  2004/11/09 23:00:18  stuart
# Limit recursion and DNS lookups separately.
#
#
# Revision 1.17  2004/09/10 18:08:26  stuart
# Return unknown for null mechanism
#
# Revision 1.16  2004/09/04 23:27:06  stuart
# More mechanism aliases.
#
# Revision 1.15  2004/08/30 21:19:05  stuart
# Return unknown for invalid ip syntax in mechanism
#
# Revision 1.14  2004/08/23 02:28:24  stuart
# Remove Perl usage message.
#
# Revision 1.13  2004/07/23 19:23:12  stuart
# Always fail to match on ip6, until we support it properly.
#
# Revision 1.12  2004/07/23 18:48:15  stuart
# Fold CID parsing into spf
#
# Revision 1.11  2004/07/21 21:32:01  stuart
# Handle CID records (Microsoft XML format).
#
# Revision 1.10  2004/04/19 22:12:11  stuart
# Release 0.6.9
#
# Revision 1.9  2004/04/18 03:29:35  stuart
# Pass most tests except -local and -rcpt-to
#
# Revision 1.8  2004/04/17 22:17:55  stuart
# Header comment method.
#
# Revision 1.7  2004/04/17 18:22:48  stuart
# Support default explanation.
#
# Revision 1.6  2004/04/06 20:18:02  stuart
# Fix bug in include
#
# Revision 1.5  2004/04/05 22:29:46  stuart
# SPF best_guess
#
# Revision 1.4  2004/03/25 03:27:34  stuart
# Support delegation of SPF records.
#
# Revision 1.3  2004/03/13 12:23:23  stuart
# Expanded result codes.  Tolerate common method misspellings.
#
# Development taken over by Stuart Gathman <stuart@bmsi.com> 
#
#   18-dec-2003, v1.6, Failures on Intel hardware: endianness.  Use ! on
#                      struct.pack(), struct.unpack().
#   17-dec-2003, v1.5, ttw use socket.inet_aton() instead of DNS.addr2bin, so
#                      n, n.n, and n.n.n forms for IPv4 addresses work, and to
#                      ditch the annoying Python 2.4 FutureWarning
#   13-dec-2003, v1.3, ttw added %{o} original domain macro,
#                      print spf result on command line, support default=,
#                      support localhost, follow DNS CNAMEs, cache DNS results
#                      during query, support Python 2.2 for Mac OS X
#   16-dec-2003, v1.4, ttw fixed include handling (include is a mechanism,
#                      complete with status results, so -include: should work.
#                      Expand macros AFTER looking for status characters ?-+
#                      so altavista.com SPF records work.
#   11-dec-2003, v1.2, ttw added macro expansion, exp=, and redirect=
#    9-dec-2003, v1.1, Meng Weng Wong added PTR code, THANK YOU




