# API Reference

This document describes the public API for simple-email-gw.

## Installation

### Requirements

- Python 3.10 or higher
- An email account (IMAP/SMTP access)

### Install from PyPI

```bash
pip install simple-email-gw
```

### Install with uv

```bash
uv add simple-email-gw
```

### Run with uvx

```bash
uvx --from simple-email-gw mcp-server
```

### Dependencies

| Package | Purpose |
|---------|---------|
| `fastmcp` | MCP server framework |
| `aioimaplib` | Async IMAP client |
| `aiosmtplib` | Async SMTP client |
| `pydantic` | Data validation |
| `pydantic-settings` | Settings management |

## Clients

### IMAPClient

Async IMAP client for reading and managing emails.

```python
from simple_email_gw import IMAPClient, EmailAccount

account = EmailAccount(
  name="work",
  imap_host="imap.gmail.com",
  smtp_host="smtp.gmail.com",
  username="user@gmail.com",
  password="app-password"
)

async with IMAPClient(account) as client:
  folders = await client.list_folders()
  messages = await client.search(folder="INBOX", criteria="UNSEEN")
  msg = await client.fetch_message(messages[0])
```

#### Methods

| Method | Description |
|--------|-------------|
| `connect()` | Establish IMAP connection |
| `disconnect()` | Close IMAP connection |
| `list_folders()` | List all folders/mailboxes |
| `select_folder(folder)` | Select a folder and return message count |
| `search(folder, criteria, limit)` | Search for messages |
| `fetch_message(message_id, folder)` | Fetch a single message |
| `move_message(message_id, source, dest)` | Move message between folders |
| `delete_message(message_id, folder, expunge)` | Delete a message |
| `mark_message(message_id, folder, flag, action)` | Add/remove flags |
| `download_attachment(message_id, folder, filename, output_dir)` | Download attachment |

### SMTPClient

Async SMTP client for sending emails.

```python
from simple_email_gw import SMTPClient, EmailAccount

account = EmailAccount(
  name="work",
  imap_host="imap.gmail.com",
  smtp_host="smtp.gmail.com",
  username="user@gmail.com",
  password="app-password"
)

smtp = SMTPClient(account)
result = await smtp.send_email(
  to=["recipient@example.com"],
  subject="Hello",
  body="World!"
)
```

#### Methods

| Method | Description |
|--------|-------------|
| `send_email(to, subject, body, cc, bcc, html_body, attachments)` | Send new email |
| `reply_email(to, subject, body, in_reply_to, references, html_body)` | Reply to thread |
| `forward_email(to, subject, original_from, original_date, original_body)` | Forward email |

## Configuration

### EmailAccount

Pydantic model for account configuration.

```python
from simple_email_gw import EmailAccount

account = EmailAccount(
  name="work",
  imap_host="imap.gmail.com",
  imap_port=993,
  smtp_host="smtp.gmail.com",
  smtp_port=587,
  username="user@gmail.com",
  password="app-password",
  auth_method="password",
  use_ssl=True
)
```

#### Fields

| Field | Type | Default | Description |
|-------|------|---------|-------------|
| `name` | str | "default" | Account name |
| `imap_host` | str | required | IMAP server hostname |
| `imap_port` | int | 993 | IMAP port |
| `smtp_host` | str | required | SMTP server hostname |
| `smtp_port` | int | 587 | SMTP port |
| `username` | str | required | Email address/username |
| `password` | SecretStr | None | Password or app password |
| `oauth2_token` | SecretStr | None | OAuth2 access token |
| `auth_method` | str | "password" | "password" or "oauth2" |
| `use_ssl` | bool | True | Use SSL/TLS |

### Multiple Accounts

Configure multiple accounts using JSON:

```bash
export EMAIL_ACCOUNTS_JSON='[
  {
    "name": "work",
    "imap_host": "imap.work.com",
    "smtp_host": "smtp.work.com",
    "username": "work@company.com",
    "password": "work-password"
  },
  {
    "name": "personal",
    "imap_host": "imap.gmail.com",
    "smtp_host": "smtp.gmail.com",
    "username": "personal@gmail.com",
    "password": "app-password"
  }
]'
```

### Connection Pool

Manage connections with automatic pooling.

```python
from simple_email_gw import get_pool

pool = await get_pool()

# Get accounts from environment
accounts = await pool.get_accounts()

# Get client for specific account
client = await pool.get_imap_client("work")
```

## Safety Utilities

### RateLimiter

Token bucket rate limiter.

```python
from simple_email_gw import RateLimiter

limiter = RateLimiter(rate=60, window=60)

if await limiter.acquire("account_name"):
  # Request allowed
  pass
```

### Sanitization

Functions to sanitize user input.

```python
from simple_email_gw import (
  sanitize_subject,
  sanitize_message_id,
  sanitize_references,
  sanitize_header_value,
  sanitize_folder_name,
  sanitize_filename,
  sanitize_message_id_numeric,
)

# Sanitize subject line (removes CRLF)
safe = sanitize_subject("Hello\r\nBcc: attacker@evil.com")
# Returns: "Hello Bcc: attacker@evil.com"

# Validate Message-ID format
safe_id = sanitize_message_id("<msg123@example.com>")

# Sanitize folder name (prevents CRLF injection)
safe_folder = sanitize_folder_name("INBOX")

# Sanitize filename (prevents CRLF injection)
safe_filename = sanitize_filename("document.pdf")
```

### Audit Logging

Log security events.

```python
from simple_email_gw import (
  log_event,
  log_email_sent,
  log_auth_attempt,
  log_rate_limited,
  log_attachment_download,
)

log_email_sent(
  account="work",
  recipients=["user@example.com"],
  subject="Hello",
  has_attachments=False
)

log_auth_attempt(
  account="work",
  success=True,
  method="password"
)
```

## Errors

### SecurityError

Raised when a security constraint is violated.

```python
from simple_email_gw import SecurityError

try:
  await client.download_attachment(...)
except SecurityError as e:
  # Handle security violation
  pass
```

### WhitelistError

Raised when a recipient is not in the whitelist.

```python
from simple_email_gw import WhitelistError

try:
  await smtp.send_email(to=["untrusted@evil.com"], ...)
except WhitelistError as e:
  # Handle whitelist violation
  pass
```

### RateLimitError

Raised when rate limit is exceeded.

```python
from simple_email_gw import RateLimitError

try:
  client = await pool.get_imap_client("work")
except RateLimitError:
  # Wait and retry
  pass
```

## MCP Server

For MCP server tools and resources, see [MCP Tools Reference](mcp-tools.md).

## Next Steps

- [Configuration](configuration.md) - All configuration options
- [Security](security.md) - Security features
- [MCP Tools Reference](mcp-tools.md) - MCP tools documentation