网页收件箱 MVP PRD(只收不发 / 纯文本)
#1. 背景与目标
我拥有域名 hbue.edu.kg,希望售卖“收件箱账号”。用户购买后获得一个邮箱地址(如 xxx@hbue.edu.kg)与登录密码,仅用于接收邮件并在网页端查看,不支持发送邮件。系统需支持用户自助修改登录密码。
MVP 目标:7 天内上线可用的网页收件箱(纯文本、含基础管理),实现“可售卖、可收信、可登录查看、可改密”。
#2. 目标用户与使用场景
2.1 目标用户
- ▸需要临时收邮件的个人用户(注册验证、接收通知、接收文件信息等)
- ▸不希望暴露个人主邮箱的用户
- ▸仅需要“收件”能力的轻量使用者
2.2 典型使用场景
- ▸用户购买账号后获得
xxx@hbue.edu.kg - ▸用户将该邮箱用于注册网站/接收验证码/接收通知
- ▸邮件到达后,用户登录网页收件箱查看邮件内容(纯文本)
- ▸用户在设置页修改登录密码
#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 核心架构流程
- ▸用户向
xxx@hbue.edu.kg发邮件 - ▸Cloudflare Email Routing 接收邮件,路由到 Email Worker
- ▸Worker 解析 raw 邮件 → 生成结构化 JSON → 带签名请求 Vercel
/api/inbound - ▸Vercel 校验签名 → 查询收件人是否为已售邮箱 → 写入 Supabase
messages - ▸用户登录网页 → 查询
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 退信/丢弃)
- ▸200
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 生效)


