From edcad4560cb55472bc18fd70a8151d7d61fbdb72 Mon Sep 17 00:00:00 2001 From: Hans Wienen Date: Sun, 5 Jul 2026 11:48:09 +0200 Subject: [PATCH] Harden historical sorter header parsing The prompts used to arrive at this change since the previous commit User asked to check the audit log in the current directory before reordering the real mailbox. Any special observations that may be relevant for version management for this version. Be brief. The inspected log was a partial real backup run, not a hans audit. Header parsing now skips non-bytes FETCH payloads instead of aborting. verplaats_log.json and plan.md were left unstaged. --- restart_prompt.md | 4 ++++ verplaats_bestaand.py | 26 ++++++++++++++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/restart_prompt.md b/restart_prompt.md index cba6a53..f82e0bd 100644 --- a/restart_prompt.md +++ b/restart_prompt.md @@ -85,6 +85,7 @@ Historical sorting: - Account selection is explicit with `--account `, for example `--account backup`. - `--audit` is available in dry-run mode. - It logs to `verplaats_log.json`, retries IMAP aborts where implemented, and parses FETCH responses defensively. +- Header parsing now guards against non-bytes FETCH payloads in both step 2 and step 3 so a malformed/odd IMAP response is logged as a failed header fetch instead of aborting the whole run. Folder creation: @@ -228,6 +229,8 @@ Totaal gepland: 0 | Totaal geen match: 2218 | Totaal overgeslagen: 8219 | Totaal Treat that as a successful backup historical-sorter run with no immediate recovery work needed. +A later local `verplaats_bestaand.log` in the workspace is not a `hans` audit. It shows a real `backup` execution (`LET OP`, `Account: backup`) that aborted at `INBOX.Bestellingen.PostNL` with `AttributeError: 'int' object has no attribute 'decode'`. The visible partial counters before the crash were 74 folder summaries, 5,921 planned, 5,920 moved, 3,105 no match, 1,765 skipped, and 1 error. Do not treat this log as approval to run the real `hans` mailbox move. + ## Verification Commands Latest local verification included: @@ -241,6 +244,7 @@ git diff --check ``` After the plain-mode stop wrapper change, `bash -n deploy_vps.sh` was rerun successfully. +After the historical-sorter header guard change, `python3 -m py_compile verplaats_bestaand.py` was rerun successfully. Useful routing sanity check: diff --git a/verplaats_bestaand.py b/verplaats_bestaand.py index 44228bd..e9738e2 100644 --- a/verplaats_bestaand.py +++ b/verplaats_bestaand.py @@ -372,6 +372,19 @@ def stap2_bronmappen_routing(session: ImapSession, log: dict, dry: bool): mislukt += 1 log_failure(log, "stap2", bron, uid, None, "fetch_header", status, data) continue + if not isinstance(raw_header, bytes): + mislukt += 1 + log_failure( + log, + "stap2", + bron, + uid, + None, + "fetch_header_type", + status, + f"expected bytes, got {type(raw_header).__name__}", + ) + continue msg = email.message_from_bytes(raw_header) from_raw = decode_hdr(msg.get("From", "")) @@ -502,6 +515,19 @@ def stap3_facturen(session: ImapSession, log: dict, dry: bool): mislukt += 1 log_failure(log, "stap3", bron, uid, None, "fetch_header", status, data) continue + if not isinstance(raw_header, bytes): + mislukt += 1 + log_failure( + log, + "stap3", + bron, + uid, + None, + "fetch_header_type", + status, + f"expected bytes, got {type(raw_header).__name__}", + ) + continue msg = email.message_from_bytes(raw_header) date_str = msg.get("Date", "")