# @convex-dev/resend 中文文档

规范地址：https://npmcn.com/package/%40convex-dev/resend/

版本：0\.2\.10
npm 元数据更新时间：2026-10-22T23:32:04.519Z
中文译文更新时间：2026-11-10T17:41:41.830Z
软件包许可：Apache-2\.0

本文由上游 README 翻译，可能存在偏差，请结合原文核对 API、命令与配置。版权与许可归原作者所有。

原始 npm 页面：https://www.npmjs.com/package/%40convex-dev/resend
原文对照：https://npmcn.com/package/%40convex-dev/resend/?lang=original
项目主页：https://github.com/convex/resend#readme
源码仓库：https://github.com/convex/resend

## 关键信息（来自 npm 元数据）

- 包体积（解压后）：392 kB，64 个文件
- 模块格式：ES Module
- TypeScript 类型：包内自带
- 运行依赖：5 个
- peer 依赖：convex ^1\.43\.0，convex-helpers ^0\.1\.106
- 首次发布：2025-06-13T21:57:00.449Z
- 最新版本发布：2026-10-22T23:32:04.292Z
- 近 30 天下载量：842038（2026-10-11 至 2026-11-09，npm 官方下载统计）
- 已发布版本数：32（近 12 个月 11 个）

## 中文简介

Convex 的再发送组件 .

## 安装

```sh
npm install @convex-dev/resend
```

也可以使用：`pnpm add @convex-dev/resend`、`yarn add @convex-dev/resend`、`bun add @convex-dev/resend`

## README

# 重新发送对流组件

[![npm version](https://badge.fury.io/js/@convex-dev%2Fresend.svg)](https://badge.fury.io/js/@convex-dev%2Fresend)

此组件是将Resend电子邮件服务与 你的Convex项目.

特征 :

-   排队:随想寄多少邮件,随想寄多少电子邮件——都会是 交付(最终交付).
-   Batching: 自动批发多组邮件并发送到 重新发送 `/emails/batch` 有效结束点.
-   持久执行: 使用 Convex 工作池确保电子邮件最终实现 即使面对暂时的故障或网络中断,也提供.
-   同上:管理 Resend idepotency 密钥以保证电子邮件的发送 就一次 防止意外的垃圾邮件重复.
-   速率限制:荣耀由Resend设定的API速率限制.

见 [实例](https://npmcn.com/package/%40convex-dev/resend/example) 演示如何将这个钩子融入你的 应用.

[![Navigate the Email MINEFIELD with the Resend Component!](https://thumbs.video-to-markdown.com/bf0f179c.jpg)](https://youtu.be/iIq67N8vuMU)

## 安装

```bash
npm install @convex-dev/resend
```

## 开始

创建一个 [重新发送](https://resend.com/) 账户并抓取 API 密钥。 准备吧 `RESEND_API_KEY` 在您的部署环境中.

下一个,通过 Convex 应用程序添加组件 `convex/convex.config.ts`数字 :

```ts
import { defineApp } from "convex/server";
import resend from "@convex-dev/resend/convex.config.js";

const app = defineApp();
app.use(resend);

export default app;
```

然后,你可以使用它,正如我们看到的 `convex/sendEmails.ts`数字 :

```ts
import { components } from "./_generated/api";
import { Resend } from "@convex-dev/resend";
import { internalMutation } from "./_generated/server";

export const resend: Resend = new Resend(components.resend, {});

export const sendTestEmail = internalMutation({
  handler: async (ctx) => {
    await resend.sendEmail(ctx, {
      from: "Me <test@mydomain.com>",
      to: "delivered@resend.dev",
      subject: "Hi there",
      html: "This is a test email",
    });
  },
});
```

然后,打电话 `sendTestEmail` 您的应用程序中的任何地方都会发送此测试 电子邮件.

如果您想要向真实地址发送电子邮件, 您需要禁用 `testMode`。 。 。 . 你可以这样 `ResendOptions`, (中文(简体) ), [详见下文](https://npmcn.com/package/%40convex-dev/resend/#readme-resend-component-options-and-going-into-production)。 。 。 .

关于测试电子邮件地址的说明 : [重新发送允许使用标签](https://resend.com/docs/dashboard/emails/send-test-emails#using-labels-effectively) 用于测试电子邮件。 为简单起见, 此组件只允许标签匹配 `[a-zA-Z0-9_-]*`,比如说. `delivered+user-1@resend.dev`。 。 。 .

## 高级使用

### 设置一个 Resend webhook 系统

虽然我们到目前为止的设置 将可靠地发送电子邮件, 你没有任何 任何送货、弹出或引发垃圾邮件投诉的反馈。 对于 那,我们需要设置一个网页库!

Convex方面,我们需要在我们的工程上挂上一个 http end point 来引导它 重新发送组件 `convex/http.ts`数字 :

```ts
import { httpRouter } from "convex/server";
import { httpAction } from "./_generated/server";
import { resend } from "./sendEmails";

const http = httpRouter();

http.route({
  path: "/resend-webhook",
  method: "POST",
  handler: httpAction(async (ctx, req) => {
    return await resend.handleResendEventWebhook(ctx, req);
  }),
});

export default http;
```

如果我们的Convex项目是快乐的 -leopard-123, 我们现在有一个Resend Webhook 为我们 项目运行于 `https://happy-leopard-123.convex.site/resend-webhook`。 。 。 .

因此,导航到Resend仪表板 并创建一个新的网页hook 在那个URL。 制作 当然可以使所有 `email.*` 事件; 其他事件类型将被忽略.

最后,从Resend仪表板上复制出"Webhook"的秘密,并将其设定为 `RESEND_WEBHOOK_SECRET` convex 部署中的环境变量.

您现在应该看到邮件状态的更新, 因为 Resend 正在推进您的 批发!

说到...

### 正在注册邮件状态处理器 .

如果您的 Webhook 已建立, 您也可以在 您的应用程序在电子邮件状态改变时会收到通知 .

更新您的 `sendEmails.ts` 看起来像这样:

```ts
import { components, internal } from "./_generated/api";
import { internalMutation } from "./_generated/server";
import { vEmailId, vEmailEvent, Resend } from "@convex-dev/resend";

export const resend: Resend = new Resend(components.resend, {
  onEmailEvent: internal.example.handleEmailEvent,
});

export const handleEmailEvent = internalMutation({
  args: vOnEmailEventArgs,
  handler: async (ctx, args) => {
    // Handle however you want
    // args provides { id: EmailId; event: EmailEvent; }
    // see /example/example.ts
  },
});
```

看看这个 `example/` 在此重播中进行一个完整演示.

### 重新发送组件选项并开始生产

有一个 `ResendOptions` 参数 定制它的行为.

看看这个 [剂量字符串](https://npmcn.com/package/%40convex-dev/resend/src/client/index.ts),但值得注意的选择包括:

-   `apiKey`: 提供 Resend API 密钥,而不是将其读取 环境变量.
-   `webhookSecret`(笑声) (笑声) (掌声) (掌声) (掌声) (掌声) (掌声) (掌声) (掌声) (掌声) (掌声) (掌声) (掌声) (掌声) (掌声) (掌声) (掌声) (掌声) (掌声) (掌声) (掌声) (掌声) (掌声) (掌声) (掌声) (掌声) (掌声) (掌声) (掌声) (掌声) (掌声) (掌声) (掌声) (掌声) (掌声) .
-   `testMode`:只允许交付测试地址. 保护你的安全 开发您的项目, `testMode` 默认 **真实**您需要明确 设定为 `false` 允许您将电子邮件排入 手工业地址.
-   `onEmailEvent`: 您的电子邮件事件召回, 如上所述 ! 看看这个 [剂量字符串](https://npmcn.com/package/%40convex-dev/resend/src/client/index.ts) 事件详情 发射.

### 可选电子邮件发送参数

除了基本文本机构外 `sendEmail` 方法允许您提供列表 `replyTo` 地址和其他电子邮件 头.

### 排队时间

组件已经向 Resend 发送了 idepotency 密钥, 所以一个批次是 最多交付一次。 防止组件重试 API 拨打,但这并不能阻止您的应用程序在相同的逻辑电子邮件中排序 两次(例如,当商业流动再起火或动作再起时).

要排队,通过一个 `idempotencyKey`。如果电子邮件内容相同 密钥已经选中, `sendEmail` 返回已有的 `EmailId` 换成 排队(和交付)

```ts
const emailId = await resend.sendEmail(ctx, {
  from: "Me <test@mydomain.com>",
  to: "delivered@resend.dev",
  subject: "Order confirmation",
  html: "...",
  // Derive this from the triggering event so retries collapse to one send.
  idempotencyKey: `order-confirmation:${orderId}`,
});
```

因为 `sendEmail` 运行于交易的变异中, 并排 同一个钥匙是安全的:一个赢,另一个得到它 `EmailId`。 。 。 .

### 使用调试模板

你用得着 [重新发送模板](https://resend.com/docs/dashboard/templates/introduction) 改为 从您的Resend仪表板上发送带有预设计的模板的电子邮件。 用一个 模板,提供模板ID和任何所需的模板变量:

```ts
await resend.sendEmail(ctx, {
  from: "Me <test@mydomain.com>",
  to: "delivered@resend.dev",
  subject: "Welcome to our app",
  template: {
    id: "my-template-id",
    variables: {
      name: "John Doe",
      verificationLink: "https://example.com/verify?token=abc123",
    },
  },
});
```

> \[大 无法同时使用 `template` 财务报告和审定财务报表 `html`编号 :`text` 中标 电子邮件 如果您需要发送动态 HTML 内容, 请使用模板 模板变量,或使用 `html`编号 :`text` 直接字段(可选为 [反应电子邮件](https://npmcn.com/package/%40convex-dev/resend/#readme-using-react-email)) (中文(简体) ).

### 跟踪、获取状态和取消电子邮件

这个 `sendEmail` 方法返回品牌类型, `EmailId`。您可以使用这个 少许东西:

-   在您的邮件事件更改状态时重新连接原始邮件 处理者.
-   随时使用 `resend.status(ctx, emailId)`。 。 。 .
-   要使用 `resend.cancelEmail(ctx, emailId)`。 。 。 .

如果电子邮件已经发送到Resend API,则无法取消 . 取消不会触发邮件事件 .

#### 程序检查电子邮件状态

使用 `status` 检查电子邮件当前状态的方法 :

```ts
const emailStatus = await resend.status(ctx, emailId);
if (emailStatus) {
  console.log(emailStatus.status); // e.g., "delivered", "bounced", "sent"
  console.log(emailStatus.bounced); // boolean
  console.log(emailStatus.failed); // boolean
  console.log(emailStatus.complained); // spam complaint (boolean)
  console.log(emailStatus.deliveryDelayed); // boolean
  console.log(emailStatus.opened); // if open tracking enabled (boolean)
  console.log(emailStatus.clicked); // if click tracking enabled (boolean)
  console.log(emailStatus.errorMessage); // error details (string | null)
}
```

#### 在仪表板上查看电子邮件和网络浏览事件

您可以在组件的 Convex 仪表板上直接查看所有电子邮件数据 数据视图。 用一个拼图片点击下放, 上面写着:

![Component tables screenshot](https://npmcn.com/package/%40convex-dev/resend/component_tables.png)

1.  **电子邮件表**导航到您的 Convex 仪表板 ~ 数据 。 选择 `resend` 从组件下移,然后选择 `emails` 页:1 显示所有 具有当前状态的电子邮件、收件人、主题和跟踪 资料.
    
2.  **交付事件表**: 导航到组件 `resend` → `deliveryEvents` 页:1 本表存储所有从 Ergine 收到的 Webhook 事件 重新发送,包括:
    
    -   `emailId`: 链接到电子邮件表格中的电子邮件
    -   `resendId`: 重新发送电子邮件的ID
    -   `eventType`:事件类型(例如, `email.delivered`, (中文(简体) ), `email.bounced`, (中文(简体) ), `email.opened`, (中文(简体) ), `email.clicked`, (中文(简体) ), `email.complained`(中文(简体) )
    -   `createdAt`: 事件发生时
    -   `message`: 其他细节(例如弹出理由)

这对调试传送问题、查看电子邮件历史和 知道你发的每封邮件都发生了什么.

### 保留数据

此组件保留"已定稿"(交付,取消,回弹)电子邮件. 这是 你有责任在自己的日程上清除这些邮件 你们可以跑 `cleanupOldEmails` 财务报告和审定财务报表 `cleanupAbandonedEmails` 从仪表板,在 在函数运行器中“ resend” 组件标签, 或设置 cron 任务 .

如果没有通过参数, 它默认删除超过7天的电子邮件 .

如果你不关心历史邮件状况, 建议的方法是 使用 curon 工作,如下所示:

```ts
// in convex/crons.ts
import { cronJobs } from "convex/server";
import { components, internal } from "./_generated/api.js";
import { internalMutation } from "./_generated/server.js";

const crons = cronJobs();
crons.interval(
  "Remove old emails from the resend component",
  { hours: 1 },
  internal.crons.cleanupResend,
);

const ONE_WEEK_MS = 7 * 24 * 60 * 60 * 1000;
export const cleanupResend = internalMutation({
  args: {},
  handler: async (ctx) => {
    await ctx.scheduler.runAfter(0, components.resend.lib.cleanupOldEmails, {
      olderThan: ONE_WEEK_MS,
    });
    await ctx.scheduler.runAfter(
      0,
      components.resend.lib.cleanupAbandonedEmails,
      // These generally indicate a bug, so keep them around for longer.
      { olderThan: 4 * ONE_WEEK_MS },
    );
  },
});

export default crons;
```

### 使用反应邮件

你用得着 [反应电子邮件](https://react.email/) 生成您的 HTML 从JSX.

首先安装 [依赖关系](https://react.email/docs/getting-started/manual-setup#2-install-dependencies)数字 :

```bash
npm install @react-email/components react react-dom react-email @react-email/render
```

然后在您的 Convex 目录中创建一个新的.tsx 文件, 例如 . `/convex/emails.tsx`数字 :

```tsx
// IMPORTANT: this is a Convex Node Action
"use node";
import { action } from "./_generated/server";
import { render, pretty } from "@react-email/render";
import { Button, Html } from "@react-email/components";
import { components } from "./_generated/api";
import { Resend } from "@convex-dev/resend";

export const resend: Resend = new Resend(components.resend, {
  testMode: false,
});

export const sendEmail = action({
  args: {},
  handler: async (ctx, args) => {
    // 1. Generate the HTML from your JSX
    // This can come from a custom component in your /emails/ directory
    // if you would like to view your templates locally. For more info see:
    // https://react.email/docs/getting-started/manual-setup#5-run-locally
    const html = await pretty(
      await render(
        <Html>
          <Button
            href="https://example.com"
            style={{ background: "#000", color: "#fff", padding: "12px 20px" }}
          >
            Click me
          </Button>
        </Html>,
      ),
    );

    // 2. Send your email as usual using the component
    await resend.sendEmail(ctx, {
      from: "Me <test@mydomain.com>",
      to: "delivered@resend.dev",
      subject: "Hi there",
      html,
    });
  },
});
```

> \[尖叫声\] React Email 需要一些节点依赖, 因此它必须在 Convex 中运行 [节点动作](https://docs.convex.dev/functions/actions#choosing-the-runtime-use-node) 而不是常规行动.

### 手动发送电子邮件, 例如附件

如果您需要组件不提供的东西( 这是当前) 受Resend中的批量 API 支持的限制,您可以发送电子邮件 手动使用 `sendEmailManually`不同 `sendEmail` 编辑电子邮件 并分批地通过 `/emails/batch` 终点, `sendEmailManually` 调用调用 `/emails` 直接结束点而不排队。 这给你 对电子邮件发送过程的精细控制, 同时仍然跟踪它 使用组件状态和 Webhook APIs 进度.

```ts
import { components, internal } from "./_generated/api";
import { internalAction } from "./_generated/server";
import { Resend as ResendComponent } from "@convex-dev/resend";
import { Resend } from "resend";

const resendSdk = new Resend("re_xxxxxxxxx");

export const resend = new ResendComponent(components.resend, {});

export const sendManualEmail = internalAction({
  args: {},
  handler: async (ctx, args) => {
    const from = "Acme <onboarding@resend.dev>";
    const to = ["delivered@resend.dev"];
    const subject = "hello world";
    const html = "<p>it works!</p>";

    const emailId = await resend.sendEmailManually(
      ctx,
      { from, to, subject },
      async (emailId) => {
        const {data, error} = await resendSdk.emails.send({
          from,
          to,
          subject,
          html,
          headers: {
            "Idempotency-Key": emailId,
          },
        });
        if (error) {
          throw new Error(`[Email] Failed to send: ${error.message}`);
        }
        return data.id!;
      },
    );
  },
});
```

使用 `sendEmailManually` 当您需要批量 API 不支持的特性时, 例如附件,或当您想立即发送电子邮件时,不带 等待分批系统.

## 常见问题

### @convex-dev/resend 是什么？

Convex 的再发送组件 \.

### 如何安装 @convex-dev/resend？

在项目目录运行 npm install @convex-dev/resend，或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖：convex（^1\.43\.0）、convex-helpers（^0\.1\.106）。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖，Yarn 需要手动安装。

### @convex-dev/resend 支持 TypeScript 吗？

支持。包内自带 TypeScript 类型声明（package\.json 声明了 types 入口），安装后即可获得类型提示，无需再安装 @types 包。

### @convex-dev/resend 支持 ESM 还是 CommonJS？

以 ES Module 形式发布，推荐使用 import 引入。在 CommonJS 项目中，Node\.js 20\.19\+ / 22\.12\+ 可以直接 require\(\) 不含顶层 await 的 ES Module，更早的版本需要改用动态 import\(\)。

### @convex-dev/resend 可以商用吗？

@convex-dev/resend 使用 Apache-2\.0 许可。宽松许可：允许商业使用、修改和再分发，并附带明确的专利授权；分发时需保留许可与 NOTICE 文件，修改过的文件要注明改动。以上为概括，不构成法律意见，请以许可原文为准。

### @convex-dev/resend 的下载量有多少？

根据 npm 官方下载统计，@convex-dev/resend 在 2026/10/11 – 2026/11/09 这 30 天内被下载 842,038 次，日均约 28,068 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入，适合横向比较热度，不能直接等同于使用人数。

### @convex-dev/resend 还在维护吗？

最新版本 0\.2\.10 发布于 2026/10/23（18 天前）；至今共发布 32 个版本，其中过去 12 个月发布了 11 个；首次发布于 2025/06/14。发布频率只是参考信号：功能稳定的工具可能很少需要更新，建议结合源码仓库的 issue 和提交记录判断。

