接收邮件后自动解析 OpenAI(验证码、登录链接、登录提醒、账单等)并在日志中以美观、可读的方式展示关键数据,同时保存到 SQLite 方便后续查询。
发送到本 val 的专属地址(在 main.ts 的 links.email 中查看)即可触发处理。
Web 页面现在由 React + Vite 构建,支持创建随机 Email trigger 别名,适合用不同收件地址注册/接收验证码。 Dashboard 只展示“当前可用邮箱”,历史生成过的别名会保留在 SQLite 中用于追踪,但不会再作为列表打扰日常使用。
可接收邮箱列表会显示每个 Email trigger
文件已生成过多少个邮箱,也就是本服务成功把该文件改名的次数。非当前邮箱、非
Cookie 修改目标的文件可以直接在列表里删除,用来清理 Val Town 中堆积的
alias-*.ts 文件。
需要先配置:
| 环境变量 | 作用 |
|---|---|
TIGA_EMAIL_DASHBOARD_TOKEN | 可选;首次设置 TOTP 时的管理员引导 token,也兼容自动化 API 鉴权 |
TIGA_EMAIL_VAL_ID | 当前 Val 的 id,用于调用 Val Town API 读取/创建/删除 Email trigger 文件 |
TIGA_VALTOWN_API_KEY | 推荐使用的 Val Town API token,需要包含 val:write 权限,避免平台保留变量名被覆盖 |
VAL_TOWN_API_KEY | 兼容旧配置;若在 Val Town 运行时权限不足,请改用 TIGA_VALTOWN_API_KEY |
TIGA_VALTOWN_COOKIE | 可选;也可以首次登录 Dashboard 后在网页中保存,保存后会持久化到 SQLite |
网页中保存的 Val Town Cookie、Val ID、Val Town API token、复用接收器路径/File ID
都会存到服务端 SQLite,不会再依赖浏览器
sessionStorage。因此同一套服务在不同设备上登录后,都能继续使用已经保存的配置和当前邮箱。
首次访问 Dashboard 时会进入 TOTP 设置流程:
- 页面显示二维码。
- 使用认证器 App 扫描二维码。
- 输入 6 位动态验证码完成设置。
设置成功后,TOTP 密钥会持久化保存到 SQLite。下次会话过期或换设备访问时,只需要输入认证器中的动态验证码,不再显示二维码或密钥。
如果已配置 TIGA_EMAIL_DASHBOARD_TOKEN,首次设置 TOTP 时需要先输入该
token,避免公开 HTTP 入口被他人抢先初始化。
页面还支持保存 Val Town 登录 Cookie、API token、Val ID 和要复用的接收器文件。
默认复用 main.ts 这个 Email trigger;如果填写了 File ID,会优先用 File
ID,避免接口查询路径失败。Cookie/API token 会保存在服务端
SQLite。当前项目处于开发阶段,已登录 Dashboard 会明文回显这些配置,方便直接查看和修改。
Cookie 获取步骤:
- 登录
https://www.val.town,打开浏览器 DevTools 的 Network 面板。 - 在 Val Town 页面里手动修改一次 Email trigger 的邮箱 label。
- 找到
POST https://www.val.town/api/trpc/files.valLabelSet请求。 - 在 Request Headers 里复制完整的
Cookieheader 值,或直接复制__Secure-better-auth.session_token的 Value 值。 - 必须保留登录会话 cookie。当前新版 Val Town 常见的是
__Secure-better-auth.session_token,旧版可能是__Secure-next-auth.session-token;如果出现.0、.1这类分片,所有分片都要一起保留。本地 / 非 HTTPS 环境可能去掉__Secure-前缀。csrf-token、callback-url、分析 cookie 通常不是这个接口鉴权的必要值。只粘贴 session token 裸值时,后端会自动补成__Secure-better-auth.session_token=...。
设置 Cookie 后,本项目会优先调用 Val Town Web 前端使用的内部 tRPC 接口
files.valLabelSet,把已配置的现有 Email trigger 改成指定邮箱或
固定前缀-随机后缀@valtown.email,不会反复创建新的 alias-*.ts 文件。
读取、创建和删除 Email trigger 文件都走 Val Town REST API 的 API token;Cookie
只用于这个固定邮箱名改名接口。
如果 Cookie 缺失或失效,Dashboard 不会直接创建系统分配邮箱,而是先提示二次确认。 只有确认后,才会调用官方 Val Town API 新建一个系统分配的 Email trigger 文件,并把这个新文件记录为后续复用对象。缺少 Val ID 或可用的 Val Town API token 时,请求会返回明确错误。
前端工程在 frontend/:
cd frontend npm install npm run build
构建产物输出到仓库根目录的 dist/,web.ts 会用 Val Town 的静态文件能力服务
dist/index.html 和 dist/assets/*。
Val Town 对单文件大小有限制,前端生产包会把 React、React Query、Lucide 和 QRCode
等大依赖作为 esm.sh 外部 ESM 模块加载,避免把过大的 JS bundle 推送到 Val
Town。frontend/package-lock.json 只用于本地构建,不需要部署到 Val Town。
注意:这个自定义邮箱步骤依赖 Val Town 内部接口
/api/trpc/files.valLabelSet,不是公开稳定 API。Cookie 过期或 Val Town
前端接口变更时,需要重新设置 Cookie 或调整代码。
给 Codex Vault 这类外部工具使用时,不建议让调用方解析完整收件箱。服务提供两个窄接口:
-
POST /api/openai-receivers- Body:
{ "email": "tigacodex5121311@valtown.email" } - 可传
allowSystemFallback: false,要求必须绑定调用方指定的精确邮箱;这种模式下 Cookie 不可用、改名失败或达到改名上限时会快速返回结构化错误,不会继续创建系统分配邮箱。 - 如果调用方自己安全保存了 Val Town Cookie,也可以额外传
valTownCookie;服务只把它用于本次“指定邮箱”创建,不会写入 SQLite。 - 默认会复用已配置的 Email trigger 并改成指定邮箱;如果 Cookie
不可用或固定邮箱改名失败, 服务会自动创建 Val Town 系统分配的新 Email
trigger,并把响应里的
email返回给调用方。 - 如果当前复用的 Email trigger 达到 Val Town 30
次改名上限,服务会自动创建一个新的 Email trigger
文件,把它设为后续复用对象,并重试绑定本次指定邮箱;成功响应里会带
rotatedManagedReceiver: true,调用方不需要中断注册流程。 - 需要
TIGA_EMAIL_DASHBOARD_TOKEN鉴权;如果需要创建精确地址,还需要通过环境变量或 Dashboard 持久化配置 Val ID、Val Town API token、Val Town Cookie 和复用接收器路径/File ID。 - 失败响应会带
stage和details/diagnostics.steps,用于定位具体卡点,例如alias_cache_lookup、managed_alias_lookup、valtown_label_set、system_alias_create_api或system_alias_create_cookie。接口内部有总时限保护, 会在 Val Town 60 秒平台硬超时前返回alias_operation_deadline_exceeded。
- Body:
-
GET /api/openai-code?email=...¬BeforeMs=...&waitMs=25000- 作用:只返回目标邮箱最新的 OpenAI 6 位验证码。
- 成功返回:
{ "ok": true, "email": "tigacodex5121311@valtown.email", "verificationCode": "915219", "receivedAt": "2026-05-16T07:20:00.000Z" }
未收到验证码时返回
verification_code_timeout,调用方可以继续轮询或把错误原因展示给用户。
Rendering mermaid diagram...
| 文件 | 作用 |
|---|---|
main.ts | Email 触发入口,串起解析→渲染→存储 |
parser.ts | 识别 OpenAI 邮件、分类、抽取验证码 / 链接 / 登录信息 |
renderer.ts | 把解析结果排成带框线、对齐良好的控制台输出(支持中文/emoji) |
storage.ts | 把每封邮件存入 received_emails_v1 表 |
test.ts | 本地模拟测试,可直接 Run |
- 验证码:6 位数字(多种正则兜底,截图里的
915219可被识别) - 登录链接:
auth.openai.com/ magic link - 登录提醒:IP / 位置 / 设备 / 时间
- 附件列表:名称 / 类型 / 大小
- 基本信息:发件人 / 域名 / 主题 / 接收时间(北京时间)
┌── 📬 收到新邮件 🔐 验证码 (Verification Code) ────────────────┐
├── 基本信息 ────────────────────────────────────────────────────┤
│ 发件人: OpenAI <noreply@tm.openai.com> │
│ 域名: tm.openai.com │
│ 收件人: leixinlin1@example.com │
│ 主题: 你的 ChatGPT 临时验证码 │
│ 接收时间: 2026/05/12 11:31:28 (北京时间) │
│ 是否 OpenAI: ✅ 是 │
├── 🔑 关键数据 ─────────────────────────────────────────────────┤
│ 验证码: 🔢 915219 │
├── 📝 正文预览 ─────────────────────────────────────────────────┤
│ OpenAI 输入此临时验证码以继续: 915219 如果并非你本人尝试创建 │
│ ChatGPT 帐户,请忽略此电子邮件。 谨致问候 ChatGPT 团队 │
├── 📊 元信息 ───────────────────────────────────────────────────┤
│ 正文长度: text 79 字符 / html 0 字符 │
└────────────────────────────────────────────────────────────────┘
可以在 Val Town 的 SQLite 控制台执行:
SELECT received_at, email_type, from_addr, subject, verification_code
FROM received_emails_v1
ORDER BY id DESC
LIMIT 20;
打开 test.ts 点击 Run,即可看到两份样例邮件(OpenAI 验证码 +
普通邮件)的可视化日志。