# Mail Integration

The Nexios Mail contrib module provides a comprehensive email sending solution with SMTP support, template integration, and background task processing.

## Overview

Nexios Mail is a powerful and easy-to-use email sending solution for Nexios applications that includes:

- **SMTP Support**: Full SMTP configuration with TLS/SSL support
- **Template Integration**: Jinja2-based HTML email templates
- **Background Tasks**: Async email sending with nexios-contrib tasks
- **Dependency Injection**: Easy integration with Nexios applications
- **Multiple Providers**: Pre-configured settings for Gmail, Outlook, SendGrid
- **Attachments**: Support for file attachments and inline images
- **Error Handling**: Comprehensive error reporting and logging

## Installation

```bash
# Basic installation
pip install nexios-contrib[mail]

# With template support
pip install nexios-contrib[mail,templating]

# With all features
pip install nexios-contrib[all]
```

## Quick Start

### Basic Setup

```python
from nexios import NexiosApp
from nexios_contrib.mail import setup_mail, MailConfig

app = NexiosApp()

# Setup with environment variables
mail_client = setup_mail(app)

# Or with custom configuration
config = MailConfig(
    smtp_host="smtp.gmail.com",
    smtp_port=587,
    smtp_username="your-email@gmail.com",
    smtp_password="your-app-password",
    use_tls=True,
    default_from="Your Name <your-email@gmail.com>"
)
mail_client = setup_mail(app, config=config)
```

### Environment Variables

```bash
# SMTP Configuration
SMTP_HOST=smtp.gmail.com
SMTP_PORT=587
SMTP_USERNAME=your-email@gmail.com
SMTP_PASSWORD=your-app-password
SMTP_USE_TLS=true
SMTP_USE_SSL=false

# Email Defaults
MAIL_DEFAULT_FROM=Your Name <your-email@gmail.com>
MAIL_DEFAULT_REPLY_TO=support@yourcompany.com

# Template Directory
MAIL_TEMPLATE_DIR=templates/emails

# Debug Settings
MAIL_DEBUG=false
MAIL_SUPPRESS_SEND=false
```

## Usage Examples

### Sending Basic Emails

```python
from nexios.http import Request, Response
from nexios_contrib.mail import MailDepend

@app.post("/send-email")
async def send_email(
    request: Request,
    response: Response,
    mail_client: MailClient = MailDepend()
):
    result = await mail_client.send_email(
        to="user@example.com",
        subject="Welcome to Our Service",
        body="Thank you for joining our platform!",
        html_body="<h1>Welcome!</h1><p>Thank you for joining our platform!</p>"
    )
    
    return response.json({
        "success": result.success,
        "message_id": result.message_id,
        "sent_at": result.sent_at.isoformat()
    })
```

### Using Email Templates

Create templates in your `templates/emails/` directory:

**templates/emails/welcome.html**
```html
<!DOCTYPE html>
<html>
<head>
    <title>Welcome {{ name }}!</title>
</head>
<body>
    <h1>Welcome {{ name }}!</h1>
    <p>Thank you for joining {{ company_name }}.</p>
    <p>Your account has been created with email: {{ email }}</p>
    <a href="{{ activation_url }}">Activate Your Account</a>
</body>
</html>
```

**templates/emails/welcome.txt**
```text
Welcome {{ name }}!

Thank you for joining {{ company_name }}.
Your account has been created with email: {{ email }}.

Activate Your Account: {{ activation_url }}
```

Send template emails:

```python
@app.post("/send-welcome")
async def send_welcome_email(
    request: Request,
    response: Response,
    mail_client: MailClient = MailDepend()
):
    result = await mail_client.send_template_email(
        to="newuser@example.com",
        subject="Welcome to Our Platform!",
        template_name="welcome",
        context={
            "name": "John Doe",
            "email": "newuser@example.com",
            "company_name": "Acme Corp",
            "activation_url": "https://example.com/activate/12345"
        }
    )
    
    return response.json({"success": result.success, "message_id": result.message_id})
```

### Background Email Sending

Send emails asynchronously without blocking your API responses:

```python
from nexios_contrib.mail import send_email_async

@app.post("/send-async")
async def send_async_email(
    request: Request,
    response: Response
):
    task = await send_email_async(
        request=request,
        to="user@example.com",
        subject="Processing Your Request",
        body="We're processing your request and will notify you when complete."
    )
    
    return response.json({
        "message": "Email queued for sending",
        "task_id": task.id if task else None
    })
```

## Configuration

### Provider-Specific Configurations

#### Gmail
```python
config = MailConfig.for_gmail(
    username="your-email@gmail.com",
    password="your-app-password",  # Use app password, not regular password
    default_from="Your Name <your-email@gmail.com>"
)
```

#### Outlook/Office 365
```python
config = MailConfig.for_outlook(
    username="your-email@outlook.com",
    password="your-password",
    default_from="Your Name <your-email@outlook.com>"
)
```

#### SendGrid
```python
config = MailConfig.for_sendgrid(
    api_key="your-sendgrid-api-key",
    default_from="your-email@yourdomain.com"
)
```

## Advanced Features

### Custom Email Messages

```python
from nexios_contrib.mail import EmailMessage

# Create detailed email message
message = EmailMessage(
    to="recipient@example.com",
    subject="Custom Email",
    body="Plain text content",
    html_body="<h1>HTML Content</h1>",
    cc="manager@example.com",
    bcc="archive@example.com",
    priority=1  # High priority
)

# Add custom headers
message.add_header("X-Campaign-ID", "summer-2024")
message.add_header("X-Mailer", "Nexios Mail")

# Add attachments
message.add_attachment("report.pdf", b"PDF content", "application/pdf")

# Send the message
result = await mail_client.send_message(message)
```

### Template Custom Filters

```python
# Add custom Jinja2 filters
def format_currency(value, currency="USD"):
    return f"{value:.2f} {currency}"

# In your mail client setup
mail_client._template_env.filters["currency"] = format_currency

# Use in templates
{{ price | currency }}
```

## API Reference

### MailClient

The main mail client class for sending emails.

#### Methods

- `send_email(to, subject, body=None, html_body=None, **kwargs)` - Send an email
- `send_message(message)` - Send an EmailMessage object
- `send_template_email(to, subject, template_name, context=None, **kwargs)` - Send template email
- `create_message(to, subject, **kwargs)` - Create EmailMessage object

### EmailMessage

Represents an email message with all its components.

#### Properties

- `to` - Recipient email addresses
- `subject` - Email subject
- `body` - Plain text body
- `html_body` - HTML body
- `attachments` - List of attachments
- `headers` - Custom headers

#### Methods

- `add_attachment(filename, content, content_type=None, content_id=None)` - Add attachment
- `set_template(template_name, context=None)` - Set template
- `add_header(name, value)` - Add custom header

### MailConfig

Configuration for the mail client.

#### Class Methods

- `for_gmail(username, password, **kwargs)` - Gmail configuration
- `for_outlook(username, password, **kwargs)` - Outlook configuration
- `for_sendgrid(api_key, **kwargs)` - SendGrid configuration

## Best Practices

### Security

1. **Never hardcode credentials** - Always use environment variables
2. **Use app passwords** - For Gmail, generate app passwords instead of using your main password
3. **Enable TLS** - Always use TLS/SSL for secure connections
4. **Validate inputs** - Sanitize and validate all email inputs

### Performance

1. **Use background tasks** - Send emails asynchronously to avoid blocking responses
2. **Connection pooling** - Reuse SMTP connections when possible
3. **Template caching** - Templates are automatically cached for performance

### Reliability

1. **Error handling** - Always handle email sending errors gracefully
2. **Logging** - Enable debug mode during development
3. **Testing** - Use `suppress_send=True` for testing without actually sending emails

## Troubleshooting

### Common Issues

1. **Authentication Failed**
   - Check SMTP credentials
   - For Gmail, use an App Password instead of your regular password
   - Verify 2FA settings

2. **Connection Timeout**
   - Check SMTP host and port
   - Verify firewall settings
   - Increase `smtp_timeout` value

3. **Template Not Found**
   - Verify template directory path
   - Check template file names and extensions
   - Ensure template files exist

4. **Background Tasks Not Working**
   - Install nexios-contrib tasks: `pip install nexios-contrib[tasks]`
   - Setup tasks in your app: `setup_tasks(app)`

### Debug Mode

Enable debug mode to see SMTP communication:

```python
config = MailConfig(
    debug=True,  # Enables SMTP debug logging
    suppress_send=True  # Test mode - don't actually send
)
```

## Integration with Other Modules

### Background Tasks

The mail module integrates seamlessly with the nexios-contrib tasks module for async email sending:

```python
from nexios_contrib.tasks import setup_tasks
from nexios_contrib.mail import setup_mail

app = NexiosApp()

# Setup tasks first
task_manager = setup_tasks(app)

# Then setup mail (will automatically integrate with tasks)
mail_client = setup_mail(app)
```

### Templates

The mail module uses Jinja2 for template rendering, which can be integrated with your existing template setup:

```python
# Share template environment with your web templates
from jinja2 import FileSystemLoader, Environment

# Create shared template environment
template_env = Environment(
    loader=FileSystemLoader(["templates/web", "templates/emails"])
)

# Use with mail client
mail_client._template_env = template_env
```

## Examples

### Complete Email Service

```python
from nexios import NexiosApp
from nexios_contrib.mail import setup_mail, MailConfig, MailDepend
from nexios_contrib.tasks import setup_tasks
import os

app = NexiosApp()

# Setup background tasks
task_manager = setup_tasks(app)

# Setup mail
config = MailConfig(
    smtp_host=os.getenv("SMTP_HOST"),
    smtp_port=int(os.getenv("SMTP_PORT")),
    smtp_username=os.getenv("SMTP_USERNAME"),
    smtp_password=os.getenv("SMTP_PASSWORD"),
    use_tls=True,
    default_from=os.getenv("MAIL_DEFAULT_FROM"),
    template_directory="templates/emails"
)
mail_client = setup_mail(app, config=config)

@app.post("/send-welcome")
async def send_welcome_email(
    request: Request,
    response: Response,
    mail_client: MailClient = MailDepend()
):
    data = await request.json
    
    result = await mail_client.send_template_email(
        to=data["email"],
        subject="Welcome to Our Platform!",
        template_name="welcome",
        context={
            "name": data["name"],
            "email": data["email"],
            "company_name": "Acme Corp"
        }
    )
    
    return response.json({
        "success": result.success,
        "message_id": result.message_id,
        "error": result.error
    })

@app.post("/send-async")
async def send_async_email(
    request: Request,
    response: Response
):
    data = await request.json
    
    task = await send_email_async(
        request=request,
        to=data["email"],
        subject=data["subject"],
        body=data["body"]
    )
    
    return response.json({
        "message": "Email queued for sending",
        "task_id": task.id if task else None
    })
```

This comprehensive mail integration provides everything you need to add professional email functionality to your Nexios applications with ease.
