Harden mail move audit logging

The prompts used to arrive at this change since the previous commit

Read restart_prompt.md first, then continue from there.

Any special observations that may be relevant for version management for this version. Be brief.

No mailbox-affecting scripts were run by Codex. A generated dry-run transcript appeared locally as verplaats_bestaand.log and is now ignored via *.log.
This commit is contained in:
2026-07-04 16:33:58 +02:00
parent 33005a7cde
commit f44c363025
4 changed files with 197 additions and 71 deletions
+75 -14
View File
@@ -88,39 +88,69 @@ def kopieer_map(
doel: imaplib.IMAP4_SSL,
folder: str,
log: dict,
) -> tuple[int, int]:
) -> tuple[int, int, int]:
"""
Kopieer berichten van bron-folder naar doel-folder.
Geeft (gekopieerd, overgeslagen) terug.
Geeft (gekopieerd, overgeslagen, mislukt) terug.
"""
# Selecteer bronmap
status, data = bron.select(quote_mailbox(folder), readonly=True)
if status != "OK":
print(f" Kan bronmap niet openen: {folder}")
return 0, 0
log.setdefault("fouten", []).append({
"folder": folder,
"actie": "select_bron",
"status": status,
"response": repr(data),
})
return 0, 0, 1
totaal = int(data[0])
if totaal == 0:
return 0, 0
return 0, 0, 0
# Haal alle bron-UIDs op
status, data = bron.search(None, "ALL")
if status != "OK" or not data[0]:
return 0, 0
log.setdefault("fouten", []).append({
"folder": folder,
"actie": "search_bron",
"status": status,
"response": repr(data),
})
return 0, 0, 1
ids = data[0].split()
# Zorg dat doelmap bestaat
doel.create(quote_mailbox(folder)) # negeer fout als al bestaat
create_status, create_data = doel.create(quote_mailbox(folder))
if create_status not in {"OK", "NO"}:
log.setdefault("fouten", []).append({
"folder": folder,
"actie": "create_doel",
"status": create_status,
"response": repr(create_data),
})
return 0, 0, 1
select_status, select_data = doel.select(quote_mailbox(folder), readonly=True)
if select_status != "OK":
log.setdefault("fouten", []).append({
"folder": folder,
"actie": "select_doel_na_create",
"status": select_status,
"response": repr(select_data),
})
return 0, 0, 1
# Welke Message-IDs staan al in de doelmap?
bestaande = haal_bestaande_message_ids(doel, folder)
gekopieerd = 0
overgeslagen = 0
mislukt = 0
for i, uid in enumerate(ids, 1):
# Voortgang op één regel
print(f"\r {folder}: {i}/{totaal} ({gekopieerd} gekopieerd, {overgeslagen} skip) ",
print(f"\r {folder}: {i}/{totaal} ({gekopieerd} gekopieerd, {overgeslagen} skip, {mislukt} fout) ",
end="", flush=True)
# Haal volledige bericht op + vlaggen + datum
@@ -128,6 +158,14 @@ def kopieer_map(
uid, "(FLAGS INTERNALDATE BODY.PEEK[])"
)
if status != "OK" or not data:
mislukt += 1
log.setdefault("fouten", []).append({
"folder": folder,
"uid": uid.decode(errors="replace"),
"actie": "fetch_bron",
"status": status,
"response": repr(data),
})
continue
# Parse fetch-response
@@ -144,6 +182,14 @@ def kopieer_map(
internaldate = parse_internaldate(item[0])
if not raw_message:
mislukt += 1
log.setdefault("fouten", []).append({
"folder": folder,
"uid": uid.decode(errors="replace"),
"actie": "fetch_lege_body",
"status": status,
"response": repr(data),
})
continue
# Controleer Message-ID voor deduplicatie
@@ -159,7 +205,7 @@ def kopieer_map(
# Schrijf naar doelmap
flag_str = "(" + " ".join(flags) + ")" if flags else "()"
status, _ = doel.append(
status, append_data = doel.append(
quote_mailbox(folder),
flag_str,
internaldate,
@@ -170,14 +216,22 @@ def kopieer_map(
if mid:
bestaande.add(mid)
else:
pass # stil doorgaan bij incidentele fout
mislukt += 1
log.setdefault("fouten", []).append({
"folder": folder,
"uid": uid.decode(errors="replace"),
"actie": "append_doel",
"message_id": mid,
"status": status,
"response": repr(append_data),
})
# Even pauzeren elke 50 berichten om server te ontlasten
if gekopieerd % 50 == 0 and gekopieerd > 0:
time.sleep(0.2)
print(f"\r {folder}: {totaal}/{totaal}{gekopieerd} gekopieerd, {overgeslagen} al aanwezig ")
return gekopieerd, overgeslagen
print(f"\r {folder}: {totaal}/{totaal}{gekopieerd} gekopieerd, {overgeslagen} al aanwezig, {mislukt} fout ")
return gekopieerd, overgeslagen, mislukt
# ── log ───────────────────────────────────────────────────────────────────────
@@ -247,6 +301,7 @@ def run():
totaal_gekopieerd = log.get("totaal_gekopieerd", 0)
totaal_overgeslagen = 0
totaal_mislukt = 0
for i, folder in enumerate(alle_mappen, 1):
print(f"[{i}/{len(alle_mappen)}] {folder}")
@@ -255,12 +310,17 @@ def run():
print(f" ✓ al volledig gekopieerd, overgeslagen.\n")
continue
gekopieerd, overgeslagen = kopieer_map(bron, doel, folder, log)
gekopieerd, overgeslagen, mislukt = kopieer_map(bron, doel, folder, log)
totaal_gekopieerd += gekopieerd
totaal_overgeslagen += overgeslagen
totaal_mislukt += mislukt
log["voltooide_mappen"] = list(al_klaar | {folder})
al_klaar.add(folder)
if mislukt == 0:
log["voltooide_mappen"] = list(al_klaar | {folder})
al_klaar.add(folder)
else:
log["voltooide_mappen"] = list(al_klaar)
print(f" ! niet als voltooid gemarkeerd door {mislukt} fout(en)")
log["totaal_gekopieerd"] = totaal_gekopieerd
log["laatste_run"] = datetime.now().isoformat()
save_log(log)
@@ -273,6 +333,7 @@ def run():
print(f"Klaar.")
print(f" Gekopieerd : {totaal_gekopieerd}")
print(f" Al aanwezig : {totaal_overgeslagen}")
print(f" Fouten : {totaal_mislukt}")
print(f" Log : {LOG_FILE}")