Bug fixes
- Failure reports without a
message/feedback-reportpart are no longer silently dropped by the Elasticsearch and OpenSearch outputs (#332). Some Exim/cPanel-based gateways send DMARC failure reports asmultipart/reportwithout areport-type=feedbackparameter and without a machine-readablemessage/feedback-reportpart — only a plain-text summary starting with "A message claiming to be from you has failed".parse_report_email()has a dedicated fallback for this format that synthesizes a minimal feedback report containing onlyArrival-DateandSource-IP, andparse_failure_report()already defaulted most missing fields — but notfeedback_typeorauthentication_results, both of which the Elasticsearch/OpenSearch save paths access with hard key lookups. The result: every such report was parsed, archived to the failure folder, and then rejected at the sink withFailure report missing required field: 'feedback_type', so it never reached the index.parse_failure_report()now defaultsfeedback_typetoauth-failure(RFC 5965 §3.1) andauthentication_resultstoNone(RFC 6591 §3.1), each with a logged warning naming the offending omission — the same treatment the REQUIREDAuth-FailureandIdentity-Alignmentfields already receive. A sanitized sample (samples/failure/exim_plain_text_only_no_arf_part.eml) and a regression test asserting the sink-required keys are present cover the fallback path. - The "Aggregate DMARC passage over time" and "Aggregate DMARC message disposition over time" OpenSearch Dashboards visualizations no longer default to a 12-hour X-axis interval (#828). Both
date_histogramaggregations were configured with"interval": "auto", which OpenSearch Dashboards sizes off the currently viewed time range rather than the data's actual cadence. Aggregate DMARC reports post onedate_range-bucketed data point per reporting period (typically daily), so an auto-computed sub-day bucket size produced empty buckets and a misleading sawtooth/spike pattern. Both visualizations indashboards/opensearch/opensearch_dashboards.ndjsonnow hardcode"interval": "d", matching the fix the reporter applied manually in the visualization editor (the "Day" option in the interval picker). - The same auto-interval time-bucketing bug from #828 also affected the PostgreSQL Grafana dashboard's "Over Time" panels (
dashboards/grafana/Grafana-DMARC_Reports-PostgreSQL.json): "SPF Results Over Time", "DKIM Results Over Time", "DMARC Pass/Fail Over Time", "Disposition Over Time", "SMTP TLS Sessions Over Time", and one unlabeled summarystatpanel all grouped rows with$__timeGroup(<column>, $__interval), where$__intervalis a Grafana-computed value that scales with the panel's pixel width and the selected time range, not the reports' actual daily cadence. All 7 occurrences now hardcode the bucket width to'1d', matching thefixed_interval: "1d"already used by the equivalent panels in the companion Elasticsearch/Grafana dashboard (Grafana-DMARC_Reports.json), which was already correct and needed no change. - The same bug also affected the Splunk "DMARC passage over time" and "Message disposition over time" panels (
dashboards/splunk/dmarc_aggregate_dashboard.xml). Both| timechartcalls had no explicitspan, so Splunk auto-computes a bin size targeting 100 buckets across whatever time range is selected; this only coincidentally lands on a 1-day span for the dashboard's default "last 7 days" time-range input — any other selected range (e.g. "last 24 hours" → 30 minutes) reproduces the same gapped/spiked chart. Both queries now setspan=1dexplicitly.