# @bernierllc/nevarmail 中文文档

规范地址：https://npmcn.com/package/%40bernierllc/nevarmail/

版本：0\.30\.0
npm 元数据更新时间：2026-11-05T01:25:21.360Z
中文译文更新时间：2026-11-07T23:13:18.264Z
软件包许可：MIT

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

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

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

- 包体积（解压后）：128 kB，9 个文件
- 模块格式：ES Module
- TypeScript 类型：包内自带
- Node.js 要求：\>=20\.0\.0
- 运行依赖：0 个
- 首次发布：2026-09-10T19:52:27.260Z
- 最新版本发布：2026-11-05T01:25:21.162Z
- 近 30 天下载量：2492（2026-10-08 至 2026-11-06，npm 官方下载统计）
- 已发布版本数：31（近 12 个月 31 个）

## 中文简介

NevarMail v1 API的官方客户端. 已打入,回放429/5xx,将NevarMailError投向了每个非-2xx.

## 安装

```sh
npm install @bernierllc/nevarmail
```

也可以使用：`pnpm add @bernierllc/nevarmail`、`yarn add @bernierllc/nevarmail`、`bun add @bernierllc/nevarmail`

## README

# @bernierllc/ nevarmail (英语)

NevarMail v1 API的官方客户端.

> **此所住之处.** 此软件包发布于 `bernierllc/tools` (单位:千美元)`packages/core/nevarmail`),是客户端唯一的真相来源. 它所包裹的 NevarMail API 构建于 `bernierllc/email_demo`。 。 。 . **任何更改 NevarMail v1 API 表面需要匹配的更改, 在同一工作单位中** —— 说 看那个雷波的 `CLAUDE.md` - "NevarMail SDK(英语:`@bernierllc/nevarmail`) (中文(简体) ).

**一个规则: 每一次非-2xx投出.** 如果回电,API接受. 没有 "成功"物体内含故障 无法平息出错——审计 生产这个包 发现一个生产集成 吞噬每一个错误,所以 org可能已经邮寄到 `403` 几个月来,两边都没发现.

## 安装

```bash
npm install @bernierllc/nevarmail
```

仅服务器侧; 需要节点 20+( 使用全局) `fetch` 财务报告和审定财务报表 `crypto.randomUUID`) (中文(简体) ). 永远不要在浏览器代码中披露API证书. 零从属.

## 融合状况

| 一体化 | 状态 | 为什么 |
| --- | --- | --- |
| 锁定器( L)`@bernierllc/logger`(中文(简体) ) | 不适用 | 零依赖性 API 客户端保持零依赖性. 每一次失败都像掷出 `NevarMailError` 携带 `status`, (中文(简体) ), `code`, (中文(简体) ), `requestId` 财务报告和审定财务报表 `cause` ——登录在消费者身上,加上消费者的伐木机. |
| Never Hub (没有`@bernierllc/neverhub-adapter`(中文(简体) ) | 不适用 | 核心级软件包没有运行时间生命周期可以注册; NeverHub 注册属于构成此客户端的服务或套件. 因此,此处不需要严重退化. |

## 使用量

```ts
import { NevarMail } from "@bernierllc/nevarmail";

const nevarmail = new NevarMail({ apiKey: process.env.NEVARMAIL_API_KEY! });

const result = await nevarmail.sendEmail({
  to: "customer@example.com",
  subject: "Your quote is ready",
  html: "<p>Here it is.</p>",
  use_case_id: process.env.NEVARMAIL_USE_CASE_TRANSACTIONAL,
});

console.log(result.id, result.status);
```

## 租赁——一键是一角

NevarMail API 密钥 **实值** 该组织。 任何请求机构都不存在Org id 服务器从密钥中解析并忽略您发送的任何东西。 有两个后果:

-   每人一把钥匙 键不能被指向第二个键 和一个多租户应用程序 代表 NevarMail orgs 发送若干键.
-   永远不要接受来自终端用户的Org标识符并经过. 无处可去 说吧,尝试是一个征兆 融合是建模租借错误.

## 键、表面和模式

钥匙看起来像 `nvm_api_live_…`, (中文(简体) ), `nvm_api_test_…`, (中文(简体) ), `nvm_mcp_live_…`, (中文(简体) ), `nvm_mcp_test_…`。 。 。 .

-   **表面** (单位:千美元)`api` 对 `mcp`)——这个包裹会说REST,所以它需要一个 `api` 键。 通过一个 `mcp` 键和构造器会立即扔出,而不是让服务器回答 `403 KEY_TYPE_MISMATCH` 在您的第一个发送, 它读起来像一个认证错误.
-   **模式** (单位:千美元)`live` 对 `test`)——测试密钥只发送到org测试上的地址 允许列表; 其他任何东西都是 `422 TEST_MODE_RECIPIENT_NOT_ALLOWED`模式为 属性,绝不是客户端选项: `client.mode` 报告关键是什么.

```ts
const nevarmail = new NevarMail({ apiKey: key });
if (nevarmail.mode === "test") console.warn("test key — sends are allow-list only");
```

## 错误

每一次失败都是 `NevarMailError`数字 :

```ts
import { NevarMail, NevarMailError } from "@bernierllc/nevarmail";

try {
  await nevarmail.sendEmail({ to, subject, html });
} catch (err) {
  if (err instanceof NevarMailError && err.code === "RECIPIENT_SUPPRESSED") {
    // Expected: this person opted out. Not an outage.
    return;
  }
  throw err; // everything else is worth waking someone for
}
```

| 外地 | 含义 |
| --- | --- |
| `status` | HTTP 状态 ; `0` 当请求从未到达 API 时 |
| `code` | 机器可读代码——这个分支,永远不要打开 `message` |
| `requestId` | 引用支持; 匹配 API `x-request-id` |
| `retryAfter` | 秒,从 `Retry-After` 在429号公路上 等待30多或更短的时间会为你重试;一个更长的时间(每天一顶帽子)会同时抛出 |
| `body` | 解析的回复, 对于比您安装的版本更新的代码 |

值得明确处理的代码:

| 代码 | 状态 | 这是什么意思 |
| --- | --- | --- |
| `RECIPIENT_SUPPRESSED` | 422个 | 被弹出,被抱怨,或未认购. 不要重试. |
| `COMPLIANCE_ADDRESS_REQUIRED` | 422个 | `emailType: "marketing"` (或用例收件人可以选择退出)从一个没有邮政地址的项目. 设定为 `setProjectAddress`。 。 。 . |
| `TEST_MODE_RECIPIENT_NOT_ALLOWED` | 422个 | 测试密钥, 收件人不在允许列表中 . |
| `CC_BCC_NOT_SUPPORTED_FOR_TEMPLATE` | 400个 | 按收件人制作模板邮件; 发送一个请求 . |
| `VALIDATION_ERROR` | 400个 | 身体错. 复试无益. |
| `SCOPE_DENIED` | 403 (韩语) | 密钥缺乏这条路线需要的范围. |
| `KEY_TYPE_MISMATCH` | 403 (韩语) | 在 REST 路径上的 MCP 密钥( 此客户端在构建时拒绝) . |
| `RATE_LIMITED` | 429个 | 自动复试;预算用完后浮出水面. |
| `SCHEDULE_NOT_CANCELLABLE` | 409个 | 预定发送已发射或已取消 . |
| `NETWORK_ERROR` | 0 个 | 完全没有反应——DNS,TLS,或超时. |

## 检索

复试: `429` (荣誉) `Retry-After`, (中文(简体) ), `5xx`,和网络故障——指数倒置 与 jitter , 默认的两次额外尝试(`maxRetries`) (中文(简体) ).

从未再审:任何其他 `4xx`它会永远失败 所以重试会变成一个坏的 请求为三。 发送不是同位素 `5xx` 可能交付两次.

## 案件使用和制止范围

每个项目都有禁忌. `checkSuppression(email, useCaseId?, projectId?)` 答案为 一个项目: `projectId`,否则项目 `useCaseId`,否则组织的唯一 项目。 一个有多个项目的组织 `400 PROJECT_REQUIRED` 当两者都不是 通过了。 对供应商账户的回弹或垃圾邮件投诉会阻碍每个项目;任何其他 镇压只能阻止它自己.

`use_case_id` 命名信件类别。 这是区别于 "这个人不订阅你的通讯"和"这个人不能再被电子邮件":

-   **说吧**,并选择退出 _不同_ 类别列表不阻碍发送, 并且标记为不可压制的类别可免于选择不适用.
-   **别管了**,并且对该项目的每一个积极抑制都适用——严格解读. 仅a **项目范围密钥** 可能会漏掉 `sendEmail` 编号 : `scheduleEmail`: 发送为 那个项目的默认使用大小写。 一个 **粗略键** 省略它会得到 `422 USE_CASE_REQUIRED`· ; `listUseCases()` 显示你的.

弹跳、垃圾邮件投诉和手动压制 阻止了每个类别 仅a `use_case_id` 您通过自身可以缩小一个块;默认服务器解析不能.

`sendEmail` 也用"弹"来表示 `useCase: "receipts"` - 而不是其编号(其中之一 两个,不是两个。 弹簧必须存在于键可以打开的完全一个工程中:未知是一个 404, 几个项目中的同一颗子弹是: `400 USE_CASE_AMBIGUOUS` (通过) `use_case_id` ) (中文(简体) ). `listUseCases` 显示弹壳.

## 方法

| 方法 | 路线 | 范围 |
| --- | --- | --- |
| `sendEmail` | `POST /api/v1/email/send` | `email:send` |
| `sendEmailToList` | `POST /api/v1/email/send-to-list` | `email:send` |
| `scheduleEmail` | `POST /api/v1/email/schedule` | `email:send` |
| `listScheduledEmails` | `GET /api/v1/email/schedule` | `email:send` |
| `cancelScheduledEmail` | `DELETE /api/v1/email/schedule/{id}` | `email:send` |
| `checkSuppression` | `GET /api/v1/suppressions/check` | `org:read` |
| `getPreferences(email, projectId?)` - 一个项目中的一个地址名单; `projectId` 当鼠标有多个时需要 | `GET /api/v1/preferences` | `contacts:read` |
| `setPreferences(email, { subscribedListIds, unsubscribeAll, projectId? })` ——保留完整的一组名单 | `PUT /api/v1/preferences` | `contacts:write` |
| `listTemplates` 编号 : `createTemplate` 编号 : `getTemplate` 编号 : `updateTemplate` 编号 : `deleteTemplate` | `/api/v1/templates` | `templates:read` 编号 : `templates:write` |
| `renderTemplate` | `POST /api/v1/templates/{id}/render` | `templates:read` |
| `listCampaigns({ projectId?, page?, perPage? })` 编号 : `getCampaign(id, { projectId? })` ——只读 | `GET /api/v1/campaigns`, (中文(简体) ), `GET /api/v1/campaigns/{id}` | `campaigns:read` |
| `getCampaignAnalytics(id, { projectId? })` ——计数加交付/打开/点击/弹出/不认购率(0比1) | `GET /api/v1/campaigns/{id}/analytics` | `analytics:read` |
| `getAnalyticsSummary({ period? } | { start, end })` - 总体计算和跟踪率 `7d`编号 :`30d`编号 :`90d` (默认) `30d`)或包容性世界协调时 `YYYY-MM-DD` 范围 | `GET /api/v1/analytics/summary` | `analytics:read` |
| `getUsage({ start, end })` ——用于包容性世界协调世界时的计量吸入器外送电子邮件计数(可填单和测试模式分开) `YYYY-MM-DD` 最多366天; 仅计数,不计费用 | `GET /api/v1/usage` | `usage:read` |
| `listLists` 编号 : `createList` 编号 : `getList` | `/api/v1/lists` | `contacts:read` 编号 : `contacts:write` |
| `addListContacts` | `POST /api/v1/lists/{id}/contacts` | `contacts:write` |
| `removeListContact` | `DELETE /api/v1/lists/{id}/contacts?email=` (只列出一个清单;保持联系) | `contacts:write` |
| `listContacts` 编号 : `upsertContacts` 编号 : `updateContact` 编号 : `deleteContact` | `/api/v1/contacts` | `contacts:read` 编号 : `contacts:write` |
| `listBusinesses({ projectId?, page?, perPage? })` 编号 : `getBusiness(id, { projectId? })` | `GET /api/v1/businesses`, (中文(简体) ), `GET /api/v1/businesses/{id}` | `contacts:read` |
| `createBusiness(input)` 编号 : `updateBusiness(id, input)` 编号 : `deleteBusiness(id, { projectId? })` - 更新替换 `domains`合并 `attributes`; 删除保留联系人 | `POST /api/v1/businesses`, (中文(简体) ), `PATCH` 编号 : `DELETE /api/v1/businesses/{id}` | `contacts:write` |
| `upsertBusinessByExternalRef(system, ref, input)` ——同位素;返回 `{ business, created }` | `PUT /api/v1/businesses/by-ref/{system}/{ref}` | `contacts:write` |
| `listBusinessMembers(id, { projectId?, page?, perPage? })` | `GET /api/v1/businesses/{id}/members` | `contacts:read` |
| `addBusinessMembers(id, members, { addedBy?, projectId? })` (最多100个)/ `removeBusinessMembers(id, { contactIds?, emails?, projectId? })` 仅限成员 | `POST` 编号 : `DELETE /api/v1/businesses/{id}/members` | `contacts:write` |
| `addBusinessMembersByDomain(id, { projectId? })` - 在企业领域增加联系人 | `POST /api/v1/businesses/{id}/members/by-domain` | `contacts:write` |
| `listSenders` 编号 : `createSender(input)` —— 说 `input.projectId?` 当鼠标有多个时, 目标为项目 | `/api/v1/senders` | `senders:read` 编号 : `senders:write` |
| `getSender` 编号 : `updateSender` 编号 : `deleteSender` | `/api/v1/senders/{id}` | `senders:read` 编号 : `senders:write` |
| `listUseCases({ projectId?, includeArchived? })` 编号 : `createUseCase(input)` —— 说 `input.projectId?` 关于 `createSender` | `/api/v1/use-cases` | `use-cases:read` 编号 : `use-cases:write` |
| `getUseCase` 编号 : `updateUseCase` 编号 : `archiveUseCase` 编号 : `restoreUseCase` ——删除档案;恢复撤销 | `/api/v1/use-cases/{id}` | `use-cases:read` 编号 : `use-cases:write` |
| `importSenders({ projectId? })` ——采用项目供应商账户身份;再运行以获取供应商核查 | `POST /api/v1/senders/import` | `senders:write` |
| `listDomains` 编号 : `createDomain(domain, { projectId })` 编号 : `getDomain` 编号 : `deleteDomain` | `/api/v1/domains` | `domains:read` 编号 : `domains:write` |
| `getDomainDnsRecords` 编号 : `verifyDomain` | `/api/v1/domains/{id}/…` | `domains:read` 编号 : `domains:write` |
| `getDomainBrandedTracking` 编号 : `enableDomainBrandedTracking` | `GET` 编号 : `POST /api/v1/domains/{id}/branded-tracking` | `domains:read` 编号 : `domains:write` |
| `listInboxes` 编号 : `getInbox` 编号 : `updateInbox(id, { displayName?, forwardTo?, storeMessages?, openTracking?, status? })` —— 说 `openTracking: true` 需要一个活跃的 HTTPS 品牌主机 | `/api/v1/inboxes`, (中文(简体) ), `/api/v1/inboxes/{id}` | `inboxes:read` 编号 : `inboxes:write` |
| `listSuppressions` 编号 : `addSuppressions` | `/api/v1/suppressions` | `org:read` 编号 : `org:write` |
| `getProjectAddress(projectId)` 编号 : `setProjectAddress(projectId, { physicalAddress, addressComponents? })` | `GET` 编号 : `PUT /api/v1/projects/{id}/address` | `org:read` 编号 : `org:write` |
| `getInboxDbStatus` | `GET /api/v1/inbox-db/status` | `org:read` |
| `connectInboxDb({ connectionString, provider? })` (202,启动背景连接) / `testInboxDbConnection` | `POST /api/v1/inbox-db/connection` 编号 : `…/connection/test` | `org:write` |
| `getInboxDbConnectAttempt` (投弹直到 `status` 没有 `running`(中文(简体) ) | `GET /api/v1/inbox-db/connection` | `org:read` |

应用程序级别的细节, 在您击中它们之前需要知道 :

-   **列表方法保持pagination.** `listTemplates` 和朋友回来 `{ data, pagination: { page, perPage, total } }` - 信封的标注是 调用列表路由, 因此它不会被取消 。 单资源方法返回有效载荷 直接,与发送方法相同.
-   **企业.** `client.businesses` 组合十种商业方法: `list`, (中文(简体) ), `get`, (中文(简体) ), `create`, (中文(简体) ), `update`, (中文(简体) ), `delete`, (中文(简体) ), `upsertByExternalRef`, (中文(简体) ), `addByDomain` 财务报告和审定财务报表 `members.{list, add, remove}`,每个 授权给上面的平面方法。 租赁: `projectId` 查询中 `get`, (中文(简体) ), `delete` 财务报告和审定财务报表 `addByDomain`,在体内为 `update`, (中文(简体) ), `createBusiness` 而会员写作。 别管了 仅当 org 有一个项目时.
-   **更新为 `PATCH`和部分.** 只发送您正在更改的字段 .
-   **运动读取选择 `projectId`。 。 。 .** 只有在雄兽有一个项目时才开放; 否则服务器会回答 400 `PROJECT_REQUIRED`. 另一个项目中的运动是404 `NOT_FOUND`和失踪的一样 无工程的Org得到422 `NO_PROJECT`; 无 销售商得到404 `NO_MARKETING_PROVIDER`。 。 。 . `listCampaigns` 在提供者的页面后过滤, 所以是一个页面 可持有少于 `perPage` 作行相会. 分析路径需要 `analytics:read`没有 `campaigns:read`。 。 。 .
-   **`renderTemplate(id, variables)` 将变量映射为整个正文** - 不包着 (单位:千美元) `variables` 键.
-   **`deleteTemplate` 从来没有404s**: 未知的 id 解析 `{ deleted: false }` 两百块 每个 其他删除将丢入缺失的资源.
-   **列表没有更新或删除** ——API不曝光;SDK不发明.
-   **禁止范围是跨战地的**数字 : `scope: "use_case"` 需求 `use_case_id`,以及 `use_case_id` 与 `scope: "account"` 是一个 `400`。 。 。 . `projectId` 命名工程所在区域 输入;省略后,它们会降落在使用项目中,否则每个项目中钥匙的所有人都可以打开.
-   **管理中的账户无法删除域** —— 说 `deleteDomain` 掷出 `403 MANAGED_ACCOUNT`。 。 。 .
-   **收件箱- db 连接字符串发送一次, 从未重复 .** `connectInboxDb` 存储加密; `InboxDbStatus` 省却. `schemaName` 您数据库中的Postgres schema NevarMail 拥有 .

任何尚未覆盖的东西——一个网点——都经过 `request()` (或 `requestPaginated()` 用于列表路由),它应用相同的认证,信封 打开、丢弃和重试 :

```ts
const endpoints = await nevarmail.request<unknown>("GET", "/api/v1/webhook-endpoints");
```

到达 `request()` 而不是写第二个 HTTP 客户端 。 就是这样 第一次发生了吞咽-过敏症.

### `sendEmailToList` 返回卷起而非判决

发送到一些收件人的列表是 `200` 与 `status: "partial"` 和一个非零 `failedCount`。检查字段;2xx并不意味着每个人都收到.

```ts
const run = await nevarmail.sendEmailToList({ listId, subject, htmlContent });
if (run.status !== "sent") console.error(run.failedCount, run.failures);
```

### 日程安排需要实时

`scheduled_for` 必须带有明确的抵消—— `2026-09-01T14:00:00Z` 或者说 `2026-09-01T10:00:00-04:00`赤裸的当地时间是四个不同的时刻,取决于谁 输入,所以API拒绝而不是猜测. 在你的一侧转换区域 其实已经知道。 模板的调度发送被拒绝: 处理器不渲染 模板,所以接受一个会排队一个空体.

## 代理收件箱 - `NevarMailInbox`

一个代理收件箱有自己的API(`/api/v1/inbox/*`)及其本人的证书:客户身份 (单位:千美元)`nvm_inbox_…`从收件箱的代理标签里找到的秘密 API 密钥在那里被拒绝, 并且 a 收件箱的证书在自己的收件箱之外没有任何内容,所以它是一个单独的客户端:

```ts
import { NevarMailInbox } from "@bernierllc/nevarmail";

const inbox = new NevarMailInbox({
  clientId: process.env.NEVARMAIL_INBOX_CLIENT_ID!,
  clientSecret: process.env.NEVARMAIL_INBOX_CLIENT_SECRET!,
  // scopes: ["inbox:read"], // narrow the token; defaults to inbox:read + inbox:send
});

const { data } = await inbox.listEmails({ perPage: 10 });
for (const summary of data.filter((e) => !e.isRead)) {
  const email = await inbox.getEmail(summary.id);
  await inbox.send({
    to: email.from,
    subject: `Re: ${email.subject ?? ""}`,
    text: "Got it.",
    reply_to_email_id: email.id,
  });
  await inbox.markEmailRead(email.id);
}
```

| 方法 | 路线 | 范围 |
| --- | --- | --- |
| `listEmails({ page, perPage, threadId })` | `GET /api/v1/inbox/emails` | `inbox:read` |
| `getEmail(id)` | `GET /api/v1/inbox/emails/{id}` | `inbox:read` |
| `markEmailRead(id)` | `POST /api/v1/inbox/emails/{id}/read` | `inbox:read` |
| `deleteEmail(id)` | `DELETE /api/v1/inbox/emails/{id}` | `inbox:read` |
| `send(input)` | `POST /api/v1/inbox/send` | `inbox:send` |
| `rotateCredentials()` | `POST /api/v1/inbox/credentials/rotate` | `inbox:read` |

-   **托肯斯为你处理.** 客户将证书交换为短命 符号( OAuth) `client_credentials` 时间 `/api/oauth/token`在第一次使用, 更新一分钟 期满前,以及 `401` 得到一个新鲜的标志 并重复一次。 被拒绝的证书 掷出 `code: "INVALID_CLIENT"`。 。 。 .
-   **`send` 是故意缩小.** 总是收件箱的地址,最多5个 整个接收者 `to` 财务报告和审定财务报表 `cc`; 没有模板或列表。 击中每天的限制是 `429 inbox_daily_limit_reached` {\\fn黑体\\fs22\\bord1\\shad0\\3ahbe\\4ah00\\fscx67\\fscy66\\2chffffff\\3ch808080}马上抛出 `retryAfter` 设置到 直到协调世界时午夜.
-   **`rotateCredentials()` 返回新密钥一次** 并切换客户端到它. 贮之. 老秘密停止运作.

相同的选项( O)`baseUrl`, (中文(简体) ), `timeoutMs`, (中文(简体) ), `maxRetries`, (中文(简体) ), `fetch`)和与 `NevarMail`。 。 。 .

## 选项

```ts
new NevarMail({
  apiKey: process.env.NEVARMAIL_API_KEY!,
  baseUrl: "https://app.nevarmail.com", // default
  timeoutMs: 30_000,                    // default
  maxRetries: 2,                        // default
  fetch: undefined,                     // inject one for tests or a custom runtime
});
```

### 使用大小写组和继承的设置

创建可重复使用的项目默认值 `createUseCaseGroup`,然后创建只使用其名称和组ID的用例。 组合允许可压制的,交易的,或混合使用的案例;混合组合每个类型都有默认的种类和单独的跟踪默认.

```ts
const group = await mail.createUseCaseGroup({
  name: "Account emails", projectId,
  allowedKind: "transactional", defaultSuppressable: false,
  defaults: {
    shared: { fromName: { value: "Accounts" } },
    suppressable: {}, transactional: { clickTracking: { value: false } },
  },
});
const login = await mail.createUseCase({ name: "Login", groupId: group.id });
await mail.updateUseCase(login.id, {
  expectedRevision: login.settingsRevision,
  settings: { set: { replyToEmail: null }, inherit: ["fromName"] },
});
```

省略的覆盖继承; 明示 `false` 禁用; 明确 `null` 清除一个无效的字段. `settings` 关于答复的内容包括有效/已配置的值、源和覆被状态。 与组值等同的覆被仍为覆被. 集团默认为继承人保留活性.

使用 `listUseCaseGroups`, (中文(简体) ), `getUseCaseGroup`,以及 `deleteUseCaseGroup` 管理团体。 删除返回 `{id, deleted: true}` 并拒绝包含任何成员的团体,包括存档成员。 要编辑默认,请调用 `previewUseCaseGroupUpdate(id, {changes})`然后审查受影响的成员,然后 `updateUseCaseGroup` 这些修改,预览的修改和符号.

```ts
const target = { groupId: destinationId }; // null means Ungrouped
const preview = await mail.previewUseCaseGroupMove(login.id, target);
// Show preview.rows and both outcomes to the user before applying.
const idempotencyKey = globalThis.crypto.randomUUID();
const moved = await mail.moveUseCaseToGroup(login.id, {
  ...target, previewToken: preview.previewToken,
  policy: "inherit_destination", // or "preserve_effective"
  idempotencyKey,
});
```

移动保留已有的覆盖 . `preserve_effective` 附加快照 。 一种变换用品 `suppressable` 通过相同的预览/应用流,而不是普通的元数据 PATCH. Tokens在15分钟后过期并绑定在演员/镜像上;在预览时使用相同的证书并应用. 一个 stale 预览返回 409, 并且没有重试 : 获取另一个比较并再次获得确认 .

移动键是请求正文中的UUID. 每一次SDK呼叫都会产生一次出局,保存在自动回放中. 在网络结果模糊后重新测试整个呼叫时,保留和再利用一个明确的关键。 承诺的重试即使在符后返回其原始结果;为不同的动作重用密钥是冲突.

生产过渡需要 `confirmation: {productionSending: true}` 和服务器权限/准备状态。 对交易邮件进行跟踪 `transactionalTracking: "transactional-tracking-v1"` 在用户看到披露后。 永远不要自动确认这些选择。 跟踪是解决的服务器侧; `SendEmailInput` 没有追踪功能。 保留 API 证书服务器侧:应用浏览器组件使用会话路由.

## 常见问题

### @bernierllc/nevarmail 是什么？

NevarMail v1 API的官方客户端\. 已打入,回放429/5xx,将NevarMailError投向了每个非-2xx\.

### 如何安装 @bernierllc/nevarmail？

在项目目录运行 npm install @bernierllc/nevarmail，或使用 pnpm add / yarn add / bun add。

### @bernierllc/nevarmail 支持 TypeScript 吗？

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

### @bernierllc/nevarmail 支持 ESM 还是 CommonJS？

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

### @bernierllc/nevarmail 需要什么版本的 Node\.js？

package\.json 的 engines 字段要求 Node\.js \>=20\.0\.0。版本不符时 npm 默认只给出警告，开启 engine-strict 后会拒绝安装。

### @bernierllc/nevarmail 可以商用吗？

@bernierllc/nevarmail 使用 MIT 许可。宽松许可：允许商业使用、修改和再分发，通常只需在分发时保留原版权与许可声明。以上为概括，不构成法律意见，请以许可原文为准。

### @bernierllc/nevarmail 的下载量有多少？

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

### @bernierllc/nevarmail 还在维护吗？

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

