alimail-node-sdk
v1.0.3
Published
AliMail SDK
Maintainers
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_token 和 expires_in,文档也明确建议调用方缓存 token。所有开放 API 都要在 Authorization 请求头中带上 bearer {token}。单个域内总访问流量不能超过 40 次/秒,超限会返回 429。fileciteturn2file0
手动测试获取 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.All 或 User.ReadWrite.All。fileciteturn2file2
参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---:|---|
| 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 指定,例如 internetMessageId、body、toRecipients 等;权限要求为 Mail.Read.All 或 Mail.ReadWrite.All。默认情况下 SDK 会直接返回响应中的 message 字段。fileciteturn2file1
参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---:|---|
| 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 返回附加字段;请求体必须包含 query、cursor 和 size(最大 100)。权限要求为 Mail.Read.All 或 Mail.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。
可读字段:
messagestatuscodedetailsresponseBodyrequestIdmethodurlcause
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 响应头。fileciteturn2file0
自定义重试策略
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.jsexamples/get-user.js
node examples/get-user.jsexamples/get-message.js
node examples/get-message.jsexamples/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
