The previous fix reverted the reminder to "draft" on any failure after
mark_reminder_sent, including failures that happened after the mail had
already been handed to send_via_smtp or appended to an IMAP folder. That
made a successful send followed by a Sent-folder-copy or archive-move
failure look like nothing was sent, inviting a duplicate send/fee booking
on retry -- the same "sent" flag needs to be preserved once delivery is
no longer reversible, per follow-up review.
reminder_mail.generate_and_send_reminder_mail and
sepa_mail.generate_debit_mails now track whether the mail actually left
the building (SMTP accepted / IMAP append succeeded / local file written)
separately from the later archiving step:
- Failure before that point: reminder_mail reverts to draft (unchanged);
sepa_mail now records a warning and continues with the remaining
debits instead of aborting the whole batch.
- Failure after that point (Sent-copy append, moving the archive file
into place): the reminder stays "sent" / the debit stays in the
batch's results, an event is still logged for traceability (with an
archive_error note and no document reference), and the caller gets a
clear error to follow up on manually -- no rollback, no silent loss of
the fact that the mail already went out.
A raw SMTP send has no server-side "Sent" copy on its own (unlike IMAP
drafts, which are inherently server-side) -- add an opt-in checkbox plus a
configurable target folder so directly sent Mahnungen/SEPA-info-mails still
show up in the account's Gesendet/Sent folder like a normal mail client
would leave them. Applies only to "send" delivery; drafts already live on
the server by definition.
Both the Entwürfe- and Gesendet-folder fields are now editable comboboxes:
a new "Ordnerliste laden" button fetches the real folder list from the IMAP
server (needs working credentials first) via LIST, decoding folder names
from modified UTF-7 (RFC 3501) so names like "Entwürfe" render correctly
instead of as "Entw&APw-rfe". Free text still works -- ensure_imap_folder()
creates the folder on first use if it doesn't exist yet, checked once per
batch rather than before every single message.
mail_delivery.append_to_imap_drafts() became the more general
append_message(client, content, folder=, flags=), reused for both the
\Draft and \Seen cases.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Mahnungs- and SEPA-info-mails could previously only be saved as a local .eml
file that still had to be manually imported into Thunderbird. Add a per-store
"E-Mail-Versand" configuration (Optionen -> E-Mail-Versand, stored in
repository.json alongside the rest of the club's settings, since different
stores may use different mailboxes) with four delivery modes:
- "Lokal speichern": today's behaviour, unchanged default for existing stores.
- "Direkt versenden": sends via SMTP.
- "Als Entwurf ablegen": IMAP APPENDs into a configurable drafts folder, so it
shows up live in whatever mail client is already watching that account.
- "Jedes Mal fragen": prompts once per generation action (not per e-mail --
a SEPA batch can cover dozens of members) with Senden/Entwürfe/Abbrechen.
New ccma.services.mail_delivery module (smtplib/imaplib, no new dependency)
opens one authenticated connection per batch and reuses it across all
messages instead of reconnecting per recipient. Both "Verbindung testen"
buttons in Options exercise the same connection path used for real delivery.
The archived per-member copy of every generated e-mail is unaffected and
still always written regardless of delivery mode.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>