Files
orion/docs/features/email-system.md
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

7.9 KiB

Email System

The email system provides multi-provider support with database-stored templates and comprehensive logging for the Wizamart platform.

Overview

The email system supports:

  • Multiple Providers: SMTP, SendGrid, Mailgun, Amazon SES
  • Multi-language Templates: EN, FR, DE, LB (stored in database)
  • Jinja2 Templating: Variable interpolation in subjects and bodies
  • Email Logging: Track all sent emails for debugging and compliance
  • Debug Mode: Log emails instead of sending during development

Configuration

Environment Variables

Add these settings to your .env file:

# Provider: smtp, sendgrid, mailgun, ses
EMAIL_PROVIDER=smtp
EMAIL_FROM_ADDRESS=noreply@wizamart.com
EMAIL_FROM_NAME=Wizamart
EMAIL_REPLY_TO=

# Behavior
EMAIL_ENABLED=true
EMAIL_DEBUG=false

# SMTP Settings (when EMAIL_PROVIDER=smtp)
SMTP_HOST=smtp.example.com
SMTP_PORT=587
SMTP_USER=
SMTP_PASSWORD=
SMTP_USE_TLS=true
SMTP_USE_SSL=false

# SendGrid (when EMAIL_PROVIDER=sendgrid)
# SENDGRID_API_KEY=SG.your_api_key_here

# Mailgun (when EMAIL_PROVIDER=mailgun)
# MAILGUN_API_KEY=your_api_key_here
# MAILGUN_DOMAIN=mg.yourdomain.com

# Amazon SES (when EMAIL_PROVIDER=ses)
# AWS_ACCESS_KEY_ID=your_access_key
# AWS_SECRET_ACCESS_KEY=your_secret_key
# AWS_REGION=eu-west-1

Debug Mode

Set EMAIL_DEBUG=true to log emails instead of sending them. This is useful during development:

EMAIL_DEBUG=true

Emails will be logged to the console with full details (recipient, subject, body preview).

Database Models

EmailTemplate

Stores multi-language email templates:

Column Type Description
id Integer Primary key
code String(100) Template identifier (e.g., "signup_welcome")
language String(5) Language code (en, fr, de, lb)
name String(255) Human-readable name
description Text Template purpose
category String(50) AUTH, ORDERS, BILLING, SYSTEM, MARKETING
subject String(500) Email subject (supports Jinja2)
body_html Text HTML body
body_text Text Plain text fallback
variables Text JSON list of expected variables
is_active Boolean Enable/disable template

EmailLog

Tracks all sent emails:

Column Type Description
id Integer Primary key
template_code String(100) Template used (if any)
recipient_email String(255) Recipient address
subject String(500) Email subject
status String(20) PENDING, SENT, FAILED, DELIVERED, OPENED
sent_at DateTime When email was sent
error_message Text Error details if failed
provider String(50) Provider used (smtp, sendgrid, etc.)
vendor_id Integer Related vendor (optional)
user_id Integer Related user (optional)

Usage

Using EmailService

from app.services.email_service import EmailService

def send_welcome_email(db, user, vendor):
    email_service = EmailService(db)

    email_service.send_template(
        template_code="signup_welcome",
        to_email=user.email,
        to_name=f"{user.first_name} {user.last_name}",
        language="fr",  # Falls back to "en" if not found
        variables={
            "first_name": user.first_name,
            "company_name": vendor.name,
            "vendor_code": vendor.vendor_code,
            "login_url": f"https://wizamart.com/vendor/{vendor.vendor_code}/dashboard",
            "trial_days": 30,
            "tier_name": "Essential",
        },
        vendor_id=vendor.id,
        user_id=user.id,
        related_type="signup",
    )

Convenience Function

from app.services.email_service import send_email

send_email(
    db=db,
    template_code="order_confirmation",
    to_email="customer@example.com",
    language="en",
    variables={"order_number": "ORD-001"},
)

Sending Raw Emails

For one-off emails without templates:

email_service = EmailService(db)

email_service.send_raw(
    to_email="user@example.com",
    subject="Custom Subject",
    body_html="<h1>Hello</h1><p>Custom message</p>",
    body_text="Hello\n\nCustom message",
)

Email Templates

Creating Templates

Templates use Jinja2 syntax for variable interpolation:

<p>Hello {{ first_name }},</p>
<p>Welcome to {{ company_name }}!</p>

Seeding Templates

Run the seed script to populate default templates:

python scripts/seed_email_templates.py

This creates templates for:

  • signup_welcome (en, fr, de, lb)

Available Variables

For signup_welcome:

Variable Description
first_name User's first name
company_name Vendor company name
email User's email address
vendor_code Vendor code for dashboard URL
login_url Direct link to dashboard
trial_days Number of trial days
tier_name Subscription tier name

Provider Setup

SMTP

Standard SMTP configuration:

EMAIL_PROVIDER=smtp
SMTP_HOST=smtp.gmail.com
SMTP_PORT=587
SMTP_USER=your-email@gmail.com
SMTP_PASSWORD=your-app-password
SMTP_USE_TLS=true

SendGrid

  1. Create account at sendgrid.com
  2. Generate API key in Settings > API Keys
  3. Configure:
EMAIL_PROVIDER=sendgrid
SENDGRID_API_KEY=SG.xxxxxxxxxxxxxxxxxxxx
  1. Install package: pip install sendgrid

Mailgun

  1. Create account at mailgun.com
  2. Add and verify your domain
  3. Get API key from Domain Settings
  4. Configure:
EMAIL_PROVIDER=mailgun
MAILGUN_API_KEY=key-xxxxxxxxxxxxxxxx
MAILGUN_DOMAIN=mg.yourdomain.com

Amazon SES

  1. Set up SES in AWS Console
  2. Verify sender domain/email
  3. Create IAM user with SES permissions
  4. Configure:
EMAIL_PROVIDER=ses
AWS_ACCESS_KEY_ID=AKIAXXXXXXXXXXXXXXXX
AWS_SECRET_ACCESS_KEY=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
AWS_REGION=eu-west-1
  1. Install package: pip install boto3

Email Logging

All emails are logged to the email_logs table. Query examples:

# Get failed emails
failed = db.query(EmailLog).filter(
    EmailLog.status == EmailStatus.FAILED.value
).all()

# Get emails for a vendor
vendor_emails = db.query(EmailLog).filter(
    EmailLog.vendor_id == vendor_id
).order_by(EmailLog.created_at.desc()).all()

# Get recent signup emails
signups = db.query(EmailLog).filter(
    EmailLog.template_code == "signup_welcome",
    EmailLog.created_at >= datetime.now() - timedelta(days=7)
).all()

Language Fallback

The system automatically falls back to English if a template isn't available in the requested language:

  1. Request template for "de" (German)
  2. If not found, try "en" (English)
  3. If still not found, return None (log error)

Testing

Run email service tests:

pytest tests/unit/services/test_email_service.py -v

Test coverage includes:

  • Provider abstraction (Debug, SMTP, etc.)
  • Template rendering with Jinja2
  • Language fallback behavior
  • Email sending success/failure
  • EmailLog model methods
  • Template variable handling

Architecture

app/services/email_service.py    # Email service with provider abstraction
models/database/email.py         # EmailTemplate and EmailLog models
app/core/config.py               # Email configuration settings
scripts/seed_email_templates.py  # Template seeding script

Provider Abstraction

The system uses a strategy pattern for email providers:

EmailProvider (ABC)
├── SMTPProvider
├── SendGridProvider
├── MailgunProvider
├── SESProvider
└── DebugProvider

Each provider implements the send() method with the same signature, making it easy to switch providers via configuration.

Future Enhancements

Planned improvements:

  1. Email Queue: Background task queue for high-volume sending
  2. Webhook Tracking: Track deliveries, opens, clicks via provider webhooks
  3. Template Editor: Admin UI for editing templates
  4. A/B Testing: Test different email versions
  5. Scheduled Emails: Send emails at specific times