网页收件箱
otherbeta

网页收件箱

解决教育邮箱接收验证码需求

W
作者
wll
10 浏览2026年1月上线
变现方式其他方式

技术栈

Next.js
Vercel
TypeScript
Tailwind CSS
Supabase
Node.js

网页收件箱 MVP PRD(只收不发 / 纯文本)

#1. 背景与目标

我拥有域名 hbue.edu.kg,希望售卖“收件箱账号”。用户购买后获得一个邮箱地址(如 xxx@hbue.edu.kg)与登录密码,仅用于接收邮件并在网页端查看,不支持发送邮件。系统需支持用户自助修改登录密码。

MVP 目标:7 天内上线可用的网页收件箱(纯文本、含基础管理),实现“可售卖、可收信、可登录查看、可改密”。


#2. 目标用户与使用场景

2.1 目标用户

  • 需要临时收邮件的个人用户(注册验证、接收通知、接收文件信息等)
  • 不希望暴露个人主邮箱的用户
  • 仅需要“收件”能力的轻量使用者

2.2 典型使用场景

  1. 用户购买账号后获得 xxx@hbue.edu.kg
  2. 用户将该邮箱用于注册网站/接收验证码/接收通知
  3. 邮件到达后,用户登录网页收件箱查看邮件内容(纯文本)
  4. 用户在设置页修改登录密码

#3. 产品范围

3.1 MVP 只做(In Scope)

  • 账号体系:登录、退出、改密码
  • 收件:域名接收邮件 → 入库 → 网页列表/详情展示(纯文本)
  • 邮件操作:已读/未读
  • 基础安全:Webhook 验签、防重放、去重入库、权限隔离(用户只能看自己的邮件)
  • 管理能力(最小):管理员创建“邮箱账号”(生成邮箱地址 + 初始密码)

3.2 MVP 不做(Out of Scope)

  • 发信(SMTP/网页发送)完全不支持
  • HTML 邮件渲染、附件下载(后续迭代)
  • IMAP/POP3 客户端收取
  • 复杂规则(自动转发/过滤/标签/搜索/垃圾邮件识别)
  • 退款/支付系统(先人工/闲鱼交付)

#4. 功能明细(MVP)

4.1 用户端

4.1.1 登录/会话

  • 用户使用「邮箱地址 + 密码」登录
  • 登录成功后进入收件箱
  • 支持退出登录

4.1.2 收件箱列表

  • 展示最近邮件列表(分页/加载更多)
  • 列表字段:发件人、主题、接收时间、已读状态
  • 点击进入邮件详情

4.1.3 邮件详情(纯文本)

  • 展示:From、To、Subject、接收时间、正文(纯文本)
  • 支持标记已读(打开即自动标记已读)

4.1.4 修改密码

  • 输入旧密码、新密码
  • 修改成功后下次使用新密码登录(可选择强制重新登录)

4.2 管理端(最小化)

4.2.1 创建邮箱账号(管理员)

  • 输入邮箱前缀(或自动生成)
  • 系统生成初始密码(强随机)
  • 绑定生成 prefix@hbue.edu.kg
  • 输出:邮箱地址 + 初始密码(仅展示一次,管理员复制发给用户)
  • 可停用账号(停用后不再接收/拒收邮件,用户也无法登录)

#5. 技术方案与技术栈

5.1 技术栈

  • 前端/全栈:Next.js(App Router) + TypeScript
  • UI:TailwindCSS + shadcn/ui
  • 部署:Vercel
  • 数据库/鉴权:Supabase(Auth + Postgres)
  • 入站收信:Cloudflare Email Routing → Email Worker → Webhook 转发到 Vercel API
  • 邮件解析:Cloudflare Worker 使用 postal-mime 将 raw MIME 解析为字段(MVP 只取 text)

5.2 核心架构流程

  1. 用户向 xxx@hbue.edu.kg 发邮件
  2. Cloudflare Email Routing 接收邮件,路由到 Email Worker
  3. Worker 解析 raw 邮件 → 生成结构化 JSON → 带签名请求 Vercel /api/inbound
  4. Vercel 校验签名 → 查询收件人是否为已售邮箱 → 写入 Supabase messages
  5. 用户登录网页 → 查询 messages 列表/详情展示

#6. 数据模型(建议)

6.1 表:mailboxes

  • id:uuid(= auth.users.id)
  • email:text unique(如 abc@hbue.edu.kg
  • is_active:boolean
  • created_at:timestamptz

6.2 表:messages

  • id:bigint
  • mailbox_id:uuid(关联 user)
  • from_email:text
  • subject:text
  • text_body:text
  • message_id:text(用于去重)
  • received_at:timestamptz
  • is_read:boolean

RLS:用户只能 SELECT 自己 mailbox_id 的 messages;写入由服务端 service_role 完成。


#7. 接口设计(MVP)

7.1 外部接入(收信)

POST /api/inbound

用途:Cloudflare Worker 推送入站邮件

  • Headers:

    • x-ts:时间戳(毫秒)
    • x-sig:HMAC-SHA256(base64),签名内容:${x-ts}.${rawBody}
  • Body(JSON):

    • to:收件人邮箱(单个)
    • from:发件人邮箱
    • subject:主题
    • text:纯文本正文
    • messageId:message-id(可空)
    • receivedAt:ISO 时间(可空)
  • 返回:

    • 200 { ok: true }
    • 404 Mailbox not found(未售邮箱,建议 Worker 退信/丢弃)

7.2 站内接口(用户端)

GET /api/messages

  • 需要登录
  • 参数:cursor/page(任选其一)
  • 返回:邮件列表(含 is_read)

GET /api/messages/:id

  • 需要登录
  • 返回:邮件详情(纯文本)

PATCH /api/messages/:id/read

  • 需要登录
  • 标记已读

7.3 站内接口(管理端)

POST /api/admin/mailboxes

  • 管理员鉴权(先用简单 admin token)
  • 请求:prefix?(可选)
  • 返回:email + initialPassword

PATCH /api/admin/mailboxes/:id/disable

  • 停用邮箱账号

#8. 验收标准(MVP)

8.1 功能验收

  • [ ] 管理员可创建邮箱账号(输出邮箱地址与初始密码)
  • [ ] 用户可用邮箱+密码登录网页收件箱
  • [ ] 外部向该邮箱发送邮件后,30 秒内能在网页端看到新邮件
  • [ ] 收件箱列表正确展示:发件人/主题/时间/已读状态
  • [ ] 邮件详情可查看纯文本正文
  • [ ] 打开邮件自动标记已读,列表状态同步变化
  • [ ] 用户可成功修改登录密码,并用新密码重新登录
  • [ ] 未售邮箱收到邮件:系统不会入库(按策略退信或丢弃)

8.2 安全/稳定性验收

  • [ ] /api/inbound 必须验签通过才写库(非法请求 401)
  • [ ] 重放攻击:超过时间窗的请求拒绝(401)
  • [ ] 去重:同一 mailbox_id + messageId 重复推送不会产生重复记录
  • [ ] 权限隔离:用户只能看到自己邮箱的邮件(RLS 生效)

📸

项目截图

Screenshot 1
Screenshot 2