move mails without Message-ID; log the reason for failed actions

A spam mail matched stefanhacker@gmx.de but "Aktion fehlgeschlagen"
every time: it has no Message-ID header, and the safe move refused to
proceed because it verifies the copy by Message-ID. So every mail
without that header stayed in INBOX forever, and the log didn't say why.

Verification now falls back when there is no Message-ID:
- COPYUID from the COPY response when the server supports UIDPLUS
- otherwise count mails in the target with the same exact size and
  sender before and after COPY; exactly one more means it arrived
The source is still only flagged/expunged after verification, and
move_mail now refuses to run without source_folder (the verification
selects the target, so STORE could otherwise hit the wrong folder).
Checked against a simulated IMAP server for success, rejected COPY,
copy not arriving, and missing source folder.

IMAPClient.last_error carries the reason (rejected COPY with server
text, copy not found incl. how it was checked, missing target folder,
no SMTP config, ...); the scheduler appends it to the log message.
"Fehlgeschlagene neu einlesen" now also retries failed actions, not
only fetch errors.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-09-29 12:02:30 +02:00
co-authored by Claude Opus 5.5
parent 7d03c62d8e
commit fbb2fe95c8
5 changed files with 131 additions and 60 deletions
+2 -1
View File
@@ -246,8 +246,9 @@ def _poll_account_sync(account_id: int) -> None:
)
else:
total_errors += 1
reason = client.last_error or "unbekannter Grund"
write_log(
message=f"Aktion fehlgeschlagen: {action_label}",
message=f"Aktion fehlgeschlagen: {action_label} — {reason}"[:1000],
level=LogLevel.ERROR,
account_id=account.id,
account_name=account.name,