Metadata-Version: 2.5
Name: render-lab-tasks-gmail
Version: 0.1.0
Summary: gmail tasks for Render Workflows
Project-URL: Repository, https://github.com/render-lab/render-tasks-python
License-Expression: MIT
License-File: LICENSE
Requires-Python: >=3.12
Requires-Dist: httpx<0.29,>=0.28
Requires-Dist: render-lab-tasks-core<0.2,>=0.1.1
Requires-Dist: render==1.0.1
Description-Content-Type: text/markdown

# render-lab-tasks-gmail

Python port of all 16 registered tasks in the pinned TypeScript pack at
`45f9c2d44bd28e01ae9813e0d2ff56ee6c533816`. Python 3.12+.

Install this distribution and its dependencies:

```sh
pip install render-lab-tasks-gmail==0.1.0
```

Import definitions from `render_lab_tasks_gmail.tasks`; combine `app` objects
with `Workflows.from_workflows(...)`. JSON fields retain TS spelling; functions
use snake_case. Package root imports are inert.

## Tasks

| Registered name | Python export (also exposes `_impl`) |
| --- | --- |
| `gmail.archive` | `archive` |
| `gmail.awaitReply` | `await_reply` |
| `gmail.createLabel` | `create_label` |
| `gmail.draft` | `draft` |
| `gmail.draftReply` | `draft_reply` |
| `gmail.forward` | `forward` |
| `gmail.getFullThread` | `get_full_thread` |
| `gmail.getMessage` | `get_message` |
| `gmail.getThread` | `get_thread` |
| `gmail.label` | `label` |
| `gmail.labelThread` | `label_thread` |
| `gmail.listLabels` | `list_labels` |
| `gmail.reply` | `reply` |
| `gmail.search` | `search` |
| `gmail.send` | `send` |
| `gmail.trash` | `trash` |

## Dependencies and retries

Raw implementations accept context first and keyword-only `deps`. The `.client`
module exports typed `Port`, `Deps`, and `Client` classes. Inject a fake port, or
pass a caller-owned `httpx.AsyncClient` to `Client`. Default dependencies close
their client after one operation. Credentials resolve at first use. Transport
retries are disabled; `retry.py` owns durable policies. DTO types are in `.types`.
Requires core >=0.1.1.

## Environment

| Variable | Contract |
| --- | --- |
| `GOOGLE_ACCESS_TOKEN` | Optional pre-issued token; takes precedence. |
| `GOOGLE_CLIENT_ID` | Required with secret and refresh token when no access token is supplied. |
| `GOOGLE_CLIENT_SECRET` | OAuth client secret for refresh. |
| `GOOGLE_REFRESH_TOKEN` | Refresh token granted the scopes for the operations you use. |

## Verification and limitations

Reads, labels, drafts, sends, replies, forwards, and reply polling use Gmail v1.
Reply drafts prefer the latest inbound message and preserve MIME threading headers;
optional From must be a verified send-as address. Header CR/LF injection is rejected.
getFullThread defaults to 20 messages and 20,000 UTF-16 units per body; Python drops
a split surrogate pair rather than returning invalid Unicode and rejects invalid
limits. `list_labels_impl(ctx, *, deps=...)` and wrapped `list_labels(ctx)` take no
input, matching the TS operation. awaitReply checks one page of ten messages per
attempt; it does not independently verify sender identity. Send/draft/forward
retain retries and may duplicate mail after an ambiguous response. Use test mailboxes.

Shared fixtures execute the actual pinned TS implementations and compare Python
outputs and requests. Sanity's SDK calls are translated into separately asserted
REST requests. These are hermetic checks, not real account or hosted verification.
See [the testing backlog](https://github.com/render-lab/render-tasks-python/issues/1)
and the root verification tracker. Licensed under MIT.
