{greeting}
Klicke auf den Button, um fortzufahren:
Oder kopiere diesen Link in deinen Browser:
{verify_url}
Dieser Link ist 15 Minuten gültig und kann nur einmal verwendet werden.
""" Email-Service fuer Verifizierungs-Emails und Magic Links """ import smtplib import secrets import hashlib from email.mime.text import MIMEText from email.mime.multipart import MIMEMultipart from config import Config from datetime import datetime, timedelta def generate_verification_token(): """Generiert einen sicheren Verifizierungs-Token""" return secrets.token_urlsafe(32) def generate_slug_from_email(email: str) -> str: """ Generiert eindeutigen Slug aus Email Format: Erste 12 Zeichen von SHA256(email) """ email_lower = email.lower().strip() hash_obj = hashlib.sha256(email_lower.encode()) slug = hash_obj.hexdigest()[:12] return slug def generate_magic_link_token() -> str: """ Generiert sicheren Token für Magic Links 32 Byte = ~43 Zeichen URL-safe Base64 """ return secrets.token_urlsafe(32) def check_rate_limit(email: str) -> bool: """ Prüft ob User zu viele Magic Links angefordert hat Max. 3 Tokens pro Email in den letzten 60 Minuten Returns: True wenn OK, False wenn Rate Limit erreicht """ from models import User, MagicLinkToken user = User.query.filter_by(email=email).first() if not user: return True # Neue Email, kein Limit one_hour_ago = datetime.utcnow() - timedelta(hours=1) recent_tokens = MagicLinkToken.query.filter( MagicLinkToken.user_id == user.id, MagicLinkToken.created_at >= one_hour_ago ).count() return recent_tokens < 3 def send_magic_link_email(email: str, token: str, token_type: str) -> bool: """ Sendet Magic Link Email Args: email: Empfänger-Email token: Magic Link Token token_type: 'signup' oder 'login' Returns: True bei Erfolg, False bei Fehler """ # URL basierend auf Type if token_type == 'signup': verify_url = f"{Config.FRONTEND_URL}/verify-signup?token={token}" subject = "Registrierung abschließen - Container Spawner" action_text = "Registrierung abschließen" greeting = "Vielen Dank für deine Registrierung!" else: # login verify_url = f"{Config.FRONTEND_URL}/verify-login?token={token}" subject = "Login-Link - Container Spawner" action_text = "Jetzt einloggen" greeting = "Hier ist dein Login-Link:" html_content = f"""
{greeting}
Klicke auf den Button, um fortzufahren:
Oder kopiere diesen Link in deinen Browser:
{verify_url}
Dieser Link ist 15 Minuten gültig und kann nur einmal verwendet werden.