Forward Email - Webmail, Desktop, and Mobile
这是 Forward Email 的官方、开源且端到端加密的 webmail 客户端。它以快速现代的 web 应用、支持 Windows、macOS 和 Linux 的跨平台桌面应用,以及适用于 iOS 和 Android 的原生移动应用形式提供。
Table of Contents
下载与发布
官方桌面版和 Android 版制品发布在 GitHub Releases 页面。桌面版构建由公开的 GitHub Actions 发布工作流生成,桌面版发布矩阵现针对 macOS arm64/x64、Windows x64/arm64 和 Linux x64/arm64。
| 平台 | 架构 | 下载 | 商店 |
|---|---|---|---|
| Web | — | mail.forwardemail.net | — |
| Windows | x64 | .msi / .exe on GitHub Releases | — |
| Windows | arm64 | -setup.exe on GitHub Releases | — |
| macOS | Apple Silicon & Intel | .dmg on GitHub Releases | App Store (Coming Soon) |
| Linux | x64 | .deb / .AppImage / .rpm on GitHub Releases | — |
| Linux | arm64 | .deb / .rpm on GitHub Releases | — |
| Android | Universal | .apk / .aab on GitHub Releases | Google Play (Coming Soon) |
| iOS | arm64 | TestFlight / App Store distribution | App Store (Coming Soon) |
Ubuntu / Debian 安装
对于 Ubuntu x64 / amd64,请下载当前的 .deb 资产,来自 GitHub Releases,然后使用以下命令安装:
sudo apt update
sudo apt install ./Forward.Email_<version>_amd64.deb
对于 Ubuntu arm64 / aarch64,以相同方式安装对应的 arm64 .deb:
sudo apt update
sudo apt install ./Forward.Email_<version>_arm64.deb
对于可移植的 Linux x64 / amd64 二进制文件,请从 GitHub Releases 下载 Forward.Email_<version>_amd64.AppImage,使其可执行,并直接运行。发布矩阵未提供 arm64 AppImage;Linux arm64 用户应改为安装 .deb 或 .rpm 资源。
chmod +x Forward.Email_<version>_amd64.AppImage
./Forward.Email_<version>_amd64.AppImage
如果你正在构建自己的自定义 Linux 二进制文件,而不是安装已发布的版本,请使用 docs/desktop-setup.md 中的桌面开发指南。
macOS 用户注意: 如果你从 GitHub Releases 下载
.dmg,当看到“已损坏”或未验证的应用程序错误时,可能需要运行以下命令:sudo xattr -rd com.apple.quarantine "/Applications/Forward Email.app"如果你将应用程序安装在其他位置,请将
/Applications/Forward Email.app替换为实际路径。
截图
截图截至 2026 年 8 月 5 日。
这些截图是在每次成功发布后,从生产环境的 Demo Account 自动捕获的。展开主题和设备组以浏览其视图。
深色模式 — 桌面端
| 视图 | 截图 |
|---|---|
| 登录页面 | ![]() |
| 邮件视图 | ![]() |
| 消息视图 | ![]() |
| 撰写窗口 | ![]() |
| 联系人页面 | ![]() |
| 日历页面 | ![]() |
| 个人资料页面 | ![]() |
| 诊断页面 | ![]() |
| 常规设置页面 | ![]() |
| 外观设置页面 | ![]() |
| 隐私和安全页面 | ![]() |
| 文件夹和标签设置页面 | ![]() |
| 搜索设置页面 | ![]() |
| 高级设置页面 | ![]() |
| 键盘快捷键页面 | ![]() |
| 关于和帮助页面 | ![]() |
深色模式 — 移动端
| 视图 | 截图 |
|---|---|
| 登录页面 | ![]() |
| 邮件视图 | ![]() |
| 消息视图 | ![]() |
| 撰写窗口 | ![]() |
| 联系人页面 | ![]() |
| 日历页面 | ![]() |
| 个人资料页面 | ![]() |
| 诊断页面 | ![]() |
| 常规设置页面 | ![]() |
| 外观设置页面 | ![]() |
| 隐私和安全页面 | ![]() |
| 文件夹和标签设置页面 | ![]() |
| 搜索设置页面 | ![]() |
| 高级设置页面 | ![]() |
| 键盘快捷键页面 | ![]() |
| 关于和帮助页面 | ![]() |
浅色模式 — 桌面端
| 视图 | 截图 |
|---|---|
| 登录页面 | ![]() |
| 邮件视图 | ![]() |
| 消息视图 | ![]() |
| 撰写窗口 | ![]() |
| 联系人页面 | ![]() |
| 日历页面 | ![]() |
| 个人资料页面 | ![]() |
| 诊断页面 | ![]() |
| 常规设置页面 | ![]() |
| 外观设置页面 | ![]() |
| 隐私和安全页面 | ![]() |
| 文件夹和标签设置页面 | ![]() |
| 搜索设置页面 | ![]() |
| 高级设置页面 | ![]() |
| 键盘快捷键页面 | ![]() |
| 关于和帮助页面 | ![]() |
浅色模式 — 移动端
| 视图 | 截图 |
|---|---|
| 登录页面 | ![]() |
| 邮件视图 | ![]() |
| 消息视图 | ![]() |
| 撰写窗口 | ![]() |
| 联系人页面 | ![]() |
| 日历页面 | ![]() |
| 个人资料页面 | ![]() |
| 诊断页面 | ![]() |
| 常规设置页面 | ![]() |
| 外观设置页面 | ![]() |
| 隐私和安全页面 | ![]() |
| 文件夹和标签设置页面 | ![]() |
| 搜索设置页面 | ![]() |
| 高级设置页面 | ![]() |
| 键盘快捷键页面 | ![]() |
| 关于和帮助页面 | ![]() |
安全与隐私
安全是本应用的基础原则。我们致力于保持透明,并赋予用户对其数据的控制权。有关我们安全实践的详细说明,请参阅:
客户端加密与应用锁
该应用提供强大的应用锁功能,可对您的整个客户端数据库和设置进行加密——无论是在浏览器、桌面还是移动设备上。当从设置 > 隐私与安全菜单启用时,所有本地存储的敏感数据(包括消息正文、联系人和 API 令牌)都会使用经过审计的 libsodium 库中的 XSalsa20-Poly1305 流密码进行静态加密。
此功能可通过以下两种方式进行保护:
- 通行密钥 (WebAuthn):为了获得最高级别的安全性,您可以使用符合 FIDO2/WebAuthn 标准的身份验证器来锁定和解锁应用。这允许您使用硬件安全密钥或设备内置的生物识别功能。加密密钥直接通过 PRF 扩展从身份验证器派生,这意味着密钥本身不会存储在设备上。
- PIN 码:为了方便起见,您可以设置一个简单的 PIN 码。这提供了类似 iOS 的锁屏体验,非常适合在移动设备上快速访问。
我们的实现支持用于基于通行密钥的应用锁的广泛身份验证器:
| Type | Examples |
|---|---|
| Platform Authenticators | Apple Touch ID, Face ID, Optic ID, Windows Hello, Android Biometrics (fingerprint, face) |
| Hardware Security Keys | YubiKey 5 Series, YubiKey Bio, Google Titan, Feitian ePass/BioPass, SoloKeys, Nitrokey 3, HID Crescendo, Ledger |
| Cloud/Software Passkeys | iCloud Keychain, Google Password Manager, Samsung Pass, 1Password, Dashlane, Bitwarden, Proton Pass |
防篡改构建
所有构建均由公共 GitHub Actions 工作流直接从源代码处理。桌面应用程序使用平台特定的证书进行签名(Apple Developer ID 和 Windows Authenticode),并且 Tauri 更新器使用 Ed25519 签名来验证每个更新包。邮箱内容和 WebSocket 更新直接在应用程序和 Forward Email 之间传输。仅在操作系统要求时才使用平台交付基础设施:iOS 上的 APNs,Android 上的 FCM 或用户选择的 UnifiedPush 分发器,以及用于桌面更新包的 GitHub Releases。Forward Email 不会在这些路径中添加广告、分析或跟踪中间件。
功能
- 极速体验: 基于 Rust 和 Svelte 5 构建,提供轻量且响应迅速的使用体验。
- 端到端加密: 为您的整个客户端应用提供加密保护——无论是浏览器、桌面端还是移动端。
- 开源: Web、桌面和移动应用的所有代码均可在 GitHub 上获取。
- 无广告或跟踪中间件: 邮箱数据和实时 WebSocket 更新仅在应用与 Forward Email 之间传输。平台推送服务商和发布托管仅用于交付原生通知和签名的应用更新。
- 实时更新: 邮箱更新通过 WebSockets 即时推送。
- 跨平台通知: 原生桌面和移动推送通知。
- 多账户 — 使用多个 Forward Email 账户登录,别名认证,以及可选的 API 密钥覆盖。
- 邮箱 — 文件夹、消息线程、批量操作、键盘快捷键、附件处理、PGP 解密。
- 撰写 — 富文本编辑器 (TipTap),CC/BCC,表情选择器,附件,草稿自动保存,离线发件箱队列。
- 搜索 — 基于 FlexSearch 的全文搜索,可选正文索引,保存的搜索,后台索引。
- 离线支持: 自定义的主线程同步引擎提供离线访问并排队出站操作,取代了对 Service Worker 的需求,并确保在所有平台(包括 Ionic/Capacitor 移动端)上的功能正常。
- 日历 — 月/周/日视图,快速添加/编辑/删除,iCal 导出。
- Contacts — CRUD 操作,vCard 导入/导出,用于撰写/搜索的深度链接。
- Demo Mode:无需账户即可离线评估应用功能。
mailto:Handler:在桌面平台上注册为默认邮件客户端。- Auto-Updates:桌面应用会自动安全地检查并安装新版本。
架构概览
该应用基于统一架构构建,在所有平台上复用同一个 Svelte 5 Web 应用作为 UI。Tauri v2 提供跨平台外壳,使用 Rust 后端实现原生功能,并使用系统 webview 渲染 UI。
graph TD
subgraph "Web App (Svelte 5 + Vite)"
A[UI Components] --> B(Stores)
B --> C{API Client}
C --> D[REST API]
B --> E{WebSocket Client}
E --> F[Real-time API]
end
subgraph "Tauri (Desktop & Mobile)"
G[Rust Backend] --> H{System WebView}
H -- loads --> A
I[Tauri IPC] -- JS Bridge --> A
G -- IPC --> I
J[Tauri Plugins] --> G
end
D --- M(api.forwardemail.net)
F --- M
有关更多详细信息,请参阅完整的架构文档。
技术栈
| 类别 | 技术 |
|---|---|
| Web | Svelte 5, Vite, pnpm |
| Desktop & Mobile | Tauri v2 (Rust 后端, Svelte 前端) |
| Styling | Tailwind CSS 4, PostCSS |
| State | Svelte Stores |
| Database | Dexie 4 (IndexedDB) |
| Search | FlexSearch |
| Editor | TipTap 2 |
| Calendar | schedule-x |
| Real-time | 使用 msgpackr 二进制编码的 WebSocket |
| Encryption | libsodium-wrappers (XSalsa20-Poly1305, Argon2id), OpenPGP |
| Passkeys | @passwordless-id/webauthn (带 PRF 扩展的 FIDO2/WebAuthn) |
| Testing | Vitest, 用于 E2E 测试的 Playwright, 用于 Tauri 二进制测试的 WebdriverIO |
| Tooling | ESLint 9, Prettier 3, Husky, commitlint |
关键组件
- Main Thread — Svelte 组件、stores、路由、UI 渲染
- db.worker — 通过 Dexie 拥有 IndexedDB,处理所有数据库操作
- sync.worker — API 获取、消息解析(PostalMime)、数据规范化
- search.worker — FlexSearch 索引和查询执行
Documentation
详细的架构文档可在 docs/ 目录中找到:
- 架构 — 完整架构文档
- 愿景与架构 — 设计原则和架构模式
- Worker 架构 — Worker 职责和消息传递
- 缓存与索引 — 存储层和数据流
- 搜索 — FlexSearch 配置和查询解析
- Service Worker — 资源缓存策略
- 数据库模式与恢复 — 数据库管理
- 桌面构建 CI — 桌面构建的触发和测试方式
- 桌面 CI 密钥 — 桌面签名的 CI 密钥配置
- 桌面贡献指南 — 桌面架构和 IPC 模式
- 桌面环境搭建 — 桌面开发者环境搭建
- 桌面与移动开发 — 平台特定开发指南
- iOS 环境搭建 — 本地签名、CI 和 TestFlight 工作流
- 发布流程 — 发布的管理方式
- 安全加固 — 安全实践和加固
- 应用锁架构 — 客户端加密和应用锁设计
- 推送通知 — 推送通知配置
- WebSocket — 实时 WebSocket 协议
- Tauri 测试 — Tauri 桌面/移动应用测试
- 密钥 — CI/CD 的密钥管理
- Workers — Worker 网格架构
- 技术栈 — 技术选型和理由
- 邮箱加载流程 — 加载消息的完整请求生命周期
- Clear-Site-Data — 客户端重置紧急停止开关规范
- 部署清单 — 分步部署指南
- 构建 Webmail 系列 — 技术深度博客系列概览
- 愿景差距分析 — 愿景规范与实现之间的差距分析
项目结构
src/
├── main.ts # App bootstrap, routing, service worker registration
├── config.ts # Environment configuration
├── stores/ # Svelte stores (state management)
│ ├── mailboxStore.ts # Message list, folders, threading
│ ├── mailboxActions.ts # Move, delete, flag, label actions
│ ├── messageStore.ts # Selected message, body, attachments
│ ├── searchStore.ts # Search queries and index health
│ ├── settingsStore.ts # User preferences, theme, PGP keys
│ └── ...
├── svelte/ # Svelte components
│ ├── Mailbox.svelte # Main email interface
│ ├── Compose.svelte # Email composer
│ ├── Calendar.svelte # Calendar view
│ ├── Contacts.svelte # Contact management
│ ├── Settings.svelte # User settings
│ └── components/ # Reusable components
├── workers/ # Web Workers
│ ├── db.worker.ts # IndexedDB operations
│ ├── sync.worker.ts # API sync and parsing
│ └── search.worker.ts # Search indexing
├── utils/ # Utilities
│ ├── remote.js # API client
│ ├── db.js # Database initialization
│ ├── storage.js # LocalStorage management
│ └── ...
├── lib/components/ui/ # UI component library (shadcn/ui)
├── styles/ # CSS (Tailwind + custom)
├── locales/ # i18n translations
└── types/ # TypeScript definitions
快速开始
前置条件
- Node.js 20+
- pnpm 9.0.0+
- Rust 和 Tauri v2 前置条件(用于桌面/移动开发)
安装
pnpm install
开发
pnpm dev # Start web dev server (http://localhost:5174)
pnpm tauri dev # Start desktop dev mode
pnpm tauri:android:dev # Start Android dev mode (preflight checks + adb setup)
pnpm tauri:ios:dev # Start iOS dev mode (preflight checks + simulator boot)
构建
pnpm build # Build to dist/ + generate service worker
pnpm preview # Preview production build locally
pnpm analyze # Build with bundle analyzer
代码质量
pnpm lint # Run ESLint
pnpm lint:fix # Fix linting issues
pnpm format # Check formatting
pnpm format:fix # Fix formatting
pnpm check # Run svelte-check
测试
# Unit tests (Vitest)
pnpm test # Run all tests
pnpm test:watch # Watch mode
pnpm test:coverage # Generate coverage report
# E2E tests (Playwright)
pnpm exec playwright install --with-deps # First-time setup
pnpm test:e2e # Run e2e tests
贡献
提交信息
本项目使用由 commitlint 强制执行的 Conventional Commits。每条提交信息都必须遵循以下格式:
type(scope): description
| 类型 | 使用时机 | 版本提升 |
|---|---|---|
feat | 新功能 | minor |
fix | 缺陷修复 | patch |
docs | 仅文档更新 | none |
refactor | 既不修复也不新增的代码变更 | none |
perf | 性能改进 | patch |
test | 添加或更新测试 | none |
chore | 构建、CI、工具链变更 | none |
作用域是可选的:fix(compose): handle pasted recipients 或 fix: handle pasted recipients 均有效。
要触发 major 版本提升,请添加 BREAKING CHANGE: 页脚:
feat: redesign settings page
BREAKING CHANGE: settings store schema changed, requires cache clear
发布
发布在本地使用 np 进行管理。版本升级仍然通过 pnpm release 进行,桌面端工件的发布由 Tauri 桌面端发布工作流以及用于桌面端专用热修复的 pnpm release:desktop 辅助工具处理。
pnpm release # interactive version prompt, runs checks, pushes, publishes GitHub Release
该命令将执行以下操作:
- 验证工作区干净且
main分支为最新状态 - 运行 lint、格式化、测试和构建
- 更新
package.json中的版本号并创建 git 标签 - 将提交和标签推送到 GitHub
- 发布 GitHub Release
对于桌面端发布,推送桌面标签或手动运行工作流会触发 Release Desktop (Tauri) (.github/workflows/release-desktop.yml),该流程会创建或更新一个草稿 GitHub Release,并上传 macOS x64/arm64、Windows x64/arm64 和 Linux x64/arm64 的桌面端构建产物。
配置
创建一个 .env 文件以覆盖默认设置:
# API base URL (Vite requires VITE_ prefix for client exposure)
VITE_WEBMAIL_API_BASE=https://api.forwardemail.net
部署
首次设置? 请参阅完整的 部署清单,了解 Cloudflare、GitHub Actions 和 DNS 配置的逐步说明。
基础设施
graph TB
subgraph Edge["Cloudflare Edge"]
subgraph Worker["Cloudflare Worker"]
W1["SPA routing (returns index.html for /mailbox, etc)"]
W2["Cache headers (immutable for assets, no-cache HTML)"]
end
Worker --> R2
subgraph R2["Cloudflare R2"]
R2A["Static assets (dist/)"]
R2B["Fingerprinted bundles (/assets/*.js, *.css)"]
end
end
缓存策略
| 资源类型 | Cache-Control | 原因 |
|---|---|---|
index.html, /mailbox, /calendar, 等 | no-cache, no-store | 始终获取最新 HTML 以进行更新 |
/assets/* (JS, CSS) | immutable, max-age=31536000 | 由 Vite 进行指纹处理,可永久缓存 |
sw.js, sw-*.js, version.json | no-cache, must-revalidate | Service worker 必须检查更新 |
/icons/* | max-age=2592000 | 30 天,很少更改 |
字体 (.woff2) | immutable, max-age=31536000 | 已指纹处理,永久缓存 |
CI/CD 流水线
顶层 Release 工作流 (.github/workflows/release.yml) 是每个 v* 标签的生产环境编排器。它运行 WebView E2E 门禁,创建草稿 GitHub Release,调用可复用的桌面和移动工作流,将 Web 应用程序部署到 Cloudflare R2 和 Workers,发布版本,生成校验和,并可选地发送 Matrix 通知。
编排器调用两个可复用的平台工作流:
- Release Desktop (Tauri) (
.github/workflows/release-desktop.yml) 构建 macOS x64/arm64、Windows x64/arm64 和 Linux x64/arm64 桌面工件。请参阅 Desktop Build CI guide 了解平台矩阵、运行器详情和工件预期。 - Release Mobile (
.github/workflows/release-mobile.yml) 构建已签名的双提供商 Android APK/AAB 和已签名的 iOS IPA,然后上传已配置的商店工件。请参阅 Release Process、iOS Setup 和 Secrets 了解确切的签名输入和发布流程。
独立的 deploy.yml 工作流是手动 workflow_dispatch 恢复路径,用于重新部署当前的 web 构建;常规的带标签发布从 release.yml 内联部署。
发布工作的本地验证在标记发布之前,仍应涵盖标准的 Web 检查:
- Install —
pnpm install --frozen-lockfile - Lint —
pnpm lint - Format —
pnpm format - Unit tests —
pnpm test -- --run - Build —
pnpm build - Desktop build smoke test —
pnpm tauri:buildfor the target platform you are validating
如需精确的密钥生成、GitHub 环境配置以及特定平台的签名步骤,请以 docs/SECRETS.md 作为权威指南,并以 docs/desktop-ci-secrets.md 和 docs/ios-setup.md 作为特定平台的配套文档。
必需的密钥与变量
GitHub 机密:
| Secret | Description |
|---|---|
R2_ACCOUNT_ID | Cloudflare 账户 ID(也用于 Workers) |
R2_ACCESS_KEY_ID | R2 API 访问密钥 |
R2_SECRET_ACCESS_KEY | R2 API 密钥 |
CLOUDFLARE_ZONE_ID | 用于缓存清除的 Zone ID |
CLOUDFLARE_API_TOKEN | 具有 R2 + Workers + 缓存清除权限的 API 令牌 |
TAURI_SIGNING_PRIVATE_KEY | Tauri 更新器 Ed25519 签名密钥 |
TAURI_SIGNING_PRIVATE_KEY_PASSWORD | Tauri 签名密钥的密码 |
APPLE_CERTIFICATE | Base64 编码的 macOS .p12 签名证书 |
APPLE_CERTIFICATE_PASSWORD | 用于导出 macOS .p12 的密码 |
APPLE_SIGNING_IDENTITY | Apple Developer ID 签名身份 |
APPLE_ID | 用于公证的 Apple ID |
APPLE_PASSWORD | 用于公证的应用专用密码 |
APPLE_TEAM_ID | Apple Developer 团队 ID |
WINDOWS_CERTIFICATE | Base64 编码的可导出 Windows .pfx 代码签名证书 |
WINDOWS_CERTIFICATE_PASSWORD | 用于导出 Windows .pfx 的密码 |
ANDROID_KEYSTORE_BASE64 | Android 签名密钥库(base64) |
ANDROID_KEYSTORE_PASSWORD | Android 密钥库的密码 |
ANDROID_KEY_ALIAS | Android 签名密钥别名 |
ANDROID_KEY_PASSWORD | Android 签名密钥的密码 |
IOS_CERTIFICATE_BASE64 | Base64 编码的 iOS Apple Distribution .p12 |
IOS_CERTIFICATE_PASSWORD | 用于导出 iOS .p12 的密码 |
IOS_PROVISIONING_PROFILE_BASE64 | Base64 编码的 App Store 描述文件 |
APP_STORE_CONNECT_API_KEY | 下载的 App Store Connect .p8 密钥的完整内容 |
APP_STORE_CONNECT_KEY_ID | App Store Connect API 密钥 ID |
APP_STORE_CONNECT_ISSUER_ID | App Store Connect 颁发者 ID |
GOOGLE_SERVICES_JSON_BASE64 | 双提供商构建的 Firebase Android 客户端配置 |
GOOGLE_PLAY_SERVICE_ACCOUNT | 可选的 Google Play 发布服务账户 JSON |
MATRIX_TOKEN | 可选的用于发布和活动通知的仓库密钥 |
上述所有密钥中,除 MATRIX_TOKEN 外,均属于 release 环境。MATRIX_TOKEN 是仓库级 Actions 密钥,因为通知作业未附加 release 环境。GITHUB_TOKEN 由 GitHub Actions 自动提供,不得手动创建。
GitHub 变量:
| 变量 | 描述 |
|---|---|
R2_BUCKET | 用于静态资产的 R2 存储桶名称 |
IOS_SIGNING_IDENTITY | 可选的 iOS 签名身份覆盖;默认为 Apple Distribution |
VAPID_PUBLIC_KEY | 嵌入 Android 发布构建中的后端 VAPID 密钥对的必需公钥部分 |
PLAY_TRACK | 可选的 Google Play 轨道;默认为 internal |
ALLOW_NO_UPDATER | 紧急桌面端覆盖;true 允许在没有更新器签名的情况下发布构建产物 |
ALLOW_NO_UPDATER 是应急仓库变量,而非常规发布设置。请保持其未设置状态,以便在 TAURI_SIGNING_PRIVATE_KEY 缺失时桌面端发布失败关闭。
有关生成步骤、存储位置、必需/可选状态以及确切的设置说明,请参阅 docs/SECRETS.md.
Cloudflare API 令牌设置
在 My Profile → API Tokens → Create Token → Create Custom Token 处创建令牌:
权限:
| 作用域 | 权限 | 访问 |
|---|---|---|
| 用户 | 用户详情 | 读取 |
| 账户 | Workers 脚本 | 编辑 |
| 区域 | 缓存清除 | 清除 |
账户资源:
- 选择 Include → Specific account → [Your Account]
- 或 Include → All accounts(如果您只有一个账户)
区域资源:
- 选择 Include → Specific zone → [Your Domain]
- 或 Include → All zones
常见错误: 设置了权限,但将“账户/区域资源”保留为“所有来自……的账户”下拉菜单,而未明确进行选择。您必须点击并选择特定的账户/区域。
工作节点设置
CDN 工作器(worker/)处理:
- SPA Routing — Returns
index.htmlfor navigation requests to/mailbox,/calendar,/contacts,/login - Cache Headers — Sets correct
Cache-Controlper asset type - Security Headers —
X-Content-Type-Options,X-Frame-Options
首次部署后,配置自定义域名:
- Cloudflare 控制台 → Workers & Pages → webmail-cdn
- 设置 → 触发器 → 添加自定义域名
- 输入您的域名(例如,
mail.example.com)
手动部署
# Build the app
pnpm build
# Deploy to R2 (requires AWS CLI configured with R2 credentials)
aws --endpoint-url "https://ACCOUNT_ID.r2.cloudflarestorage.com" \
s3 sync dist/ "s3://BUCKET_NAME/" --delete
# Deploy worker
cd worker
pnpm install
npx wrangler deploy
# Purge Cloudflare cache
curl -X POST "https://api.cloudflare.com/client/v4/zones/ZONE_ID/purge_cache" \
-H "Authorization: Bearer API_TOKEN" \
-H "Content-Type: application/json" \
--data '{"purge_everything":true}'
故障排除
部署后资源未更新:
- 在 GitHub Actions 日志中验证缓存清除是否成功
- 检查浏览器 DevTools → Network → Disable cache 并刷新
- 磁盘缓存了 HTML 的用户可能需要清除浏览器缓存或等待回退恢复 UI
SPA 路由返回 404:
- 确保 worker 已部署并绑定到您的域名
- 检查 worker 日志:
cd worker && npx wrangler tail
Service worker 未更新:
- 检查
version.json是否被重新获取(无缓存) - 验证
sw.js在 Network 标签页中是否有no-cache头
许可证
Business Source License 1.1 - Forward Email LLC































































