# @bumail/jmap 中文文档

规范地址：https://npmcn.com/package/%40bumail/jmap/

版本：0\.12\.0
npm 元数据更新时间：2026-11-05T09:22:13.015Z
中文译文更新时间：2026-11-08T19:35:50.528Z
软件包许可：MIT

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

原始 npm 页面：https://www.npmjs.com/package/%40bumail/jmap
原文对照：https://npmcn.com/package/%40bumail/jmap/?lang=original
源码仓库：https://github.com/softistx/bumail

弃用说明：moved to @softistx/bumail-jmap \(private, GitHub Packages\)

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

- 包体积（解压后）：886 kB，173 个文件
- 模块格式：ES Module
- TypeScript 类型：包内自带
- 运行依赖：0 个
- peer 依赖：typescript ^6\.0\.3 \|\| ^7\.0\.0，@alxia/core ^0\.19\.0，@bumail/mime ^0\.4\.0，@bumail/store ^0\.9\.0
- 首次发布：2026-10-03T23:11:23.698Z
- 最新版本发布：2026-11-05T04:18:33.102Z
- 近 30 天下载量：3439（2026-10-09 至 2026-11-07，npm 官方下载统计）
- 已发布版本数：21（近 12 个月 21 个）

## 中文简介

一个在 alxia 上的 JMAP 服务器( RFC 8620, RFC 8621) : 会话, 包含回溯引用的 API, 邮箱, 电子邮件和线索, blob 下载和上传, 服务任意的@ bumail/ store

## 安装

```sh
npm install @bumail/jmap
```

也可以使用：`pnpm add @bumail/jmap`、`yarn add @bumail/jmap`、`bun add @bumail/jmap`

## README

# @ bumail/ jmap (帮助)

Bun 的 JMAP 服务器: JMAP 核心 (RFC 8620) 和 JMAP 邮件 (RFC 8621),作为一个 [阿尔克夏](https://www.npmjs.com/package/@alxia/core) 应用 你骑在自己的。 它服务于任何邮件 [`@bumail/store`](https://github.com/softistx/bumail/blob/develop/packages/store) `MailStore` - 同一个商店 [`@bumail/imap`](https://github.com/softistx/bumail/blob/develop/packages/imap) 服务,并阅读信件 [`@bumail/mime`](https://github.com/softistx/bumail/blob/develop/packages/mime): 会话、 API 与 回历、邮箱、电子邮件和线索, `queryChanges`,blob下载和上传,以及 事件源推 (RFC 8620§7.3).

```sh
bun add @bumail/jmap @alxia/core @bumail/store @bumail/mime
```

`@alxia/core` (0.19.0或以后,0.20下), `@bumail/store` 财务报告和审定财务报表 `@bumail/mime` 为: 端口: 安装您的应用程序使用的版本 . `typescript` 是可选的 鼠标,用于类型.

## 装入Alxia应用软件

`jmap(options)` 返回 alxia 应用程序。 随你上 `plugin`: 它添加 `GET /.well-known/jmap` (届会)和 `basePath` (单位:千美元)`/jmap` 以 默认), `POST /jmap/api`, (中文(简体) ), `GET /jmap/download/:accountId/:blobId/:name` 财务报告和审定财务报表 `POST /jmap/upload/:accountId`。其每条路线都认证 ; 您的路线被单独处理.

```ts
import { alxia } from '@alxia/core';
import { jmap } from '@bumail/jmap';
import { MemoryMailStore } from '@bumail/store';

const store = new MemoryMailStore();
const alice = await store.createAccount('alice@example.com');
await store.createMailbox(alice.id, { name: 'INBOX', role: 'inbox' });

const tokens = new Map([['alice-secret-token', alice.id]]);
const passwords = new Map([['alice', await Bun.password.hash('correct horse')]]);

const server = jmap({
    store,
    origin: 'https://mail.example.com', // the public URL the session's URLs start with
    async authenticate(credentials) {
        if (credentials.scheme === 'bearer') return tokens.get(credentials.token) ?? null;
        const hash = passwords.get(credentials.username);
        if (!hash || !(await Bun.password.verify(credentials.password, hash))) return null;
        return alice.id;
    },
});

const app = alxia()
    .get('/health', ({ reply }) => reply(200, 'ok')) // not authenticated
    .plugin(server);

app.listen(8080);
```

[`examples/serve.ts`](https://github.com/softistx/bumail/blob/develop/packages/jmap/examples/serve.ts) 实值 此示例,可以从克隆中运行 : `bun install && bun run build`,则 `bun packages/jmap/examples/serve.ts`,则 `curl -H 'Authorization: Bearer alice-secret-token' http://localhost:8080/.well-known/jmap`。 。 。 .

## 认证

`authenticate` 获得 `{ scheme: 'basic', username, password }` 或者说 `{ scheme: 'bearer', token }`,则 `Request`,则 `client`数字 : `{ ip, url }`,主机应用程序 `ctx.ip` 财务报告和审定财务报表 `originalUrl(ctx)` 地址a 登录限制计数 。 它回答 id of the 存储账户以服务,或 `null` (a) 拒绝(有两项挑战的401项). 它运行在下面 `hookTimeout` (30 s):投出、悬挂或取名 商店没有的账户是503 `onError` 被告诉.

**Basic仅取自HTTPS.** 根据明确要求,法院以 前403页 `authenticate` 被称为,因为 `@bumail/imap` 财务报告和审定财务报表 `@bumail/smtp` 在 TLS 之前拒绝登录。 在结束 TLS 的代理后,声明 主机应用程序上的代理 `trustProxy`阅读他们说的话:

```ts
import { alxia, trustProxy } from '@alxia/core';

const app = alxia({
    proxy: trustProxy({ trusted: ['10.0.0.0/8'], untrusted: 'refuse-all' }),
}).plugin(
    jmap({
        …,
        // the scheme the outermost trusted proxy wrote, never the client's
        secure: (_request, client) => client.url.protocol === 'https:',
        // your own check, its limiter keyed by the forwarded client's address
        authenticate: (credentials, _request, client) => check(credentials, client.ip),
    }),
);
```

`allowInsecureBasic: true` 取消拒绝,仅供当地检验。 守护者 任何请求都带有标记.

## 它的答案是什么

| 方法 |  |
| --- | --- |
| `Core/echo` | 其论点 |
| `Mailbox/get`, (中文(简体) ), `Mailbox/changes` | 所有财产; `myRights` 全部捐赠,但 `maySubmit`,这与 `submission` 选项 |
| `Mailbox/query` | 过滤器通过 `parentId`, (中文(简体) ), `role`, (中文(简体) ), `name`, (中文(简体) ), `hasAnyRole`, (中文(简体) ), `isSubscribed`; 排序为 `sortOrder` 财务报告和审定财务报表 `name` |
| `Mailbox/queryChanges` | 过滤器和排序 `Mailbox/query`,与 `sinceQueryState`, (中文(简体) ), `maxChanges`, (中文(简体) ), `upToId`, (中文(简体) ), `calculateTotal` |
| `Mailbox/set` | 创建、更新 `name`, (中文(简体) ), `parentId` 财务报告和审定财务报表 `isSubscribed`,用 `onDestroyRemoveEmails` |
| `Email/get` | 元数据, `headers`,每个 `header:` 窗体和方便头, `bodyStructure`, (中文(简体) ), `textBody`, (中文(简体) ), `htmlBody`, (中文(简体) ), `attachments`, (中文(简体) ), `bodyValues`, (中文(简体) ), `preview`, (中文(简体) ), `hasAttachment` |
| `Email/query` | 过滤器通过 `inMailbox`, (中文(简体) ), `inMailboxOtherThan`, (中文(简体) ), `before`, (中文(简体) ), `after`, (中文(简体) ), `minSize`, (中文(简体) ), `maxSize`, (中文(简体) ), `hasKeyword`, (中文(简体) ), `notKeyword`, (中文(简体) ), `text`, (中文(简体) ), `from`, (中文(简体) ), `to`, (中文(简体) ), `cc`, (中文(简体) ), `bcc`, (中文(简体) ), `subject`, (中文(简体) ), `body`,有和,或和不;排序 `receivedAt`, (中文(简体) ), `size`, (中文(简体) ), `from`, (中文(简体) ), `to`, (中文(简体) ), `subject`· ; `collapseThreads`, (中文(简体) ), `position`, (中文(简体) ), `anchor`, (中文(简体) ), `limit`, (中文(简体) ), `calculateTotal` |
| `Email/queryChanges` | 过滤器,排序和 `collapseThreads` 联 合 国 `Email/query`,与 `sinceQueryState`, (中文(简体) ), `maxChanges`, (中文(简体) ), `upToId`, (中文(简体) ), `calculateTotal`· ; `removed` 可能是超级集 |
| `Email/changes` | 自状态起创建、更新和销毁 |
| `Email/set` | 更新 `keywords` 财务报告和审定财务报表 `mailboxIds`,完整或补丁; 销毁; 从上传创建 `blobId` |
| `Email/import` | 来自上传blobs的电子邮件 |
| `Thread/get` | 最古老的一条线的电子邮件,先通过商店的线程索引 |
| `Thread/changes` | 自状态起创建、更新并销毁线索 |
| `Identity/get`, (中文(简体) ), `Identity/changes`, (中文(简体) ), `Identity/set` | 与 `submission` 选项和 `urn:ietf:params:jmap:submission` 内 `using`:主机目录的地址表示账户发送为,只读; `/changes` 从当前状态中空出, 从其它状态中空出 `cannotCalculateChanges`· ; `/set` 答题 `forbidden` |
| `EmailSubmission/get`, (中文(简体) ), `/changes`, (中文(简体) ), `/query`, (中文(简体) ), `/queryChanges`, (中文(简体) ), `/set` | 与 `submission` 选项:通过主机发送电子邮件 `send` 钩 (参见 [发送](https://github.com/softistx/bumail/blob/develop/packages/jmap/docs/guide.md#sending)· ; `submission: { identities, send }`),它决定了谁可以发送;用电子邮件制作的信封,如RFC 8621 第7.5节所言,Bcc从不留于所出之处,在钩子运行之前存储的记录,a `deliveryStatus` 每个受援者, `onSuccessUpdateEmail` 财务报告和审定财务报表 `onSuccessDestroyEmail` 答复者 `Email/set` 在呼叫本身之后; 信封的 DSN 参数(`RET`, (中文(简体) ), `ENVID`, (中文(简体) ), `NOTIFY`, (中文(简体) ), `ORCPT`, RFC 3461, 已解码为 RFC 8621 §7 的值) 被检查并给予 `send`,和会议列表 `DSN` 内 `submissionExtensions`; 没有延迟发送或撤消( e)`cannotUnsend`(中文(简体) ) |

参考文献`#ids` 与 `resultOf`, (中文(简体) ), `name` (单位:千美元) `path` 与 `*`(中文(简体) ) 财务报告和审定财务报表 `#creationId`在一个请求中工作.

## 上传和下载

```ts
// accountId and inboxId come from the session and Mailbox/get; rawMessage is RFC 5322 bytes
const authorization = 'Bearer alice-secret-token';
const upload = await fetch(`https://mail.example.com/jmap/upload/${accountId}`, {
    method: 'POST',
    headers: { authorization, 'content-type': 'message/rfc822' },
    body: rawMessage,
}).then((response) => response.json()); // { accountId, blobId, type, size }

// then: ["Email/import", { accountId, emails: { a: { blobId: upload.blobId, mailboxIds: { [inboxId]: true } } } }, "0"]
```

下载服务于电子邮件的字节,其一部分(每个部分) `blobId` 内 `Email/get`),或上传,与 `Range` 支持: `GET /jmap/download/{accountId}/{blobId}/{name}?accept={type}`。 。 。 .

默认上传会活在记忆中. 保持它们恒久,流畅并共享 每个实例,给予 `jmap` a 一个 `UploadStore` 从 `@bumail/store`数字 :

```ts
import { SqliteUploadStore } from '@bumail/store/sqlite';

jmap({ store, origin, authenticate, uploads: SqliteUploadStore.open({ directory: '/var/lib/mail' }) });
```

内容 `ttlMs`, (中文(简体) ), `maxSize` 财务报告和审定财务报表 `quotaBytes` 然后替换 `uploadTtl` 财务报告和审定财务报表 `uploadQuota`。它的ID是随机的,所以同样的字节上传两次是两个 上传,每个上行计算在配额上;内存上传会去dupe.

## 限制

| 限制 | 默认 |  |
| --- | --- | --- |
| `maxSizeRequest` | 10 个 MB | aPI 机构: a `Content-Length` 穿过了它拒绝读取, 一块被割断了的躯体穿过它 |
| `maxCallsInRequest` | 16个 | 一个请求中的方法调用 |
| `maxConcurrentRequests` | 页:1 | 每个账户飞行中的API请求 |
| `maxObjectsInGet`, (中文(简体) ), `maxObjectsInSet` | 500个 | 编号 a `/get`; 创建、更新和销毁 `/set`; 查询的页面 |
| `maxSizeUpload` | 25个小米B | 一个上传,像 `maxSizeRequest` |
| `maxConcurrentUpload` | 页:1 | 每个账户在飞行中上传 |
| `uploadQuota` | 100个米B | 每个账户的内存上传字节数(与 `uploads`: 店铺的 `quotaBytes`(中文(简体) ) |
| `uploadTtl` | 3600 s (简体中文) | 内存上传保存时间(与 `uploads`: 店铺的 `ttlMs`(中文(简体) ) |
| `maxEventSourceStreams` | 页:1 | 每个账户打开的事件流(429个) `limit` 通过它) |
| `maxJsonDepth`, (中文(简体) ), `maxJsonTokens` | 64 100 000美元 | 在解析前检查 |
| `maxReferenceItems` | 5000块 | 一个回溯引用扩展为 |
| `maxReferenceBytes` | 4个小米B | jSON 的字节 |
| `maxSizeResponse` | 64个小米B | 一个API回复的JSON字节 |
| `maxQueryScan` | 10 000人 | 电子邮件 1 `Email/query` 它们的字节、匹配的索引 `Email/queryChanges` 和电子邮件 a `Mailbox/get` 计数读取( 过去, 商店的计数) |
| `maxBodyValueBytes` | 1个小米B | 一个身体值,不管客户问什么 |
| `maxBodyValuesTotal` | 16个小米B | 一个请求中的正体值 |

把它们放在下面 `limits`。 。 。 . `maxSizeRequest`, (中文(简体) ), `maxCallsInRequest`, (中文(简体) ), `maxConcurrentRequests`, (中文(简体) ), `maxObjectsInGet`, (中文(简体) ), `maxObjectsInSet`, (中文(简体) ), `maxSizeUpload` 财务报告和审定财务报表 `maxConcurrentUpload` 将在会话中宣布 `urn:ietf:params:jmap:core` 能力。 请求打破的限制是 `urn:ietf:params:jmap:error:limit` 命名问题( 大小为 413) 派去,429个货币,其余400个, `maxSizeResponse` 包含; 一个被呼叫中断是一个方法 错误。 药是 `[A-Za-z0-9_-]{1,255}`; 一个账户永远不会到达另一个账户 账户的数据,无论它名称是什么;错误中重复的客户端文本是 在100个字符后切出.

## OpenAPI 文档

包装了它所添加路线的OpenAPI 3.1文件,因为 `@bumail/jmap/openapi.json` (单位:千美元)`openapi/jmap.json` 在软件包中:

```ts
import document from '@bumail/jmap/openapi.json' with { type: 'json' };

document.paths['/api'].post.operationId; // 'api'
```

它涵盖会议及其会议反对, `POST {basePath}/api` 与 请求和答复信封,下载(URI模板) 参数, `Range` 和上传的《基本》和《坚忍》 rFC 8620 问题 (单位:千美元)`notJSON`, (中文(简体) ), `notRequest`, (中文(简体) ), `unknownCapability`, (中文(简体) ), `limit`,作为 `application/problem+json`。API、下载和上传服务器 谁 `basePath` 变量默认值为 `/jmap`: 与另一个 `basePath`设置 变量;路径保持不变.

一个方法调用是 `[name, arguments, callId]`,它的论点是 通用描述, 如 RFC 8620 框框: 命名为 `#name` 是一种从早先的回复中解开的回溯参照,以及一种方法,即 无法回答 `error` 在200码内引用 绝对不是HTTP状态. RFC 8620和RFC 8621定义了每种方法的论据. 该文件是 文档和合同:服务器不对其进行验证, 当一个路由和文档有分歧时,包的 spect 失败. 内容 `info.version` 是文档的版本,而不是软件包的版本.

## 陷阱

-   **搜索存在前所存储的电子邮件在第一次使用时被索引.** `Email/query` 由商店的回答 `queryMessages`,从搜索 字段中添加电子邮件`Email/import` 财务报告和审定财务报表 `Email/set` 传过来. 没有他们的电子邮件最多从其字节读取 `maxQueryScan` 和田地`setSearchFields`,没有客户看到; 电话是 `serverUnavailable` 留下一部分,每一部分 指数增加(绝不是部分结果). `Email/queryChanges` 拿着 整个结果和答案 `requestTooLarge` 过去 `maxQueryScan` 火柴。 比赛. `Thread/get` 财务报告和审定财务报表 `Thread/changes` 不扫描: 商店回答它们 . `Mailbox/get` 计数 `unreadEmails`, (中文(简体) ), `totalThreads` 财务报告和审定财务报表 `unreadThreads` 如RFC 8621 §2所问(`$seen` 在任何拼写读取, `$draft` 在同一个预算范围内,它的所有邮箱 合计(`properties` 被弃绝,被弃绝,被弃绝,被弃绝 邮箱的计数是商店的IMAP计数, `unseen` 对于两个未读 计数和 `messages` 页:1 `totalThreads`,这算不上电子邮件 线程,因为商店没有每个邮箱线程数.
-   **上传为内存** 页:1 `uploadTtl`,在此过程中 他们,除非 `uploads` 给出一个 `UploadStore`:重启会忘记它们,而且 两个进程没有共享.
-   **`sortOrder` 总是0**和邮箱的 `role` 无法更改: 商店里没有.
-   **`ifInState` 检查,然后调用**: 介于 两人没被抓.
-   **推是事件源** (RFC 8620 第7.3节):无WebSocket(RFC 8887), 无按键订阅(§7.2)。 溪流逐一地看店铺 `pushInterval` 何时 `notify` 他们被称作;他们生活在一个 因此,在几个案例中,只有民意调查才涉及客户,而客户 更改另一个实例.
-   **会议在 `/.well-known/jmap` 上面的应用程序**数字 : 挂载 `jmap()` 在一个没有前缀的应用程序上,或者那个路径也会移动.
-   **`asRaw` 显示页眉值** 失去他们的领先空间.

## 推开

`GET /jmap/eventsource` (届会) `eventSourceUrl`) 溪流 a `StateChange` 当一个账户的电子邮件,邮箱,线索,电子邮件交付, 身份或电子邮件 状态动作。 告诉服务器它没有做出修改, 并设置多久一次 寻找其他的`pushInterval`,以秒计,默认为10:

```ts
const server = jmap({ store, origin, authenticate, pushInterval: 5 });
// after a delivery into the store, or an IMAP change:
server.notify(accountId, { delivery: true });
// serving through your own Bun.serve? end the streams before you stop it:
server.close();
```

## API 密码

| 导出 |  |
| --- | --- |
| `jmap(options)` | 服务器:要挂载的 alxia 应用程序 `plugin`,与 `notify(accountId, change?)` 财务报告和审定财务报表 `close()`; 丢出一个 `JmapError` (单位:千美元)`INVALID_OPTION`) 在一个糟糕的选择 |
| `JmapServer` | `notify(accountId, { delivery? })`:唤醒账户事件流查看其状态; `delivery: true` 并移动电子邮件传送; `close()`: 结束每个已打开的事件流并拒绝新的 |
| `JmapOptions` | `store`, (中文(简体) ), `authenticate`, (中文(简体) ), `origin`, (中文(简体) ), `basePath`, (中文(简体) ), `limits`, (中文(简体) ), `pushInterval`, (中文(简体) ), `hookTimeout`, (中文(简体) ), `allowInsecureBasic`, (中文(简体) ), `secure`, (中文(简体) ), `onError`, (中文(简体) ), `submission` |
| `JmapSubmission`, (中文(简体) ), `IdentityInfo` | 页:1 `submission` 选项 : `identities(accountId)` 请回答 `{ email, name }` 一个账户发出如下:, `send(request)` 发出一个信息,并决定谁可以, `maxRecipients` (默认100);设置它宣布 `urn:ietf:params:jmap:submission` |
| `SendRequest`, (中文(简体) ), `SendEnvelope` (与 `ret`, (中文(简体) ), `envid`, (中文(简体) ), `recipients`, (中文(简体) ), `SendRecipient`, (中文(简体) ), `SendNotify`, (中文(简体) ), `SendAnswer`, (中文(简体) ), `SendRefusal`, (中文(简体) ), `SendRefusalType`, (中文(简体) ), `SendDelivery` | 什麽 `send` 给出和回答 |
| `JmapLimits` | 以上限额 |
| `JmapCredentials` | 什麽 `authenticate` 获取 : `{ scheme: 'basic', username, password }` 或者说 `{ scheme: 'bearer', token }` |
| `AuthResult` | 什麽 `authenticate` 答案:账户编号,或 `null` 编号 : `undefined` |
| `JmapClient` | 请求来自谁 `authenticate`, (中文(简体) ), `secure` 财务报告和审定财务报表 `onError` 被告知: `ip` (单位:千美元)`ctx.ip`和 `url` (单位:千美元)`originalUrl(ctx)`(中文(简体) ) |
| `ErrorContext` | 什麽 `onError` 获取到错误旁边 : `request`, (中文(简体) ), `client`, (中文(简体) ), `accountId`, (中文(简体) ), `method` |
| `JmapError`, (中文(简体) ), `JmapErrorCode` | `code`数字 : `INVALID_OPTION`,以及 `HOOK_TIMEOUT`,哪个 `onError` 钩子时得到( w)`authenticate`, (中文(简体) ), `submission.identities`, (中文(简体) ), `submission.send`(b) 未在其中结算 `hookTimeout` |
| `@bumail/jmap/openapi.json` | 作为 JSON 路径的 OpenAPI 3.1 文件 |

## 文档

-   [指数](https://github.com/softistx/bumail/blob/develop/packages/jmap/docs/README.md):各页,何时读出.
-   [指南](https://github.com/softistx/bumail/blob/develop/packages/jmap/docs/guide.md): 挂起、 认证、 会话、 每一种方法、 以及存储的映射方式, 发送(`EmailSubmission` 编辑 `send` hook),blobs,限制,OpenAPI文档,RFCs也随之而来.
-   [解决问题](https://github.com/softistx/bumail/blob/develop/packages/jmap/docs/troubleshooting.md): 每一个错误,问题和方法错误,按其准确的文字.
-   [路线图](https://github.com/softistx/bumail/blob/develop/packages/jmap/docs/roadmap.md):接下来会发生什么——搜索片段,真空响应——和商店漏洞.

## 许可证

麻省理工学院

## 常见问题

### @bumail/jmap 是什么？

一个在 alxia 上的 JMAP 服务器\( RFC 8620, RFC 8621\) : 会话, 包含回溯引用的 API, 邮箱, 电子邮件和线索, blob 下载和上传, 服务任意的@ bumail/ store注意：该包已被作者标记为弃用——moved to @softistx/bumail-jmap \(private, GitHub Packages\)

### 如何安装 @bumail/jmap？

在项目目录运行 npm install @bumail/jmap，或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖：@alxia/core（^0\.19\.0）、@bumail/mime（^0\.4\.0）、@bumail/store（^0\.9\.0）。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖，Yarn 需要手动安装。

### @bumail/jmap 支持 TypeScript 吗？

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

### @bumail/jmap 支持 ESM 还是 CommonJS？

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

### @bumail/jmap 可以商用吗？

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

### @bumail/jmap 的下载量有多少？

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

### @bumail/jmap 还在维护吗？

最新版本 0\.12\.0 发布于 2026/11/05（3 天前）；至今共发布 21 个版本，其中过去 12 个月发布了 21 个；首次发布于 2026/10/04。作者已将其标记为弃用，新项目建议寻找替代方案。

