Skip to main content

PyEVP

Documentation CI Spec drift spec: draft-hardt-02 status: alpha ty License: MIT Ask DeepWiki

日本語

Python library for the Email Verification Protocol (EVP): verify tokens as a relying party, or issue them for your own email domains. With EVP, the browser obtains a token from the user's email provider proving they control an address, and your server verifies it, with no confirmation email round-trip.

Documentation: https://docs.pyevp.dev/

Status: alpha. The protocol (draft-hardt-email-verification, WICG Email Verification API) and browser support (Chrome origin trial) are still changing. This library isolates every moving part in a versioned Profile so it can follow along.

Install

pip install "pyevp[dns,httpx2]"   # core + the DNS and HTTP adapters

The core depends only on joserfc and idna. DNS and HTTP are pluggable; [dns,httpx2] installs the default adapters used by Verifier.default(). [all] installs every optional dependency, including the Django integration and the command line.

The HTTP adapters work with httpx2 (pydantic's maintained fork of httpx) or httpx and prefer httpx2 when both are installed, so pip install "pyevp[dns,httpx]" works too. A client from either library can be passed explicitly, e.g. HttpxFetcher(httpx.Client(...)).

How it works

  1. Render a form with a fresh nonce stored in the user's session:

    <input type="email" name="email" autocomplete="email">
    <input type="hidden" name="evt" autocomplete="email-verification-token" nonce="{{ nonce }}">
    
  2. When the user picks an address, the browser fills evt with <EVT>~<KB-JWT>.

  3. On submit, verify it:

    from pyevp import Verifier, EVPError, generate_nonce
    
    verifier = Verifier.default(audience="https://example.com")  # your origin
    
    try:
        result = verifier.verify(form["evt"], nonce=session.pop("evp_nonce"), email=form["email"])
    except EVPError as exc:
        ...  # exc.code is an ErrorCode, e.g. "nonce_mismatch"; fall back to email confirmation
    else:
        result.email, result.issuer  # verified
    

    AsyncVerifier has the same API with await verifier.verify(...).

Verification checks the key-binding JWT (audience, nonce, freshness, sd_hash, holder signature) before doing any I/O. It then discovers the issuer from DNS (_email-verification.<domain> TXT iss=…), fetches its metadata and JWKS (cached), and verifies the issuer's signature. Only hosts derived from DNS are ever contacted, never hosts named in the token. Before connecting, the default fetchers also check that the host resolves only to public addresses; see private networks for what this check does not catch.

Every rejected token raises an EVPError with an ErrorCode. The safe default is to fall back to your existing verification flow; the error table tells which codes the user can retry and which point at your configuration.

Command line

pyevp[cli] installs a pyevp command for relying-party developers and operators, and for issuer operators checking their own setup. It runs without installing anything into your project:

uvx --from "pyevp[cli]" pyevp discover gmail.com           # DNS record, metadata, keys vs. profile
pbpaste | uvx --from "pyevp[cli]" pyevp inspect            # decode a token offline (no signature checks)
uvx --from "pyevp[cli]" pyevp verify "$TOKEN" --audience https://example.com --nonce "$NONCE"

See the CLI guide for every command and option.

More

Examples

Each example is a standalone project with its own tests:

Contributing

See CONTRIBUTING.md.

License

MIT

Metadata

Release files for PyEVP 0.1.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 PyEVP 0.1.0
File Size Uploaded
pyevp-0.1.0.tar.gz 64.3 kB Details

Built distribution (wheel)

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

Total release size: 150.1 kB

Release files / pyevp-0.1.0.tar.gz

Download URL pyevp-0.1.0.tar.gz
Size 64.3 kB
Tags Source
SHA-256 checksum
How to use checksums
49f354933a6d6d57c34e108ab1615329af60caf37099840d527ad9dc20e9b440
BLAKE2b-256 checksum
How to use checksums
48edd7cc08fb0bff122a4ee0a39ab99fac0605c014dacdef5a4a53389fca1f55
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 4, 2026.

Transparency log

Release files / pyevp-0.1.0-py3-none-any.whl

Download URL pyevp-0.1.0-py3-none-any.whl
Size 85.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
236774865439ffcd7f76576d30ab3ab89fe429db9eae9ced61ea563ada77b93f
BLAKE2b-256 checksum
How to use checksums
947c84d5a22b920828ac20fbc13a8fbfad68a93dbde4e1056ac6ad08545a70f2
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 4, 2026.

Transparency log

Release history Release notifications | RSS feed

0.2.0

2 release files

This release

0.1.0 This release

2 release files

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