Skip to content
gaatoPublic

About

Python library for the Email Verification Protocol (EVP): verify tokens as a relying party, or issue them for your own email domains

Resources

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

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/ · Live demo: https://pyevp.dev/demo

Status: alpha. The protocol (draft-hardt-email-verification, WICG Email Verification API) is still changing. PyEVP keeps every moving part in a versioned Profile so it can follow along.

  • Browsers: Chrome, with chrome://flags/#email-verification-protocol enabled or on a site registered for the origin trial. Tested with Chrome 154. Other browsers send no token.
  • Email providers: Gmail issues tokens today. Your own domains can too, with pyevp.issuer.
  • Python: 3.11 or newer.

Install

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

The core depends only on joserfc and idna. [dns,httpx2] adds the adapters Verifier.default() uses; httpx works too (see DNS, HTTP and caching). [all] adds the Django integration and the command line.

How it works

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

    from pyevp import SessionNonces, token_input
    
    nonce = SessionNonces(session).issue()  # Flask, Starlette and Django sessions all work
    <input type="email" name="email" autocomplete="email">
    <input type="hidden" name="evt" autocomplete="email-verification-token" nonce="{{ nonce }}">

    (token_input(nonce) renders the hidden input.)

  2. When the user picks an address, the browser fills evt with <EVT>~<KB-JWT>.

  3. On submit, verify it:

    from pyevp import EVPError, SessionNonces, Verifier
    
    verifier = Verifier.default(audience="https://example.com")  # your origin
    
    try:
        result = verifier.verify_submission(
            form.get("evt"), nonces=SessionNonces(session), email=form["email"]
        )
    except EVPError as exc:
        ...  # exc.code says why, e.g. "nonce_mismatch"; fall back to email confirmation
    else:
        if result is None:
            ...  # no token: fall back to email confirmation
        else:
            result.email, result.issuer  # verified

    AsyncVerifier has the same API with await.

Everything that can be checked offline is checked first, and only hosts found through DNS are ever contacted, never hosts named in the token. Every rejection raises an EVPError with an error code.

More

Examples

Each example is a standalone project with its own tests:

Contributing

See CONTRIBUTING.md.

License

MIT

About

Python library for the Email Verification Protocol (EVP): verify tokens as a relying party, or issue them for your own email domains

Resources

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages