- Ignore unknown forensic report fields when generating CSVs (Closes issue #148)
- Fix crash on IMAP timeout (PR #164 - closes issue #163)
- Use SMTP port from the config file when sending emails (PR #151)
- Add support for Elasticsearch 7.0 (PR #161 - closes issue #149)
- Remove temporary workaround for DMARC aggregate report records missing a SPF domain fields
This commit is contained in:
Sean Whalen
2020-05-10 17:44:14 -04:00
parent 8431207920
commit 4fca674064
5 changed files with 19 additions and 233 deletions
+12
View File
@@ -1,3 +1,15 @@
Changelog
=========
6.10.0
------
- Ignore unknown forensic report fields when generating CSVs (Closes issue #148)
- Fix crash on IMAP timeout (PR #164 - closes issue #163)
- Use SMTP port from the config file when sending emails (PR #151)
- Add support for Elasticsearch 7.0 (PR #161 - closes issue #149)
- Remove temporary workaround for DMARC aggregate report records missing a SPF domain fields
6.9.0
-----
+1 -1
View File
@@ -155,7 +155,7 @@ The full set of configuration options are:
- ``timeout`` - float: Timeout in seconds to wait for an IMAP operation to complete (Default: 30)
- ``max_retries`` - int: The maximum number of retries after a timeout
- ``user`` - str: The IMAP user
- ``password`` - str: The IMAP password
- ``password`` - str: The IMAP password (escape ``%`` with a second ``%``)
- ``reports_folder`` - str: The IMAP folder where the incoming reports can be found (Default: INBOX)
- ``archive_folder`` - str: The IMAP folder to sort processed emails into (Default: Archive)
- ``watch`` - bool: Use the IMAP ``IDLE`` command to process messages as they arrive
+5 -4
View File
@@ -34,7 +34,7 @@ from parsedmarc.utils import is_outlook_msg, convert_outlook_msg
from parsedmarc.utils import timestamp_to_human, human_timestamp_to_datetime
from parsedmarc.utils import parse_email
__version__ = "6.9.0"
__version__ = "6.10.0"
logging.basicConfig(
format='%(levelname)8s:%(filename)s:%(lineno)d:'
@@ -165,8 +165,6 @@ def _parse_report_record(record, offline=False, nameservers=None,
if type(auth_results["spf"]) != list:
auth_results["spf"] = [auth_results["spf"]]
for result in auth_results["spf"]:
if "domain" not in result:
result["domain"] = None
new_result = OrderedDict([("domain", result["domain"])])
if "scope" in result and result["scope"] is not None:
new_result["scope"] = result["scope"]
@@ -729,7 +727,10 @@ def parsed_forensic_reports_to_csv(reports):
rows = parsed_forensic_reports_to_csv_rows(reports)
for row in rows:
csv_writer.writerow(row)
new_row = {}
for key in new_row.keys():
new_row[key] = row[key]
csv_writer.writerow(new_row)
return csv_file.getvalue()
@@ -1,227 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<feedback>
<report_metadata>
<org_name>zoho.com</org_name>
<email>noreply-dmarc@zoho.com</email>
<extra_contact_info>https://www.zoho.com/mail/help/adminconsole/dmarc-policy.html</extra_contact_info>
<report_id>e2cb5d97-dcbb-470f-b2dd-45519a2abbb3</report_id>
<date_range>
<begin>1581753600</begin>
<end>1581840000</end>
</date_range>
</report_metadata>
<policy_published>
<domain>example.com</domain>
<adkim>r</adkim>
<aspf>r</aspf>
<p>none</p>
<pct>100</pct>
<fo>0</fo>
</policy_published>
<record>
<row>
<source_ip>216.71.146.18</source_ip>
<count>1</count>
<policy_evaluated>
<disposition>none</disposition>
<dkim>fail</dkim>
<spf>fail</spf>
</policy_evaluated>
</row>
<identifiers>
<header_from>example.com</header_from>
</identifiers>
<auth_results>
<dkim>
<result>pass</result>
<domain>example.com</domain>
<selector>s1</selector>
</dkim>
<spf>
<domain>example.com</domain>
<result>pass</result>
<scope>mfrom</scope>
</spf>
</auth_results>
</record>
<record>
<row>
<source_ip>216.71.143.97</source_ip>
<count>1</count>
<policy_evaluated>
<disposition>none</disposition>
<dkim>fail</dkim>
<spf>fail</spf>
</policy_evaluated>
</row>
<identifiers>
<header_from>example.com</header_from>
</identifiers>
<auth_results>
<dkim>
<result>pass</result>
<domain>example.com</domain>
<selector>s1</selector>
</dkim>
<spf>
<result>none</result>
<scope>helo</scope>
</spf>
</auth_results>
</record>
<record>
<row>
<source_ip>216.71.146.224</source_ip>
<count>1</count>
<policy_evaluated>
<disposition>none</disposition>
<dkim>fail</dkim>
<spf>fail</spf>
</policy_evaluated>
</row>
<identifiers>
<header_from>example.com</header_from>
</identifiers>
<auth_results>
<dkim>
<result>pass</result>
<domain>example.com</domain>
<selector>s1</selector>
</dkim>
<spf>
<domain>example.com</domain>
<result>pass</result>
<scope>mfrom</scope>
</spf>
</auth_results>
</record>
<record>
<row>
<source_ip>216.71.143.87</source_ip>
<count>1</count>
<policy_evaluated>
<disposition>none</disposition>
<dkim>fail</dkim>
<spf>fail</spf>
</policy_evaluated>
</row>
<identifiers>
<header_from>example.com</header_from>
</identifiers>
<auth_results>
<dkim>
<result>pass</result>
<domain>example.com</domain>
<selector>s1</selector>
</dkim>
<spf>
<domain>example.com</domain>
<result>pass</result>
<scope>mfrom</scope>
</spf>
</auth_results>
</record>
<record>
<row>
<source_ip>216.71.143.62</source_ip>
<count>1</count>
<policy_evaluated>
<disposition>none</disposition>
<dkim>fail</dkim>
<spf>fail</spf>
</policy_evaluated>
</row>
<identifiers>
<header_from>example.com</header_from>
</identifiers>
<auth_results>
<dkim>
<result>pass</result>
<domain>example.com</domain>
<selector>s1</selector>
</dkim>
<spf>
<domain>example.com</domain>
<result>pass</result>
<scope>mfrom</scope>
</spf>
</auth_results>
</record>
<record>
<row>
<source_ip>216.71.143.52</source_ip>
<count>1</count>
<policy_evaluated>
<disposition>none</disposition>
<dkim>fail</dkim>
<spf>fail</spf>
</policy_evaluated>
</row>
<identifiers>
<header_from>example.com</header_from>
</identifiers>
<auth_results>
<dkim>
<result>pass</result>
<domain>example.com</domain>
<selector>s1</selector>
</dkim>
<spf>
<result>none</result>
<scope>helo</scope>
</spf>
</auth_results>
</record>
<record>
<row>
<source_ip>216.71.148.142</source_ip>
<count>1</count>
<policy_evaluated>
<disposition>none</disposition>
<dkim>fail</dkim>
<spf>fail</spf>
</policy_evaluated>
</row>
<identifiers>
<header_from>example.com</header_from>
</identifiers>
<auth_results>
<dkim>
<result>pass</result>
<domain>example.com</domain>
<selector>s1</selector>
</dkim>
<spf>
<domain>example.com</domain>
<result>pass</result>
<scope>mfrom</scope>
</spf>
</auth_results>
</record>
<record>
<row>
<source_ip>216.71.148.247</source_ip>
<count>2</count>
<policy_evaluated>
<disposition>none</disposition>
<dkim>fail</dkim>
<spf>fail</spf>
</policy_evaluated>
</row>
<identifiers>
<header_from>example.com</header_from>
</identifiers>
<auth_results>
<dkim>
<result>pass</result>
<domain>example.com</domain>
<selector>s1</selector>
</dkim>
<spf>
<domain>example.com</domain>
<result>pass</result>
<scope>mfrom</scope>
</spf>
</auth_results>
</record>
</feedback>
+1 -1
View File
@@ -14,7 +14,7 @@ from setuptools import setup
from codecs import open
from os import path
__version__ = "6.9.0"
from parsedmarc import __version__
description = "A Python package and CLI for parsing aggregate and " \
"forensic DMARC reports"