# SMTP Backend Usage Guide

This guide covers using `amsdal_mail` with SMTP servers, with Gmail as the primary example.

## Setup

### Installation

```bash
pip install amsdal-mail[smtp]
```

### Gmail Configuration

Gmail requires an [App Password](https://support.google.com/accounts/answer/185833) (not your regular password). Enable 2-Step Verification first, then generate an App Password.

**Via environment variables:**

```bash
export AMSDAL_EMAIL_BACKEND=smtp
export AMSDAL_EMAIL_HOST=smtp.gmail.com
export AMSDAL_EMAIL_PORT=587
export AMSDAL_EMAIL_USER=you@gmail.com
export AMSDAL_EMAIL_PASSWORD=your-app-password
export AMSDAL_EMAIL_USE_TLS=true
```

**Via code:**

```python
from amsdal_mail import get_connection

connection = get_connection(
    backend='smtp',
    host='smtp.gmail.com',
    port=587,
    username='you@gmail.com',
    password='your-app-password',
    use_tls=True,
)
```

### Other SMTP Providers

| Provider | Host | Port | TLS | SSL |
|----------|------|------|-----|-----|
| Gmail | `smtp.gmail.com` | 587 | Yes | No |
| Outlook/Hotmail | `smtp.office365.com` | 587 | Yes | No |
| Yahoo | `smtp.mail.yahoo.com` | 465 | No | Yes |
| Zoho | `smtp.zoho.com` | 587 | Yes | No |
| Custom (SSL) | your-server.com | 465 | No | Yes |

For SSL on port 465 use `AMSDAL_EMAIL_USE_SSL=true` instead of `AMSDAL_EMAIL_USE_TLS`.

---

## Examples

### Send a Simple Email

```python
from amsdal_mail import send_mail

status = send_mail(
    'Welcome!',
    'Thanks for signing up.',
    'you@gmail.com',
    'recipient@example.com',
)

if status.is_success:
    print('Sent!')
```

### Multiple Recipients

```python
from amsdal_mail import send_mail

status = send_mail(
    'Team Update',
    'Here is the weekly update.',
    'you@gmail.com',
    ['alice@example.com', 'bob@example.com', 'carol@example.com'],
)

print(f'Successful: {status.get_successful_recipients()}')
print(f'Failed: {status.get_failed_recipients()}')
```

### CC, BCC, and Reply-To

Pass additional fields through `**kwargs` — they are forwarded to `EmailMessage`:

```python
from amsdal_mail import send_mail

status = send_mail(
    'Project Proposal',
    'Please review the attached proposal.',
    'you@gmail.com',
    ['client@example.com'],
    cc=['manager@example.com'],
    bcc=['archive@example.com'],
    reply_to=['support@example.com'],
)
```

### Custom Headers

```python
from amsdal_mail import send_mail

status = send_mail(
    'Urgent Request',
    'Please respond ASAP.',
    'you@gmail.com',
    ['recipient@example.com'],
    headers={
        'X-Priority': '1',
        'X-Mailer': 'amsdal_mail',
    },
)
```

### HTML Email

```python
from amsdal_mail import send_mail

status = send_mail(
    'Monthly Newsletter',
    'Your email client does not support HTML.',  # plain text fallback
    'you@gmail.com',
    ['subscriber@example.com'],
    html_message="""
    <html>
    <body>
        <h1>Monthly Newsletter</h1>
        <p>Here are the highlights for this month:</p>
        <ul>
            <li>Feature A released</li>
            <li>Performance improvements</li>
        </ul>
    </body>
    </html>
    """,
)
```

### Attachments

```python
from pathlib import Path

from amsdal_mail import Attachment
from amsdal_mail import EmailMessage
from amsdal_mail import get_connection

# Read file from disk
pdf_path = Path('report.pdf')
pdf_data = pdf_path.read_bytes()

message = EmailMessage(
    subject='Q4 Report',
    body='Please find the report attached.',
    from_email='you@gmail.com',
    to=['manager@example.com'],
    attachments=[
        Attachment(
            filename='report.pdf',
            content=pdf_data,
            mimetype='application/pdf',
        ),
    ],
)

connection = get_connection(backend='smtp')
status = connection.send_messages([message])
```

#### Multiple Attachments

```python
message = EmailMessage(
    subject='Project Files',
    body='All files are attached.',
    from_email='you@gmail.com',
    to=['colleague@example.com'],
    attachments=[
        Attachment(
            filename='document.pdf',
            content=Path('document.pdf').read_bytes(),
            mimetype='application/pdf',
        ),
        Attachment(
            filename='data.csv',
            content=Path('data.csv').read_bytes(),
            mimetype='text/csv',
        ),
        Attachment(
            filename='photo.jpg',
            content=Path('photo.jpg').read_bytes(),
            mimetype='image/jpeg',
        ),
    ],
)
```

### Inline Images (CID)

Embed images directly in HTML using `cid:` URLs. Set `content_id` on the attachment — it will be rendered inline instead of as a downloadable file.

```python
from pathlib import Path

from amsdal_mail import Attachment
from amsdal_mail import EmailMessage
from amsdal_mail import get_connection

logo_data = Path('logo.png').read_bytes()
banner_data = Path('banner.jpg').read_bytes()

message = EmailMessage(
    subject='Welcome to Our Service',
    body='Welcome! Please enable HTML to view this email.',
    html_body="""
    <html>
    <body>
        <img src="cid:logo" alt="Logo" width="120">
        <h1>Welcome!</h1>
        <img src="cid:banner" alt="Banner" width="600">
        <p>We're glad to have you on board.</p>
    </body>
    </html>
    """,
    from_email='you@gmail.com',
    to=['user@example.com'],
    attachments=[
        Attachment(
            filename='logo.png',
            content=logo_data,
            mimetype='image/png',
            content_id='logo',
        ),
        Attachment(
            filename='banner.jpg',
            content=banner_data,
            mimetype='image/jpeg',
            content_id='banner',
        ),
    ],
)

connection = get_connection(backend='smtp')
status = connection.send_messages([message])
```

#### Mixing Inline Images and Regular Attachments

You can combine inline images with regular downloadable attachments in the same email:

```python
message = EmailMessage(
    subject='Invoice with Logo',
    body='Please enable HTML to view this email.',
    html_body='<img src="cid:logo"><h1>Invoice #1234</h1><p>See attached PDF.</p>',
    from_email='you@gmail.com',
    to=['client@example.com'],
    attachments=[
        Attachment(
            filename='logo.png',
            content=Path('logo.png').read_bytes(),
            mimetype='image/png',
            content_id='logo',           # inline — embedded in HTML
        ),
        Attachment(
            filename='invoice.pdf',
            content=Path('invoice.pdf').read_bytes(),
            mimetype='application/pdf',  # regular — downloadable attachment
        ),
    ],
)
```

### Batch Sending

Reuse a single SMTP connection for multiple messages:

```python
from amsdal_mail import EmailMessage
from amsdal_mail import get_connection

messages = [
    EmailMessage(
        subject=f'Notification for {name}',
        body=f'Hello {name}, you have a new notification.',
        from_email='you@gmail.com',
        to=[email],
    )
    for name, email in [
        ('Alice', 'alice@example.com'),
        ('Bob', 'bob@example.com'),
        ('Carol', 'carol@example.com'),
    ]
]

# Single connection for all messages
with get_connection(backend='smtp') as connection:
    status = connection.send_messages(messages)

print(f'All succeeded: {status.is_success}')
print(f'Failed: {status.get_failed_recipients()}')
```

### Async Sending

```python
import asyncio

from amsdal_mail import asend_mail

async def main():
    status = await asend_mail(
        'Async Email',
        'Sent asynchronously via aiosmtplib.',
        'you@gmail.com',
        ['recipient@example.com'],
    )
    print(f'Success: {status.is_success}')

asyncio.run(main())
```

#### Async Batch via EmailMessage

```python
import asyncio

from amsdal_mail import EmailMessage
from amsdal_mail import get_connection

async def send_notifications():
    messages = [
        EmailMessage(
            subject=f'Hello {name}',
            body=f'Hi {name}, this is your notification.',
            from_email='you@gmail.com',
            to=[email],
        )
        for name, email in [('Alice', 'alice@example.com'), ('Bob', 'bob@example.com')]
    ]

    connection = get_connection(backend='smtp')
    status = await connection.asend_messages(messages)
    print(f'Success: {status.is_success}')

asyncio.run(send_notifications())
```

### Error Handling

```python
from amsdal_mail import EmailConnectionError
from amsdal_mail import SendError
from amsdal_mail import send_mail

# Raise on errors (default)
try:
    status = send_mail(
        'Test',
        'Body',
        'you@gmail.com',
        ['recipient@example.com'],
    )
except EmailConnectionError:
    print('Could not connect to SMTP server')
except SendError:
    print('Failed to send message')

# Suppress errors — failed recipients appear in status instead
status = send_mail(
    'Test',
    'Body',
    'you@gmail.com',
    ['good@example.com', 'bad-address@invalid'],
    fail_silently=True,
)

if status.has_failures:
    print(f'Failed recipients: {status.get_failed_recipients()}')
```

## Environment Variables Reference

| Variable | Default | Description |
|----------|---------|-------------|
| `AMSDAL_EMAIL_BACKEND` | `console` | Backend name or full class path |
| `AMSDAL_EMAIL_HOST` | `localhost` | SMTP server hostname |
| `AMSDAL_EMAIL_PORT` | `25` | SMTP server port |
| `AMSDAL_EMAIL_USER` | — | SMTP username |
| `AMSDAL_EMAIL_PASSWORD` | — | SMTP password |
| `AMSDAL_EMAIL_USE_TLS` | `false` | Use STARTTLS (port 587) |
| `AMSDAL_EMAIL_USE_SSL` | `false` | Use SSL/TLS (port 465) |
| `AMSDAL_EMAIL_TIMEOUT` | `30` | Connection timeout in seconds |
