npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

alimail-node-sdk

v1.0.3

Published

AliMail SDK

Readme

alimail-node-sdk

当前版本已封装:

  • OAuth2 client_credentials 获取 access_token
  • 自动缓存与刷新 token
  • 获取用户信息 getUser()
  • 获取邮件详情 getMessage()
  • 搜索邮件 searchMessages() / queryMessages()
  • 401 自动刷新后重试
  • 429 / 5xx 指数退避重试
  • TypeScript 类型声明
  • Node.js 18+ 原生 fetch 支持

运行环境:Node.js 18+


安装

本地开发

npm install

发布到 npm 后安装

npm install alimail-node-sdk

快速开始

const { AliMailClient } = require('alimail-node-sdk');

const client = new AliMailClient({
  appId: process.env.ALIMAIL_APP_ID,
  appSecret: process.env.ALIMAIL_APP_SECRET,
});

async function main() {
  const user = await client.getUser('[email protected]');
  console.log(user);
}

main().catch(console.error);

初始化方式

方式一:传入 appId 和 appSecret

SDK 会自动调用 token 接口,并缓存 access_token

const { AliMailClient } = require('alimail-node-sdk');

const client = new AliMailClient({
  appId: process.env.ALIMAIL_APP_ID,
  appSecret: process.env.ALIMAIL_APP_SECRET,
});

方式二:传入自定义 token provider

适合已经有统一 token 服务的场景。

const { AliMailClient } = require('alimail-node-sdk');

const client = new AliMailClient({
  getAccessToken: async () => {
    return process.env.ALIMAIL_ACCESS_TOKEN;
  },
});

方式三:注入自定义 fetch

适合测试、代理或埋点场景。

const { AliMailClient } = require('alimail-node-sdk');

const client = new AliMailClient({
  appId: process.env.ALIMAIL_APP_ID,
  appSecret: process.env.ALIMAIL_APP_SECRET,
  fetch: globalThis.fetch,
});

构造参数说明

const client = new AliMailClient({
  appId: process.env.ALIMAIL_APP_ID,
  appSecret: process.env.ALIMAIL_APP_SECRET,
  baseUrl: 'https://alimail-cn.aliyuncs.com',
  timeoutMs: 30000,
  maxRetries: 2,
  tokenRefreshBufferMs: 60_000,
  userAgent: 'your-app/1.0.0',
  defaultHeaders: {
    'x-trace-id': 'demo-trace-id',
  },
  onTokenUpdate: ({ accessToken, expiresAt }) => {
    console.log('token updated', accessToken, expiresAt);
  },
});

支持的参数

| 参数 | 类型 | 说明 | |---|---|---| | appId | string | 应用 appId | | appSecret | string | 应用 secret | | getAccessToken | () => string \| Promise<string> | 自定义 token 获取函数 | | baseUrl | string | 默认 https://alimail-cn.aliyuncs.com | | timeoutMs | number | 请求超时毫秒数,默认 30000 | | maxRetries | number | 429 / 5xx / 网络错误时的最大重试次数 | | tokenRefreshBufferMs | number | token 过期前多久提前刷新 | | retryDelayMs | (attempt, response?) => number | 自定义重试等待策略 | | userAgent | string | 自定义 User-Agent | | defaultHeaders | Record<string, string> | 附加默认请求头 | | onTokenUpdate | function | token 刷新成功后的回调 | | fetch | fetch | 自定义 fetch 实现 |


认证与 token

根据文档,调用邮箱 API 前,需要先在域管 API 开放平台创建应用并分配权限,然后通过 POST /oauth2/v2.0/token,以 client_credentials 模式换取 token;返回中包含 access_tokenexpires_in,文档也明确建议调用方缓存 token。所有开放 API 都要在 Authorization 请求头中带上 bearer {token}。单个域内总访问流量不能超过 40 次/秒,超限会返回 429。fileciteturn2file0

手动测试获取 token

const { AliMailClient } = require('alimail-node-sdk');

async function main() {
  const client = new AliMailClient({
    appId: process.env.ALIMAIL_APP_ID,
    appSecret: process.env.ALIMAIL_APP_SECRET,
  });

  const token = await client.getAccessToken();
  console.log(token);
}

main().catch(console.error);

强制刷新 token

await client.refreshAccessToken();

清空本地 token 缓存

client.clearTokenCache();

API 一览

client.getUser(identifier, options?)

根据用户 id 或邮箱地址获取用户信息,对应接口:GET /v2/users/{id | email}。接口支持 $select 指定额外字段,权限要求是 User.Read.AllUser.ReadWrite.All。fileciteturn2file2

参数

| 参数 | 类型 | 必填 | 说明 | |---|---|---:|---| | identifier | string | 是 | 用户 id 或邮箱地址 | | options.select | string \| string[] | 否 | 要返回的可选字段 | | options.headers | Record<string, string> | 否 | 本次请求额外头 | | options.signal | AbortSignal | 否 | 中断请求 |

示例 1:获取基础用户信息

const { AliMailClient } = require('alimail-node-sdk');

async function main() {
  const client = new AliMailClient({
    appId: process.env.ALIMAIL_APP_ID,
    appSecret: process.env.ALIMAIL_APP_SECRET,
  });

  const user = await client.getUser('[email protected]');
  console.log(JSON.stringify(user, null, 2));
}

main().catch(console.error);

示例 2:读取可选字段

const user = await client.getUser('[email protected]', {
  select: ['homeLocation', 'phone', 'managerInfo', 'customFields'],
});

示例 3:读取指定自定义字段

const user = await client.getUser('[email protected]', {
  select: 'customFields.field_12345',
});

常见 $select 示例

select: [
  'homeLocation',
  'phone',
  'managerInfo',
  'lastLoginTime',
  'departmentPath',
  'customFields'
]

client.getMessage(email, messageId, options?)

根据邮箱地址和邮件唯一标识获取邮件详情,对应接口:GET /v2/users/{email}/messages/{id}。该接口默认只返回基础信息,若要更多字段,需要通过 $select 指定,例如 internetMessageIdbodytoRecipients 等;权限要求为 Mail.Read.AllMail.ReadWrite.All。默认情况下 SDK 会直接返回响应中的 message 字段。fileciteturn2file1

参数

| 参数 | 类型 | 必填 | 说明 | |---|---|---:|---| | email | string | 是 | 用户邮箱地址 | | messageId | string | 是 | 邮件唯一标识 | | options.select | string \| string[] | 否 | 要返回的字段 | | options.unwrapMessage | boolean | 否 | 默认 true,设为 false 时返回完整响应 | | options.headers | Record<string, string> | 否 | 本次请求额外头 | | options.signal | AbortSignal | 否 | 中断请求 |

示例 1:读取基础邮件信息

const message = await client.getMessage('[email protected]', 'AAMkAGI2T...');
console.log(JSON.stringify(message, null, 2));

示例 2:读取正文、收件人、标签

const message = await client.getMessage('[email protected]', 'AAMkAGI2T...', {
  select: [
    'internetMessageId',
    'body',
    'toRecipients',
    'ccRecipients',
    'bccRecipients',
    'sender',
    'replyTo',
    'tags',
    'receivedDateTime',
    'lastModifiedDateTime',
  ],
});

示例 3:返回完整响应

const raw = await client.getMessage('[email protected]', 'AAMkAGI2T...', {
  unwrapMessage: false,
});
console.log(raw.message);

常见 $select 示例

select: [
  'internetMessageId',
  'body',
  'toRecipients',
  'ccRecipients',
  'bccRecipients',
  'sender',
  'replyTo',
  'isReadReceiptRequested',
  'receivedDateTime',
  'lastModifiedDateTime',
  'tags'
]

client.searchMessages(email, options) / client.queryMessages(email, options)

根据邮箱地址和查询语句搜索邮件,对应接口:POST /v2/users/{email}/messages/query。支持通过 $select 返回附加字段;请求体必须包含 querycursorsize(最大 100)。权限要求为 Mail.Read.AllMail.ReadWrite.All

参数

| 参数 | 类型 | 必填 | 说明 | |---|---|---:|---| | email | string | 是 | 用户邮箱地址 | | options.query | string | 是 | KQL 查询语句 | | options.cursor | string | 是 | 分页游标,首次传 "" | | options.size | number | 是 | 每页数量,取值 1-100 | | options.select | string \| string[] | 否 | 需要额外返回的字段 | | options.headers | Record<string, string> | 否 | 本次请求额外头 | | options.signal | AbortSignal | 否 | 中断请求 |

示例 1:搜索第一页邮件

const result = await client.searchMessages('[email protected]', {
  query: 'date>2025-01-01T00:00:00Z AND (NOT folderId:3) AND fromEmail="[email protected]"',
  cursor: '',
  size: 20,
  select: ['internetMessageId', 'toRecipients', 'receivedDateTime', 'tags'],
});

console.log(result.messages);
console.log(result.nextCursor);

示例 2:继续翻页

const page2 = await client.queryMessages('[email protected]', {
  query: 'fromEmail="[email protected]"',
  cursor: page1.nextCursor,
  size: 20,
});

通用底层请求

当你后面还要继续扩展更多阿里邮箱开放接口时,可以直接调用 client.request()

const result = await client.request({
  method: 'GET',
  path: '/v2/users/zhangsan%40example.com',
  query: {
    $select: 'phone,managerInfo',
  },
});

错误处理

SDK 会抛出 AliMailSdkError

可读字段:

  • message
  • status
  • code
  • details
  • responseBody
  • requestId
  • method
  • url
  • cause
try {
  const user = await client.getUser('[email protected]');
  console.log(user);
} catch (error) {
  if (error.name === 'AliMailSdkError') {
    console.error('message:', error.message);
    console.error('status:', error.status);
    console.error('code:', error.code);
    console.error('details:', error.details);
    console.error('requestId:', error.requestId);
    console.error('url:', error.url);
    console.error('responseBody:', error.responseBody);
  } else {
    console.error(error);
  }
}

超时、重试与限流建议

文档说明单域总流量上限为 40 次/秒,超限时返回 429。SDK 内置了对 429 和 5xx 的自动重试,也会优先读取 Retry-After 响应头。fileciteturn2file0

自定义重试策略

const client = new AliMailClient({
  appId: process.env.ALIMAIL_APP_ID,
  appSecret: process.env.ALIMAIL_APP_SECRET,
  maxRetries: 3,
  retryDelayMs: (attempt, response) => {
    if (response?.status === 429) {
      return 1500 * attempt;
    }
    return 500 * attempt;
  },
});

使用 AbortController 控制超时 / 取消

const controller = new AbortController();
setTimeout(() => controller.abort(), 5000);

const user = await client.getUser('[email protected]', {
  signal: controller.signal,
});

TypeScript 用法

import { AliMailClient } from 'alimail-node-sdk';

type UserInfo = {
  id: string;
  email: string;
  name: string;
  phone?: string;
};

const client = new AliMailClient({
  appId: process.env.ALIMAIL_APP_ID,
  appSecret: process.env.ALIMAIL_APP_SECRET,
});

async function main() {
  const user = await client.getUser<UserInfo>('[email protected]', {
    select: ['phone'],
  });

  console.log(user.phone);
}

示例代码

examples/get-token.js

node examples/get-token.js

examples/get-user.js

node examples/get-user.js

examples/get-message.js

node examples/get-message.js

examples/search-messages.js

node examples/search-messages.js

环境变量示例

export ALIMAIL_APP_ID="your_app_id"
export ALIMAIL_APP_SECRET="your_app_secret"
export ALIMAIL_USER_EMAIL="[email protected]"
export ALIMAIL_MESSAGE_ID="AAMkAGI2T..."
export ALIMAIL_SEARCH_QUERY='fromEmail="[email protected]"'

许可协议

MIT