Cloudflare 临时邮箱 S3 附件存储配置指南:R2 对象存储接入与附件管理实战

发布时间:2026/9/15 14:11:10
Cloudflare 临时邮箱 S3 附件存储配置指南:R2 对象存储接入与附件管理实战 Cloudflare 临时邮箱 S3 附件存储配置指南R2 对象存储接入与附件管理实战【免费下载链接】cloudflare_temp_emailCloudFlare free temp domain email 免费收发 临时域名邮箱 支持附件 IMAP SMTP TelegramBot项目地址: https://gitcode.com/GitHub_Trending/cl/cloudflare_temp_email本指南以 cloudflare_temp_email 项目的 S3 附件功能为核心讲解如何在 Cloudflare R2或其他兼容 S3 协议的对象存储上保存与下载邮件附件涵盖 bucket 与凭证创建、Worker Secrets 配置、签名 URL 上传下载流程以及前端交互与后端 API 的完整实现链路。读完本文你将能独立为本项目启用附件持久化存储并理解其底层签名 URL 机制与密钥管理方式。说明以上截图来自仓库文档 vitepress-docs/docs/zh/guide/feature/s3-attachment.md展示在邮件详情中查看附件并将附件保存到 S3 的界面操作。一、功能定位为什么需要 S3 附件在临时邮箱场景中邮件正文通常存储在 Cloudflare D1 数据库里而邮件附件的体积往往远超文本内容。若将所有附件一并写入 D1会带来两个问题数据库体积膨胀大量 Base64 编码的附件会迅速消耗 D1 的存储配额且 D1 按读取行数与存储量计费成本随之上升数据库读写效率下降列表查询、全文检索等操作会因行内的大字段而变慢。因此项目将附件外置到对象存储正文留在 D1附件按需上传到 S3 兼容存储官方文档直接以 Cloudflare R2 为例也兼容其他 S3 服务。附件与邮件分离后邮件列表页无需加载附件二进制数据只有用户主动保存或下载时才通过签名 URL 与对象存储交互。[!NOTE] 此功能是可选项。若你的使用场景不需要保存附件可以直接跳过本章节系统其余功能不受影响。二、前置条件与配置项总览启用 S3 附件功能前需要准备一个 Cloudflare 账号并在 Cloudflare 控制台创建R2 bucket也可以使用其他兼容 S3 协议的对象存储服务如遇兼容性问题可在项目仓库提 issue参考 Cloudflare 官方文档为 bucket 配置CORS 策略允许来自你部署域名的跨域请求前端需要直接向对象存储发起 PUT 请求上传附件参考 Cloudflare R2 的S3 Token文档创建访问令牌获得以下三个凭证ENDPOINTS3 兼容端点地址Access Key IDSecret Access Key这些凭证会被配置为 Cloudflare Worker 的 Secrets。从源码看Worker 侧共使用四个与 S3 相关的环境变量定义于 worker/src/types.d.ts环境变量类型作用S3_ENDPOINTstring \| undefinedS3 兼容服务的端点地址R2 的 S3 API 端点S3_ACCESS_KEY_IDstring \| undefinedR2 S3 Token 的 Access Key IDS3_SECRET_ACCESS_KEYstring \| undefinedR2 S3 Token 的 Secret Access KeyS3_BUCKETstring \| undefined对象存储 bucket 名称S3_URL_EXPIRESnumber \| undefined可选签名 URL 有效期秒默认 360 秒其中前四个变量是启用功能的必要条件。源码 worker/src/mails_api/s3_attachment.ts 中通过isS3Enabled判断四个变量是否全部非空只有全部配置后才认为 S3 附件功能可用export const isS3Enabled (c: ContextHonoCustomType) { return !(!c.env.S3_ENDPOINT || !c.env.S3_ACCESS_KEY_ID || !c.env.S3_SECRET_ACCESS_KEY || !c.env.S3_BUCKET); }S3_URL_EXPIRES是可选配置控制签名 URL 的有效期源码中取值为c.env.S3_URL_EXPIRES || 360即未配置时默认 360 秒。三、配置步骤创建 R2 Bucket 与写入 Worker Secrets3.1 创建 bucket 并准备 CORS 与凭证登录 Cloudflare 控制台进入R2 → Buckets创建一个 bucket例如命名为temp-mail-attachments记下 bucket 名称在该 bucket 的Settings → CORS中按 Cloudflare 官方文档添加 CORS 策略允许你的前端域名通过浏览器跨域上传/下载附件对应前端的PUT与GET请求进入R2 → Manage API Tokens → Create API Token按 R2 S3 Token 的方式生成凭证页面会返回ENDPOINT、Access Key ID与Secret Access Key三项信息。3.2 写入 Worker Secrets在项目根目录进入worker目录逐条执行wrangler secret put命令将凭证写入 Worker 的 Secretscd worker pnpm wrangler secret put S3_ENDPOINT pnpm wrangler secret put S3_ACCESS_KEY_ID pnpm wrangler secret put S3_SECRET_ACCESS_KEY # 请注意这里的 bucket 是你的 bucket 名称 pnpm wrangler secret put S3_BUCKET每条命令执行后终端会提示输入对应的值粘贴凭证后回车即可。wrangler secret put会将值加密存储不会明文写入代码或配置文件。[!NOTE] 除了命令行方式也可以直接在 Cloudflare Worker 的 UI 界面中通过Settings → Variables and Secrets添加同名 Secrets。3.3 验证功能是否生效配置完成后S3 功能是否开启会通过 Worker 的两个接口暴露给前端worker/src/commom_api.ts 中的公共设置接口返回isS3Enabled布尔值worker/src/admin_api/worker_config.ts 中的 Worker 配置接口同样返回S3_ENABLED字段。两者均直接复用isS3Enabled(c)的判定结果。前端拿到该值后会决定是否展示S3 附件标签页以及邮件列表中的保存到S3按钮见 frontend/src/views/Index.vue 中showSaveS3openSettings.isS3Enabled与v-ifopenSettings.isS3Enabled的写法。四、使用方式保存与下载附件配置完成后前端界面出现两个入口保存附件打开任意邮件的附件列表点击保存到S3按钮将当前附件上传至对象存储见 vitepress-docs/docs/zh/guide/feature/s3-attachment.md 中的界面截图下载附件进入S3附件标签页查看已保存的附件列表点击下载即可取回文件。说明上图为 S3 附件管理页的界面截图来源同仓库文档表格中展示附件的 key形如37/one-api.db与下载操作按钮。4.1 前端保存到S3完整流程以 frontend/src/views/Index.vue 中的saveToS3为例保存流程分两步向后端请求签名 PUT URLconst { url } await api.fetch(/api/attachment/put_url, { method: POST, body: JSON.stringify({ key: ${mail_id}/${filename} }) });注意这里前端把附件 key 组织为mail_id/文件名的形式拿到 URL 后通过表单数据直接向该 URL 发起PUT请求上传const formData new FormData(); formData.append(filename, blob); await fetch(url, { method: PUT, body: formData }); message.success(t(saveToS3Success));上传成功后提示保存到s3成功。4.2 前端S3附件列表与下载S3 附件列表页 对应后端list与get_url两个接口进入页面时调用GET /api/attachment/list拉取当前地址下的附件 key 列表点击下载时调用POST /api/attachment/get_url换取签名 GET URL再跳转下载。删除附件则调用POST /api/attachment/delete。五、后端实现原理签名 URL 与按地址隔离所有附件 API 都集中在 worker/src/mails_api/s3_attachment.ts并统一注册在 worker/src/mails_api/index.ts// attachment (S3) api.get(/api/attachment/list, s3_attachment.list) api.post(/api/attachment/delete, s3_attachment.deleteKey) api.post(/api/attachment/put_url, s3_attachment.getSignedPutUrl) api.post(/api/attachment/get_url, s3_attachment.getSignedGetUrl)5.1 客户端初始化与密钥隔离getS3Client使用aws-sdk/client-s3构造 S3 客户端region固定为autoR2 的默认区域约定端点与凭证来自上述环境变量return new S3Client({ region: auto, endpoint: c.env.S3_ENDPOINT, credentials: { accessKeyId: c.env.S3_ACCESS_KEY_ID, secretAccessKey: c.env.S3_SECRET_ACCESS_KEY, }, });值得注意的一个安全设计所有对象的 key 都以当前登录邮箱地址作为前缀。例如列表接口只列出Prefix: ${address}/下的对象删除、签名下载、签名上传也都拼接${address}/${key}。这意味着即使多个临时地址共用同一个 bucket附件也按地址相互隔离一个地址的用户无法列举或操作其他地址的附件。当前地址来自请求中的 JWT payloadc.get(jwtPayload)因此该接口必须经过登录鉴权。5.2 签名 URL附件不经过 Worker 转发四个接口中上传与下载都采用AWS S3 预签名 URLpresigned URL模式getSignedPutUrl用PutObjectCommand生成 PUT 签名 URL前端直接向对象存储上传getSignedGetUrl用GetObjectCommand生成 GET 签名 URL前端直接下载。签名 URL 的有效期由S3_URL_EXPIRES控制默认 360 秒使用aws-sdk/s3-request-presigner的getSignedUrl生成。这种设计的核心收益是附件二进制数据不经过 Worker 中转Worker 只负责鉴权与签发有时效的 URL既减轻了 Worker 的 CPU 与流量开销也避免 D1 存储被附件撑大。5.3 列表与删除list调用ListObjectsV2CommandPrefix限定为address/返回结果中剔除地址前缀后输出{ key }数组deleteKey调用DeleteObjectCommand删除指定 key 的对象返回{ success: true }。六、附件裁剪策略与 S3 的配合为了控制邮件正文与附件的整体体积Worker 还提供附件裁剪逻辑位于 worker/src/email/check_attachment.ts开启REMOVE_ALL_ATTACHMENT时收信后直接移除全部附件开启REMOVE_EXCEED_SIZE_ATTACHMENT且邮件大小 ≥ 2MB 时移除超过阈值的附件。被移除的附件在重新生成的 MIME 邮件中被清空attachments: []从而避免超大邮件写入 D1。结合 S3 附件功能合理的策略是正文与常规附件入库超大或需要留存的附件保存到 R2兼顾查询性能与存储成本。需要说明的是这两项裁剪策略与 S3 保存是相互独立的开关是否同时启用由你的业务诉求决定。七、注意事项CORS 必配由于上传是前端浏览器直接向 R2 发起PUT请求bucket 的 CORS 策略必须允许你的站点域名含请求方法PUT/GET与所需请求头否则浏览器会拦截跨域请求Secrets 不落盘S3_ACCESS_KEY_ID与S3_SECRET_ACCESS_KEY属于敏感凭证请通过wrangler secret put或 Worker UI 的 Secrets 管理不要硬编码到wrangler.toml或提交进仓库签名 URL 有时效上传/下载 URL 默认 360 秒内有效过期后需重新向后端申请bucket 名称即配置值S3_BUCKET的值就是你在 R2 中创建的 bucket 名称注意大小写与名称完全一致其他 S3 服务官方文档说明可以接入其他兼容 S3 协议的服务但 R2 之外的兼容性问题请通过 issue 反馈项目按 R2 的 S3 API 行为为主进行开发与测试。至此你已完整掌握该项目的 S3 附件配置、界面操作与底层实现。相关源码入口可继续查阅 worker/src/mails_api/s3_attachment.ts、worker/src/mails_api/index.ts 与 frontend/src/views/Index.vue。【免费下载链接】cloudflare_temp_emailCloudFlare free temp domain email 免费收发 临时域名邮箱 支持附件 IMAP SMTP TelegramBot项目地址: https://gitcode.com/GitHub_Trending/cl/cloudflare_temp_email创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考