Fence Mail provider and mailbox recovery effects

This commit is contained in:
2026-08-03 05:00:19 +02:00
parent ff3aa066ae
commit 5b5077cde7
13 changed files with 1339 additions and 63 deletions
+53 -32
View File
@@ -38,6 +38,10 @@ from govoplan_mail.backend.server_hierarchy import (
resolve_mail_transport,
)
from govoplan_mail.backend.runtime import get_registry
from govoplan_mail.backend.recovery import (
MailRecoveryError,
begin_bounce_scan_recovery,
)
class MailBounceError(RuntimeError):
@@ -465,49 +469,66 @@ class SqlMailBounceProcessingProvider(MailBounceProcessingProvider):
raise MailBounceError(
"Bounce-source IMAP settings changed; review and save the source before scanning."
)
page = list_imap_uids_since(
imap_config=resolved.config,
folder=source.folder,
highest_uid=source.highest_processed_uid,
expected_uidvalidity=source.uidvalidity,
limit=limit,
)
found = 0
calendar_replies = 0
highest = 0 if page.cursor_reset else source.highest_processed_uid
for uid in page.uids:
raw = get_imap_raw_message(
imap_config=resolved.config,
folder=source.folder,
uid=uid,
)
calendar_replies += _reconcile_calendar_replies(
session,
try:
recovery = begin_bounce_scan_recovery(
tenant_id=source.tenant_id,
profile_id=source.profile_id,
source_id=source.id,
folder=source.folder,
uid=uid,
raw_message=raw.raw,
)
found += len(
self.process_raw_message(
except MailRecoveryError as exc:
raise MailBounceError(str(exc)) from exc
try:
page = list_imap_uids_since(
imap_config=resolved.config,
folder=source.folder,
highest_uid=source.highest_processed_uid,
expected_uidvalidity=source.uidvalidity,
limit=limit,
)
found = 0
calendar_replies = 0
highest = 0 if page.cursor_reset else source.highest_processed_uid
for uid in page.uids:
raw = get_imap_raw_message(
imap_config=resolved.config,
folder=source.folder,
uid=uid,
)
calendar_replies += _reconcile_calendar_replies(
session,
tenant_id=source.tenant_id,
profile_id=source.profile_id,
folder=source.folder,
uid=uid,
raw_message=raw.raw,
reconcile_calendar=False,
)
)
highest = max(highest, int(uid))
now = utcnow()
source.uidvalidity = page.uidvalidity
source.highest_processed_uid = highest
source.last_scanned_at = now
source.last_success_at = now
source.last_error = None
session.flush()
found += len(
self.process_raw_message(
session,
tenant_id=source.tenant_id,
profile_id=source.profile_id,
folder=source.folder,
uid=uid,
raw_message=raw.raw,
reconcile_calendar=False,
)
)
highest = max(highest, int(uid))
now = utcnow()
source.uidvalidity = page.uidvalidity
source.highest_processed_uid = highest
source.last_scanned_at = now
source.last_success_at = now
source.last_error = None
session.flush()
session.commit()
except Exception as exc:
session.rollback()
if not recovery.operation.closed:
recovery.reject(code=exc.__class__.__name__)
raise
recovery.complete(highest_uid=highest, uidvalidity=page.uidvalidity)
return len(page.uids), found, calendar_replies