Public
Remixed
Relay 6-digit OTPs from forwarded emails to a browser extension
Val Town is a collaborative website to build and scale JavaScript apps.
Deploy APIs, crons, & store data – all from the browser, and deployed in milliseconds.

OTP Email → Browser Extension Relay

Securely relays 6-digit OTP codes from forwarded emails to a browser extension.

How it works

Rendering mermaid diagram...

Files

FileTypeRole
inbox.tsemailReceives forwarded emails, extracts the first 6-digit code, stores it with a timestamp.
api.tshttpReturns the most recent non-expired OTP as JSON, with full CORS headers.
db.tsscriptShared SQLite schema + helpers (extractOtp, saveOtp, getLatestOtp, purgeExpired).

Setup

  1. Forward OTP emails to the email val's address (find it in the Val Town UI for inbox.ts, or in the links.email field). You can set up an auto-forward rule in Gmail/Outlook so codes arrive automatically.

  2. (Recommended) Protect the endpoint. The HTTP endpoint is public, so anyone with the URL could read your codes. Set an OTP_API_TOKEN env var and have your extension send it. When set, callers must provide it via:

    • X-Auth-Token: <token> header, or
    • Authorization: Bearer <token> header, or
    • ?token=<token> query param.

    👉 Add OTP_API_TOKEN here: https://www.val.town/x/indenigrate/email-val/environment-variables?key=OTP_API_TOKEN

Expiry

Codes expire 5 minutes after they arrive (TTL_MS in db.ts). Expired rows are purged lazily on every read and write, so the store never serves a stale code.

API response

GET / returns:

{ "code": "614209", "sender": "no-reply@bank.example", "subject": "Your verification code", "createdAt": 1780528667360, "expiresInMs": 297315 }
  • 404 { "code": null } — no active OTP.
  • 401 { "error": "Unauthorized" } — OTP_API_TOKEN is set and the caller didn't supply it.

Example: fetching from an extension

const res = await fetch("https://YOUR-ENDPOINT.web.val.run", { headers: { "X-Auth-Token": "your-secret-token" }, }); const { code } = await res.json();