- Update to version 5.7.8
* Move SVG validation errors from ["bimi"]["warnings"] to ["bimi"]["image"]["validation_errors"] (#150) - Update to version 5.7.7 * Fix VMC validation errors not appearing. - Update to version 5.7.6 * Fix crash when trying to output to CSV format - Update to version 5.7.5 * Fix BIMI lookup for subdomains that do not have a BIMI record. - Update to version 5.7.4 * Add additional checks for tiny-ps SVG requirements - Update to version 5.7.3 * BIMI images and mark certificates + Better error handling + Simplified warning messages + sha256_hash output fields renamed to sha256 - Update to version 5.7.2 * Account for float SVG sizes - Update to version 5.7.1 * Properly parse a certificate SAN * Certificate warnings fire properly * Make the expires timestamp more readable - Update to version 5.7.0 * checkdmarc will now validate Verified Mark Certificates (VMCs) and Common Mark Certificates (CMC), snd will verify that SHA256 hash of the logo embedded in the certificate matches the SHA256 hash logo at the URL at the BIMI l tag. Additionally, SVG and certificate metadata is now included in the checkdmarc.bimi.parse_bimi_record() API and JSON CLI output. OBS-URL: https://build.opensuse.org/package/show/devel:languages:python/python-checkdmarc?expand=0&rev=9
This commit is contained in:
parent
2aa4f41f73
commit
ab93a451fd
@ -1,3 +0,0 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:d775f566f8fdd584adb9a26e792cfe1565cdf6bd50c54fe7b6d8443ce6db68cf
|
||||
size 36103
|
3
checkdmarc-5.7.8.tar.gz
Normal file
3
checkdmarc-5.7.8.tar.gz
Normal file
@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:1affa797ec976165932787ac8b46a291d5a5328e7412bf306011a1e60f6e873e
|
||||
size 58464
|
@ -1,3 +1,62 @@
|
||||
-------------------------------------------------------------------
|
||||
Sun Nov 10 10:27:03 UTC 2024 - Martin Hauke <mardnh@gmx.de>
|
||||
|
||||
- Update to version 5.7.8
|
||||
* Move SVG validation errors from ["bimi"]["warnings"] to
|
||||
["bimi"]["image"]["validation_errors"] (#150)
|
||||
- Update to version 5.7.7
|
||||
* Fix VMC validation errors not appearing.
|
||||
- Update to version 5.7.6
|
||||
* Fix crash when trying to output to CSV format
|
||||
- Update to version 5.7.5
|
||||
* Fix BIMI lookup for subdomains that do not have a BIMI record.
|
||||
- Update to version 5.7.4
|
||||
* Add additional checks for tiny-ps SVG requirements
|
||||
- Update to version 5.7.3
|
||||
* BIMI images and mark certificates
|
||||
+ Better error handling
|
||||
+ Simplified warning messages
|
||||
+ sha256_hash output fields renamed to sha256
|
||||
- Update to version 5.7.2
|
||||
* Account for float SVG sizes
|
||||
- Update to version 5.7.1
|
||||
* Properly parse a certificate SAN
|
||||
* Certificate warnings fire properly
|
||||
* Make the expires timestamp more readable
|
||||
- Update to version 5.7.0
|
||||
* checkdmarc will now validate Verified Mark Certificates (VMCs)
|
||||
and Common Mark Certificates (CMC), snd will verify that
|
||||
SHA256 hash of the logo embedded in the certificate matches
|
||||
the SHA256 hash logo at the URL at the BIMI l tag.
|
||||
Additionally, SVG and certificate metadata is now included in
|
||||
the checkdmarc.bimi.parse_bimi_record() API and JSON CLI
|
||||
output.
|
||||
- Update to version 5.6.2
|
||||
* Add a warning when BIMI records do not provide a mark
|
||||
certificate.
|
||||
* Use the correct dependency (xmltodict, not xml2dict).
|
||||
- Update to version 5.6.1
|
||||
* Fix SVG base profile detection
|
||||
- Update to version 5.6.0
|
||||
* Automatically check for a BIMI DNS record at the default
|
||||
selector when using the CLI
|
||||
* Fix parsing of BIMI record tags when they are separated by
|
||||
a ";" without a space.
|
||||
* Validate the file at the URL in the BIMI l tag value
|
||||
+ Must be an SVG file
|
||||
+ The SVG version must be 1.2
|
||||
+ The SVG base profile must be tiny-ps
|
||||
+ The SVG dimensions must be square
|
||||
+ The file size must not exceed 32 KB
|
||||
- Update to version 5.5.1
|
||||
* SPF record validation fixes (PR #147)
|
||||
+ Accept mechanisms with domains that start with all.
|
||||
+ Ignore multiple trailing mechanisms and random text with
|
||||
spaces.
|
||||
- Rebase skip-network-tests.patch
|
||||
- Remove tests.py
|
||||
* included in the now used source tarball from github
|
||||
|
||||
-------------------------------------------------------------------
|
||||
Thu Oct 10 15:49:23 UTC 2024 - Dirk Müller <dmueller@suse.com>
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
# spec file for package python-checkdmarc
|
||||
#
|
||||
# Copyright (c) 2024 SUSE LLC
|
||||
# Copyright (c) 2021, Martin Hauke <mardnh@gmx.de>
|
||||
# Copyright (c) 2021-2024, Martin Hauke <mardnh@gmx.de>
|
||||
#
|
||||
# All modifications and additions to the file contributed by third parties
|
||||
# remain the property of their copyright owners, unless otherwise agreed
|
||||
@ -18,13 +18,12 @@
|
||||
|
||||
|
||||
Name: python-checkdmarc
|
||||
Version: 5.5.0
|
||||
Version: 5.7.8
|
||||
Release: 0
|
||||
Summary: A Python module and command line parser for SPF and DMARC records
|
||||
License: Apache-2.0
|
||||
URL: https://domainaware.github.io/checkdmarc
|
||||
Source: https://files.pythonhosted.org/packages/source/c/checkdmarc/checkdmarc-%{version}.tar.gz
|
||||
Source1: https://raw.githubusercontent.com/domainaware/checkdmarc/master/tests.py
|
||||
Source: https://github.com/domainaware/checkdmarc/archive/refs/tags/%{version}.tar.gz#/checkdmarc-%{version}.tar.gz
|
||||
Patch0: skip-network-tests.patch
|
||||
BuildRequires: %{python_module hatchling}
|
||||
BuildRequires: %{python_module pip}
|
||||
@ -34,20 +33,26 @@ BuildRequires: python-rpm-macros
|
||||
Requires: python-cryptography
|
||||
Requires: python-dnspython >= 2.0.0
|
||||
Requires: python-expiringdict >= 1.1.4
|
||||
Requires: python-pem >= 23.1.0
|
||||
Requires: python-publicsuffixlist
|
||||
Requires: python-pyOpenSSL >= 24.2.1
|
||||
Requires: python-pyleri >= 1.3.2
|
||||
Requires: python-requests >= 2.25.0
|
||||
Requires: python-timeout-decorator >= 0.4.1
|
||||
Requires: python-xmltodict
|
||||
Requires(post): update-alternatives
|
||||
Requires(postun): update-alternatives
|
||||
BuildArch: noarch
|
||||
# SECTION test requirements
|
||||
BuildRequires: %{python_module dnspython >= 2.0.0}
|
||||
BuildRequires: %{python_module expiringdict >= 1.1.4}
|
||||
BuildRequires: %{python_module pem >= 23.1.0}
|
||||
BuildRequires: %{python_module publicsuffixlist}
|
||||
BuildRequires: %{python_module pyOpenSSL >= 24.2.1}
|
||||
BuildRequires: %{python_module pyleri >= 1.3.2}
|
||||
BuildRequires: %{python_module requests >= 2.25.0}
|
||||
BuildRequires: %{python_module timeout-decorator >= 0.4.1}
|
||||
BuildRequires: %{python_module xmltodict}
|
||||
# /SECTION
|
||||
%python_subpackages
|
||||
|
||||
@ -56,8 +61,7 @@ A Python module and command line parser for SPF and DMARC records.
|
||||
|
||||
%prep
|
||||
%setup -q -n checkdmarc-%{version}
|
||||
cp %{SOURCE1} .
|
||||
%patch -P 0 -p0
|
||||
%autopatch -p1
|
||||
|
||||
%build
|
||||
%pyproject_wheel
|
||||
@ -81,6 +85,6 @@ cp %{SOURCE1} .
|
||||
%doc README.md
|
||||
%python_alternative %{_bindir}/checkdmarc
|
||||
%{python_sitelib}/checkdmarc
|
||||
%{python_sitelib}/checkdmarc-%{version}.dist-info
|
||||
%{python_sitelib}/checkdmarc-*.dist-info
|
||||
|
||||
%changelog
|
||||
|
@ -1,5 +1,7 @@
|
||||
--- tests.py~ 2024-02-29 12:22:56.007309853 +1100
|
||||
+++ tests.py 2024-02-29 12:25:49.618057933 +1100
|
||||
diff --git a/tests.py b/tests.py
|
||||
index 8e58708..65605d4 100755
|
||||
--- a/tests.py
|
||||
+++ b/tests.py
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
"""Automated tests"""
|
||||
@ -8,7 +10,7 @@
|
||||
import unittest
|
||||
from collections import OrderedDict
|
||||
|
||||
@@ -94,6 +95,7 @@
|
||||
@@ -99,6 +100,7 @@ class Test(unittest.TestCase):
|
||||
|
||||
self.assertEqual(len(results["warnings"]), 0)
|
||||
|
||||
@ -16,43 +18,51 @@
|
||||
def testSplitSPFRecord(self):
|
||||
"""Split SPF records are parsed properly"""
|
||||
|
||||
@@ -129,6 +131,7 @@
|
||||
self.assertRaises(checkdmarc.spf.SPFRecordNotFound,
|
||||
checkdmarc.spf.parse_spf_record, spf_record, domain)
|
||||
@@ -140,6 +142,7 @@ class Test(unittest.TestCase):
|
||||
domain,
|
||||
)
|
||||
|
||||
+ @unittest.skipUnless(os.path.exists("/etc/resolv.conf"), "no network")
|
||||
def testTooManySPFDNSLookups(self):
|
||||
"""SPF records with > 10 SPF mechanisms that cause DNS lookups raise
|
||||
SPFTooManyDNSLookups"""
|
||||
@@ -144,6 +147,7 @@
|
||||
self.assertRaises(checkdmarc.spf.SPFTooManyDNSLookups,
|
||||
checkdmarc.spf.parse_spf_record, spf_record, domain)
|
||||
@@ -161,6 +164,7 @@ class Test(unittest.TestCase):
|
||||
domain,
|
||||
)
|
||||
|
||||
+ @unittest.skipUnless(os.path.exists("/etc/resolv.conf"), "no network")
|
||||
def testTooManySPFVoidDNSLookups(self):
|
||||
"""SPF records with > 2 void DNS lookups"""
|
||||
|
||||
@@ -216,6 +220,7 @@
|
||||
self.assertRaises(checkdmarc.spf.SPFIncludeLoop,
|
||||
checkdmarc.spf.parse_spf_record, spf_record, domain)
|
||||
@@ -274,6 +278,7 @@ class Test(unittest.TestCase):
|
||||
domain,
|
||||
)
|
||||
|
||||
+ @unittest.skipUnless(os.path.exists("/etc/resolv.conf"), "no network")
|
||||
def testSPFMissingMXRecord(self):
|
||||
"""A warning is issued if an SPF record contains a mx mechanism
|
||||
pointing to a domain that has no MX records"""
|
||||
@@ -226,6 +231,7 @@
|
||||
self.assertIn("{0} does not have any MX records".format(domain),
|
||||
results["warnings"])
|
||||
@@ -285,6 +290,7 @@ class Test(unittest.TestCase):
|
||||
"{0} does not have any MX records".format(domain), results["warnings"]
|
||||
)
|
||||
|
||||
+ @unittest.skipUnless(os.path.exists("/etc/resolv.conf"), "no network")
|
||||
def testSPFMissingARecord(self):
|
||||
"""A warning is issued if an SPF record contains a mx mechanism
|
||||
pointing to a domain that has no A records"""
|
||||
@@ -236,6 +242,7 @@
|
||||
self.assertIn("cardinalhealth.net does not have any A/AAAA records",
|
||||
results["warnings"])
|
||||
@@ -296,6 +302,7 @@ class Test(unittest.TestCase):
|
||||
"cardinalhealth.net does not have any A/AAAA records", results["warnings"]
|
||||
)
|
||||
|
||||
+ @unittest.skipUnless(os.path.exists("/etc/resolv.conf"), "no network")
|
||||
def testDMARCPctLessThan100Warning(self):
|
||||
"""A warning is issued if the DMARC pvt value is less than 100"""
|
||||
|
||||
@@ -347,6 +354,7 @@ class Test(unittest.TestCase):
|
||||
domain,
|
||||
)
|
||||
|
||||
+ @unittest.skipUnless(os.path.exists("/etc/resolv.conf"), "no network")
|
||||
def testBIMI(self):
|
||||
"""Test BIMI checks"""
|
||||
domain = "chase.com"
|
||||
|
279
tests.py
279
tests.py
@ -1,279 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""Automated tests"""
|
||||
|
||||
import unittest
|
||||
from collections import OrderedDict
|
||||
|
||||
import checkdmarc
|
||||
import checkdmarc.utils
|
||||
import checkdmarc.spf
|
||||
import checkdmarc.dmarc
|
||||
import checkdmarc.dnssec
|
||||
|
||||
known_good_domains = [
|
||||
"fbi.gov",
|
||||
"pm.me"
|
||||
]
|
||||
|
||||
|
||||
class Test(unittest.TestCase):
|
||||
@unittest.skip
|
||||
def testKnownGood(self):
|
||||
"""Domains with known good STARTTLS support, SPF and DMARC records"""
|
||||
|
||||
results = checkdmarc.check_domains(known_good_domains)
|
||||
for result in results:
|
||||
spf_error = None
|
||||
dmarc_error = None
|
||||
for mx in result["mx"]["hosts"]:
|
||||
self.assertEqual(
|
||||
mx["starttls"], True,
|
||||
"Host of known good domain {0} failed STARTTLS check: {1}"
|
||||
"\n\n{0}".format(result["domain"], mx["hostname"])
|
||||
)
|
||||
if "error" in result["spf"]:
|
||||
spf_error = result["spf"]["error"]
|
||||
if "error" in result["dmarc"]:
|
||||
dmarc_error = result["dmarc"]["error"]
|
||||
self.assertEqual(result["spf"]["valid"], True,
|
||||
"Known good domain {0} failed SPF check:"
|
||||
"\n\n{1}".format(result["domain"], spf_error))
|
||||
self.assertEqual(result["dmarc"]["valid"], True,
|
||||
"Known good domain {0} failed DMARC check:"
|
||||
"\n\n{1}".format(result["domain"], dmarc_error))
|
||||
|
||||
def testDMARCMixedFormatting(self):
|
||||
"""DMARC records with extra spaces and mixed case are still valid"""
|
||||
examples = [
|
||||
"v=DMARC1;p=ReJect",
|
||||
"v = DMARC1;p=reject;",
|
||||
"v = DMARC1\t;\tp=reject\t;",
|
||||
"v = DMARC1\t;\tp\t\t\t=\t\t\treject\t;",
|
||||
"V=DMARC1;p=reject;"
|
||||
]
|
||||
|
||||
for example in examples:
|
||||
parsed_record = checkdmarc.dmarc.parse_dmarc_record(example, "")
|
||||
self.assertIsInstance(parsed_record, OrderedDict)
|
||||
|
||||
def testGetBaseDomain(self):
|
||||
subdomain = "foo.example.com"
|
||||
result = checkdmarc.utils.get_base_domain(subdomain)
|
||||
assert result == "example.com"
|
||||
|
||||
# Test reserved domains
|
||||
subdomain = "_dmarc.nonauth-rua.invalid.example"
|
||||
result = checkdmarc.utils.get_base_domain(subdomain)
|
||||
assert result == "invalid.example"
|
||||
|
||||
subdomain = "_dmarc.nonauth-rua.invalid.test"
|
||||
result = checkdmarc.utils.get_base_domain(subdomain)
|
||||
assert result == "invalid.test"
|
||||
|
||||
subdomain = "_dmarc.nonauth-rua.invalid.invalid"
|
||||
result = checkdmarc.utils.get_base_domain(subdomain)
|
||||
assert result == "invalid.invalid"
|
||||
|
||||
subdomain = "_dmarc.nonauth-rua.invalid.localhost"
|
||||
result = checkdmarc.utils.get_base_domain(subdomain)
|
||||
assert result == "invalid.localhost"
|
||||
|
||||
# Test newer PSL entries
|
||||
subdomain = "e3191.c.akamaiedge.net"
|
||||
result = checkdmarc.utils.get_base_domain(subdomain)
|
||||
assert result == "c.akamaiedge.net"
|
||||
|
||||
def testUppercaseSPFMechanism(self):
|
||||
"""Treat uppercase SPF"SPF mechanisms as valid"""
|
||||
spf_record = "v=spf1 IP4:147.75.8.208 -ALL"
|
||||
domain = "example.no"
|
||||
|
||||
results = checkdmarc.spf.parse_spf_record(spf_record, domain)
|
||||
|
||||
self.assertEqual(len(results["warnings"]), 0)
|
||||
|
||||
def testSplitSPFRecord(self):
|
||||
"""Split SPF records are parsed properly"""
|
||||
|
||||
rec = '"v=spf1 ip4:147.75.8.208 " "include:_spf.salesforce.com -all"'
|
||||
|
||||
parsed_record = checkdmarc.spf.parse_spf_record(rec, "example.com")
|
||||
|
||||
self.assertEqual(parsed_record["parsed"]["all"], "fail")
|
||||
|
||||
def testJunkAfterAll(self):
|
||||
"""Ignore any mechanisms after the all mechanism, but warn about it"""
|
||||
rec = "v=spf1 ip4:213.5.39.110 -all MS=83859DAEBD1978F9A7A67D3"
|
||||
domain = "avd.dk"
|
||||
|
||||
parsed_record = checkdmarc.spf.parse_spf_record(rec, domain)
|
||||
self.assertEqual(len(parsed_record["warnings"]), 1)
|
||||
|
||||
@unittest.skip
|
||||
def testDNSSEC(self):
|
||||
"""Test known good DNSSEC"""
|
||||
self.assertEqual(checkdmarc.dnssec.test_dnssec("fbi.gov"), True)
|
||||
|
||||
def testIncludeMissingSPF(self):
|
||||
"""SPF records that include domains that are missing SPF records
|
||||
raise SPFRecordNotFound"""
|
||||
|
||||
spf_record = '"v=spf1 include:spf.comendosystems.com ' \
|
||||
'include:bounce.peytz.dk include:etrack.indicia.dk ' \
|
||||
'include:etrack1.com include:mail1.dialogportal.com ' \
|
||||
'include:mail2.dialogportal.com a:mailrelay.jppol.dk ' \
|
||||
'a:sendmail.jppol.dk ?all"'
|
||||
domain = "ekstrabladet.dk"
|
||||
self.assertRaises(checkdmarc.spf.SPFRecordNotFound,
|
||||
checkdmarc.spf.parse_spf_record, spf_record, domain)
|
||||
|
||||
def testTooManySPFDNSLookups(self):
|
||||
"""SPF records with > 10 SPF mechanisms that cause DNS lookups raise
|
||||
SPFTooManyDNSLookups"""
|
||||
|
||||
spf_record = "v=spf1 a include:_spf.salesforce.com " \
|
||||
"include:spf.protection.outlook.com " \
|
||||
"include:spf.constantcontact.com " \
|
||||
"include:_spf.elasticemail.com " \
|
||||
"include:servers.mcsv.net " \
|
||||
"include:_spf.google.com " \
|
||||
"~all"
|
||||
domain = "example.com"
|
||||
self.assertRaises(checkdmarc.spf.SPFTooManyDNSLookups,
|
||||
checkdmarc.spf.parse_spf_record, spf_record, domain)
|
||||
|
||||
def testTooManySPFVoidDNSLookups(self):
|
||||
"""SPF records with > 2 void DNS lookups"""
|
||||
|
||||
spf_record = "v=spf1 a:13Mk4olS9VWhQqXRl90fKJrD.example.com " \
|
||||
"mx:SfGiqBnQfRbOMapQJhozxo2B.example.com " \
|
||||
"a:VAFeyU9N2KJX518aGsN3w6VS.example.com " \
|
||||
"~all"
|
||||
domain = "example.com"
|
||||
self.assertRaises(checkdmarc.spf.SPFTooManyVoidDNSLookups,
|
||||
checkdmarc.spf.parse_spf_record, spf_record, domain)
|
||||
|
||||
def testSPFSyntaxErrors(self):
|
||||
"""SPF record syntax errors raise SPFSyntaxError"""
|
||||
|
||||
spf_record = '"v=spf1 mx a:mail.cohaesio.net ' \
|
||||
'include: trustpilotservice.com ~all"'
|
||||
domain = "2021.ai"
|
||||
self.assertRaises(checkdmarc.spf.SPFSyntaxError,
|
||||
checkdmarc.spf.parse_spf_record, spf_record, domain)
|
||||
|
||||
def testSPFInvalidIPv4(self):
|
||||
"""Invalid ipv4 SPF mechanism values raise SPFSyntaxError"""
|
||||
spf_record = "v=spf1 ip4:78.46.96.236 +a +mx +ip4:138.201.239.158 " \
|
||||
"+ip4:78.46.224.83 " \
|
||||
"+ip4:relay.mailchannels.net +ip4:138.201.60.20 ~all"
|
||||
domain = "surftown.dk"
|
||||
self.assertRaises(checkdmarc.spf.SPFSyntaxError,
|
||||
checkdmarc.spf.parse_spf_record, spf_record, domain)
|
||||
|
||||
def testSPFInvalidIPv6inIPv4(self):
|
||||
"""Invalid ipv4 SPF mechanism values raise SPFSyntaxError"""
|
||||
spf_record = "v=spf1 ip4:1200:0000:AB00:1234:0000:2552:7777:1313 ~all"
|
||||
domain = "surftown.dk"
|
||||
self.assertRaises(checkdmarc.spf.SPFSyntaxError,
|
||||
checkdmarc.spf.parse_spf_record, spf_record, domain)
|
||||
|
||||
def testSPFInvalidIPv4Range(self):
|
||||
"""Invalid ipv4 SPF mechanism values raise SPFSyntaxError"""
|
||||
spf_record = "v=spf1 ip4:78.46.96.236/99 ~all"
|
||||
domain = "surftown.dk"
|
||||
self.assertRaises(checkdmarc.spf.SPFSyntaxError,
|
||||
checkdmarc.spf.parse_spf_record, spf_record, domain)
|
||||
|
||||
def testSPFInvalidIPv6(self):
|
||||
"""Invalid ipv6 SPF mechanism values raise SPFSyntaxError"""
|
||||
spf_record = "v=spf1 ip6:1200:0000:AB00:1234:O000:2552:7777:1313 ~all"
|
||||
domain = "surftown.dk"
|
||||
self.assertRaises(checkdmarc.spf.SPFSyntaxError,
|
||||
checkdmarc.spf.parse_spf_record, spf_record, domain)
|
||||
|
||||
def testSPFInvalidIPv4inIPv6(self):
|
||||
"""Invalid ipv6 SPF mechanism values raise SPFSyntaxError"""
|
||||
spf_record = "v=spf1 ip6:78.46.96.236 ~all"
|
||||
domain = "surftown.dk"
|
||||
self.assertRaises(checkdmarc.spf.SPFSyntaxError,
|
||||
checkdmarc.spf.parse_spf_record, spf_record, domain)
|
||||
|
||||
def testSPFInvalidIPv6Range(self):
|
||||
"""Invalid ipv6 SPF mechanism values raise SPFSyntaxError"""
|
||||
record = "v=spf1 ip6:1200:0000:AB00:1234:0000:2552:7777:1313/130 ~all"
|
||||
domain = "surftown.dk"
|
||||
self.assertRaises(checkdmarc.spf.SPFSyntaxError,
|
||||
checkdmarc.spf.parse_spf_record, record, domain)
|
||||
|
||||
def testSPFIncludeLoop(self):
|
||||
"""SPF record with include loop raises SPFIncludeLoop"""
|
||||
|
||||
spf_record = '"v=spf1 include:example.com"'
|
||||
domain = "example.com"
|
||||
self.assertRaises(checkdmarc.spf.SPFIncludeLoop,
|
||||
checkdmarc.spf.parse_spf_record, spf_record, domain)
|
||||
|
||||
def testSPFMissingMXRecord(self):
|
||||
"""A warning is issued if an SPF record contains a mx mechanism
|
||||
pointing to a domain that has no MX records"""
|
||||
|
||||
spf_record = '"v=spf1 mx ~all"'
|
||||
domain = "seanthegeek.net"
|
||||
results = checkdmarc.spf.parse_spf_record(spf_record, domain)
|
||||
self.assertIn("{0} does not have any MX records".format(domain),
|
||||
results["warnings"])
|
||||
|
||||
def testSPFMissingARecord(self):
|
||||
"""A warning is issued if an SPF record contains a mx mechanism
|
||||
pointing to a domain that has no A records"""
|
||||
|
||||
spf_record = '"v=spf1 a ~all"'
|
||||
domain = "cardinalhealth.net"
|
||||
results = checkdmarc.spf.parse_spf_record(spf_record, domain)
|
||||
self.assertIn("cardinalhealth.net does not have any A/AAAA records",
|
||||
results["warnings"])
|
||||
|
||||
def testDMARCPctLessThan100Warning(self):
|
||||
"""A warning is issued if the DMARC pvt value is less than 100"""
|
||||
|
||||
dmarc_record = "v=DMARC1; p=none; sp=none; fo=1; pct=50; adkim=r; " \
|
||||
"aspf=r; rf=afrf; ri=86400; " \
|
||||
"rua=mailto:eits.dmarcrua@energy.gov; " \
|
||||
"ruf=mailto:eits.dmarcruf@energy.gov"
|
||||
domain = "energy.gov"
|
||||
results = checkdmarc.dmarc.parse_dmarc_record(dmarc_record, domain)
|
||||
self.assertIn("pct value is less than 100",
|
||||
results["warnings"][0])
|
||||
|
||||
def testInvalidDMARCURI(self):
|
||||
"""An invalid DMARC report URI raises InvalidDMARCReportURI"""
|
||||
|
||||
dmarc_record = "v=DMARC1; p=none; rua=reports@dmarc.cyber.dhs.gov," \
|
||||
"mailto:dmarcreports@usdoj.gov"
|
||||
domain = "dea.gov"
|
||||
self.assertRaises(checkdmarc.dmarc.InvalidDMARCReportURI,
|
||||
checkdmarc.dmarc.parse_dmarc_record, dmarc_record,
|
||||
domain)
|
||||
|
||||
dmarc_record = "v=DMARC1; p=none; rua=__" \
|
||||
"mailto:reports@dmarc.cyber.dhs.gov," \
|
||||
"mailto:dmarcreports@usdoj.gov"
|
||||
self.assertRaises(checkdmarc.dmarc.InvalidDMARCReportURI,
|
||||
checkdmarc.dmarc.parse_dmarc_record, dmarc_record,
|
||||
domain)
|
||||
|
||||
def testInvalidDMARCPolicyValue(self):
|
||||
"""An invalid DMARC policy value raises InvalidDMARCTagValue """
|
||||
dmarc_record = "v=DMARC1; p=foo; rua=mailto:dmarc@example.com"
|
||||
domain = "example.com"
|
||||
self.assertRaises(checkdmarc.dmarc.InvalidDMARCTagValue,
|
||||
checkdmarc.dmarc.parse_dmarc_record,
|
||||
dmarc_record,
|
||||
domain)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main(verbosity=2)
|
Loading…
x
Reference in New Issue
Block a user