# 集成上线：接一次 Resend，Func 里直接发邮件和验证码 - Creght 博客

> 编辑器新增「集成」面板。接入 Resend 后在 Func 里用 ctx.email 发送事务邮件与验证码；密钥保存在服务端不进代码，验证码的有效期、一次性、常数时间比对、错误次数与限频都由平台保证。

[![Creght](https://ugc.talizen.com/_assets/site/2061660904709165056/1780797461299__creght_logo.png)](/)

产品

[AI 建站](/ai.md) [可视化建站](/design.md)

解决方案

[设计师作品集](/solution/designer-portfolio.md) [外贸独立站](/solution/foreign-trade-website.md)

[价格](/price.md) [帮助中心](/help.md)

[资源广场](/resources.md)

[全部资源](/resources.md) [模板](/templates.md) [组件库](https://creghtlib.site.creght.com/) [动效库](/effects.md) [素材库](https://www.figma.com/community/file/1529413044116674277)

[联系我们](/contact.md)

[立即体验](https://creght.cn/project)

[返回博客](/blogs.md)

更新日志2026年7月28日

# 集成上线：接一次 Resend，Func 里直接发邮件和验证码

编辑器新增「集成」面板。接入 Resend 后在 Func 里用 ctx.email 发送事务邮件与验证码；密钥保存在服务端不进代码，验证码的有效期、一次性、常数时间比对、错误次数与限频都由平台保证。

![集成上线：接一次 Resend，Func 里直接发邮件和验证码](https://fsu.creght.com/site/2066727200882692096/1785253640287__cover_integrations_email.png)

发验证码这件事看着简单：生成六位数、存起来、比一下。但随机数够不够随机、有没有过期、能不能重复使用、比对会不会泄漏前缀、猜错几次该作废、同一个邮箱能不能被无限轰炸——六件事里错任何一件都是真实的安全问题，而且错了通常不会报错，只会静默地不安全。

所以这次没有只加一个「发邮件」的接口，而是把整件事做完：编辑器里接一次 Resend，Func 里一行代码发验证码，容易写错的部分由平台保证。

## 接入：在编辑器里连一次

编辑器 **后端 → 集成** 是这次新增的面板。填入 Resend 的 API Key 保存时，平台会真的调用一次 Resend 校验它——密钥无效当场就报错，而不是等到线上发信时才收到 403。

![编辑器后端的集成面板：Resend 显示已连接，下方是发件地址](https://fsu.creght.com/site/2066727200882692096/1785252140652__integrations_panel.png)

校验通过后，平台把 Resend 账号里 **已验证的发件域名** 拉回来让你选，而不是让你手填一个可能根本发不出去的地址。配完可以直接发一封测试邮件，把「配置到底对不对」变成当场能看见的事实。

**密钥保存在服务端**，不进入 Func 沙箱，也不会出现在代码、日志和返回值里。

## 使用：ctx.email 三个方法

发一封普通邮件：

> `ctx.email.send({ to: "someone@example.com", subject: "新的预约", html: "<p>…</p>" })`

发验证码、校验验证码：

> `ctx.email.sendCode({ to: input.email, scene: "login" })`

> `const ok = ctx.email.verifyCode({ to: input.email, scene: "login", code: input.code })`

`scene` 按用途给验证码分命名空间，所以同一个邮箱的登录码和改密码的码互不干扰。

## 这些不用你写

- **6 位随机数字码**，位数可配。

- **10 分钟过期**，最长可配到 60 分钟。

- **一次性**：校验通过立即作废，同一个码不能用第二次。

- **常数时间比对**，不通过响应快慢泄漏前缀。

- **猜错 5 次作废**，而且猜错重试不会延长有效期。

- **限频**：同一邮箱同一 scene 每 10 分钟最多 5 封；单项目每天默认 500 封，这个上限可以在集成里按自己的服务商配额调高或调低。


所以不用再用 `Math.random()` 生成验证码、把码塞进缓存自己管过期、自己数错误次数——这些都已经做完了。

## 平台没封装的，你仍然能自己接

集成默认 **不** 把密钥交给 Func。如果要用 Resend 的其他接口（联系人、批量发送、附件），或者干脆换一家自己发，可以打开集成里的 **把密钥暴露给 Func 代码** 开关：密钥会额外注入 `process.env.RESEND_API_KEY`，之后用 `fetch` 想怎么调都行。开关默认关闭——逃生舱是一个明确的选择，不是默认泄露。

## 关于支付

顺便说清楚：支付 **没有** 托管集成，也没有 `ctx.payment`。各家支付平台的参数结构和回调语义差别太大，硬抽一层只会变成一个更难懂的转发器。支付仍然在 Func 里自己写，我们有一篇完整示例： [使用 Func 接入支付宝电脑网站支付](/api/func-alipay-payment.md)。

## 完整文档

接入步骤、三个方法的参数、错误与边界都写在这里： [使用集成发送邮件与验证码](/api/func-email-integration.md)。

[2026年7月28日\
\
版本发布上线：测试、上线与回退，现在各自独立](/blogs/versioned-publishing.md)

![Creght](https://ugc.talizen.com/_assets/site/2061660904709165056/1780797461299__creght_logo.png)

此网站使用 [Creght](/) 创建

![微信客服](https://fsu.creght.com/site/2066727200882692096/1785119134612__image.png)

微信客服

## 链接

- [价格](/price.md)
- [解决方案](/solution.md)
- [客户案例](/customers.md)
- [帮助中心](/help.md)
- [联系我们](/contact.md)
- [更新记录 & 博客](/blogs.md)
- [退款说明](/tuikuan.md)

## 资源

- [全部资源](/resources.md)
- [模板](/templates.md)
- [组件库](https://creghtlib.site.creght.com)
- [动效库](/effects.md)
- [Figma to Creght](/figma2creght.md)
- [API](/api.md)

## 产品对比

- [对比上线了](/creght-vs-sxl.md)
- [对比凡科建站](/creght-vs-fkw.md)
- [自己写代码 vs Creght](/compare/self-coding.md)
- [外包 vs 自己做](/compare/outsourcing.md)

## 协议

- [用户协议](/legal/terms.md)
- [隐私政策](/legal/privacy.md)
- [可接受使用政策](/legal/acceptable-use.md)

## 社交媒体

- [小红书](https://www.xiaohongshu.com/user/profile/5a38606811be10715f4895b6)
- [哔哩哔哩](https://space.bilibili.com/513308095)

[蜀ICP备2023038192号-2](https://beian.miit.gov.cn)
