Metadata-Version: 2.4
Name: scheduled-email
Version: 0.1.1
Summary: Auto-rotating secret generation with Argon2 hashing and scheduled SMTP delivery
Author: zavier
License-Expression: MIT
Project-URL: Homepage, https://github.com/erosado15/bigroad-ai
Project-URL: Repository, https://github.com/erosado15/bigroad-ai
Project-URL: Documentation, https://github.com/erosado15/bigroad-ai/tree/main/packages/scheduled-email
Keywords: email,smtp,argon2,secret-rotation,scheduled,passwordless
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Communications :: Email
Classifier: Topic :: Security
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: argon2-cffi>=23.1.0
Provides-Extra: dev
Requires-Dist: pytest>=7.0; extra == "dev"
Dynamic: license-file

# scheduled-email

Auto-rotating secret generation — creates Argon2-hashed secrets and delivers
password-less login links via SMTP on a configurable schedule.

## Install

```bash
pip install scheduled-email
```

> 尚未发布到 PyPI 前，需先按 [PUBLISH.md](PUBLISH.md) 完成上传。
> 本地开发可用 editable 模式：`pip install -e packages/scheduled-email`

## Environment Variables

| Variable | Required | Default | Description |
|---|---|---|---|
| `SCHEDMAIL_SMTP_USER` | **yes** | — | Sender email address |
| `SCHEDMAIL_SMTP_PASS` | **yes** | — | SMTP authorization code |
| `SCHEDMAIL_RECIPIENT` | **yes** | — | Recipient email address |
| `SCHEDMAIL_BASE_URL` | no | `https://example.com/login?token=` | Prefix for login URL |
| `SCHEDMAIL_ROTATE_HOURS` | no | `24` | Rotation interval (hours) |
| `SCHEDMAIL_SCT` | no | `*****-daiju` | SCT constant |
| `SCHEDMAIL_MASK_SECRET` | no | `false` | Mask secret in email body |

Copy `.env.example` to `.env` and fill in credentials. **Never commit `.env`.**

## Usage

### Standalone

```python
from scheduled_email import start, stop

svc = start()       # immediate first rotation + email, then every 24h
# ...
stop()               # cancel timer
```

### Context Manager

```python
from scheduled_email import ScheduledEmailService

with ScheduledEmailService() as svc:
    print(svc.current_url)
```

### FastAPI Integration (minimal)

```python
from contextlib import asynccontextmanager
from fastapi import FastAPI

@asynccontextmanager
async def lifespan(app: FastAPI):
    from scheduled_email import start, stop
    start()
    yield
    stop()

app = FastAPI(lifespan=lifespan)
```

## How It Works

1. On `start()`, a 32-byte random secret is generated via `secrets.token_urlsafe`.
2. The secret is hashed with Argon2 (`argon2-cffi`).
3. A login URL is built: `{SCHEDMAIL_BASE_URL}{argon2_hash}`.
4. An email is sent via SMTP_SSL containing: rotation time, SCT, secret
   (optionally masked), and the full login URL.
5. A `threading.Timer` schedules the next rotation after `SCHEDMAIL_ROTATE_HOURS`.
