@aglyn/shared-util-email

中文文档
1.18.0发布于 2026/11/07Apache-2.0TypeScriptES Module构建来源已验证近 30 天下载 1.7万

从Aglyn monorepo出版到npm. 随后的版本 语义版本。 。 。 .

中文使用文档
文档目录10 节
  1. 安装
  2. 哪些是范围,哪些不是范围
  3. 配置
  4. 邮件提供者
  5. 使用量
  6. 运输边界
  7. 列表未订阅设置
  8. 正在检查配置
  9. 运行单元测试
  10. 许可证

@aglyn/ 共享用户电子邮件

从Aglyn monorepo出版到npm. 随后的版本 语义版本。 。 。 .

安装

npm install @aglyn/shared-util-email

一个送出的地方 应用程序 电子邮件,通过邮件提供者 部署选择 : 重新发送 默认,或 接线员自己的发件人身后一个webhook.

在这图书馆之前,一个卖家的30行 fetch 已复制 跨越 10 个文件, 每个 读取 env vars 本身, 每个处理失败 a 有点不一样 合并它们就意味着提供者,发送者 和失败的语义 在一个地方变化.

哪些是范围,哪些不是范围

邮件寄来的这里?
邀请、收据、使用摘要、运动、工作人员通知邮件提供者✅
核实、密码重置火地轴❌
寄入邮件到 @aglyn.com 邮箱谷歌工作空间❌

配置

发送者和携带邮件的提供者的设置,在 调用时间 :

USAGE_EMAIL_FROM="Aglyn <[email protected]>"
RESEND_API_KEY=re_xxxxxxxx             # the default provider
# or, for your own sender:
AGLYN_MAIL_WEBHOOK_URL=https://relay.internal/send
AGLYN_MAIL_WEBHOOK_TOKEN=…

需要发送者和提供者的设置。 和两个 失踪, sendEmail() 警告和返回 { sent: false, reason: 'unconfigured' } 它不扔出, 因此本地和预览环境运行 没有邮件提供商就没事.

邮件提供者

sendEmail() 决定信息是否、作为谁和由谁发出 -- -- 镇压 派遣率高的总督 钓鱼屏 派遣 身份,未订阅页脚。 A 类 MailProvider (单位:千美元)mail-provider.ts仅限 并回答平台的其他问题 关于平台本身词汇中的邮件: 是否其认证有效, 一个送货的网友说, 收到的信息包含什么 账户已发送 .

mail-providers.ts 选择部署的提供者 :

  • AGLYN_MAIL_PROVIDER 一个名字.. resend, (中文(简体) ), webhook,或 id 插件或 登记在 registerMailProvider()。 。 。 .
  • 取消设置, 第一个内置设置胜出 : resend 何时 RESEND_API_KEY 已经设定, webhook 仅当 AGLYN_MAIL_WEBHOOK_URL 这是, 否则 resend,没有配置.
  • 既未建入也未注册的名称是 拒绝: 每一次发送 被错误命名而跳过, 没有任何东西会回到另一个 卖家.

内置内容汇编到这个库中,而不是由 插件, 因为这是交易栏: 它必须从每个服务器发送 已装入或未装入插件的进程,以及未装入的注册 事情的发生 看起来像邮件关闭.

其余的平台通过询问 normalizeDeliveryEvents(), (中文(简体) ), readInboundMailEvent() 财务报告和审定财务报表 mailProviderReads(),从未通过提供者 以名为相. mail-provider-resend.ts 是唯一一个知道Resend的模块 有线格式,以及 mail-provider-webhook.ts 记录了webhook的.

设置和 DNS 记录在 docs/EMAIL_SETUP.md。 。 。 .

使用量

import { sendEmail } from '@aglyn/shared-util-email'

const result = await sendEmail({
  to: '[email protected]',
  subject: 'You have been invited',
  text: 'Sign in to accept.',
  context: 'invite', // shows up in logs on failure
})

if (!result.sent) {
  // 'unconfigured' | 'no-recipient' | 'rejected' | 'network'
  console.warn('no mail went out:', result.reason)
}

sendEmail() 从不扔。出局邮件在任何地方都是最好的 这个代码库——退票不能因为收件被反弹而失败——所以,每个 结果作为结果对象回来。 检查 sent:这是让 控制台诚实地告诉用户消息是否真的发出.

可选字段 : html, (中文(简体) ), headers (例如:. List-Unsubscribe, (中文(简体) ), tags (网络 归属问题), replyTo,以及 from (覆盖所配置的发送者——很少) 对,因为 USAGE_EMAIL_FROM 是一个经过验证的身份.

运输边界

postResendEmail() (单位:千美元) mail-provider-resend.ts)是唯一一个函数 Resend发送端点的 POSTs, 和这个 掷出 没有有效载荷 to 而不是把它放在线上. 此有效载荷不能成为消息; 重新发送答案 422 missing_required_field,它花费API电话,然后坐在供应商 仪表板看起来就像邮件 未能交付,什么都没有 给负责的代码起名. sendEmail() 筛选很久之前的收件人 这一点,所以普通的发送者从来没有遇到过警卫——它的存在是因为 RESEND_SEND_ENDPOINT 导出并直接取回它的模块 绕过每次检查 sendEmail() 拥有.

列表未订阅设置

list-unsubscribe.ts 就是那个地方 List-Unsubscribe 编号 : List-Unsubscribe-Post (RFC 8058)对对是模型,每个发送者制作 它是一个背景——一个外联序列(默认)和营销活动 (默认的) :

import {
  decideListUnsubscribe,
  listUnsubscribeHeaders,
  readListUnsubscribeSetting,
} from '@aglyn/shared-util-email/list-unsubscribe'

const requested = readListUnsubscribeSetting(stored.listUnsubscribe, true)
const decision = decideListUnsubscribe({
  requested,
  recentVolume, // the organization's campaign messages in the last day
  sendVolume, // everyone this email will address
})
const headers = decision.on ? listUnsubscribeHeaders({ url: oneClickUrl }) : {}

decideListUnsubscribe 是散装的守望者。当他们出发的时候 这需要组织 EMAIL_LIST_UNSUBSCRIBE_BULK_THRESHOLD 信件 (默认5000, Gmail's and Yahoo's line) 背负的对反正 判决说这是强迫的,为什么。 头是普通头,所以任何 后置提供者 sendEmail 送他们.

正在检查配置

import { isEmailConfigured, describeEmailConfig, checkEmailCredentials }
  from '@aglyn/shared-util-email'
  • isEmailConfigured() ——提供者有其设置,发送者有设置. 用来回答 501 而不是假装送来的.
  • describeEmailConfig() ——哪个提供者,其设置中哪个是 缺少, 加上发送者及其域名, 不包括任何证书 .
  • checkEmailCredentials() ——询问提供者是否具有 已接受 没有发送任何信息。没有探测器答案的提供者 unknown。Resend的探测器 GETs 域集和 读取错误 NAME 而不是状态。 A 类 2xx,或一个 restricted_api_key编号 :invalid_permission 拒绝( 发送范围) 密钥获得,并且只有在Resend认证了密钥后才能到达, 是指证书的作品. missing_api_key, (中文(简体) ), validation_error 财务报告和审定财务报表 suspended_api_key 意思是被拒绝了 还有什么是 unknown永远 invalid-key。它从不触及发送端点:瞄准它的探测器 由Resend 登录为 a 422 打开 POST /emails 并在仪表板上宣读, 作为失败的邮件。 它无法确认域验证—— 只有真正的发送 这样做.

这些只有工作人员才能拿回来 /api/admin/email-health 运行在控制台.

运行单元测试

运行 nx test shared-util-email 通过 欢乐。 。 。 .

注意: 倾向于裸体 jest 结束 nx test 当测试取决于env vars—— nx 输入根 .env,这可以让真正的失败 测试绿色.

许可证

阿帕奇2.0 (英语). 资料来源: https://github.com/aglyn/aglyn/tree/main/libs/shared/util/email 互联网档案馆的存檔,存档日期2013-12-02

版本与发布记录

@aglyn/shared-util-email 共发布 159 个版本,首次发布于 2026/09/21;过去 12 个月发布了 159 个版本。最新版本附带 npm provenance 构建来源证明,可追溯到公开的 CI 构建记录。

版本发布日期距今
1.18.0latest2026/11/07今天
1.17.02026/11/07今天
1.16.02026/11/07今天
1.15.22026/11/061 天前
1.15.12026/11/061 天前
1.15.02026/11/061 天前

其他发布通道:beta → 1.0.0-beta.296。

关于 @aglyn/shared-util-email 的常见问题

@aglyn/shared-util-email 是什么?

从Aglyn monorepo出版到npm. 随后的版本 语义版本。 。 。 .

如何安装 @aglyn/shared-util-email?

在项目目录运行 npm install @aglyn/shared-util-email,或使用 pnpm add / yarn add / bun add。

@aglyn/shared-util-email 支持 TypeScript 吗?

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

@aglyn/shared-util-email 支持 ESM 还是 CommonJS?

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

@aglyn/shared-util-email 可以商用吗?

@aglyn/shared-util-email 使用 Apache-2.0 许可。宽松许可:允许商业使用、修改和再分发,并附带明确的专利授权;分发时需保留许可与 NOTICE 文件,修改过的文件要注明改动。以上为概括,不构成法律意见,请以许可原文为准。

@aglyn/shared-util-email 的下载量有多少?

根据 npm 官方下载统计,@aglyn/shared-util-email 在 2026/10/05 – 2026/11/03 这 30 天内被下载 17,325 次,日均约 578 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@aglyn/shared-util-email 还在维护吗?

最新版本 1.18.0 发布于 2026/11/07(今天);至今共发布 159 个版本,其中过去 12 个月发布了 159 个;首次发布于 2026/09/21。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。