mirror of
https://github.com/domainaware/parsedmarc.git
synced 2026-10-04 03:20:31 +00:00
Fix blank SMTP TLS failure-detail fields crashing saves; read RFC 8460 additional-information (11.0.3) (#916)
* Treat blank SMTP TLS failure-detail fields as absent; read RFC 8460 additional-information
Some reporters send optional failure-details fields as empty strings
(e.g. "sending-mta-ip": "" on sts-policy-fetch-error). The parser copied
them verbatim, so the PostgreSQL save failed on the INET columns
("invalid input syntax for type inet") and the Elasticsearch/OpenSearch
saves failed Ip() validation, discarding the whole report. Blank or
whitespace-only optional values are now omitted.
RFC 8460 section 4.4 names the URI key "additional-information"; the
parser only read "additional-info-uri" (the schema's value placeholder),
so conformant reports lost the URI. The RFC key is now read, with the old
key kept as a fallback.
Bump version to 11.0.3.
Closes #915
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
* Import parse_report_file directly in the ES/OpenSearch tests
Addresses github-code-quality's "Module is imported with 'import' and
'import from'" findings on tests/test_elastic.py and
tests/test_opensearch.py.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
6648be7d02
commit
e077136b60
@@ -658,6 +658,46 @@ class TestPostgreSQLClientSave(unittest.TestCase):
|
||||
self.assertIn(100, policy_params)
|
||||
self.assertIn(2, policy_params)
|
||||
|
||||
def test_save_smtp_tls_report_blank_failure_detail_fields_become_null(self):
|
||||
"""Blank optional failure-detail fields reach PostgreSQL as None,
|
||||
not "" (issue #915).
|
||||
|
||||
samples/smtp_tls/empty_failure_detail_fields.json reproduces a
|
||||
real reporter's shape: sending-mta-ip/receiving-ip/
|
||||
receiving-mx-hostname/additional-information sent as "" on an
|
||||
sts-policy-fetch-error. "" is not a valid PostgreSQL INET value, so
|
||||
before the parser fix in parsedmarc/__init__.py this reached
|
||||
cur.execute() as an empty string and crashed the save with
|
||||
"invalid input syntax for type inet: \"\"" against a real server.
|
||||
This test goes through the real parser (parsedmarc.parse_report_file)
|
||||
rather than a hand-built dict, so it fails on unfixed
|
||||
parsedmarc/__init__.py even though this test file only mocks
|
||||
psycopg.
|
||||
"""
|
||||
client, mock_conn = _make_client()
|
||||
cur = _mock_cursor(mock_conn, [(1,), (10,)])
|
||||
|
||||
result = parsedmarc.parse_report_file(
|
||||
"samples/smtp_tls/empty_failure_detail_fields.json", offline=True
|
||||
)
|
||||
report = result["report"]
|
||||
|
||||
client.save_smtp_tls_report_to_postgresql(cast(dict, report))
|
||||
|
||||
sqls = _executed_sql(cur)
|
||||
self.assertIn("smtp_tls_failure_detail", sqls[2])
|
||||
|
||||
detail_params = _named_params(cur.execute.call_args_list[2])
|
||||
self.assertIsNone(detail_params["sending_mta_ip"])
|
||||
self.assertIsNone(detail_params["receiving_ip"])
|
||||
self.assertIsNone(detail_params["receiving_mx_hostname"])
|
||||
self.assertIsNone(detail_params["additional_info_uri"])
|
||||
# A non-blank optional field is preserved.
|
||||
self.assertEqual(detail_params["failure_reason_code"], "no-policy-served")
|
||||
# Required fields are preserved.
|
||||
self.assertEqual(detail_params["result_type"], "sts-policy-fetch-error")
|
||||
self.assertEqual(detail_params["failed_session_count"], 1)
|
||||
|
||||
def test_save_smtp_tls_report_already_saved(self):
|
||||
"""AlreadySaved is raised when ON CONFLICT returns no row."""
|
||||
client, mock_conn = _make_client()
|
||||
|
||||
Reference in New Issue
Block a user