关于 customware-email
customware-email 指导开发者在 Customware 生成的应用中实现客户邮件能力,涵盖入站接收与出站发送。它规定了 Postmark 集成、持久化处理、安全边界和验证要求。
主要功能
- 01Postmark 入站 Webhook 接收
- 02入站邮件持久化与去重
- 03待处理邮件恢复机制
- 04通过 HTTPS API 发送邮件
- 05凭据与邮件内容安全规范
- 06测试及交付核验要求
适用场景
- 01为应用接收客户邮件回复
- 02将邮件投递保存后再确认
- 03从应用业务流程发送邮件
- 04核验邮件集成的安全与恢复
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ customware-ai/ skills --skill customware-email安装后在 Claude Code 中输入/customware-email确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
agents/openai.yamlreferences/common-architecture.mdcommon-quality.mdinbound.mdoutbound.md详细介绍
客户邮件
为 Customware 生成的应用实现一套完整的 Customware 邮件能力。该能力通过已配置的 Postmark 入站 webhook 接收客户回复,并通过同一个开发用 Postmark 服务的 HTTPS API 发送面向客户的消息。
任务会提供项目专属的地址。两个托管服务 ENV 值提供凭据。本技能提供实现方法、持久化行为和验证约定。
基于现有应用构建。 复用其 Hono 路由、Drizzle schema、SQLite 数据库、日志记录、错误处理和
Result模式。小巧的原生集成比另一个邮件框架更容易理解,也更安全。
请先阅读
编辑源文件前,请阅读以下参考资料:
- references/common-architecture.md — 任务输入、平台边界、凭据、技术栈和通用集成结构。
- references/inbound.md — 固定的 webhook、身份验证、持久化接收、去重和恢复约定。
- references/outbound.md — 直接调用 Postmark API 发送邮件、消息结构、发件人/回复路由和故障处理。
- references/common-quality.md — 验证、安全日志记录、迁移、测试和最终验证。
即使任务一开始看起来只涉及单向邮件,也请阅读入站和出站参考资料。回复让两个方向成为一项功能:入站邮件必须能够到达应用,出站邮件也必须将回复路由回同一个虚拟地址。
<read_order>
开始实现前,还要阅读目标仓库的 AGENTS.md、完整的 Builder 任务、相关项目文档,以及现有的数据库/路由/服务约定。若框架细节与此处示例不同,以目标仓库为准。
</read_order>
固定的平台约定
| 关注点 | 必须采用的方案 |
|---|---|
| Postmark 服务 | 使用已为此项目配置的唯一开发服务。应用不会创建、删除或配置该服务。 |
| 入站路由 | POST /api/email/inbound |
| 入站身份验证 | HTTP Basic Auth,用户名为 customware,密码来自 POSTMARK_INBOUND_WEBHOOK_SECRET |
| 服务凭据 | 仅在服务端读取 POSTMARK_INBOUND_WEBHOOK_SECRET 和 POSTMARK_SERVER_TOKEN。 |
| 入站地址 | 使用任务提供的准确虚拟地址。不要为其创建 ENV。 |
| 出站发件人 | 使用任务提供的准确发件人地址,目前为 [email protected]。不要为其创建 ENV。 |
| 出站流 | Postmark 现有的 Default Transactional 流(outbound)。 |
| 传输方式 | 在服务端代码中直接通过 HTTPS 请求 Postmark Email API。 |
| SMTP | 不要启用或使用 SMTP。 |
| Customware 网关 | 不要添加 Customware 发送端点、代理或邮件网关。 |
| 生产环境 | 实现任务描述的开发环境能力。不要添加生产服务、发布或环境分支逻辑。 |
<address_source_of_truth>
任务描述是虚拟入站地址和出站 From 地址的唯一依据。将每个值保存在一个由服务端维护的常量/模块中,避免发件人、回复路由和审核人员可见的代码中出现不一致。绝不能将任一地址替换成占位符、猜测的地址或新的 ENV。
</address_source_of_truth>
不可妥协事项
- 将两个 Postmark 凭据都仅保留在服务器端。绝不要将它们放入浏览器代码、
VITE_*、HTML、JSON 响应、任务输出、日志或客户端状态中。 - 将
.env和.env.*视为不可访问。不要使用文件命令检查它们。运行时检查可以使用node --env-file=.env ...,但不得打印环境变量值。 - 在静态资源服务和 SPA 回退之前注册入站路由。
- 在确认收到入站投递前,先将其持久化。200 响应表示原始投递可以安全恢复,并不表示应用处理已完成。
- 在数据库中强制保证
MessageID唯一。不要通过先读取再插入的方式实现去重。 - 确保入站处理在崩溃或重启后可以恢复;内存中的回调不能是工作的唯一记录。
- 返回入站参考文档中约定的状态码。绝不要向 Postmark 返回
403。 - 仅从服务器代码发送出站邮件,并使用
X-Postmark-Server-Token和MessageStream: "outbound"。 - 使用任务指定的虚拟入站地址作为
ReplyTo,这样客户回复会通过现有 webhook 返回。 - 不要在日志中记录邮件内容和凭据。仅记录安全的运维标识符和错误类别。
- 复用现有契约和错误/结果约定。避免重复验证、臆测性的抽象、兼容性分支或第二套持久化框架。
实施工作流
1. 确立任务契约
- 完整阅读任务。
- 提取确切的虚拟入站地址和出站 From 地址。
- 确认任务提到了
customware-email,并且 Postmark 服务端已完成配置。 - 如果任一地址或任一托管凭据契约不可用,请明确返回
action_required并停止。不要自行编造值。
2. 检查生成的应用
找到 Hono 入口点、路由注册顺序、静态资源/回退处理器、Drizzle 架构与迁移、查询/服务约定、环境变量辅助模块、日志边界,以及现有的 Result/Zod 模式。确定应用的客户工作流应在哪里处理已接收的邮件,以及现有业务操作在哪里生成出站消息。
3. 构建共享的服务器基础
创建一个小型、由服务器管理的邮件配置模块,用于存放任务提供的地址并读取两个托管环境变量。将提供商调用封装在精简的 Postmark 客户端/适配器后,并遵循应用现有的结果与错误模式。不要允许浏览器请求选择服务器令牌、From 地址、ReplyTo 地址、邮件流或 Postmark URL。
4. 实现入站和出站功能
按照 references/inbound.md 实现接收器和持久化工作进程。按照 references/outbound.md 实现 Postmark Email API 适配器和面向应用的发送辅助函数。将两者集成到现有领域流程中,而不是另建一套邮件子系统。
5. 逐步验证
实施过程中运行有针对性的契约检查,然后运行仓库常规的格式检查、lint、类型检查、构建、单元测试和交互式检查。使用 references/common-quality.md 中的测试矩阵。如果要求发送外部邮件,只能使用明确批准的安全收件人;否则,使用模拟的 Postmark 客户端和路由级测试,验证确切请求。
6. 执行最终审计
在最终差异中搜索凭据名称、硬编码密钥、SMTP 用法、POSTMARK_ACCOUNT_TOKEN、生产环境分支、直接从浏览器调用 Postmark、原始邮件日志记录以及第二个网关。确认任务地址是生成的应用代码中唯一嵌入的邮件地址,并确认数据库迁移已包含在内,且已通过应用的常规命令执行。
完成检查清单
- 任务指定的精确入站和出站地址均在一个由服务端管理的配置模块中使用。
-
POSTMARK_INBOUND_WEBHOOK_SECRET用于保护入站路由,POSTMARK_SERVER_TOKEN用于授权出站 HTTPS 调用。 - 入站路由会捕获原始 JSON、验证
MessageID、在返回 200 前持久化数据、通过数据库约束去重,并恢复待处理或过期的工作。 - 出站请求使用
POST /email、X-Postmark-Server-Token、MessageStream: "outbound"、任务指定的 From,以及任务指定的入站 ReplyTo。 - 不包含 SMTP、原始邮件、账户级配置、生产环境行为或 Customware 发送网关。
- 浏览器捆绑包、响应和日志中均不包含敏感值和消息内容。
- 迁移、专项测试、仓库检查、构建及相关浏览器验证均通过。
- 签署前已重新检查最终差异和审核者要求。
边界
此技能用于生成的应用中的 Customware 邮件实现。Customware 控制平面负责 Postmark 服务配置、加密、隐藏 ENV 的物化、沙盒重启时的 Webhook URL 协调、清理和发布保护。不要在生成的应用中重复这些职责。
AI 网关或 AI Elements 工作请使用 customware-ai,支持组件请使用 customware-support-widget,当 Builder 任务要求完整的门控执行协议时请使用 task-workflow。这些技能可与本技能配合使用,但不能取代此处的邮件约定。