implementation of the verification email for the admin

This commit is contained in:
2026-10-03 11:48:35 +02:00
parent bd8ff143ad
commit 13aca86d5d
2 changed files with 108 additions and 1 deletions
+63 -1
View File
@@ -27,7 +27,12 @@ from bson.binary import Binary
import user as user_store
import buchungen
import server_steering as steering
from modules.emailservice.email import send_register_token, send_accreditation_email, send_trial_notification
from modules.emailservice.email import (
send_register_token,
send_accreditation_email,
send_trial_notification,
send_booking_admin_notification,
)
import secrets
import requests
from server_steering import Instance
@@ -2411,6 +2416,37 @@ def background_booking_provisioning(
)
print(f"[WARNING] E-Mail-Versand fehlgeschlagen: {mail_err}")
booking_request = req_col.find_one({"_id": ObjectId(prov_id)}) or {}
booking_data = booking_request.get("booking_data") or {}
admin_email_sent = send_booking_admin_notification({
"booking_number": booking_request.get("booking_number"),
"username": username,
"school_name": school_name,
"contact_person": booking_data.get("contact_person"),
"contact_email": booking_data.get("contact_email") or user_email,
"contact_phone": booking_data.get("contact_phone"),
"school_number": booking_data.get("school_number"),
"billing_organization": booking_data.get("billing_organization"),
"billing_street": booking_data.get("billing_street"),
"billing_zip": booking_data.get("billing_zip"),
"billing_city": booking_data.get("billing_city"),
"billing_reference": booking_data.get("billing_reference"),
"package": booking_request.get("package_label") or booking_request.get("package"),
"amount_eur": booking_request.get("amount_eur"),
"booking_flow": booking_request.get("booking_flow"),
"invoice_id": booking_request.get("invoice_id"),
"subdomain": effective_subdomain,
"domain": domain,
"payment_due_at": booking_request.get("due_date") or expires_at,
"avv_version": booking_data.get("avv_version"),
"legal_consents_accepted_at": booking_data.get("legal_consents_accepted_at"),
"notes": booking_data.get("notes"),
})
req_col.update_one(
{"_id": ObjectId(prov_id)},
{"$set": {"admin_email_status": "sent" if admin_email_sent else "failed", "admin_email_updated_at": _utc_now_iso()}},
)
# 8. Status in instance_requests auf "ready" setzen
update_fields = {
"provision_status": "ready",
@@ -3153,6 +3189,31 @@ def booking_payment():
finally:
req_client.close()
admin_email_sent = send_booking_admin_notification({
"booking_number": booking_number,
"username": session.get("username"),
"school_name": form_data.get("school_name"),
"contact_person": form_data.get("contact_person"),
"contact_email": form_data.get("contact_email") or user_email,
"contact_phone": form_data.get("contact_phone"),
"school_number": form_data.get("school_number"),
"billing_organization": form_data.get("billing_organization"),
"billing_street": form_data.get("billing_street"),
"billing_zip": form_data.get("billing_zip"),
"billing_city": form_data.get("billing_city"),
"billing_reference": form_data.get("billing_reference"),
"package": selected_package,
"amount_eur": total_price,
"booking_flow": booking_flow,
"invoice_id": invoice_id,
"subdomain": subdomain,
"domain": reuse_instance.get("domain") or f"{subdomain}.invario-software.de",
"payment_due_at": (date.today() + timedelta(days=PAYMENT_GRACE_DAYS)).isoformat(),
"avv_version": form_data.get("avv_version"),
"legal_consents_accepted_at": form_data.get("legal_consents_accepted_at"),
"notes": form_data.get("notes"),
})
email_status = "not_sent"
if user_email:
try:
@@ -3181,6 +3242,7 @@ def booking_payment():
{"$set": {
"email_status": email_status,
"email_recipient": user_email or "",
"admin_email_status": "sent" if admin_email_sent else "failed",
"email_updated_at": _utc_now_iso(),
}},
)
+45
View File
@@ -1,6 +1,7 @@
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.application import MIMEApplication
from html import escape
import smtplib
import time
import os
@@ -237,6 +238,50 @@ def send_trial_notification(
"""
return send(recipient, subject, text_body=text_body, html_body=html_body)
def send_booking_admin_notification(booking: dict, recipient: str = "info@invario-software.de") -> bool:
"""Notify the internal address about every completed product booking."""
labels = {
"booking_number": "Buchungsnummer",
"username": "Benutzername",
"school_name": "Schule",
"contact_person": "Ansprechpartner",
"contact_email": "Dienstliche E-Mail",
"contact_phone": "Telefon",
"school_number": "Dienststellennummer",
"billing_organization": "Rechnungsempfänger",
"billing_street": "Rechnungsstraße",
"billing_zip": "Rechnungs-PLZ",
"billing_city": "Rechnungsort",
"billing_reference": "Kassenzeichen / Aktenzeichen",
"package": "Gebuchte Produkte",
"amount_eur": "Betrag netto",
"booking_flow": "Buchungsfluss",
"invoice_id": "Rechnungs-ID",
"subdomain": "Subdomain",
"domain": "Domain",
"payment_due_at": "Zahlungsziel",
"avv_version": "AVV-Fassung",
"legal_consents_accepted_at": "Rechtsannahmen bestätigt am",
"notes": "Notizen",
}
rows = [(label, str(booking.get(key) or "-")) for key, label in labels.items()]
text_body = "Neue Produktbuchung\n\n" + "\n".join(f"{label}: {value}" for label, value in rows)
html_rows = "".join(
f"<tr><td><strong>{escape(label)}</strong></td><td>{escape(value)}</td></tr>"
for label, value in rows
)
html_body = f"""
<div style="font-family: Arial, sans-serif; color: #333333;">
<h2>Neue Produktbuchung</h2>
<table cellpadding="6" cellspacing="0" border="1" style="border-collapse: collapse; border-color: #d9e2e8;">
{html_rows}
</table>
<p style="color:#64748b;">Das Initialpasswort wird aus Sicherheitsgründen nicht per Admin-Benachrichtigung versendet.</p>
</div>
"""
return send(recipient, "Neue Produktbuchung bei Invario", text_body=text_body, html_body=html_body)
def send_password_reset_token(email: str, token: str) -> bool:
"""Sends a professionally styled password reset token to the user."""
subject = "Aktion erforderlich: Ihr Passwort-Zurücksetzungs-Code für Invario"