Changes
- Microsoft Graph connections are now observable (#814). Previously
--debugshowed nothing about Graph connection activity: the mailbox layer logs undermailsuite.mailbox.graph, token acquisition underazure.identity, and HTTP traffic underhttpx/msgraph— none of which parsedmarc configured, so everything below WARNING was silently dropped, and_main()logged nothing around the connection attempt itself. Now:- A redacted connection summary is logged at INFO before connecting (auth method, tenant ID, client ID, mailbox, Graph URL), with a
--debugdetail line adding the certificate path, token-file path, and set/not-set flags for secrets. Secret values (passwords, client secrets, certificate passwords, client assertions) are never logged, and a regression test asserts they don't appear in captured output. - A timing line (
Microsoft Graph connection initialized in N seconds) is logged after the connection object is created. - parsedmarc's
--verbose/--debuglevel now propagates to the dependency loggers (mailsuite,azure,msgraph,httpx,httpcore), so--debugsurfaces azure-identity's token-endpoint activity — including theAADSTSerror codes that distinguish a local config problem from an Exchange Online / Entra ID one — and the Graph SDK's HTTP requests. At the default level, dependency loggers sit at WARNING so their warnings keep surfacing (now formatted) without new noise. This also benefits the IMAP backend, which lives in mailsuite too.
- A redacted connection summary is logged at INFO before connecting (auth method, tenant ID, client ID, mailbox, Graph URL), with a
Bug fixes
- Failure-report timestamps are no longer skewed by the host's UTC offset in the Elasticsearch, OpenSearch, and Splunk HEC outputs (#811, bug 1).
arrival_date_utcis a UTC wall-clock string, but the three sinks parsed it into a naivedatetimeand called.timestamp(), which per the Python docs interprets naive values as local time — so on any non-UTC host, the epoch stored as the ES/OpenSearcharrival_datefield, used in the failure-report dedup query, and sent as the Splunk HEC eventtimewas off by the host's UTC offset (1–2 h for most of Europe).human_timestamp_to_datetime()/human_timestamp_to_unix_timestamp()gained anassume_utckeyword that attachestimezone.utcto naive parses, and thearrival_date_utcconsumers now use it. - A system GeoIP file no longer silently overrides the bundled IPinfo database (#810). The IP database path resolution searched standard system paths (e.g.
/usr/share/GeoIP/GeoLite2-Country.mmdb, plus CWD-relative names) before the database managed by parsedmarc, so on any host with a distro GeoIP package installed — often as a stale dependency of an unrelated package — every lookup used a country-only (and possibly years-old) database instead of the bundled IPinfo Lite database. That silently disabled ASN enrichment (asn,as_name,as_domainwereNonefor every IP) and with it the ASN-fallback path into the reverse-DNS map. The precedence is now: explicitip_db_path→ the database selected byload_ip_db()(downloaded/cached/bundled) → the bundled copy → system paths as a true last resort. The selected database file is logged at debug level. If you deliberately relied on the automatic system-path pickup to use MaxMind GeoLite2, setip_db_pathexplicitly — see the "Using MaxMind GeoLite2" section in the installation docs.