存储与限额
Lumen 共有三类数据:
| 类型 | 位置 | 是否必须 |
|---|---|---|
| 邮件元数据 + 正文 | D1 | 必须 |
| 附件 | R2 | 可选(开关) |
原始 .eml | R2 | 可选(开关) |
| 会话、应用配置 | KV | 必须 |
R2 默认 关闭。未启用前 Lumen 工作于 “只元数据” 模式:入站附件会被 列出但字节内容被丢弃;邮件正文(文本 + 净化后的 HTML)依然写入 D1。
四级存储限额
Lumen 在四个层级上检查存储,任何写入都必须同时通过它们。范围由小到大:
单附件 ≤ 单封邮件 ≤ 单用户合计 ≤ 全站合计| 层级 | 作用范围 |
|---|---|
max_attachment_bytes | 单封邮件中的一份附件 |
…_max_message_bytes | 整封邮件(text + html + 全部附件) |
…_max_user_storage_bytes | 单个用户在所有文件夹中的字节总和 |
global_storage_bytes | 整套 Lumen 部署的全部字节 |
中间两层各有 站点默认值 与可选的 单用户覆盖。优先级:
team_members.max_storage_bytes(单用户)优先于default_max_user_storage_bytes(站点默认)。team_members.max_message_bytes(单用户)优先于default_max_message_bytes(站点默认)。global_storage_bytes是全站硬上限,不可被任何单用户覆盖。
单用户列中的 null 表示 “继承站点默认”;字面值 0 表示 “在该层级显式不限”。 两者含义不同。
配置项
| 键 | 默认 | 作用 |
|---|---|---|
r2_enabled | 关 | 是否持久化附件和原始 .eml |
store_raw_email | 关 | 是否在 R2 中保留原始 RFC 822 字节 |
max_attachment_bytes | 10 MB | 单附件上限。0 = 不限 |
default_max_message_bytes | 25 MB | 单封邮件默认上限,可被单用户覆盖 |
default_max_user_storage_bytes | 100 MB | 单用户合计默认上限,可被单用户覆盖 |
global_storage_bytes | 1 GB | 全站硬上限,不可 被覆盖 |
image_proxy_default | 开 | 站点默认是否代理远程图片 |
image_proxy_user_override | 开 | 是否允许成员覆盖站点默认 |
InitPage 在首启时会询问以上全部值。owner/co-owner 后续可通过 PUT /api/init/config 修改。
单用户覆盖
owner / co-owner 可在 设置 → 成员 → 存储限额 为指定成员覆盖 “单用户合计” 与 “单封” 两项,每项可选:
- 继承站点默认(数据库中存
null)。 - 单独设置:输入 MB 值;
0表示该层级显式不限。
global_storage_bytes 始终 在最外层生效,即便单用户被设为不限, 也不能突破全站硬上限。
触顶时的行为
- 入站超过 单封 上限:Cloudflare Email Routing 处理器调用
setReject,发件方 SMTP 收到拒绝;不写 D1 / R2。 - 入站超过 单用户合计:同样
setReject,用户已有的存储不受影响。 - 入站超过 全站合计:同样
setReject。这是省钱关键——一旦触顶, 所有入站写入操作都会被弹回,直到管理员释放空间或上调上限。 - 出站
POST /api/send:在发送前直接返回 HTTP 413(单封)或 507(单用户 / 全站)。 - 草稿自动保存
POST /api/drafts:同上;前端会展示错误。
回收站算配额。清空回收站(或在回收站内删除单封邮件——会硬删除)即可释放空间。
记账方式
每行 messages 的 storage_bytes 列等于该邮件占用配额的字节数(文本 + 净化 HTML + 真正写入 R2 的附件字节)。用户合计存于 team_members.storage_bytes。增删改、草稿自动保存、发送、硬删除、清空回收站 都同步更新两边。全站合计在请求时通过 SUM(team_members.storage_bytes) 实时计算。
图片代理
入站邮件中的 <img src=...> 可能向发件人泄露收件人 IP 与读取时间。开启图片代理后, 每个外部 http(s) <img> 在读取时被改写为 /api/proxy/image?url=…, Worker 在服务端代为抓取,并应用以下防护:
- 仅允许 HTTP/HTTPS。
- 主机名黑名单:私有 / 回环 / 链路本地的 IPv4 + IPv6,
localhost、*.local、*.internal、metadata.*等。 - 手动处理重定向,最多 3 跳,每跳都重新校验。
- 8 秒响应超时;同时按 Content-Length 与流式截断 10 MB 上限。
- Content-Type 必须以
image/开头;响应附nosniff与 same-origin CORP。 - 不携带 Cookie;User-Agent 固定。
成员可在 设置 → 个人资料 中选择 “总是代理 / 从不代理”, 覆盖站点默认——前提是管理员开启了 image_proxy_user_override。