Feature: Gesendete Mails via IMAP in Sent-Ordner ablegen
This commit is contained in:
parent
b9ee67b8dd
commit
31fae63658
1 changed files with 49 additions and 7 deletions
|
|
@ -1,5 +1,6 @@
|
|||
"""BAN YARO — Mailing (Admin)"""
|
||||
|
||||
import imaplib
|
||||
import os
|
||||
import smtplib
|
||||
import ssl
|
||||
|
|
@ -19,6 +20,8 @@ router = APIRouter()
|
|||
|
||||
_SMTP_HOST = os.getenv("SMTP_HOST", "mail.your-server.de")
|
||||
_SMTP_PORT = int(os.getenv("SMTP_PORT", "587"))
|
||||
_IMAP_HOST = os.getenv("IMAP_HOST", "mail.your-server.de")
|
||||
_IMAP_PORT = int(os.getenv("IMAP_PORT", "993"))
|
||||
|
||||
_ACCOUNTS = {
|
||||
"partner": {
|
||||
|
|
@ -35,23 +38,62 @@ _ACCOUNTS = {
|
|||
},
|
||||
}
|
||||
|
||||
# Mögliche Namen für den Sent-Ordner (Hetzner/Dovecot)
|
||||
_SENT_CANDIDATES = ["Sent", "Sent Messages", "Sent Items", "INBOX.Sent", "Gesendete Objekte"]
|
||||
|
||||
|
||||
def _imap_save_sent(msg_bytes: bytes, account: str):
|
||||
acc = _ACCOUNTS.get(account) or _ACCOUNTS["partner"]
|
||||
if not acc["user"] or not acc["pass"]:
|
||||
return
|
||||
try:
|
||||
ctx = ssl.create_default_context()
|
||||
with imaplib.IMAP4_SSL(_IMAP_HOST, _IMAP_PORT, ssl_context=ctx) as imap:
|
||||
imap.login(acc["user"], acc["pass"])
|
||||
# Sent-Ordner finden
|
||||
folder = None
|
||||
_, folders = imap.list()
|
||||
available = [f.decode() for f in (folders or [])]
|
||||
for candidate in _SENT_CANDIDATES:
|
||||
if any(candidate.lower() in f.lower() for f in available):
|
||||
folder = candidate
|
||||
break
|
||||
if not folder:
|
||||
folder = "Sent" # Fallback: anlegen lassen
|
||||
imap.append(
|
||||
folder,
|
||||
r"\Seen",
|
||||
imaplib.Time2Internaldate(datetime.now().timestamp()),
|
||||
msg_bytes,
|
||||
)
|
||||
except Exception:
|
||||
pass # Nicht blockieren wenn IMAP fehlschlägt
|
||||
|
||||
|
||||
def _build_message(to: str, subject: str, body: str, account: str) -> MIMEMultipart:
|
||||
acc = _ACCOUNTS.get(account) or _ACCOUNTS["partner"]
|
||||
msg = MIMEMultipart("alternative")
|
||||
msg["Subject"] = subject
|
||||
msg["From"] = formataddr((acc["name"], acc["from"]))
|
||||
msg["To"] = to
|
||||
msg["Reply-To"] = acc["from"]
|
||||
msg.attach(MIMEText(body, "plain", "utf-8"))
|
||||
return msg
|
||||
|
||||
|
||||
def _send_smtp(to: str, subject: str, body: str, account: str = "partner"):
|
||||
acc = _ACCOUNTS.get(account) or _ACCOUNTS["partner"]
|
||||
if not acc["user"] or not acc["pass"]:
|
||||
raise RuntimeError(f"SMTP-Account '{account}' nicht konfiguriert.")
|
||||
msg = MIMEMultipart("alternative")
|
||||
msg["Subject"] = subject
|
||||
msg["From"] = formataddr((acc["name"], acc["from"]))
|
||||
msg["To"] = to
|
||||
msg["Reply-To"] = acc["from"]
|
||||
msg.attach(MIMEText(body, "plain", "utf-8"))
|
||||
msg = _build_message(to, subject, body, account)
|
||||
msg_bytes = msg.as_bytes()
|
||||
ctx = ssl.create_default_context()
|
||||
with smtplib.SMTP(_SMTP_HOST, _SMTP_PORT, timeout=15) as s:
|
||||
s.ehlo()
|
||||
s.starttls(context=ctx)
|
||||
s.login(acc["user"], acc["pass"])
|
||||
s.sendmail(acc["from"], [to], msg.as_bytes())
|
||||
s.sendmail(acc["from"], [to], msg_bytes)
|
||||
_imap_save_sent(msg_bytes, account)
|
||||
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue