Hotfix: E-Mail-Versand mit Retry (IONOS-Farm-Stoerung) #50

Zusammengeführt
IntelSight_Admin hat 1 Commits von fix/email-retry-live nach main 2026-07-10 12:20:22 +02:00 zusammengeführt
Nur Änderungen aus Commit d32746b00f werden angezeigt - Alle Commits anzeigen

Datei anzeigen

@@ -1,4 +1,5 @@
"""Async E-Mail-Versand via SMTP.""" """Async E-Mail-Versand via SMTP."""
import asyncio
import logging import logging
from email.mime.text import MIMEText from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart from email.mime.multipart import MIMEMultipart
@@ -17,6 +18,12 @@ from config import (
logger = logging.getLogger("osint.email") logger = logging.getLogger("osint.email")
# Die IONOS-SMTP-Farm (smtp.ionos.de) besteht aus ~10 Backends im DNS-Round-Robin;
# einzelne Backends koennen tot/ueberlastet sein (beobachtet 2026-07-10). Jeder
# Versuch oeffnet eine neue Verbindung und wuerfelt damit ein neues Backend.
MAIL_VERSUCHE = 3
MAIL_TIMEOUT_S = 20
async def send_email(to_email: str, subject: str, html_body: str) -> bool: async def send_email(to_email: str, subject: str, html_body: str) -> bool:
"""Sendet eine HTML-E-Mail. """Sendet eine HTML-E-Mail.
@@ -38,17 +45,30 @@ async def send_email(to_email: str, subject: str, html_body: str) -> bool:
msg.attach(MIMEText(text_content, "plain", "utf-8")) msg.attach(MIMEText(text_content, "plain", "utf-8"))
msg.attach(MIMEText(html_body, "html", "utf-8")) msg.attach(MIMEText(html_body, "html", "utf-8"))
try: letzter_fehler = None
await aiosmtplib.send( for versuch in range(1, MAIL_VERSUCHE + 1):
msg, try:
hostname=SMTP_HOST, await aiosmtplib.send(
port=SMTP_PORT, msg,
username=SMTP_USER if SMTP_USER else None, hostname=SMTP_HOST,
password=SMTP_PASSWORD if SMTP_PASSWORD else None, port=SMTP_PORT,
start_tls=SMTP_USE_TLS, username=SMTP_USER if SMTP_USER else None,
) password=SMTP_PASSWORD if SMTP_PASSWORD else None,
logger.info(f"E-Mail gesendet an {to_email}: {subject}") start_tls=SMTP_USE_TLS,
return True timeout=MAIL_TIMEOUT_S,
except Exception as e: )
logger.error(f"E-Mail-Versand fehlgeschlagen an {to_email}: {e}") logger.info(f"E-Mail gesendet an {to_email}: {subject}")
return False return True
except Exception as e:
letzter_fehler = e
logger.warning(
f"E-Mail-Versand Versuch {versuch}/{MAIL_VERSUCHE} an {to_email} fehlgeschlagen: {e}"
)
if versuch < MAIL_VERSUCHE:
await asyncio.sleep(1.5)
logger.error(
f"E-Mail-Versand endgueltig fehlgeschlagen an {to_email} "
f"nach {MAIL_VERSUCHE} Versuchen: {letzter_fehler}"
)
return False