v1.31: PDF-Lightbox mit Druck/E-Mail/Download, Mail-API Anhang-Support

This commit is contained in:
2026-10-04 18:30:42 +02:00
parent aa6f97df5f
commit a6ade223e1
7 changed files with 326 additions and 29 deletions
+22 -1
View File
@@ -13,7 +13,8 @@ Endpunkte:
GET /outbox → aktuelle Outbox (Demo/Debug)
POST /send → {"ok": true, "id": ..., "versandt": true/false}
Body: {"to": "...", "subject": "...", "text": "...", "html": "...",
optional "cc": "a@b.de, c@d.de", "from_address"/"from_name" (nur @hocks.eu)}
optional "cc": "a@b.de, c@d.de", "from_address"/"from_name" (nur @hocks.eu),
optional "attachment_b64" (base64), "attachment_filename", "attachment_mime"}
Auth: Header X-Api-Token oder Body-Feld "token" == MAIL_API_TOKEN
"""
@@ -87,6 +88,16 @@ def versenden(e: dict) -> bool:
msg.set_content(e.get("text") or "")
if e.get("html"):
msg.add_alternative(e["html"], subtype="html")
# Optionaler Anhang (base64, v1.31) – z. B. erzeugte PDF-Abrechnungen
if e.get("anhang_b64"):
import base64
daten = base64.b64decode(e["anhang_b64"])
mime = e.get("anhang_mime") or "application/pdf"
haupt, _, unter = mime.partition("/")
msg.add_attachment(
daten, maintype=haupt or "application", subtype=unter or "octet-stream",
filename=e.get("anhang_dateiname") or "anhang.pdf",
)
with smtplib.SMTP(RELAY_HOST, RELAY_PORT, timeout=20) as smtp:
smtp.send_message(msg)
return True
@@ -199,6 +210,16 @@ class Handler(BaseHTTPRequestHandler):
"versandt": False,
"angenommenAm": time.strftime("%d.%m.%Y %H:%M:%S"),
}
# Optionaler Anhang (v1.31): base64 + Dateiname + MIME, max. ca. 20 MB
anhang_b64 = str(body.get("attachment_b64", ""))
if anhang_b64:
if len(anhang_b64) > 28_000_000:
self._antwort(413, {"fehler": "Anhang zu gross (max. ca. 20 MB)"})
return
dateiname = os.path.basename(str(body.get("attachment_filename", "anhang.pdf"))) or "anhang.pdf"
eintrag["anhang_b64"] = anhang_b64
eintrag["anhang_dateiname"] = dateiname
eintrag["anhang_mime"] = str(body.get("attachment_mime", "application/pdf"))
try:
versenden(eintrag)
eintrag["versandt"] = True