mirror of
https://git.hiabuto.net/C3MA/CCMA.git
synced 2026-08-26 23:35:19 +02:00
Roll back reminder status when direct send/draft delivery fails
generate_and_send_reminder_mail marked a reminder as "sent" before attempting SMTP send/IMAP append. If the connection, login, or append failed, the reminder stayed persisted as sent even though no mail was ever delivered or filed, so it could not be corrected and resent. Wrap content generation, archiving, and delivery in a try/except that calls the existing revert_reminder_sent on any failure and re-raises, putting the reminder back into "draft" for all three delivery modes.
This commit is contained in:
@@ -152,56 +152,63 @@ def generate_and_send_reminder_mail(
|
||||
raise RepositoryError(f"Die Ausgabedatei existiert bereits: {target}")
|
||||
|
||||
sent_reminder = repository.mark_reminder_sent(member_id, claim_id, reminder_id)
|
||||
updated_data, updated_claim = repository.get_claim(member_id, claim_id)
|
||||
organization = repository.get_configuration().get("organization") or {}
|
||||
content = reminder_mail_bytes(
|
||||
recipient=member.email,
|
||||
first_name=member.first_name,
|
||||
reminder=sent_reminder,
|
||||
claim=updated_claim,
|
||||
balance=f"{claim_balance(updated_data, updated_claim):.2f}",
|
||||
organization=organization,
|
||||
sender_name=sender_name,
|
||||
sender_email=sender_email,
|
||||
signature=signature,
|
||||
)
|
||||
archive_dir = repository.members_root / member_id / "files" / "documents" / "Mahnungen"
|
||||
archive_dir.mkdir(parents=True, exist_ok=True)
|
||||
filename = (
|
||||
f"{datetime.now().date().isoformat()}-"
|
||||
f"{_safe_filename(str(sent_reminder.get('name', 'Mahnung')))}.eml"
|
||||
)
|
||||
archive_path = _available_path(archive_dir, filename)
|
||||
archive_temp = archive_path.with_name(f".{archive_path.name}.tmp")
|
||||
export_path: Path | None = None
|
||||
try:
|
||||
archive_temp.write_bytes(content)
|
||||
if delivery_mode == "local":
|
||||
export_temp = target.with_name(f".{target.name}.tmp")
|
||||
try:
|
||||
export_temp.write_bytes(content)
|
||||
os.replace(export_temp, target)
|
||||
finally:
|
||||
export_temp.unlink(missing_ok=True)
|
||||
export_path = target
|
||||
elif delivery_mode == "send":
|
||||
settings = repository.get_email_settings()
|
||||
sent_copy = imap_session(settings) if settings["imap_sent_enabled"] else nullcontext(None)
|
||||
with smtp_session(settings) as smtp_client, sent_copy as imap_client:
|
||||
send_via_smtp(smtp_client, content)
|
||||
if imap_client is not None:
|
||||
ensure_imap_folder(imap_client, settings["imap_sent_folder"])
|
||||
append_message(
|
||||
imap_client, content, folder=settings["imap_sent_folder"], flags=r"(\Seen)"
|
||||
)
|
||||
else:
|
||||
settings = repository.get_email_settings()
|
||||
with imap_session(settings) as client:
|
||||
ensure_imap_folder(client, settings["imap_drafts_folder"])
|
||||
append_message(client, content, folder=settings["imap_drafts_folder"], flags=r"(\Draft)")
|
||||
os.replace(archive_temp, archive_path)
|
||||
finally:
|
||||
archive_temp.unlink(missing_ok=True)
|
||||
updated_data, updated_claim = repository.get_claim(member_id, claim_id)
|
||||
organization = repository.get_configuration().get("organization") or {}
|
||||
content = reminder_mail_bytes(
|
||||
recipient=member.email,
|
||||
first_name=member.first_name,
|
||||
reminder=sent_reminder,
|
||||
claim=updated_claim,
|
||||
balance=f"{claim_balance(updated_data, updated_claim):.2f}",
|
||||
organization=organization,
|
||||
sender_name=sender_name,
|
||||
sender_email=sender_email,
|
||||
signature=signature,
|
||||
)
|
||||
archive_dir = repository.members_root / member_id / "files" / "documents" / "Mahnungen"
|
||||
archive_dir.mkdir(parents=True, exist_ok=True)
|
||||
filename = (
|
||||
f"{datetime.now().date().isoformat()}-"
|
||||
f"{_safe_filename(str(sent_reminder.get('name', 'Mahnung')))}.eml"
|
||||
)
|
||||
archive_path = _available_path(archive_dir, filename)
|
||||
archive_temp = archive_path.with_name(f".{archive_path.name}.tmp")
|
||||
export_path: Path | None = None
|
||||
try:
|
||||
archive_temp.write_bytes(content)
|
||||
if delivery_mode == "local":
|
||||
export_temp = target.with_name(f".{target.name}.tmp")
|
||||
try:
|
||||
export_temp.write_bytes(content)
|
||||
os.replace(export_temp, target)
|
||||
finally:
|
||||
export_temp.unlink(missing_ok=True)
|
||||
export_path = target
|
||||
elif delivery_mode == "send":
|
||||
settings = repository.get_email_settings()
|
||||
sent_copy = imap_session(settings) if settings["imap_sent_enabled"] else nullcontext(None)
|
||||
with smtp_session(settings) as smtp_client, sent_copy as imap_client:
|
||||
send_via_smtp(smtp_client, content)
|
||||
if imap_client is not None:
|
||||
ensure_imap_folder(imap_client, settings["imap_sent_folder"])
|
||||
append_message(
|
||||
imap_client, content, folder=settings["imap_sent_folder"], flags=r"(\Seen)"
|
||||
)
|
||||
else:
|
||||
settings = repository.get_email_settings()
|
||||
with imap_session(settings) as client:
|
||||
ensure_imap_folder(client, settings["imap_drafts_folder"])
|
||||
append_message(client, content, folder=settings["imap_drafts_folder"], flags=r"(\Draft)")
|
||||
os.replace(archive_temp, archive_path)
|
||||
finally:
|
||||
archive_temp.unlink(missing_ok=True)
|
||||
except Exception:
|
||||
# The mail was not (verifiably) delivered/filed -- roll the reminder back to
|
||||
# "draft" so it does not sit in the "sent" state without ever having gone out,
|
||||
# and so it can be corrected and sent again.
|
||||
repository.revert_reminder_sent(member_id, claim_id, reminder_id)
|
||||
raise
|
||||
relative_path = archive_path.relative_to(
|
||||
repository.members_root / member_id / "files"
|
||||
).as_posix()
|
||||
|
||||
Reference in New Issue
Block a user