@flink-app/inbound-email-plugin

中文文档
2.0.0-alpha.134发布于 2026/11/07MITTypeScriptCommonJS近 30 天下载 2178

SMTP 输入电子邮件的 Flink 插件, 带有自动发现的 EmailHandler 文件

中文使用文档
文档目录16 节
  1. 安装
  2. 设置
  3. 1. 注册编译器插件
  4. 2. 添加运行时间插件
  5. 3. 创建电子邮件处理器
  6. 路线
  7. SPF/DKIM核查
  8. 信件标识
  9. 页眉
  10. 插件选项
  11. 请求背景
  12. CLI——试验交付
  13. 方案交付
  14. 1. 增加上下文类型
  15. 2. 有ctx接入的任何地方的呼叫发送
  16. 自定义扫描目录

@flink-app/ inbound-email-plugin (英语)

为 Flink 应用程序输入 SMTP 电子邮件 。 启动 SMTP 服务器和自动发现 EmailHandler 文件在 src/inbound-email-handlers/,将每个发送的邮件传送到第一个匹配的处理器.

安装

pnpm add @flink-app/inbound-email-plugin

设置

1. 注册编译器插件

// flink.config.js
const { compilerPlugin } = require("@flink-app/inbound-email-plugin/compiler");

module.exports = {
  compilerPlugins: [compilerPlugin()],
};

2. 添加运行时间插件

// src/index.ts
import { inboundEmailPlugin } from "@flink-app/inbound-email-plugin";

new FlinkApp<Ctx>({
  // ...
  plugins: [
    inboundEmailPlugin({
      port: 2525,
      allowedDomains: ["myapp.com"],
      resolveUser: async (email, ctx) =>
        ctx.repos.userRepo.getOne({ email: email.from }),
      resolvePermissions: async (user, ctx) =>
        ctx.repos.permRepo.getForUser(user.id),
      onUnhandled: async (email) =>
        console.warn("No handler matched", email.from),
    }),
  ],
});

3. 创建电子邮件处理器

// src/inbound-email-handlers/HandleSupportEmail.ts
import { EmailHandler, EmailRouteProps } from "@flink-app/inbound-email-plugin";
import { Ctx } from "../Ctx";

export const Route: EmailRouteProps = {
  from: /.*@customers\.com/,
};

const handler: EmailHandler<Ctx> = async ({ ctx, email, user }) => {
  await ctx.repos.ticketRepo.create({
    subject: email.subject,
    body: email.text,
    from: email.from,
    userId: user?.id,
  });
};

export default handler;

路线

EmailRouteProps 字段都是可选的 —— 省略任何匹配所有 :

外地类型匹配时
fromstring | RegExp | (email) => boolean发送地址( 信头) From:(中文(简体) )
tostring | RegExp任何收件人地址
subjectstring | RegExp主题行

to 与 SMTP 信封接收者匹配(RCPT TO,其中包含BCC,并反映实际交付目标. 标题 To: 对路由不可靠,因为BCC,邮件列表,以及转发收件人不在其内. 用于方案 deliver() 不提供电话 envelopeTo火柴倒回头顶 to。 。 。 .

每一个处理者 Route 以发现顺序引用匹配 .

SPF/DKIM核查

过 verify: true 既允许默认检查,也允许精确控制的对象:

inboundEmailPlugin({
  verify: {
    spf: true,           // default: true
    dkim: true,          // default: true
    rejectOnFail: true,  // bounce with SMTP 550 on failure — default: false
    mta: "mx.myapp.com", // your MTA hostname for SPF — default: os.hostname()
  },
})

何时 rejectOnFail 假的(默认的),结果将传递给每个处理器,作为 auth 和您的代码决定怎么做:

const handler: EmailHandler<Ctx> = async ({ email, auth }) => {
  if (!auth?.passed) {
    console.warn("Unauthenticated email from", email.from);
    return;
  }
  // ...
};

auth.passed 实值 true 仅在每次启用的检查返回时 "pass". 各项结果可在 auth.spf.result 财务报告和审定财务报表 auth.dkim.result (有签名细节) auth.dkim.signatures) (中文(简体) ).

核查工作由 邮件 并懒惰地装入,所以启动时间不会在 verify 未配置.

信件标识

InboundEmail 曝光两个消息ID:

  • messageId —— 说 总是在场. 镜像发送者的 SMTP Message-ID 在提供时,否则即为中继生成的UUID. 用这个做你的独能钥匙.
  • smtpMessageId —— 说 选项. 最初的SMTP Message-ID 头(取出角括号). 用于 In-Reply-To 编号 : References 关联,发件人-侧去dupe,或交叉引用发件人的日志. 发件人控制——不要作为信任边界.

页眉

email.headers 是一个 Record<string, string[]> 以小写头名键入。 值为 RFC822 逐字记录后文本 <key>: 前缀( 已修剪的白空间) 。 A 类 string[] 被使用,因为真实信件中包含重复头- Received: 例如,每一次中继跳出一次,除一人外,丢掉所有信息就会丢失.

email.headers["from"];        // ['"Alice" <[email protected]>']
email.headers["received"];    // ['from mx1...', 'from mx2...', ...]
email.headers["dkim-signature"]; // raw `v=1; a=rsa-sha256; d=...; b=...`

插件选项

选项类型默认说明
portnumber2525SMTP 监听端口
allowedDomainsstring[]—— 说拒绝邮件到其他域
maxMessageSizenumber10MB以字节表示的最大消息大小
tls{ key, cert }—— 说TLS 的 PEM 文件路径
verifyboolean | VerifyOptions—— 说SPF/DKIM核查(见上文)
resolveUser(email, ctx) => Promise<any>—— 说查找发送用户
resolvePermissions(user, ctx) => Promise<string[]>—— 说为用户装入权限
onUnhandled(email, ctx) => Promise<void>—— 说没有处理器匹配时调用

请求背景

何时 resolveUser 财务报告和审定财务报表 resolvePermissions 配置,用户和权限可以通过标准的Flink帮助在内部处理器中获取:

import { getRequestUser, getRequestPermissions } from "@flink-app/flink";

const handler: EmailHandler<Ctx> = async ({ ctx, email }) => {
  const user = getRequestUser(); // same as the `user` arg
  const perms = getRequestPermissions();
};

这意味着从处理器内部调用的Flink工具和代理也自动接收正确的用户上下文.

CLI——试验交付

送来生的 .eml 文件到正在运行的本地 SMTP 服务器而不需要外部工具 swaks数字 :

# Built-in samples — quickest way to verify your handler is working
npx flink-email deliver --sample plain
npx flink-email deliver --sample attachment

# Your own .eml file
npx flink-email deliver ./my-email.eml

# Override port or envelope addresses
npx flink-email deliver --sample plain --port 2525 --from [email protected] --to [email protected]

# Pipe from stdin (e.g. paste from Gmail "Show original")
pbpaste | npx flink-email deliver -

该工具会说真正的 SMTP —— 页眉被解析 From编号 :To 信封地址自动, 并且 SPF/ DKIM 检查 运行在原始字节上 完全如实 从真正的中继.

方案交付

插件曝光一个 deliver 用于从应用代码中发送电子邮件的上下文方法 – 用于从webhooks,队列消费者或其他插件中转发。 它运行的管道与真正的SMTP送出(用户分辨率,路由匹配,requestContext)相同,但跳过SPF/DKIM验证,因为没有原始的SMTP信封.

1. 增加上下文类型

// src/Ctx.ts
import { FlinkContext } from "@flink-app/flink";
import { InboundEmailPluginContext } from "@flink-app/inbound-email-plugin";

export interface Ctx extends FlinkContext<InboundEmailPluginContext> {
  repos: { /* ... */ };
}

2. 有ctx接入的任何地方的呼叫发送

import { InboundEmail } from "@flink-app/inbound-email-plugin";

const email: InboundEmail = {
  from: "[email protected]",
  to: ["[email protected]"],
  // envelopeFrom / envelopeTo are optional — supply them to mirror the
  // SMTP envelope (incl. BCC) so route `to` matchers behave the same as
  // for real SMTP deliveries.
  subject: "Forwarded from webhook",
  messageId: "abc-123",
  text: "Hello from a webhook",
  attachments: [],
  headers: {},
  receivedAt: new Date(),
};

const { handled } = await ctx.plugins.inboundEmailPlugin.deliver(email);

if (!handled) {
  console.warn("No handler matched the programmatic email");
}

返回值 { handled: boolean } 表示是否至少一个 EmailHandler 匹配电子邮件。 如果没有处理器匹配和 onUnhandled 在插件上被配置,它将被自动调用——与SMTP发送的电子邮件相同.

自定义扫描目录

// flink.config.js
compilerPlugins: [compilerPlugin({ scanDir: "src/mail-handlers" })]

版本与发布记录

@flink-app/inbound-email-plugin 共发布 76 个版本,首次发布于 2026/03/01;过去 12 个月发布了 76 个版本。

版本发布日期距今
2.0.0-alpha.134latest2026/11/078 天前
2.0.0-alpha.1332026/11/069 天前
2.0.0-alpha.1322026/11/0510 天前
2.0.0-alpha.1312026/10/2818 天前
2.0.0-alpha.1302026/10/2521 天前
2.0.0-alpha.1292026/10/2521 天前

关于 @flink-app/inbound-email-plugin 的常见问题

@flink-app/inbound-email-plugin 是什么?

SMTP 输入电子邮件的 Flink 插件, 带有自动发现的 EmailHandler 文件

如何安装 @flink-app/inbound-email-plugin?

在项目目录运行 npm install @flink-app/inbound-email-plugin,或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖:@flink-app/flink(>=2.0.0-alpha.134)。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖,Yarn 需要手动安装。它还提供命令行工具 flink-email,可以用 npx flink-email 直接运行。

@flink-app/inbound-email-plugin 支持 TypeScript 吗?

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

@flink-app/inbound-email-plugin 支持 ESM 还是 CommonJS?

以 CommonJS 形式发布,可以直接 require();在 ES Module 项目中也可以用 import 引入(Node.js 会把 module.exports 作为默认导出)。

@flink-app/inbound-email-plugin 可以商用吗?

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

@flink-app/inbound-email-plugin 的下载量有多少?

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

@flink-app/inbound-email-plugin 还在维护吗?

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