Metadata-Version: 2.4
Name: freemobile-sms-client
Version: 0.1.0
Summary: Python client for the Free Mobile SMS API — send SMS notifications programmatically.
Author: Marc Chen
License-Expression: MIT
License-File: LICENSE
Keywords: api,client,free-mobile,notification,sms
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
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: Topic :: Communications
Requires-Python: >=3.10
Requires-Dist: httpx>=0.27
Requires-Dist: pydantic-settings>=2.0
Requires-Dist: pydantic>=2.0
Requires-Dist: typer>=0.12
Provides-Extra: dev
Requires-Dist: bump-my-version>=0.25; extra == 'dev'
Requires-Dist: mkdocs-material>=9.5; extra == 'dev'
Requires-Dist: mkdocs>=1.6; extra == 'dev'
Requires-Dist: mkdocstrings[python]>=0.25; extra == 'dev'
Requires-Dist: pre-commit>=3.7; extra == 'dev'
Requires-Dist: pytest-cov>=5.0; extra == 'dev'
Requires-Dist: pytest-httpx>=0.30; extra == 'dev'
Requires-Dist: pytest>=8.0; extra == 'dev'
Requires-Dist: ruff>=0.4; extra == 'dev'
Description-Content-Type: text/markdown

# freemobile-sms

Python client for the [Free Mobile SMS API](https://mobile.free.fr/). Send SMS notifications to your Free Mobile phone programmatically.

## Installation

```bash
pip install freemobile-sms-client
```

## Quick Start

### Environment Variables

```bash
export FREE_MOBILE_USER=12345678      # Your Free Mobile customer ID
export FREE_MOBILE_PASSWORD=yourApiKey # Your API key (from your Free Mobile account)
```

### Python (Programmatic)

```python
from freemobile_sms import FreeMobileClient

# Uses FREE_MOBILE_USER / FREE_MOBILE_PASSWORD from environment
with FreeMobileClient() as client:
    result = client.send("Server alert: disk usage at 90%")
    print(result.ok)       # True
    print(result.message)   # "SMS sent successfully"
```

Or with explicit credentials:

```python
from freemobile_sms import FreeMobileClient, FreeMobileSettings

settings = FreeMobileSettings(user="12345678", password="yourApiKey")
with FreeMobileClient(settings=settings) as client:
    result = client.send("Hello from Python!")
```

### POST Method (No URL Encoding)

The API supports POST requests where the message doesn't need to be URL-encoded:

```python
with FreeMobileClient() as client:
    result = client.send("Hello with émojis and special chars!", method="POST")
```

### Async Python

```python
from freemobile_sms import AsyncFreeMobileClient

async with AsyncFreeMobileClient() as client:
    result = await client.send("Async alert!")
    print(result.message)
```

### CLI

```bash
# Using environment variables
freemobile-sms send "Hello from the command line!"

# Using options
freemobile-sms send "Hello!" --user 12345678 --password yourApiKey

# Using POST method (no URL encoding needed)
freemobile-sms send "Hello!" --method POST --user 12345678 --password yourApiKey
```

## API Reference

### `FreeMobileClient`

Synchronous client. Use as a context manager for automatic cleanup.

| Method | Description |
|--------|-------------|
| `send(message, method="GET")` | Send an SMS. Returns `SMSResult`. Use `method="POST"` to avoid URL-encoding. |

### `AsyncFreeMobileClient`

Asynchronous client. Same interface, but `send()` is `async`.

### `FreeMobileSettings`

Pydantic Settings model. Reads from environment variables with `FREE_MOBILE_` prefix, or from a `.env` file.

| Field | Env var | Default |
|-------|---------|---------|
| `user` | `FREE_MOBILE_USER` | `""` |
| `password` | `FREE_MOBILE_PASSWORD` | `""` |
| `api_url` | `FREE_MOBILE_API_URL` | `https://smsapi.free-mobile.fr/sendmsg` |

### `SMSResult`

| Field | Type | Description |
|-------|------|-------------|
| `success` | `bool` | Whether the SMS was sent |
| `status_code` | `int` | HTTP status code from the API |
| `message` | `str` | Human-readable description |
| `ok` | `bool` | Alias for `success` |

### Exceptions

| Exception | Status | Description |
|-----------|--------|-------------|
| `FreeMobileClientError` | — | Base exception |
| `RateLimitError` | 402 | Too many SMS sent in too short a time |
| `AccessDeniedError` | 403 | Service not activated or incorrect login/key |
| `ServerError` | 500 | Free Mobile server error |

## Development

```bash
# Install with dev dependencies
uv pip install -e ".[dev]"

# Run tests with coverage (requires 100%)
pytest

# Lint and format
ruff check .
ruff format .

# Install pre-commit hooks
pre-commit install
```

## License

MIT
