Skip to main content

kuvert

The python client for kuvert, the Arkitekt mail service: the mailboxes you linked, their folders and conversations, tasks over those conversations, and sending mail.

Installation

pip install kuvert

Usage

Every kuvert operation is a method of the Kuvert client, in a blocking and an a-prefixed async flavour.

In an arkitekt app

The client is injected by annotation. Add the service to your app and ask for kuvert: Kuvert:

from arkitekt import App, run
from kuvert import Kuvert, kuvert_service

app = App("mail-digest", "0.1.0", services=[kuvert_service])


@app.action
async def unread_subjects(kuvert: Kuvert) -> list[str]:
    """The subjects of the unread conversations in my inboxes."""
    threads = await kuvert.alist_threads(filter={"unread": True, "folderRole": "INBOX"})
    return [thread.subject for thread in threads]


if __name__ == "__main__":
    run(app)

Messages, threads, outgoing mail, mailboxes, tasks and task lists travel between actions by id (@kuvert/message, @kuvert/thread, @kuvert/outgoingmessage, @kuvert/mailaccount, @kuvert/task, @kuvert/tasklist), so an action can take and return them directly, and a trigger on a kuvert signal hands them over.

From a script

from arkitekt import easy
from kuvert import kuvert_service

with easy("my-script", kuvert_service) as kuvert:
    for account in kuvert.list_mail_accounts():
        print(account.email_address, account.unread_count)

Standalone

Without arkitekt, build the client over a rath link of your own:

from kuvert import Kuvert
from kuvert.rath import KuvertRath

kuvert = Kuvert(rath=KuvertRath(link=...))

with kuvert:
    for account in kuvert.list_mail_accounts():
        print(account.email_address, account.unread_count)

    kuvert.send_message(
        account=account.id,
        to=[{"address": "someone@example.org"}],
        subject="Hello",
        text="From kuvert.",
    )

Arguments the server defaults (cc, bcc, attachments of send_message, notes/pinned of create_task, …) are optional: leave them out rather than passing None. An explicit None is sent as null, which the server rejects for those fields.

Changes to mail (flags, moves, deletes, categories) are local-first: they apply at once and reach the mail server when the mailbox next pushes. list_mail_changes shows what is still pending and undo_mail_changes takes a change back while it is.

Development

The generated API (kuvert/api/schema.py) comes from the checked-in schema.graphql and the documents in graphql/. The config comment in graphql.config.yaml has the command that refreshes the schema from a kuvert-server checkout. Then run turms to regenerate the API.

uv run pytest -m "not integration"   # no server needed
uv run pytest -m integration          # a real kuvert + mail server via dokker

See RELEASING.md for how versions are cut.

Metadata

Release files for kuvert 2.0.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for kuvert 2.0.0
File Size Uploaded Provenance
kuvert-2.0.0.tar.gz 62.5 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for kuvert 2.0.0
File Interpreter ABI Platform
kuvert-2.0.0-py3-none-any.whl Python 3 none any Details

Total release size: 126.2 kB

Release files / kuvert-2.0.0.tar.gz

Download URL kuvert-2.0.0.tar.gz
Size 62.5 kB
Tags Source
SHA-256 checksum
How to use checksums
b702eda406b4cde235ead6f30ccc759bd26d7a46afc7b91ac856d0f7e0a31b1a
BLAKE2b-256 checksum
How to use checksums
8b0ef783b6b5f209cb43d429c0e0a2a0444f3ab760ea47b47c450dfed92731da
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.13.3 {"installer":{"name":"uv","version":"0.13.3","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / kuvert-2.0.0-py3-none-any.whl

Download URL kuvert-2.0.0-py3-none-any.whl
Size 63.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
ba74ed57e21e624174f99e659c8931ed19cbfe7a4bde8a350f96846dd889a6f2
BLAKE2b-256 checksum
How to use checksums
ddbcbad47db148c5822e63791c095970632a841652475bf43c5db40c289bad4b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.13.3 {"installer":{"name":"uv","version":"0.13.3","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Security for kuvert 2.0.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

Release history Release notifications | RSS feed

This release

2.0.0 This release

2 release files No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page