Metadata-Version: 2.1
Name: sendgrid-async
Version: 2.3.1
Summary: SendGrid using an httpx client
Home-page: https://github.com/EM51641/async-sendgrid-
License: MIT
Keywords: sendgrid,client,async
Author: Elyes Mahjoubi
Author-email: elyesmahjoubi@gmail.com
Requires-Python: >=3.10
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Requires-Dist: httpx (>=0.24.1,<0.29.0)
Requires-Dist: httpx-retries (>=0.4.0)
Requires-Dist: opentelemetry-api (>=1.34.0,<2.0.0)
Requires-Dist: opentelemetry-exporter-otlp-proto-grpc (>=1.34.0,<2.0.0)
Requires-Dist: opentelemetry-sdk (>=1.34.0,<2.0.0)
Requires-Dist: sendgrid (>=6.7.0,<7.0.0)
Project-URL: Repository, https://github.com/EM51641/async-sendgrid-
Description-Content-Type: text/markdown

# Async SendGrid

[![Python](https://img.shields.io/pypi/pyversions/sendgrid-async)](https://pypi.org/project/sendgrid-async/)
[![PyPI Latest Release](https://img.shields.io/pypi/v/sendgrid-async.svg)](https://pypi.org/project/sendgrid-async/)
[![PyPI Downloads](https://img.shields.io/pypi/dm/sendgrid-async.svg?label=PyPI%20downloads)](https://pypi.org/project/sendgrid-async/)
[![License - MIT](https://img.shields.io/pypi/l/async_sendgrid.svg)](https://github.com/sensodevices/async_sendgrid/blob/main/LICENSE)

A modern, asynchronous SendGrid client built on top of `httpx`. This library provides a simple and efficient way to send emails using SendGrid's API with Python's async/await syntax.

## Features

- 🚀 Asynchronous API client for SendGrid
- 🔄 Connection pooling for better performance
- 📊 OpenTelemetry integration for monitoring
- 🔍 Detailed error tracking and tracing
- 🛠️ Customizable configuration
- 📝 Comprehensive documentation

## Installation

Install the package using pip:

```bash
pip install sendgrid-async
```

## Quick Start

```python
from async_sendgrid import SendgridAPI
from sendgrid.helpers.mail import Mail

# Initialize the client
sendgrid = SendgridAPI(api_key="YOUR_API_KEY")

# Create and send an email
email = Mail(
    from_email="from@example.com",
    to_emails="to@example.com",
    subject="Hello World",
    plain_text_content="Hello World!",
)

response = await sendgrid.send(email)
```

## Advanced Features

### Connection Pooling

Optimize performance with connection pooling:

```python
from async_sendgrid import SendgridAPI
from async_sendgrid.pool import ConnectionPool

pool = ConnectionPool(
    max_connections=20,
    max_keepalive_connections=10,
    keepalive_expiry=10.0,
)

sendgrid = SendgridAPI(
    api_key="YOUR_API_KEY",
    pool=pool,
)
```

### Retry Configuration

By default, requests are automatically retried up to 5 times with exponential backoff on transient failures (429 Too Many Requests, 502, 503, 504, and timeouts).

The delay between retries is calculated as:

```
delay = backoff_factor * (2 ** attempt) * random(1 - backoff_jitter, 1)
```

With the defaults (`backoff_factor=0.5`, `backoff_jitter=1.0`), delays range from 0 to 1s, 0 to 2s, 0 to 4s, etc. Jitter prevents thundering herd problems when multiple clients retry simultaneously.

Customize the retry behavior through the connection pool:

```python
from async_sendgrid import SendgridAPI
from async_sendgrid.pool import ConnectionPool

pool = ConnectionPool(
    retry_attempts=3,    # Maximum retry attempts (default: 5)
    backoff_factor=1.0,  # Backoff multiplier in seconds (default: 0.5)
    backoff_jitter=0.0,  # Jitter multiplier, 0 to 1 (default: 1.0)
)

sendgrid = SendgridAPI(
    api_key="YOUR_API_KEY",
    pool=pool,
)
```

To disable retries entirely, set `retry_attempts=0`:

```python
pool = ConnectionPool(retry_attempts=0)
```

### Shutdown

When your application is shutting down, call `shutdown()` on the pool to close all connections and release resources:

```python
pool = ConnectionPool()
sendgrid = SendgridAPI(api_key="YOUR_API_KEY", pool=pool)

# ... send emails ...

# On application shutdown
await pool.shutdown()
```

> **Note:** Per-call `retry` or `backoff` overrides on `send()` create and tear down an ephemeral connection (TCP + TLS handshake) for every request. Because an email send is a lightweight operation — a small JSON payload answered with a `202` — the connection overhead can easily exceed the request itself. Configure retry and backoff on the `ConnectionPool` at initialization instead.

### Send emails on behalf of another user

Send emails on behalf of subusers:

```python
sendgrid = SendgridAPI(
    api_key="YOUR_API_KEY",
    on_behalf_of="John Smith",
)
```

### Custom Endpoints

Use custom API endpoints:

```python
sendgrid = SendgridAPI(
    api_key="YOUR_API_KEY",
    endpoint="https://custom.endpoint.com/v3/mail/send",
)
```

## Telemetry Integration

Monitor and trace your SendGrid operations with OpenTelemetry:

### Setup

```python
from opentelemetry import trace
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import OTLPSpanExporter

# Configure OpenTelemetry
tracer_provider = TracerProvider()
trace.set_tracer_provider(tracer_provider)

# Add your exporter
otlp_exporter = OTLPSpanExporter()
span_processor = BatchSpanProcessor(otlp_exporter)
tracer_provider.add_span_processor(span_processor)
```

### Available Metrics

The library automatically tracks:

#### HTTP Metrics
- Status codes
- Response sizes
- URLs
- Methods

#### SendGrid Metrics
- Number of recipients
- Attachment presence
- Email content type

### Configuration

Control telemetry behavior with environment variables:

```bash
# Disable telemetry
SENDGRID_TELEMETRY_IS_ENABLED=false

# Custom span name
SENDGRID_TELEMETRY_SPAN_NAME=custom.span.name
```

## Error Handling

Robust error handling for API operations:

```python
try:
    response = await sendgrid.send(email)
except Exception as e:
    # Handle the error
    print(f"Error sending email: {e}")
```

## Development

### Setup

```bash
# Clone the repository
git clone https://github.com/yourusername/async-sendgrid.git
cd async-sendgrid

# Install development dependencies
pip install -e ".[test]"
```

### Testing

```bash
# Run all tests
pytest

# Run with coverage
pytest --cov=async_sendgrid
```

## Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

## License

This project is licensed under the MIT License - see the LICENSE file for details.
