Metadata-Version: 2.4
Name: kirimemail-smtp-sdk
Version: 1.5.0
Summary: Python SDK for Kirim.Email SMTP API
Project-URL: Homepage, https://github.com/kirimemail/kirimemail-smtp-python-sdk
Project-URL: Repository, https://github.com/kirimemail/kirimemail-smtp-python-sdk
Project-URL: Issues, https://github.com/kirimemail/kirimemail-smtp-python-sdk/issues
Project-URL: Documentation, https://github.com/kirimemail/kirimemail-smtp-python-sdk#readme
Author-email: "Kirim.Email" <support@kirim.email>
License: MIT
License-File: LICENSE
Keywords: api,email,kirim-email,sdk,smtp,transactional-email
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Communications :: Email
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.9
Requires-Dist: httpx>=0.25.0
Requires-Dist: pydantic>=2.0.0
Provides-Extra: dev
Requires-Dist: mypy>=1.0.0; extra == 'dev'
Requires-Dist: pytest-asyncio>=0.21.0; extra == 'dev'
Requires-Dist: pytest-cov>=4.0.0; extra == 'dev'
Requires-Dist: pytest>=7.0.0; extra == 'dev'
Requires-Dist: respx>=0.20.0; extra == 'dev'
Requires-Dist: ruff>=0.1.0; extra == 'dev'
Provides-Extra: test
Requires-Dist: pytest-asyncio>=0.21.0; extra == 'test'
Requires-Dist: pytest-cov>=4.0.0; extra == 'test'
Requires-Dist: pytest>=7.0.0; extra == 'test'
Requires-Dist: respx>=0.20.0; extra == 'test'
Description-Content-Type: text/markdown

# Kirim.Email SMTP Python SDK

Python SDK for Kirim.Email SMTP API - A modern, type-safe Python client for sending emails and managing SMTP services.

## Features

- 🚀 Modern Python with full type hints
- ⚡ Async/await support with httpx
- 📝 Pydantic models for data validation
- 🔄 Comprehensive error handling
- 📎 Email validation with spam detection
- 🎯 Webhook management
- 📊 User quota tracking
- 📧 Full API coverage (Domains, Credentials, Messages, Logs, Suppressions, Webhooks, Email Validation)
- 📦 Minimal dependencies

## Installation

```bash
pip install kirimemail-smtp-sdk
```

## Quick Start

```python
import asyncio
from kirimemail_smtp import SmtpClient, MessagesApi

async def send_email():
    # Initialize client
    client = SmtpClient(username="your-username", token="your-token")
    messages_api = MessagesApi(client)
    
    # Send email
    result = await messages_api.send_message(
        domain="example.com",
        message={
            "from": "sender@example.com",
            "from_name": "Company Name",
            "to": "recipient@example.com",
            "subject": "Hello from Python SDK",
            "text": "This is a test email sent using the Kirim.Email Python SDK."
        }
    )
    
    print(f"Email sent: {result}")

# Run the async function
asyncio.run(send_email())
```

## API Reference

### Client

The `SmtpClient` is the core HTTP client with authentication and error handling.

```python
from kirimemail_smtp import SmtpClient

client = SmtpClient(
    username="your-username",
    token="your-token",
    base_url="https://smtp-app.kirim.email"  # Optional, defaults to production
)
```

### Messages API

Send emails and templates:

```python
from kirimemail_smtp import MessagesApi

messages_api = MessagesApi(client)

# Send simple email
await messages_api.send_message(domain="example.com", message={
    "from": "sender@example.com",
    "from_name": "Company Name",
    "to": "recipient@example.com",
    "subject": "Test Email",
    "text": "Email content"
})

# Send with attachments
await messages_api.send_message_with_attachments(
    domain="example.com",
    message={
        "from": "sender@example.com",
        "to": "recipient@example.com",
        "subject": "Email with attachments",
        "text": "Please find attached files"
    },
    files=[
        {"field": "attachment", "filename": "document.pdf", "content": b"PDF content"}
    ]
)

# Send template email
await messages_api.send_template_message(
    domain="example.com",
    template={
        "template_guid": "template-uuid",
        "from": "sender@example.com",
        "from_name": "Company Name",
        "to": "recipient@example.com",
        "variables": {"name": "John", "product": "Premium Plan"}
    }
)

# Send with attachment processing options
await messages_api.send_message_with_attachment_options(
    domain="example.com",
    message={
        "from": "sender@example.com",
        "to": "recipient@example.com",
        "subject": "Secure Document",
        "text": "Please find attached"
    },
    files=[{"field": "attachment", "filename": "doc.pdf", "content": b"content"}],
    attachment_options={
        "compress": True,
        "password": "SecureDoc2024",
        "watermark": {"enabled": True, "text": "CONFIDENTIAL", "position": "center"}
    }
)
```

### Domains API

Manage domains:

```python
from kirimemail_smtp import DomainsApi

domains_api = DomainsApi(client)

# List domains
domains = await domains_api.list_domains()

# List domains with search
domains = await domains_api.list_domains(search="example")

# Create domain
domain = await domains_api.create_domain(
    domain="newdomain.com",
    dkim_key_length=2048
)

# Get domain details
domain = await domains_api.get_domain("example.com")

# Update domain tracking settings
await domains_api.update_domain("example.com", {
    "open_track": True,
    "click_track": True,
    "unsub_track": True
})

# Delete domain
await domains_api.delete_domain("example.com")

# Setup authentication domain
await domains_api.setup_auth_domain("example.com", {
    "auth_domain": "auth.example.com",
    "dkim_key_length": 2048
})

# Verify mandatory DNS records
result = await domains_api.verify_mandatory_records("example.com")

# Verify authentication domain records
result = await domains_api.verify_auth_domain_records("example.com")

# Setup tracking domain
await domains_api.setup_tracklink("example.com", "track.example.com")

# Verify tracking domain
result = await domains_api.verify_tracklink("example.com")
```

### Credentials API

Manage SMTP credentials:

```python
from kirimemail_smtp import CredentialsApi

credentials_api = CredentialsApi(client)

# List credentials
credentials = await credentials_api.list_credentials("example.com")

# Create credential
result = await credentials_api.create_credential(
    domain="example.com",
    username="new-credential"
)
# Save the returned password securely
print(f"Password: {result['data']['password']}")

# Get credential details
credential = await credentials_api.get_credential("example.com", "credential-guid")

# Delete credential
await credentials_api.delete_credential("example.com", "credential-guid")

# Reset credential password
result = await credentials_api.reset_password("example.com", "credential-guid")
# Save the new password securely
print(f"New password: {result['data']['new_password']}")
```

### Logs API

Retrieve and stream email logs:

```python
from kirimemail_smtp import LogsApi
from kirimemail_smtp.models import LogEntry

logs_api = LogsApi(client)

# Get logs
logs = await logs_api.get_logs("example.com", {
    "limit": 50,
    "start": "2023-01-01T00:00:00Z",
    "end": "2023-12-31T23:59:59Z",
    "sender": "sender@example.com",
    "recipient": "recipient@example.com"
})

# Filter by event type (queued, delivered, bounced, failed, opened, clicked, unsubscribed, etc.)
logs = await logs_api.get_logs("example.com", {
    "event_type": "delivered"
})

# Or use the helper method with constants
logs = await logs_api.get_logs_by_event_type("example.com", LogEntry.SMTP_EVENT_DELIVERED)

# Filter by tags (partial match)
logs = await logs_api.get_logs("example.com", {
    "tags": "newsletter"
})

# Or use the helper method
logs = await logs_api.get_logs_by_tags("example.com", "newsletter")

# Combine filters
logs = await logs_api.get_logs("example.com", {
    "event_type": "bounced",
    "tags": "marketing",
    "start": "2023-01-01T00:00:00Z",
    "limit": 100
})

# Get logs for specific message
logs = await logs_api.get_message_logs("example.com", "message-guid")

# Stream logs (async generator)
async for log_entry in logs_api.stream_logs("example.com", {
    "limit": 10000,
    "start": "2023-01-01T00:00:00Z",
    "end": "2023-12-31T23:59:59Z"
}):
    print(f"Log: {log_entry}")

# Stream with event_type filter
async for log_entry in logs_api.stream_logs("example.com", {
    "event_type": "delivered",
    "limit": 5000
}):
    print(f"Delivered: {log_entry}")
```

### Suppressions API

Manage email suppressions:

```python
from kirimemail_smtp import SuppressionsApi

suppressions_api = SuppressionsApi(client)

# Get all suppressions
suppressions = await suppressions_api.get_suppressions("example.com", {
    "type": "bounce",
    "per_page": 10,
    "page": 1
})

# Get unsubscribe suppressions
unsubscribes = await suppressions_api.get_unsubscribe_suppressions("example.com")

# Get bounce suppressions
bounces = await suppressions_api.get_bounce_suppressions("example.com")

# Get whitelist suppressions
whitelist = await suppressions_api.get_whitelist_suppressions("example.com")

# Search suppressions
results = await suppressions_api.search_suppressions("example.com", "user@example.com")

# Create whitelist suppression
await suppressions_api.create_whitelist_suppression(
    domain="example.com",
    recipient="trusted@example.com",
    recipient_type="email",
    description="Trusted sender"
)

# Delete suppressions by IDs
await suppressions_api.delete_unsubscribe_suppressions("example.com", [1, 2, 3])
await suppressions_api.delete_bounce_suppressions("example.com", [4, 5, 6])
await suppressions_api.delete_whitelist_suppressions("example.com", [7, 8, 9])
```

### Email Validation API

Validate email addresses:

```python
from kirimemail_smtp import EmailValidationApi

validation_api = EmailValidationApi(client)

# Validate single email
result = await validation_api.validate_email("user@example.com")
print(f"Valid: {result['data']['is_valid']}")

# Strict validation
result = await validation_api.validate_email_strict("user@example.com")
print(f"Valid: {result['data']['is_valid']}")

# Bulk validation
result = await validation_api.validate_bulk([
    "user1@example.com",
    "user2@test.org",
    "invalid-email"
])
print(f"Valid: {result['data']['summary']['valid']}, Invalid: {result['data']['summary']['invalid']}")

# Bulk strict validation
result = await validation_api.validate_bulk_strict([
    "user1@example.com",
    "user2@test.org"
])
```

### User API

Get user quota information:

```python
from kirimemail_smtp import UserApi

user_api = UserApi(client)

# Get quota
quota = await user_api.get_quota()
print(f"Available: {quota['data']['current_quota']}/{quota['data']['max_quota']}")
print(f"Usage: {quota['data']['usage_percentage']}%")
```

### Webhooks API

Manage webhooks for email events:

```python
from kirimemail_smtp import WebhooksApi

webhooks_api = WebhooksApi(client)

# List webhooks
webhooks = await webhooks_api.list_webhooks("example.com")

# List webhooks by type
webhooks = await webhooks_api.list_webhooks("example.com", webhook_type="delivered")

# Create webhook
webhook = await webhooks_api.create_webhook(
    domain="example.com",
    webhook_type="delivered",
    url="https://example.com/webhook"
)

# Get webhook details
webhook = await webhooks_api.get_webhook("example.com", "webhook-guid")

# Update webhook
webhook = await webhooks_api.update_webhook(
    domain="example.com",
    webhook_guid="webhook-guid",
    webhook_type="opened",
    url="https://example.com/new-webhook"
)

# Delete webhook
await webhooks_api.delete_webhook("example.com", "webhook-guid")

# Test webhook URL
result = await webhooks_api.test_webhook(
    domain="example.com",
    url="https://example.com/webhook",
    event_type="delivered"
)
print(f"Response status: {result['data']['response_status']}")
```

## Error Handling

The SDK provides comprehensive error handling with specific exception types:

```python
from kirimemail_smtp.exceptions import (
    ApiException,
    AuthenticationException,
    ValidationException,
    NotFoundException,
    ServerException
)

try:
    await messages_api.send_message(domain="example.com", message=message_data)
except AuthenticationException:
    print("Authentication failed - check your credentials")
except ValidationException as e:
    print(f"Validation error: {e.message}")
    print(f"Field errors: {e.errors}")
except NotFoundException:
    print("Domain not found")
except ServerException:
    print("Server error - please try again later")
except ApiException as e:
    print(f"API error: {e.message}")
```

## Data Models

The SDK provides Pydantic models for type-safe data handling:

```python
from kirimemail_smtp.models import (
    Credential,
    Domain,
    EmailValidationResult,
    EmailValidationBatchResult,
    LogEntry,
    Pagination,
    Quota,
    Suppression,
    Webhook
)

# Usage
email_validation = EmailValidationResult(
    email="user@example.com",
    is_valid=True,
    cached=False,
    validated_at="2024-01-01T12:00:00Z",
    is_spamtrap=False
)

# LogEntry event type constants
LogEntry.SMTP_EVENT_QUEUED        # 'queued'
LogEntry.SMTP_EVENT_SEND          # 'send'
LogEntry.SMTP_EVENT_DELIVERED     # 'delivered'
LogEntry.SMTP_EVENT_BOUNCED       # 'bounced'
LogEntry.SMTP_EVENT_FAILED        # 'failed'
LogEntry.SMTP_EVENT_PERMANENT_FAIL  # 'permanent_fail'
LogEntry.SMTP_EVENT_OPENED        # 'opened'
LogEntry.SMTP_EVENT_CLICKED       # 'clicked'
LogEntry.SMTP_EVENT_UNSUBSCRIBED  # 'unsubscribed'
LogEntry.SMTP_EVENT_TEMP_FAILURE  # 'temp_fail'
LogEntry.SMTP_EVENT_DEFERRED      # 'deferred'

# All valid event types
print(LogEntry.VALID_EVENT_TYPES)
```

## Development

### Setup

```bash
# Clone repository
git clone https://github.com/kirimemail/kirimemail-smtp-python-sdk.git
cd kirimemail-smtp-python-sdk

# Install with uv
uv sync --dev

# Run tests
uv run pytest

# Run with coverage
uv run pytest --cov=src/kirimemail_smtp --cov-report=html
```

### Code Quality

```bash
# Lint code
uv run ruff check src/

# Format code
uv run ruff format src/

# Type checking
uv run mypy src/
```

## API Endpoints Coverage

The SDK provides full coverage of the Kirim.Email SMTP API:

### Domains
- `GET /api/domains` - List domains
- `POST /api/domains` - Create domain
- `GET /api/domains/{domain}` - Get domain details
- `PUT /api/domains/{domain}` - Update domain tracking settings
- `DELETE /api/domains/{domain}` - Delete domain
- `POST /api/domains/{domain}/setup-auth-domain` - Setup authentication domain
- `POST /api/domains/{domain}/verify-mandatory` - Verify mandatory DNS records
- `POST /api/domains/{domain}/verify-auth-domain` - Verify auth domain DNS records
- `POST /api/domains/{domain}/setup-tracklink` - Setup tracking domain
- `POST /api/domains/{domain}/verify-tracklink` - Verify tracking domain DNS records

### Credentials
- `GET /api/domains/{domain}/credentials` - List credentials
- `POST /api/domains/{domain}/credentials` - Create credential
- `GET /api/domains/{domain}/credentials/{credential}` - Get credential details
- `DELETE /api/domains/{domain}/credentials/{credential}` - Delete credential
- `PUT /api/domains/{domain}/credentials/{credential}/reset-password` - Reset credential password

### Messages
- `POST /api/domains/{domain}/message` - Send transactional email with attachments
- `POST /api/domains/{domain}/message/template` - Send template email with attachments

### Logs
- `GET /api/domains/{domain}/log` - Get logs with filters
- `GET /api/domains/{domain}/log/{message_guid}` - Get specific message logs
- `GET /api/domains/{domain}/log/stream` - Stream logs (Server-Sent Events)

### Suppressions
- `GET /api/domains/{domain}/suppressions` - Get all suppressions
- `GET /api/domains/{domain}/suppressions/unsubscribes` - Get unsubscribe suppressions
- `DELETE /api/domains/{domain}/suppressions/unsubscribes` - Delete unsubscribe suppressions
- `GET /api/domains/{domain}/suppressions/bounces` - Get bounce suppressions
- `DELETE /api/domains/{domain}/suppressions/bounces` - Delete bounce suppressions
- `GET /api/domains/{domain}/suppressions/whitelist` - Get whitelist suppressions
- `POST /api/domains/{domain}/suppressions/whitelist` - Create whitelist suppression
- `DELETE /api/domains/{domain}/suppressions/whitelist` - Delete whitelist suppressions

### Email Validation
- `POST /api/email/validate` - Validate single email
- `POST /api/email/validate/strict` - Validate single email (strict mode)
- `POST /api/email/validate/bulk` - Validate multiple emails
- `POST /api/email/validate/bulk/strict` - Validate multiple emails (strict mode)

### User
- `GET /api/quota` - Get user quota information

### Webhooks
- `GET /api/domains/{domain}/webhooks` - List webhooks
- `POST /api/domains/{domain}/webhooks` - Create webhook
- `GET /api/domains/{domain}/webhooks/{webhookGuid}` - Get webhook details
- `PUT /api/domains/{domain}/webhooks/{webhookGuid}` - Update webhook
- `DELETE /api/domains/{domain}/webhooks/{webhookGuid}` - Delete webhook
- `POST /api/domains/{domain}/webhooks/test` - Test webhook URL

## License

MIT License - see [LICENSE](LICENSE) file for details.

## Support

- 📧 Email: support@kirim.email
- 🐛 Issues: [GitHub Issues](https://github.com/kirimemail/kirimemail-smtp-python-sdk/issues)
- 📖 Documentation: [GitHub Repository](https://github.com/kirimemail/kirimemail-smtp-python-sdk)
