From 28a115a223fedc5ccaa353406b4a3c48a8008cb9 Mon Sep 17 00:00:00 2001 From: Sean Whalen Date: Tue, 6 Mar 2018 07:14:37 -0500 Subject: [PATCH] 2.1.1 - Documentation fixes --- CHANGELOG.md | 4 ++++ README.rst | 6 ++++++ docs/index.rst | 6 ++++++ parsedmarc.py | 46 +++++++++++++++++++++++++++++----------------- 4 files changed, 45 insertions(+), 17 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9cf18ea..f2301b7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +2.1.1 +----- +- Documentation fixes + 2.1.0 ----- - Add `get_report_zip()` and `email_results()` diff --git a/README.rst b/README.rst index fb1f986..c95ed24 100644 --- a/README.rst +++ b/README.rst @@ -75,6 +75,12 @@ CLI help --test Do not move or delete IMAP messages -v, --version show program's version number and exit +SPF and DMARC record validation +=============================== + +If you are looking for SPF and DMARC record validation and parsing, +check out the sister project, `checkdmarc `_. + Sample aggregate report output ============================== diff --git a/docs/index.rst b/docs/index.rst index adf59e4..9d63dda 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -80,6 +80,12 @@ CLI help --test Do not move or delete IMAP messages -v, --version show program's version number and exit +SPF and DMARC record validation +=============================== + +If you are looking for SPF and DMARC record validation and parsing, +check out the sister project, `checkdmarc `_. + Sample aggregate report output ============================== diff --git a/parsedmarc.py b/parsedmarc.py index a0812c4..cc6f3f5 100644 --- a/parsedmarc.py +++ b/parsedmarc.py @@ -44,7 +44,7 @@ import imapclient.exceptions import dateparser import mailparser -__version__ = "2.1.0" +__version__ = "2.1.1" logger = logging.getLogger(__name__) logger.setLevel(logging.INFO) @@ -541,13 +541,13 @@ def parse_aggregate_report_file(_input, nameservers=None, timeout=6.0): timeout=timeout) -def parsed_aggregate_report_to_csv(_input): +def parsed_aggregate_report_to_csv(reports): """ Converts one or more parsed aggregate reports to flat CSV format, including headers Args: - _input: A parsed aggregate report or list of parsed aggregate reports + reports: A parsed aggregate report or list of parsed aggregate reports Returns: str: Parsed aggregate report data in flat CSV format, including headers @@ -566,10 +566,10 @@ def parsed_aggregate_report_to_csv(_input): writer = DictWriter(csv_file_object, fields) writer.writeheader() - if type(_input) == OrderedDict: - _input = [_input] + if type(reports) == OrderedDict: + reports = [reports] - for report in _input: + for report in reports: xml_schema = report["xml_schema"] org_name = report["report_metadata"]["org_name"] org_email = report["report_metadata"]["org_email"] @@ -798,7 +798,17 @@ def parse_forensic_report(feedback_report, sample, sample_headers_only, error.__str__())) -def parsed_dmarc_forensic_reports_to_csv(report): +def parsed_dmarc_forensic_reports_to_csv(reports): + """ + Converts one or more parsed forensic reports to flat CSV format, including + headers + + Args: + reports: A parsed forensic report or list of parsed forensic reports + + Returns: + str: Parsed forensic report data in flat CSV format, including headers + """ fields = ["feedback_type", "user_agent", "version", "original_envelope_id", "original_mail_from", "original_rcpt_to", "arrival_date", "arrival_date_utc", "subject", "message_id", @@ -807,19 +817,21 @@ def parsed_dmarc_forensic_reports_to_csv(report): "delivery_result", "auth_failure", "reported_domain", "authentication_mechanisms", "sample_headers_only"] + if type(reports) == OrderedDict: + reports = [reports] csv_file = StringIO() csv_writer = DictWriter(csv_file, fieldnames=fields) csv_writer.writeheader() - for row in report: - row = row.copy() - row["source_ip_address"] = row["source"]["ip_address"] - row["source_reverse_dns"] = row["source"]["reverse_dns"] - row["source_base_domain"] = row["source"]["base_domain"] - row["source_country"] = row["source"]["country"] + for report in reports: + row = report.copy() + row["source_ip_address"] = report["source"]["ip_address"] + row["source_reverse_dns"] = report["source"]["reverse_dns"] + row["source_base_domain"] = report["source"]["base_domain"] + row["source_country"] = report["source"]["country"] del row["source"] - row["subject"] = row["parsed_sample"]["subject"] - row["auth_failure"] = ",".join(row["auth_failure"]) - authentication_mechanisms = row["authentication_mechanisms"] + row["subject"] = report["parsed_sample"]["subject"] + row["auth_failure"] = ",".join(report["auth_failure"]) + authentication_mechanisms = report["authentication_mechanisms"] row["authentication_mechanisms"] = ",".join( authentication_mechanisms) del row["sample"] @@ -1212,7 +1224,7 @@ def email_results(results, host, mail_from, mail_to, port=0, starttls=True, mail_to : A list of addresses to mail to port (int): Port to use starttls (bool): use STARTTLS - use_ssl (bool): Require an SSL connection from the start + use_ssl (bool): Require a SSL connection from the start user: An optional username password: An optional password subject: Overrides the default message subject