Files
orion/docs/features/email-system.md
Samir Boulahtit 7a9dda282d refactor(scripts): reorganize scripts/ into seed/ and validate/ subfolders
Move 9 init/seed scripts into scripts/seed/ and 7 validation scripts
(+ validators/ subfolder) into scripts/validate/ to reduce clutter in
the root scripts/ directory. Update all references across Makefile,
CI/CD configs, pre-commit hooks, docs (~40 files), and Python imports.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-09 21:35:53 +01:00

332 lines
7.9 KiB
Markdown

# 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:
```env
# 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:
```env
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.) |
| store_id | Integer | Related store (optional) |
| user_id | Integer | Related user (optional) |
## Usage
### Using EmailService
```python
from app.services.email_service import EmailService
def send_welcome_email(db, user, store):
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,
"merchant_name": store.name,
"store_code": store.store_code,
"login_url": f"https://wizamart.com/store/{store.store_code}/dashboard",
"trial_days": 30,
"tier_name": "Essential",
},
store_id=store.id,
user_id=user.id,
related_type="signup",
)
```
### Convenience Function
```python
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:
```python
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:
```html
<p>Hello {{ first_name }},</p>
<p>Welcome to {{ merchant_name }}!</p>
```
### Seeding Templates
Run the seed script to populate default templates:
```bash
python scripts/seed/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 |
| merchant_name | Store merchant name |
| email | User's email address |
| store_code | Store 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:
```env
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](https://sendgrid.com)
2. Generate API key in Settings > API Keys
3. Configure:
```env
EMAIL_PROVIDER=sendgrid
SENDGRID_API_KEY=SG.xxxxxxxxxxxxxxxxxxxx
```
4. Install package: `pip install sendgrid`
### Mailgun
1. Create account at [mailgun.com](https://mailgun.com)
2. Add and verify your domain
3. Get API key from Domain Settings
4. Configure:
```env
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:
```env
EMAIL_PROVIDER=ses
AWS_ACCESS_KEY_ID=AKIAXXXXXXXXXXXXXXXX
AWS_SECRET_ACCESS_KEY=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
AWS_REGION=eu-west-1
```
5. Install package: `pip install boto3`
## Email Logging
All emails are logged to the `email_logs` table. Query examples:
```python
# Get failed emails
failed = db.query(EmailLog).filter(
EmailLog.status == EmailStatus.FAILED.value
).all()
# Get emails for a store
store_emails = db.query(EmailLog).filter(
EmailLog.store_id == store_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:
```bash
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/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