#!/usr/bin/env python3 """Test Cloudflare Email Worker code API (and optional local hybrid path).""" from __future__ import annotations import argparse import json import os import sys import time from pathlib import Path from urllib.parse import urlencode from urllib.request import Request, urlopen ROOT = Path(__file__).resolve().parents[1] def load_cfg(): p = ROOT / "config.json" if p.is_file(): return json.loads(p.read_text(encoding="utf-8")) return {} def main(): cfg = load_cfg() ap = argparse.ArgumentParser(description="Test gmail Email Worker /code API") ap.add_argument("--url", default=cfg.get("gmail_worker_url") or os.getenv("GMAIL_WORKER_URL") or "") ap.add_argument("--key", default=cfg.get("gmail_worker_api_key") or os.getenv("GMAIL_WORKER_API_KEY") or "") ap.add_argument("--to", required=True, help="alias@domain to query") ap.add_argument("--timeout", type=float, default=20) ap.add_argument("--interval", type=float, default=0.5) ap.add_argument("--ingest-demo", action="store_true", help="POST a fake code then GET it") ap.add_argument("--no-consume", action="store_true") args = ap.parse_args() base = (args.url or "").rstrip("/") key = args.key or "" if not base or not key: print("需要 --url/--key 或 config.json 的 gmail_worker_url / gmail_worker_api_key") return 1 def get(path, params=None): q = dict(params or {}) q["key"] = key url = f"{base}{path}?{urlencode(q)}" req = Request(url, headers={"x-api-key": key}) with urlopen(req, timeout=10) as r: return r.status, json.loads(r.read().decode()) def post(path, body): url = f"{base}{path}?{urlencode({'key': key})}" data = json.dumps(body).encode() req = Request(url, data=data, headers={"content-type": "application/json", "x-api-key": key}, method="POST") with urlopen(req, timeout=10) as r: return r.status, json.loads(r.read().decode()) st, health = get("/health") print("health", st, health) if args.ingest_demo: code = "AB1-CD2" st, body = post("/ingest", {"to": args.to, "code": code, "subject": f"{code} xAI confirmation code"}) print("ingest", st, body) deadline = time.time() + args.timeout while time.time() < deadline: try: st, body = get( "/code", {"to": args.to.lower(), "consume": "0" if args.no_consume else "1"}, ) print("code", st, body) if st == 200 and body.get("code"): return 0 except Exception as e: print("wait", e) time.sleep(args.interval) print("timeout — 若是真实邮件,检查 Email Routing 是否绑到 Worker") return 2 if __name__ == "__main__": sys.exit(main())