# Email System

The email system provides multi-provider support with database-stored templates and comprehensive logging for the Orion 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@orion.lu
EMAIL_FROM_NAME=Orion
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://orion.lu/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
