@civitas-cerebrum/电子邮件客户端
一个高度稳健,零依赖的SMTP/IMAP电子邮件客户端专门为E2E测试自动化而建. 使用可相容的、决定性的过滤器发送、接收、搜索、管理和清理电子邮件.
为什么是这个客户?
- 零播放机运行时间依赖 ——与"Playwright","Cypress","Vitest","Jest"或任何节点测试跑取者无缝合作.
- 智能投票引擎 ——内置重试逻辑防止了由于电子邮件发送缓慢而导致的片面测试.
- 内存保护 ——自动封盖原始的MIME取取来来防止Node.js内存在打出大型,未管理的测试收件箱时出事.
- 两相匹配 ——首先评价准确的IMAP标准,然后回到智能的,对案例不敏感的客户端匹配,以捕捉格式不完善的自动电子邮件.
- 完整邮箱管理 ——发送,接收,旗帜,存档,并大力清理你的测试环境.
安装
npm install @civitas-cerebrum/email-client
快速启动
只发送( SMTP)
import { EmailClient } from '@civitas-cerebrum/email-client';
const client = new EmailClient({
smtp: {
email: '[email protected]',
password: 'app-password',
host: 'smtp.example.com',
},
});
await client.send({
to: '[email protected]',
subject: 'Your OTP Code',
text: 'Your code is 123456',
});
仅接收( IMAP)
import { EmailClient, EmailFilterType } from '@civitas-cerebrum/email-client';
const client = new EmailClient({
imap: {
email: '[email protected]',
password: 'app-password',
},
});
const email = await client.receive({
filters: [{ type: EmailFilterType.SUBJECT, value: 'Your OTP Code' }],
});
console.log(email.text);
完全客户端( 发送+接收)
SMTP和IMAP证书是独立的——它们可以指向不同的提供者或账户. 例如,通过交易中继发送并从Gmail接收:
import { EmailClient, EmailFilterType, EmailMarkAction } from '@civitas-cerebrum/email-client';
const client = new EmailClient({
smtp: {
email: '[email protected]',
password: 'app-password',
host: 'smtp.example.com',
},
imap: {
email: '[email protected]',
password: 'app-password',
},
});
await client.send({ to: '[email protected]', subject: 'OTP', text: '123456' });
const email = await client.receive({
filters: [{ type: EmailFilterType.SUBJECT, value: 'OTP' }],
});
await client.mark({
action: EmailMarkAction.READ,
filters: [{ type: EmailFilterType.SUBJECT, value: 'OTP' }],
});
await client.clean({
filters: [{ type: EmailFilterType.SUBJECT, value: 'OTP' }],
});
API 参考
初始化
构造器 : new EmailClient({ smtp?, imap? }) 或者说 new EmailClient(legacyCredentials)
证书 (需为 send():
| 外地 | 类型 | 默认 | 说明 |
|---|---|---|---|
email | string | —— 说 | SMTP 发送电子邮件地址 |
password | string | —— 说 | SMTP 发送密码或应用程序密码 |
host | string | —— 说 | SMTP主机(例如, 'smtp.gmail.com'(中文(简体) ) |
port | number | 587 | SMTP 端口 |
图像证书 (需为 receive(), (中文(简体) ), receiveAll(), (中文(简体) ), clean(), (中文(简体) ), mark():
| 外地 | 类型 | 默认 | 说明 |
|---|---|---|---|
email | string | —— 说 | IMAP 电子邮件地址 |
password | string | —— 说 | IMAP 密码或应用程序密码 |
host | string | 'imap.gmail.com' | IMAP 主机 |
port | number | 993 | IMAP 端口 |
遗留格式
旧公寓 EmailCredentials 界面仍然被支持用于向后兼容。 鼓励向新的分裂模式过渡.
// Legacy format (still supported)
const client = new EmailClient({
senderEmail: '[email protected]',
senderPassword: 'app-password',
senderSmtpHost: 'smtp.example.com',
receiverEmail: '[email protected]',
receiverPassword: 'app-password',
});
发送电子邮件send(中文(简体) )
支持纯文本,内置HTML,并直接从磁盘上加载HTML文件.
// Plain text
await client.send({ to: '[email protected]', subject: 'Test', text: 'Hello' });
// Inline HTML
await client.send({ to: '[email protected]', subject: 'Report', html: '<h1>Results</h1>' });
// HTML template from disk
await client.send({ to: '[email protected]', subject: 'Report', htmlFile: 'emails/template.html' });
接收电子邮件receive 编号 : receiveAll(中文(简体) )
客户使用强有力的投票机制。 它会不断查询 IMAP 服务器直到 waitTimeout 到达或过滤器满足。 组合多个过滤器以创建严格的 AND 逻辑制约. 当多个邮件匹配时, receive() 返回最新的日期.
// Get the single most recent matching email
const email = await client.receive({
filters: [{ type: EmailFilterType.SUBJECT, value: 'Your OTP' }],
waitTimeout: 15000 // Optional: fail if not found in 15s
});
// Get ALL matching emails in the inbox (useful for batch processing)
const allEmails = await client.receiveAll({
filters: [
{ type: EmailFilterType.FROM, value: '[email protected]' },
{ type: EmailFilterType.SINCE, value: new Date('2025-01-01') },
],
});
接收选项
| 选项 | 类型 | 默认 | 说明 |
|---|---|---|---|
filters | EmailFilter[] | —— 说 | 要求. 过滤器阵列( AND 逻辑) |
folder | string | 'INBOX' | 要搜索的IMAP文件夹 。 接受文字路径或文字路径 specialUse 角色(例如:. '\\Sent', (中文(简体) ), '\\Trash'(中文(简体) ) |
folders | string[] | —— 说 | 数个文件夹同时搜索 。 胜过 folder。见 正在搜索多个文件夹 |
waitTimeout | number | 30000 | 投出错误前, 最多为毫秒 |
pollInterval | number | 3000 | 在 IMAP 之间等待尝试的毫秒 |
expectedCount | number | 1 | 返回前需要匹配的邮件数量 |
downloadDir | string | os.tmpdir() | 要保存的目录 .html 副本 |
maxFetchLimit | number | 50 | 每个投票周期获取的电子邮件最多(邮件保护) |
正在搜索多个文件夹
信息并不总是到达你期望的地方。 来自新邮件或 低信誉发送域通常由接收者作为垃圾邮件存档 服务器,而仅通过收件箱搜索无法找到垃圾邮件文件信件 不论你等了多久.
过 folders 在一个电话中搜索几个邮箱。 每个文件夹都被搜索
在每一个投票周期, 和比赛集合, 所以等待一结束
消息在设定的任何地方出现 :
const email = await client.receive({
filters: [{ type: EmailFilterType.SUBJECT, value: 'Your verification code' }],
folders: ['INBOX', '[Gmail]/Spam'], // or ['INBOX', '\\Junk'] to stay portable
waitTimeout: 60000,
});
folders 由 receive, (中文(简体) ), receiveAll, (中文(简体) ), clean 财务报告和审定财务报表 mark,并带走
优先于 folder 当两者都给予。 对于 clean 财务报告和审定财务报表 mark 动作
每个文件夹依次应用,返回的计数为总数.
缺少文件夹 . 单个文件夹很严格——命名不存在的文件夹 丢出,列出服务器拥有的文件夹。 一个文件夹 列表 宽容: 一个缺席的文件夹被跳过,所以一个便携式集对缺少的服务器有用 其中一个 如果无法打开列出的文件夹, 调用仍会丢出 .
不达到
\All作为捷径. 所有邮件还包含发送, 存档和最近删除的复制件,所以在它之间搜索会不断发现 您已移动或删除信件。 指定您实际的文件夹 讨厌.
可用的过滤器( N)EmailFilterType(中文(简体) )
| 类型 | 数值类型 | 说明 |
|---|---|---|
SUBJECT | string | 电子邮件主题的精确或部分匹配 |
FROM | string | 发送者电子邮件地址 |
TO | string | 收件人电子邮件地址 |
CONTENT | string | 匹配 HTML 正文或纯文本倒置的任意位置 |
SINCE | Date | 只获取此时间戳后收到的邮件 |
管理收件箱( E)mark 编号 : clean(中文(简体) )
保持您的自动测试收件箱清洁,并组织起来,防止IMAP节奏和内存问题.
标记( 浮动和移动)
修改符合特定标准的电子邮件状态 。 返回受影响的电子邮件数量 .
// Apply standard flags
await client.mark({
action: EmailMarkAction.READ, // READ, UNREAD, FLAGGED, UNFLAGGED
filters: [{ type: EmailFilterType.SUBJECT, value: 'Welcome' }]
});
// Move emails to an archive folder (using specialUse role — works across all locales)
await client.mark({
action: EmailMarkAction.ARCHIVED,
filters: [{ type: EmailFilterType.FROM, value: '[email protected]' }],
archiveFolder: '\\Trash' // Resolves to the server's actual Trash path at runtime
});
// Apply custom IMAP flags
await client.mark({
action: ['\\Draft', '\\Answered'],
filters: [{ type: EmailFilterType.SUBJECT, value: 'Custom State' }]
});
清除( 删除)
永久删除服务器的邮件 .
// Delete specific emails
await client.clean({
filters: [{ type: EmailFilterType.FROM, value: '[email protected]' }],
});
// Delete across several folders in one call
await client.clean({
filters: [{ type: EmailFilterType.SUBJECT, value: 'my-test-run-42' }],
folders: ['INBOX', '[Gmail]/Spam'],
});
// Nuke an entire folder (Use with caution!)
await client.clean(); // every message in INBOX
await client.clean({ folder: 'scratch' }); // every message in "scratch"
分享邮箱?
clean()没有过滤器删除所有 目标文件夹,包括信息 。 如果不止一个 测试运行可以触摸同一个邮箱,将每个运行的独一无二的代号印入每个 主题您发送并总是通过过滤器选择它- 然后清理可以 只能删除自己的邮件。 为您的文件夹保留未过滤表单 运行创建和拥有.
文件夹分辨率
任意 folder 或者说 archiveFolder 选项 文字路径 (例如:. '[Gmail]/Trash'或一个 specialUse 角色 前缀为 \。客户端使用 IMAP 列表元数据在运行时将角色解析到正确的服务器路径,所以无论邮件服务器的语言或命名常规,您的代码都会起作用.
| 作用 | 说明 |
|---|---|
\All | 所有邮件 |
\Trash | 回收站/ 删除项目 |
\Sent | 发送邮件 |
\Drafts | 草稿 |
\Junk | 垃圾邮件 |
\Flagged | 星形/ 有标志 |
\Inbox | 收件箱 |
// These are equivalent on a Turkish Gmail account:
await client.clean({ folder: '[Gmail]/Çöp kutusu' }); // literal path
await client.clean({ folder: '\\Trash' }); // specialUse role (locale-independent)
这个 ReceivedEmail 对象
当您收到电子邮件时, 客户端会解析原始的 MIME 源头, 并返回一个干净, 强烈类型的对象 :
| 财产 | 类型 | 说明 |
|---|---|---|
subject | string | 电子邮件主题行 |
from | string | 发送地址 |
to | string | 收件人地址 |
date | Date | 电子邮件发送日期 |
html | string | 解析 HTML 正文( 如果仅是纯文本则为空字符串) |
text | string | 解析出纯文本内容 |
filePath | string | 下载的本地路径 .html 复制 |
处理错误
当缺少特定操作的证书时, 客户端会提供明确的错误消息 :
| 运行 | 证书缺失 | 错误消息 |
|---|---|---|
send() | SMTP 软件 | SMTP credentials are required to send emails. Provide { smtp: { email, password, host } } when constructing EmailClient. |
receive() 编号 : receiveAll() | IMAP 地图 | IMAP credentials are required to receive/manage emails. Provide { imap: { email, password } } when constructing EmailClient. |
clean() 编号 : mark() | IMAP 地图 | IMAP credentials are required to receive/manage emails. Provide { imap: { email, password } } when constructing EmailClient. |
捐款
git clone https://github.com/Umutayb/email-client.git
cd email-client
npm install
npm run test
许可证
麻省理工学院