Files
TK-Wiki-Newsletter/app/services/smtp_sender.py
2026-07-03 11:35:25 +02:00

90 lines
3.2 KiB
Python

import smtplib
from datetime import datetime
from email.mime.text import MIMEText
from typing import Sequence
from sqlalchemy.orm import Session
from app.models.system import SendLog
from app.services.config_store import get_config
def get_smtp_settings(db: Session) -> dict[str, str]:
return {
"enabled": get_config(db, "smtp.enabled", "false"),
"host": get_config(db, "smtp.host", ""),
"port": get_config(db, "smtp.port", "587"),
"username": get_config(db, "smtp.username", ""),
"password": get_config(db, "smtp.password", ""),
"from_email": get_config(db, "smtp.from_email", ""),
"use_tls": get_config(db, "smtp.use_tls", "true"),
"recipients": get_config(db, "smtp.recipients", ""),
"schedule_time": get_config(db, "smtp.schedule_time", "08:00"),
"last_scheduled_date": get_config(db, "smtp.last_scheduled_date", ""),
}
def send_newsletter(
db: Session,
subject: str,
html_content: str,
text_content: str,
recipients: Sequence[str],
scheduled: bool = False,
) -> None:
settings = get_smtp_settings(db)
if settings["enabled"].lower() != "true":
_log(db, subject, recipients, "skipped", "SMTP ist deaktiviert.", scheduled)
return
if not settings["host"] or not settings["from_email"] or not recipients:
_log(db, subject, recipients, "failed", "SMTP unvollständig konfiguriert.", scheduled)
return
msg = MIMEText(html_content, "html", "utf-8")
msg["Subject"] = subject
msg["From"] = settings["from_email"]
msg["To"] = ", ".join(recipients)
try:
port = int(settings["port"])
with smtplib.SMTP(settings["host"], port, timeout=20) as server:
if settings["use_tls"].lower() == "true":
server.starttls()
if settings["username"]:
server.login(settings["username"], settings["password"])
server.sendmail(settings["from_email"], list(recipients), msg.as_string())
_log(db, subject, recipients, "sent", "Versand erfolgreich.", scheduled)
except Exception as exc:
_log(db, subject, recipients, "failed", f"Versandfehler: {exc}", scheduled)
def run_scheduled_send_if_due(db: Session, subject: str, html_content: str, text_content: str) -> None:
settings = get_smtp_settings(db)
if settings["enabled"].lower() != "true":
return
now = datetime.now()
schedule_time = settings["schedule_time"] or "08:00"
if now.strftime("%H:%M") < schedule_time:
return
today = now.strftime("%Y-%m-%d")
if settings["last_scheduled_date"] == today:
return
recipients = [r.strip() for r in settings["recipients"].split(",") if r.strip()]
send_newsletter(db, subject, html_content, text_content, recipients, scheduled=True)
from app.services.config_store import set_config
set_config(db, "smtp.last_scheduled_date", today)
def _log(db: Session, subject: str, recipients: Sequence[str], status: str, detail: str, scheduled: bool) -> None:
db.add(
SendLog(
subject=subject,
recipients=", ".join(recipients) if recipients else "-",
status=status,
detail=detail,
scheduled=scheduled,
)
)
db.commit()