Files
orion/scripts/seed_email_templates.py
Samir Boulahtit 64fd8b5194 feat: add email system with multi-provider support
Implements a comprehensive email system with:
- Multi-provider support (SMTP, SendGrid, Mailgun, Amazon SES)
- Database-stored templates with i18n (EN, FR, DE, LB)
- Jinja2 template rendering with variable interpolation
- Email logging for debugging and compliance
- Debug mode for development (logs instead of sending)
- Welcome email integration in signup flow

New files:
- models/database/email.py: EmailTemplate and EmailLog models
- app/services/email_service.py: Provider abstraction and service
- scripts/seed_email_templates.py: Template seeding script
- tests/unit/services/test_email_service.py: 28 unit tests
- docs/features/email-system.md: Complete documentation

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-27 21:05:50 +01:00

419 lines
16 KiB
Python

#!/usr/bin/env python3
"""
Seed default email templates.
Run: python scripts/seed_email_templates.py
"""
import json
import sys
from pathlib import Path
# Add project root to path
sys.path.insert(0, str(Path(__file__).parent.parent))
from app.core.database import get_db
from models.database.email import EmailCategory, EmailTemplate
# =============================================================================
# EMAIL TEMPLATES
# =============================================================================
TEMPLATES = [
# -------------------------------------------------------------------------
# SIGNUP WELCOME
# -------------------------------------------------------------------------
{
"code": "signup_welcome",
"language": "en",
"name": "Signup Welcome",
"description": "Sent to new vendors after successful signup",
"category": EmailCategory.AUTH.value,
"variables": json.dumps([
"first_name", "company_name", "email", "vendor_code",
"login_url", "trial_days", "tier_name"
]),
"subject": "Welcome to Wizamart, {{ first_name }}!",
"body_html": """<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body style="font-family: Arial, sans-serif; line-height: 1.6; color: #333; max-width: 600px; margin: 0 auto; padding: 20px;">
<div style="background: linear-gradient(135deg, #6366f1 0%, #8b5cf6 100%); padding: 30px; border-radius: 10px 10px 0 0;">
<h1 style="color: white; margin: 0; font-size: 28px;">Welcome to Wizamart!</h1>
</div>
<div style="background: #f9fafb; padding: 30px; border-radius: 0 0 10px 10px;">
<p style="font-size: 16px;">Hi {{ first_name }},</p>
<p>Thank you for signing up for Wizamart! Your account for <strong>{{ company_name }}</strong> is now active.</p>
<div style="background: white; border-radius: 8px; padding: 20px; margin: 20px 0; border-left: 4px solid #6366f1;">
<h3 style="margin-top: 0; color: #6366f1;">Your Account Details</h3>
<p style="margin: 5px 0;"><strong>Vendor Code:</strong> {{ vendor_code }}</p>
<p style="margin: 5px 0;"><strong>Plan:</strong> {{ tier_name }}</p>
<p style="margin: 5px 0;"><strong>Trial Period:</strong> {{ trial_days }} days free</p>
</div>
<p>You can start managing your orders, inventory, and invoices right away:</p>
<div style="text-align: center; margin: 30px 0;">
<a href="{{ login_url }}" style="background: #6366f1; color: white; padding: 14px 28px; text-decoration: none; border-radius: 8px; font-weight: bold; display: inline-block;">
Go to Dashboard
</a>
</div>
<h3 style="color: #374151;">Getting Started</h3>
<ol style="color: #4b5563;">
<li>Complete your company profile</li>
<li>Connect your Letzshop API credentials</li>
<li>Import your products</li>
<li>Start syncing orders!</li>
</ol>
<p style="color: #6b7280; font-size: 14px; margin-top: 30px;">
If you have any questions, just reply to this email or visit our help center.
</p>
<p>Best regards,<br><strong>The Wizamart Team</strong></p>
</div>
<div style="text-align: center; padding: 20px; color: #9ca3af; font-size: 12px;">
<p>&copy; 2024 Wizamart. Built for Luxembourg e-commerce.</p>
</div>
</body>
</html>""",
"body_text": """Welcome to Wizamart!
Hi {{ first_name }},
Thank you for signing up for Wizamart! Your account for {{ company_name }} is now active.
Your Account Details:
- Vendor Code: {{ vendor_code }}
- Plan: {{ tier_name }}
- Trial Period: {{ trial_days }} days free
You can start managing your orders, inventory, and invoices right away.
Go to Dashboard: {{ login_url }}
Getting Started:
1. Complete your company profile
2. Connect your Letzshop API credentials
3. Import your products
4. Start syncing orders!
If you have any questions, just reply to this email.
Best regards,
The Wizamart Team
""",
},
{
"code": "signup_welcome",
"language": "fr",
"name": "Bienvenue après inscription",
"description": "Envoyé aux nouveaux vendeurs après inscription",
"category": EmailCategory.AUTH.value,
"variables": json.dumps([
"first_name", "company_name", "email", "vendor_code",
"login_url", "trial_days", "tier_name"
]),
"subject": "Bienvenue sur Wizamart, {{ first_name }} !",
"body_html": """<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body style="font-family: Arial, sans-serif; line-height: 1.6; color: #333; max-width: 600px; margin: 0 auto; padding: 20px;">
<div style="background: linear-gradient(135deg, #6366f1 0%, #8b5cf6 100%); padding: 30px; border-radius: 10px 10px 0 0;">
<h1 style="color: white; margin: 0; font-size: 28px;">Bienvenue sur Wizamart !</h1>
</div>
<div style="background: #f9fafb; padding: 30px; border-radius: 0 0 10px 10px;">
<p style="font-size: 16px;">Bonjour {{ first_name }},</p>
<p>Merci de vous être inscrit sur Wizamart ! Votre compte pour <strong>{{ company_name }}</strong> est maintenant actif.</p>
<div style="background: white; border-radius: 8px; padding: 20px; margin: 20px 0; border-left: 4px solid #6366f1;">
<h3 style="margin-top: 0; color: #6366f1;">Détails de votre compte</h3>
<p style="margin: 5px 0;"><strong>Code vendeur :</strong> {{ vendor_code }}</p>
<p style="margin: 5px 0;"><strong>Forfait :</strong> {{ tier_name }}</p>
<p style="margin: 5px 0;"><strong>Période d'essai :</strong> {{ trial_days }} jours gratuits</p>
</div>
<p>Vous pouvez commencer à gérer vos commandes, stocks et factures dès maintenant :</p>
<div style="text-align: center; margin: 30px 0;">
<a href="{{ login_url }}" style="background: #6366f1; color: white; padding: 14px 28px; text-decoration: none; border-radius: 8px; font-weight: bold; display: inline-block;">
Accéder au tableau de bord
</a>
</div>
<h3 style="color: #374151;">Pour commencer</h3>
<ol style="color: #4b5563;">
<li>Complétez votre profil d'entreprise</li>
<li>Connectez vos identifiants API Letzshop</li>
<li>Importez vos produits</li>
<li>Commencez à synchroniser vos commandes !</li>
</ol>
<p style="color: #6b7280; font-size: 14px; margin-top: 30px;">
Si vous avez des questions, répondez simplement à cet email.
</p>
<p>Cordialement,<br><strong>L'équipe Wizamart</strong></p>
</div>
<div style="text-align: center; padding: 20px; color: #9ca3af; font-size: 12px;">
<p>&copy; 2024 Wizamart. Conçu pour le e-commerce luxembourgeois.</p>
</div>
</body>
</html>""",
"body_text": """Bienvenue sur Wizamart !
Bonjour {{ first_name }},
Merci de vous être inscrit sur Wizamart ! Votre compte pour {{ company_name }} est maintenant actif.
Détails de votre compte :
- Code vendeur : {{ vendor_code }}
- Forfait : {{ tier_name }}
- Période d'essai : {{ trial_days }} jours gratuits
Accéder au tableau de bord : {{ login_url }}
Pour commencer :
1. Complétez votre profil d'entreprise
2. Connectez vos identifiants API Letzshop
3. Importez vos produits
4. Commencez à synchroniser vos commandes !
Cordialement,
L'équipe Wizamart
""",
},
{
"code": "signup_welcome",
"language": "de",
"name": "Willkommen nach Anmeldung",
"description": "An neue Verkäufer nach erfolgreicher Anmeldung gesendet",
"category": EmailCategory.AUTH.value,
"variables": json.dumps([
"first_name", "company_name", "email", "vendor_code",
"login_url", "trial_days", "tier_name"
]),
"subject": "Willkommen bei Wizamart, {{ first_name }}!",
"body_html": """<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body style="font-family: Arial, sans-serif; line-height: 1.6; color: #333; max-width: 600px; margin: 0 auto; padding: 20px;">
<div style="background: linear-gradient(135deg, #6366f1 0%, #8b5cf6 100%); padding: 30px; border-radius: 10px 10px 0 0;">
<h1 style="color: white; margin: 0; font-size: 28px;">Willkommen bei Wizamart!</h1>
</div>
<div style="background: #f9fafb; padding: 30px; border-radius: 0 0 10px 10px;">
<p style="font-size: 16px;">Hallo {{ first_name }},</p>
<p>Vielen Dank für Ihre Anmeldung bei Wizamart! Ihr Konto für <strong>{{ company_name }}</strong> ist jetzt aktiv.</p>
<div style="background: white; border-radius: 8px; padding: 20px; margin: 20px 0; border-left: 4px solid #6366f1;">
<h3 style="margin-top: 0; color: #6366f1;">Ihre Kontodaten</h3>
<p style="margin: 5px 0;"><strong>Verkäufercode:</strong> {{ vendor_code }}</p>
<p style="margin: 5px 0;"><strong>Tarif:</strong> {{ tier_name }}</p>
<p style="margin: 5px 0;"><strong>Testzeitraum:</strong> {{ trial_days }} Tage kostenlos</p>
</div>
<p>Sie können sofort mit der Verwaltung Ihrer Bestellungen, Bestände und Rechnungen beginnen:</p>
<div style="text-align: center; margin: 30px 0;">
<a href="{{ login_url }}" style="background: #6366f1; color: white; padding: 14px 28px; text-decoration: none; border-radius: 8px; font-weight: bold; display: inline-block;">
Zum Dashboard
</a>
</div>
<h3 style="color: #374151;">Erste Schritte</h3>
<ol style="color: #4b5563;">
<li>Vervollständigen Sie Ihr Firmenprofil</li>
<li>Verbinden Sie Ihre Letzshop API-Zugangsdaten</li>
<li>Importieren Sie Ihre Produkte</li>
<li>Starten Sie die Bestellungssynchronisierung!</li>
</ol>
<p style="color: #6b7280; font-size: 14px; margin-top: 30px;">
Bei Fragen antworten Sie einfach auf diese E-Mail.
</p>
<p>Mit freundlichen Grüßen,<br><strong>Das Wizamart-Team</strong></p>
</div>
<div style="text-align: center; padding: 20px; color: #9ca3af; font-size: 12px;">
<p>&copy; 2024 Wizamart. Entwickelt für den luxemburgischen E-Commerce.</p>
</div>
</body>
</html>""",
"body_text": """Willkommen bei Wizamart!
Hallo {{ first_name }},
Vielen Dank für Ihre Anmeldung bei Wizamart! Ihr Konto für {{ company_name }} ist jetzt aktiv.
Ihre Kontodaten:
- Verkäufercode: {{ vendor_code }}
- Tarif: {{ tier_name }}
- Testzeitraum: {{ trial_days }} Tage kostenlos
Zum Dashboard: {{ login_url }}
Erste Schritte:
1. Vervollständigen Sie Ihr Firmenprofil
2. Verbinden Sie Ihre Letzshop API-Zugangsdaten
3. Importieren Sie Ihre Produkte
4. Starten Sie die Bestellungssynchronisierung!
Mit freundlichen Grüßen,
Das Wizamart-Team
""",
},
{
"code": "signup_welcome",
"language": "lb",
"name": "Wëllkomm no der Umeldung",
"description": "Un nei Verkeefer no erfollegräicher Umeldung geschéckt",
"category": EmailCategory.AUTH.value,
"variables": json.dumps([
"first_name", "company_name", "email", "vendor_code",
"login_url", "trial_days", "tier_name"
]),
"subject": "Wëllkomm op Wizamart, {{ first_name }}!",
"body_html": """<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body style="font-family: Arial, sans-serif; line-height: 1.6; color: #333; max-width: 600px; margin: 0 auto; padding: 20px;">
<div style="background: linear-gradient(135deg, #6366f1 0%, #8b5cf6 100%); padding: 30px; border-radius: 10px 10px 0 0;">
<h1 style="color: white; margin: 0; font-size: 28px;">Wëllkomm op Wizamart!</h1>
</div>
<div style="background: #f9fafb; padding: 30px; border-radius: 0 0 10px 10px;">
<p style="font-size: 16px;">Moien {{ first_name }},</p>
<p>Merci fir d'Umeldung op Wizamart! Äre Kont fir <strong>{{ company_name }}</strong> ass elo aktiv.</p>
<div style="background: white; border-radius: 8px; padding: 20px; margin: 20px 0; border-left: 4px solid #6366f1;">
<h3 style="margin-top: 0; color: #6366f1;">Är Kontdetailer</h3>
<p style="margin: 5px 0;"><strong>Verkeefer Code:</strong> {{ vendor_code }}</p>
<p style="margin: 5px 0;"><strong>Plang:</strong> {{ tier_name }}</p>
<p style="margin: 5px 0;"><strong>Testperiod:</strong> {{ trial_days }} Deeg gratis</p>
</div>
<p>Dir kënnt direkt ufänken Är Bestellungen, Lager a Rechnungen ze verwalten:</p>
<div style="text-align: center; margin: 30px 0;">
<a href="{{ login_url }}" style="background: #6366f1; color: white; padding: 14px 28px; text-decoration: none; border-radius: 8px; font-weight: bold; display: inline-block;">
Zum Dashboard
</a>
</div>
<h3 style="color: #374151;">Fir unzefänken</h3>
<ol style="color: #4b5563;">
<li>Fëllt Äre Firmeprofil aus</li>
<li>Verbindt Är Letzshop API Zougangsdaten</li>
<li>Importéiert Är Produkter</li>
<li>Fänkt un Bestellungen ze synchroniséieren!</li>
</ol>
<p style="color: #6b7280; font-size: 14px; margin-top: 30px;">
Wann Dir Froen hutt, äntwert einfach op dës E-Mail.
</p>
<p>Mat beschte Gréiss,<br><strong>D'Wizamart Team</strong></p>
</div>
<div style="text-align: center; padding: 20px; color: #9ca3af; font-size: 12px;">
<p>&copy; 2024 Wizamart. Gemaach fir de lëtzebuergeschen E-Commerce.</p>
</div>
</body>
</html>""",
"body_text": """Wëllkomm op Wizamart!
Moien {{ first_name }},
Merci fir d'Umeldung op Wizamart! Äre Kont fir {{ company_name }} ass elo aktiv.
Är Kontdetailer:
- Verkeefer Code: {{ vendor_code }}
- Plang: {{ tier_name }}
- Testperiod: {{ trial_days }} Deeg gratis
Zum Dashboard: {{ login_url }}
Fir unzefänken:
1. Fëllt Äre Firmeprofil aus
2. Verbindt Är Letzshop API Zougangsdaten
3. Importéiert Är Produkter
4. Fänkt un Bestellungen ze synchroniséieren!
Mat beschte Gréiss,
D'Wizamart Team
""",
},
]
def seed_templates():
"""Seed email templates into database."""
db = next(get_db())
try:
created = 0
updated = 0
for template_data in TEMPLATES:
# Check if template already exists
existing = (
db.query(EmailTemplate)
.filter(
EmailTemplate.code == template_data["code"],
EmailTemplate.language == template_data["language"],
)
.first()
)
if existing:
# Update existing template
for key, value in template_data.items():
setattr(existing, key, value)
updated += 1
print(f"Updated: {template_data['code']} ({template_data['language']})")
else:
# Create new template
template = EmailTemplate(**template_data)
db.add(template)
created += 1
print(f"Created: {template_data['code']} ({template_data['language']})")
db.commit()
print(f"\nDone! Created: {created}, Updated: {updated}")
except Exception as e:
db.rollback()
print(f"Error: {e}")
raise
finally:
db.close()
if __name__ == "__main__":
seed_templates()