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", "")