OneUptime 传入电子邮件监控器(Incoming Email Monitor)实战指南:用邮件驱动告警创建与解除
【免费下载链接】oneuptimeComplete open-source monitoring and observability platform.项目地址: https://gitcode.com/GitHub_Trending/on/oneuptime
OneUptime 的Incoming Email Monitor(传入电子邮件监控器)允许你为每个监控器生成一个专属的接收邮箱地址,任何发往该地址的邮件都会被解析,并按你配置的判定条件自动创建或解除告警。本文将系统讲解其工作原理、创建步骤、六类可用过滤字段与全部过滤条件、五种典型配置场景、模板变量、自托管时的 SendGrid 收件链路与环境变量配置,并结合仓库源码剖析底层判定逻辑,帮助你快速把基于邮件的第三方告警体系接入 OneUptime 的事件管理流程。
工作原理:邮件如何变成告警
传入电子邮件监控器的工作流程只有三步,核心思想是"以邮件为信令(signal)":
- 生成专属地址:当你创建 Incoming Email Monitor 时,OneUptime 会为该监控器生成一个独一无二的接收邮箱地址;
- 解析与判定:任何发往该地址的邮件都会被接收,并与你配置的 Alert Creation Criteria(告警创建条件)和 Alert Resolution Criteria(告警解除条件)逐一比对;
- 自动处置:根据判定结果,OneUptime 创建新告警,或解除当前处于激活状态的既有告警。
这是把旧式邮件告警体系接入 OneUptime 事件管理工作流的强力桥梁——尤其适合那些没有现代 API、只能发邮件的遗留系统。
从源码看,邮件的解析与判定是异步进行的。服务端在收到 webhook 后,将邮件结构化封装为IncomingEmailMonitorRequest(定义见 Common/Types/Monitor/IncomingEmailMonitor/IncomingEmailMonitorRequest.ts),其中携带emailFrom、emailTo、emailSubject、emailBody、emailBodyHtml、emailHeaders、emailReceivedAt、checkedAt、attachments等字段;随后 MonitorCriteriaEvaluator.ts 在监控器类型为MonitorType.IncomingEmail时,把该请求交给IncomingEmailCriteria.isMonitorInstanceCriteriaFilterMet()逐条评估用户配置的过滤条件(详见下文"过滤条件"一节)。
创建传入电子邮件监控器
在 OneUptime 仪表盘(Dashboard)中按以下步骤创建:
- 进入Monitors(监控器)页面;
- 点击Create Monitor(创建监控器);
- 监控器类型选择Incoming Email(传入电子邮件);
- 配置监控器基本信息:
- Name(名称):给监控器起一个描述性名称;
- Description(描述):说明该监控器的用途;
- 配置Alert Creation Criteria(告警创建条件)——满足哪些条件时创建告警;
- 配置Alert Resolution Criteria(告警解除条件)——满足哪些条件时解除告警;
- 点击Create(创建)。
创建完成后,该监控器的专属邮箱地址会显示在监控器详情页中,你可以直接复制,并配置到外部系统中,让它们向该地址发送邮件。
地址格式
每个传入电子邮件监控器都会获得一个符合如下格式的专属地址:
monitor-{secret-key}@{inbound-domain}例如:monitor-abc123def456@inbound.yourdomain.com
地址中的monitor-前缀、{secret-key}密钥段与@{inbound-domain}入站域名结构,在 SendGridInboundProvider.ts 中有精确的源码实现:extractSecretKeyFromEmail()使用正则^monitor-([a-zA-Z0-9-]+)@...(不区分大小写)从To地址中提取密钥,generateMonitorEmailAddress(secretKey)则用monitor-${secretKey}@${inboundDomain}拼回完整地址。密钥本质上是一个随机对象 ID(UUID 形态字符串),具体形如monitor-{uuid}@inbound.example.com。该地址本身即身份凭据:仓库中的密钥脱敏逻辑(MonitorPayloadRedaction.ts)专门对monitor-{secretKey}@{inboundDomain}形态的地址进行扫描遮蔽,防止密钥落入日志等出口管道,这也再次印证了地址必须像密码一样保密。
创建后开箱即得的默认条件
新建的传入电子邮件监控器会自带两个读取邮件正文(Email Body)的默认判定条件:
| 条件 | 过滤类型 | 过滤条件 | 值 | 作用 |
|---|---|---|---|---|
| Offline(离线) | Email Body | Contains(包含) | error | 将监控器标记为离线,并打开一个告警事件 |
| Online(在线) | Email Body | Not Contains(不包含) | error | 将监控器标记为在线 |
这套默认配置覆盖了最常见的场景:某个任务或第三方工具会把执行结果通过邮件发送出来——正文包含error的邮件让监控器变红(触发告警),下一条不含error的邮件又让监控器恢复绿色(解除告警)。所有字符串匹配均不区分大小写,因此Error、ERROR都会命中。
你可以把默认值改成发送方真正会写的文案,例如FAILED、exit code 1等。
需要注意的是:这些默认条件不是"静默检测(dead man switch)"——只有当邮件真正送达时,读取主题、发件人、正文或收件人的条件才会被评估,其余时间什么都不会触发。如果想对"邮件长时间未到"发出告警,需要额外添加Email Received/Not Received In Minutes类型的条件(见下文示例三)。
六种可用的过滤字段(Filter Types)
你可以基于邮件的以下六个字段维度来构建判定条件:
| 过滤类型 | 说明 |
|---|---|
| Email Subject | 入站邮件的主题行 |
| Email From | 发件人邮箱地址 |
| Email Body | 邮件的纯文本正文内容 |
| Email To | 收件人邮箱地址 |
| Email Received | 基于时间的条件,用于判断邮件接收时间 |
| JavaScript Expression | 一段必须求值为 true 的自定义 JavaScript 表达式 |
在 CriteriaFilter.ts 的CheckOn枚举中,对应值为EmailSubject = "Email Subject"、EmailFrom = "Email From Address"、EmailBody = "Email Body"、EmailTo = "Email To Address"、EmailReceivedAt = "Email Received",与界面展示名称完全一致。
邮件正文只用纯文本
正文匹配基于邮件的纯文本版本,HTML 格式会被剥离。对应源码中,SendGrid 解析器取 webhook 表单里的text字段作为正文(SendGridInboundProvider.ts),html字段仅作为bodyHtml附加信息保留在请求结构中。因此配置正文匹配时,应以纯文本内容为准。
过滤条件(Filter Conditions)详解
不同过滤类型支持不同的条件运算。下面按类别完整列出。
字符串类条件(主题、发件人、正文、收件人)
| 过滤条件 | 说明 | 示例 |
|---|---|---|
| Contains | 字段包含指定文本 | 主题包含 "CRITICAL" |
| Not Contains | 字段不包含指定文本 | 主题不含 "TEST" |
| Equals | 字段与指定文本完全相等 | 发件人等于 "alerts@service.com" |
| Not Equals | 字段与指定文本不相等 | 主题不等于 "OK" |
| Starts With | 字段以指定文本开头 | 主题以 "[ALERT]" 开头 |
| Ends With | 字段以指定文本结尾 | 主题以 "- Production" 结尾 |
| Is Empty | 字段为空或全为空白 | 正文为空 |
| Is Not Empty | 字段有内容 | 主题非空 |
这些字符串条件的底层实现在 IncomingEmailCriteria.ts 的evaluateStringCriteria()方法中。关键实现事实:
- 大小写不敏感:所有比较都先做
toLowerCase()再执行includes/===/startsWith/endsWith,与文档声明一致; - 空值处理:
IsEmpty判断!fieldValue || fieldValue.trim() === "",即空白字符串也视为空; - 返回值即判定理由:每条条件命中后返回类似
Email subject contains "CRITICAL".的人类可读字符串,这些文本会进入评估摘要(evaluation summary),供你在监控器详情中回看"这条告警为什么被触发"。
时间类条件(Email Received)
| 过滤条件 | 说明 | 示例 |
|---|---|---|
| Received In Minutes | 邮件在 X 分钟内被收到 | 邮件在 30 分钟内被收到 |
| Not Received In Minutes | X 分钟内没有收到任何邮件 | 60 分钟内未收到邮件 |
对应源码枚举值为RecievedInMinutes = "Recieved In Minutes"与NotRecievedInMinutes = "Not Recieved In Minutes"(见 CriteriaFilter.ts)。判定逻辑在 IncomingEmailCriteria.ts:
- 计算
emailReceivedAt(最近一封邮件的接收时间)与checkedAt(或当前时间)的分钟差differenceInMinutes; RecievedInMinutes:当differenceInMinutes <= value时命中,返回Email received in X minutes. It was received N minutes ago.;NotRecievedInMinutes:当differenceInMinutes > value时命中,返回Email not received in X minutes. It was received N minutes ago.;- 配置值会被
parseInt解析为数字,解析失败则视为不命中。
JavaScript 表达式条件
| 过滤条件 | 说明 |
|---|---|
| Evaluates To True | 表达式求值返回真值(truthy) |
需要特别注意:表达式运行在隔离环境(isolated environment)中,邮件字段不会被注入为变量,因此表达式无法读取触发评估的那封邮件的主题、发件人、正文或收件人。要基于邮件内容做匹配,请使用Email Subject、Email From、Email Body、Email To四类字段型条件。
典型配置示例
示例一:根据关键邮件的主题创建与解除告警
告警创建条件:
- Email SubjectContains"CRITICAL"
- 或 Email SubjectContains"ALERT"
- 或 Email SubjectContains"ERROR"
告警解除条件:
- Email SubjectContains"RESOLVED"
- 或 Email SubjectContains"OK"
- 或 Email SubjectContains"RECOVERED"
同一条件组内的多个子条件默认按"或"(OR)组合,任一命中即触发;跨组(创建组与解除组)则是相互独立的评估逻辑。
示例二:盯住指定发件人
告警创建条件:
- Email FromEquals"monitoring@legacy-system.com"
- 且(AND)Email SubjectContains"Failed"
告警解除条件:
- Email FromEquals"monitoring@legacy-system.com"
- 且(AND)Email SubjectContains"Success"
当需要在同一条件组内实现"并且"(AND)语义时,将多个子条件加入同一组即可。
示例三:心跳监控(没有邮件 = 告警)
告警创建条件:
- Email ReceivedNot Received In Minutes,值为
60
如果 60 分钟内没有收到任何邮件,就触发告警——非常适合监控必须按时发送完成邮件的定时任务(cron job)或批处理流程。
告警解除条件:
- Email ReceivedReceived In Minutes,值为
5
只要收到一封邮件,就立即解除告警。注意Received In Minutes判定的是"最近一封邮件的接收时间距现在是否在阈值分钟之内"(differenceInMinutes <= value),因此一旦新邮件到达,该条件即满足。
典型应用场景
集成遗留系统
很多老系统只支持邮件告警。利用 Incoming Email Monitor 可以:
- 把邮件告警转化为 OneUptime 告警事件;
- 收到"恢复"邮件时自动解除事件;
- 集中管理多个遗留系统的告警流。
监控第三方服务
接入一切能发通知邮件的服务:
- 云厂商告警(AWS、GCP、Azure 的通知邮件);
- 安全扫描工具;
- 备份完成通知;
- SSL 证书到期告警。
监控定时任务
- 完成邮件未按时到达即触发告警;
- 通过错误通知邮件追踪任务失败;
- 监控数据管道的完成状态。
多供应商告警聚合
- 通过邮件接入 Nagios、Zabbix 等工具的告警;
- 在 OneUptime 中统一事件管理流程;
- 让所有告警拥有单一事实来源(single source of truth)。
事件模板变量
配置告警事件模板(Incident Templates)时,可以直接引用以下从入站邮件中提取的变量:
| 变量 | 说明 |
|---|---|
{{emailSubject}} | 收到的邮件主题 |
{{emailFrom}} | 发件人邮箱地址 |
{{emailTo}} | 收件人邮箱地址 |
{{emailBody}} | 邮件的纯文本正文 |
{{emailReceivedAt}} | 邮件接收时间 |
这些变量与请求结构IncomingEmailMonitorRequest的字段一一对应(emailSubject、emailFrom、emailTo、emailBody、emailReceivedAt),使事件描述可以自动带上触发邮件的完整上下文。
监控器摘要视图(Monitor Summary)
创建监控器后,其摘要页面会展示最近一封入站邮件的关键信息:
- Last Email Received At:最近一封邮件的接收时间;
- From:最近一封邮件的发件人;
- Subject:最近一封邮件的主题行;
- Email Headers:最近一封邮件的完整邮件头(可展开查看);
- Email Body:最近一封邮件的正文内容(可展开查看)。
这些信息对排查"邮件是否送达、条件为何未命中"非常有用——也对应源码中emailHeaders与emailBody等字段被完整保留在请求结构中的设计。
自托管配置:接入 SendGrid Inbound Parse
如果你在自托管 OneUptime,必须配置入站邮件提供商(Inbound Email Provider)。当前仓库支持SendGrid Inbound Parse,完整英文版配置指南见 SendGrid Inbound Email Integration。
网络访问要点
SendGrid Inbound Parse 需要主动发起连接到你的 OneUptime 实例,因此只允许 OneUptime 出网是不够的。关键通路如下:
| 方向 | 目标 | 协议/端口 | 用途 |
|---|---|---|---|
| SendGrid → OneUptime | https://your-oneuptime-domain.com/incoming-email/sendgrid/YOUR_SECRET | HTTPS / TCP 443 | 以 multipart POST 形式投递解析后的邮件 |
| 发件服务器 → SendGrid | mx.sendgrid.net(由入站域名的公共 MX 记录决定) | SMTP / TCP 25 | 在 SendGrid 侧接收邮件,不直连你的 OneUptime |
| OneUptime → SendGrid | api.sendgrid.com(仅当另行配置 SendGrid 作为发件服务时) | HTTPS / TCP 443 | 通过 Mail Send API 发送通知邮件 |
Webhook 主机名需有公共 DNS 与受信证书;私有化部署可通过公共反向代理仅暴露该 webhook 路径,但要保留路径、密钥、Content-Type 与 multipart 请求体,且不能有交互式登录或浏览器验证挑战。OneUptime 服务器本身不需要监听 SMTP 端口。
配置步骤摘要
选择入站域名:推荐使用专用子域名,如
inbound.yourdomain.com、email.yourdomain.com、monitor.yourdomain.com;配置 DNS MX 记录:
类型 主机/名称 优先级 值 MX inbound 10 mx.sendgrid.net 即
inbound.example.com. IN MX 10 mx.sendgrid.net.。DNS 变更最长可能需要 48 小时生效,通常几小时内完成;在 SendGrid 中认证该域名(Settings > Sender Authentication > Authenticate Your Domain,并按提示添加 DKIM 的 CNAME 记录);
配置 Inbound Parse(Settings > Inbound Parse > Add Host & URL):
字段 值 Receiving Domain 你的入站子域名(如 inbound.yourdomain.com)Destination URL https://your-oneuptime-domain.com/incoming-email/sendgrid/YOUR_SECRETCheck incoming emails for spam 可选,按需开启 Send raw, full MIME message 不勾选(无需) POST the raw, full MIME message 不勾选(无需) 配置 OneUptime 环境变量(见下节);
创建 Incoming Email Monitor(步骤见上文"创建"一节);
端到端测试:从仪表盘复制监控器地址,发送一封主题命中创建条件的测试邮件,然后在监控器摘要页确认邮件已收到、告警已创建。
环境变量参考
源码层面,入站邮件相关配置集中定义在 EnvironmentConfig.ts,由 InboundEmailProviderFactory.ts 读取并实例化对应提供商:
| 变量 | 说明 | 是否必填 | 默认值 |
|---|---|---|---|
INBOUND_EMAIL_PROVIDER | 入站邮件提供商,当前仅支持SendGrid | 是 | SendGrid |
INBOUND_EMAIL_DOMAIN | 配置的入站子域名 | 是 | 无 |
INBOUND_EMAIL_WEBHOOK_SECRET | 与 webhook URL 最后一段比较:/incoming-email/sendgrid/YOUR_SECRET;公网端点建议配置,置空则跳过校验 | 推荐 | 无 |
Docker Compose 部署时,在config.env中加入:
# Inbound Email Configuration INBOUND_EMAIL_PROVIDER=SendGrid INBOUND_EMAIL_DOMAIN=inbound.yourdomain.com INBOUND_EMAIL_WEBHOOK_SECRET=replace-with-a-strong-random-secretKubernetes(Helm)部署时,在values.yaml中加入:
inboundEmail: provider: "SendGrid" domain: "inbound.yourdomain.com" webhookSecret: "replace-with-a-strong-random-secret"INBOUND_EMAIL_WEBHOOK_SECRET必须与 Step 4 中 Destination URL 末尾的YOUR_SECRET保持一致;修改后需重启 OneUptime 服务。当配置了密钥时,SendGridInboundProvider.ts 的validateWebhook()会比较 URL 路径中的 secret 与配置值;未配置则放行所有请求(此时 webhook URL 本身即秘密)。另外,SendGrid Inbound Parse 默认不提供 webhook 签名,仓库当前也未校验其签名头或 OAuth token——若需要此类机制,应在转发给 OneUptime 之前由网关完成校验。
入站邮件解析的底层细节
SendGrid 会把邮件以multipart/form-data表单形式 POST 到 OneUptime,字段包括from、to、subject、text、html、headers、envelope、attachments、attachment-info等(见 SendGridInboundProvider.ts 的注释)。解析器据此提取出:
from/to:通过正则提取尖括号内的地址,兼容"Name <user@domain.com>"与<user@domain.com>等格式,并统一转小写、去除首尾空白;subject:原样保留;body:取text字段(纯文本);bodyHtml:取html字段;headers:按行拆分、以第一个冒号分隔成键值对象;attachments:解析附件的文件名、Content-Type 与大小。
这些字段最终成为IncomingEmailMonitorRequest,驱动后续的条件评估。
注意事项
- 邮箱地址安全:监控器邮箱地址内含机密密钥,请像对待密码一样对待它,不要公开分享;
- 邮件大小:过大(尤其带大附件)的邮件可能被邮件服务商截断或拒绝;
- 处理延迟:邮件是异步处理的,从发送邮件到告警创建之间可能存在数秒延迟;
- 大小写不敏感:所有字符串比较(Contains、Equals 等)均不区分大小写;
- 纯文本正文:正文条件只评估邮件的纯文本版本,HTML 格式会被忽略。
故障排查
收不到邮件
- 确认邮箱地址拼写正确(检查是否有笔误);
- 检查邮件是否被垃圾邮件过滤器拦截;
- 确认入站邮件提供商配置正确(参考上文的 DNS 与 Inbound Parse 校验,可用
dig MX inbound.yourdomain.com确认 MX 记录是否返回mx.sendgrid.net); - 查看 OneUptime 日志中是否有错误信息(关注 webhook 请求是否到达、Telemetry / ProbeIngest 相关日志)。
告警未被创建
- 确认你的条件与邮件内容相匹配;
- 检查监控器是否处于禁用状态;
- 在监控器详情中回看评估日志(evaluation logs)与摘要,确认邮件是否收到、每条条件是否命中;
- 先用精确字符串匹配做测试,再过渡到模式匹配。
告警未被解除
- 确认解除条件与恢复邮件内容相匹配;
- 确保确实存在一个处于激活状态的告警可以被解除;
- 确认恢复邮件发送到了同一个监控器地址(地址错误则无法触发评估)。
结语
Incoming Email Monitor 是 OneUptime 把"邮件即信令"落地的功能:通过monitor-{secret-key}@{inbound-domain}专属地址与完整的字符串、时间、表达式判定体系,它能把遗留系统、第三方服务、定时任务乃至多供应商告警全部收敛进 OneUptime 的事件管理流程。自托管场景下,配合 SendGrid Inbound Parse 与INBOUND_EMAIL_*环境变量即可在数小时内完成端到端接通;而源码中对大小写不敏感匹配、纯文本正文、时间差判定与密钥脱敏的严谨处理,则为这条链路提供了可验证的可靠性保障。想要深入源码的读者,可以从 IncomingEmailCriteria.ts 与 SendGridInboundProvider.ts 两个文件开始。
【免费下载链接】oneuptimeComplete open-source monitoring and observability platform.项目地址: https://gitcode.com/GitHub_Trending/on/oneuptime
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考