尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
Zabbix告警收不到?用Python脚本实现稳定SMTP邮件告警配置指南
1. 方案背景为什么用Python脚本发邮件做运维监控的都知道Zabbix本身自带的邮件告警功能虽然能用但实际生产环境里痛点很多。官方自带的邮件媒介虽然简单但一遇到稍微复杂一点的场景就捉襟见肘——比如公司要求告警邮件正文带上自定义的格式、告警级别不同要发送到不同收件人、或者需要把告警信息顺便写到某个日志系统。我所在的某公司之前用的是Zabbix自带的邮件告警但运维群里隔三差五就有人说没收到告警邮件。排查下来发现自带的邮件媒介对SMTP 25端口的依赖很大且部分云厂商默认封禁25端口导致邮件发不出去。后来我把告警方式切换成Python脚本调用SMTP发送邮件用了一段时间稳定性和灵活性都明显提升这才有了这篇分享。这篇内容适合谁看呢正在被Zabbix告警不落地、邮件收不到、告警格式混乱困扰的运维工程师以及想搞清楚Zabbix告警如何对接脚本的中级运维。整体思路是用Python脚本作为Zabbix告警媒介Media的执行程序由Zabbix Server在产生告警事件时调用脚本脚本负责拼装内容、通过SMTP协议发送邮件。2. 整体设计与方案拆解2.1 三种邮件告警方案对比配置Zabbix邮件告警常见的有三条路官方自带的Simple Email媒介、Webhook方式、以及本文要讲的Python脚本方式。踩过坑之后我对三种方案的感受可以用一张表说清楚。方案优点缺点适用场景自带邮件媒介配置简单无需开发格式单一、SMTP端口受限、不易扩展临时测试、极简需求Webhook灵活度高可对接钉钉/飞书/企微依赖网关、对新手不友好有现成Webhook网关时Python脚本完全可控、可自定义逻辑、复用现有邮件服务需要写代码、需要处理脚本运行环境生产环境常态化告警我自己选Python脚本的原因有三点。第一脚本方式完全绕开了Zabbix对邮件端口的管理逻辑SMTP服务器参数完全由脚本自己掌控想用465端口走SSL、想用587走STARTTLS都行怎么稳怎么来。第二Python的email和smtplib库是标准库不需要额外安装依赖在任何一台机器上都能跑。第三脚本方式可以自己写函数、写逻辑未来想往告警里加东西非常方便。2.2 脚本方案的运行链路弄明白整条告警链路的走向后续配置就不会晕。Zabbix的告警流程是这样的监控项Item采集到数据触发触发器Trigger的异常条件触发器状态变为Problem产生告警事件Zabbix Server根据事件匹配动作Action中的条件动作命中后调用操作Operation里指定的告警媒介类型告警媒介Media Type执行配置好的脚本命令传入预先定义好的参数脚本完成邮件拼装与发送把结果输出到日志。也就是说我们所有要自定义的东西都集中在第5步和第6步。理解了这个链路配置起来就清楚多了——不是去改Zabbix内部逻辑而是把邮件发送这个动作完全接管过来。2.3 为什么建议脚本内做告警聚合额外的经验脚本方案最大的价值不只是把邮件发出去而是可以在脚本里对告警内容做二次处理比如去掉重复告警、按主机分组排序、把英文Key换成中文说明。Zabbix触发器里写的中文信息在告警中有时会变成一串转义符而脚本里可以用正则把\r\n正确还原成换行把消息体整理得干干净净。3. 核心细节与实际部署3.1 第一步准备Python脚本以下脚本是我实际部署在Zabbix Server上的版本使用/usr/bin/python3运行。如果你的Zabbix Server是CentOS 7自带的Python 2.7建议安装Python 3后使用避免编码问题。先创建目录mkdir -p /usr/lib/zabbix/alertscripts cd /usr/lib/zabbix/alertscripts再创建脚本文件zabbix_mail.py#!/usr/bin/env python3 # -*- coding: utf-8 -*- import sys import smtplib from email.mime.text import MIMEText from email.header import Header import logging import os # 配置日志方便排障 LOG_FILE /var/log/zabbix_mail.log logging.basicConfig( filenameLOG_FILE, levellogging.INFO, format%(asctime)s %(levelname)s %(message)s, datefmt%Y-%m-%d %H:%M:%S ) # SMTP 服务器配置按需修改 SMTP_HOST smtp.example.com SMTP_PORT 465 SMTP_USER zabbixexample.com SMTP_PASS your_password MAIL_FROM zabbixexample.com def send_mail(to, subject, body): msg MIMEText(body, plain, utf-8) msg[Subject] Header(subject, utf-8) msg[From] MAIL_FROM msg[To] to try: # 使用 SSL 方式连接465端口 server smtplib.SMTP_SSL(SMTP_HOST, SMTP_PORT, timeout30) server.login(SMTP_USER, SMTP_PASS) server.sendmail(MAIL_FROM, [to], msg.as_string()) server.quit() logging.info(邮件发送成功 - %s | 主题: %s, to, subject) except Exception as e: logging.error(邮件发送失败 - %s | 错误: %s, to, str(e)) # 输出到 stderr方便 Zabbix 捕捉 sys.stderr.write(邮件发送失败: %s\n % str(e)) sys.exit(1) if __name__ __main__: # Zabbix 调用时传3个参数收件人、主题、正文 if len(sys.argv) 4: logging.warning(参数不足无法发送邮件) sys.exit(1) to sys.argv[1] subject sys.argv[2] body sys.argv[3] send_mail(to, subject, body)这段脚本的核心逻辑非常简单从命令行读取三个参数第一个是收件人地址第二个是邮件主题第三个是邮件正文然后调用smtplib发送邮件。日志操作是必须保留的后续排查到底有没有调用脚本脚本执行报什么错全都靠它。3.2 第二步脚本权限与SELinux这一步很多人容易漏却又是实际问题高发区。脚本放到alertscripts目录下后一定要给足权限chown zabbix:zabbix /usr/lib/zabbix/alertscripts/zabbix_mail.py chmod 755 /usr/lib/zabbix/alertscripts/zabbix_mail.py之所以强调属主和属组是zabbix因为Zabbix Server进程以zabbix用户运行脚本执行和日志写入都需要对应权限。如果日志文件没有写权限Python的logging模块会直接抛异常脚本会失败邮件自然发不出去。再检查SELinux。很多Linux服务器上SELinux处于Enforcing模式Zabbix Server调用脚本时可能会被拦截。稳妥的操作是getenforce如果输出是Enforcing有两种处理方式一是临时把SELinux设为Permissive调试确认是SELinux阻断后再做精细策略二是直接放行zabbix相关执行权限。我在某公司部署时遇到了这个坑执行setenforce 0后脚本立刻正常说明就是SELinux的问题。生产环境建议用setsebool -P zabbix_can_network1如果这个布尔值不存在再考虑写自定义模块或保持Permissive但我的建议是能不开机重启就不动全局配置。提示如果Zabbix Server是用容器方式运行的则不需要在宿主机上处理SELinux只需确认容器内能访问宿主机上的SMTP端口。3.3 第三步Zabbix前端配置告警媒介前面脚本只是脚本还得让Zabbix认识它这一步在Zabbix前端界面操作。登录Zabbix Web界面进入告警媒介类型点击右上角的创建媒体类型。关键配置项如下名称Python邮件告警类型脚本脚本名称zabbix_mail.py脚本参数三个参数每个参数一行三个参数的值写法是Zabbix的约定按下表填写参数位置值含义第一个参数{ALERT.SENDTO}收件人地址来自用户的媒介配置第二个参数{ALERT.SUBJECT}邮件主题来自动作的默认主题第三个参数{ALERT.MESSAGE}邮件正文来自动作的默认信息配置完成后已启用的勾必须打上之后点更新保存。3.4 第四步用户与告警媒介绑定媒体类型建好了只解决能用什么方式发还需要告诉Zabbix发到哪个邮箱。这一步在用户管理里配置找到运维人员的账号进入告警媒介页签点击添加类型选择Python邮件告警收件人填写实际的邮箱地址启用时间建议1-7,00:00-24:00一周七天全时段使用默认严重程度勾选所有级别关键点来了这里配置的收件人邮箱会通过{ALERT.SENDTO}参数传给脚本所以务必和用户实际常用的邮箱保持一致不要写错。另外如果同一个用户配置了多个媒介Zabbix会按照媒介的使用默认严重程度做优先级匹配多个类型同时启用时告警会重复发送自己取舍就好。3.5 第五步配置动作与操作动作配置是整条链路里最灵活的部分决定了什么样的告警触发什么样的邮件。在配置 → 动作里选择触发源然后创建动作动作名称Python邮件告警-Active条件Conditions推荐这么配触发器严重性 ≥ 警告主机组 包含 某业务组操作Operations里添加操作步骤设置为1即第1步就发送持续时间0表示不重复发送。然后添加发送消息给用户选择之前配置好告警媒介的用户名媒介类型选Python邮件告警。操作里的默认信息才是决定邮件正文的关键用Zabbix内置宏拼接内容主机: {HOST.NAME} IP: {HOST.IP} 监控项: {ITEM.NAME} 当前值: {ITEM.LASTVALUE} 触发器: {TRIGGER.NAME} 严重性: {TRIGGER.SEVERITY} 状态: {TRIGGER.STATUS} 事件ID: {EVENT.ID}这一个模板信息比Zabbix默认的单行告警清晰太多收到邮件第一眼就能定位到故障主机和监控项。3.6 第六步脚本连通性测试一切配置完成先不急着等真实告警自己动手验证。首选方式是直接模拟Zabbix调用脚本/usr/lib/zabbix/alertscripts/zabbix_mail.py testexample.com 测试告警 这是一封测试邮件执行后看输出没有报错、退出码为0就说明脚本本身通了。再去收件箱确认邮件是否送达。如果脚本走不通看日志tail -f /var/log/zabbix_mail.log可能的情况有几种SMTP认证失败账号密码错误、连接超时网络不通或端口被墙、发件地址被服务商拒绝需要设置SPF记录。4. 生产环境接入要点与告警内容优化4.1 生产接入前必须处理的权限设计我见过不少人在测试环境把脚本跑通了一到生产环境就各种问题。其实是漏了几个生产环境特有的细节脚本目录放在/usr/lib/zabbix/alertscripts是最常见的位置但如果你用的是编译安装或者源码包路径可能不同。检查zabbix_server.conf文件里的AlertScriptsPath参数确保路径一致。某些部署方式下Web前端和管理端跑在同一台机器脚本执行时会以zabbix用户触发而手动测试用的是root用户两者的环境和权限不同。手动测试通过不代表Zabbix能执行必须在Zabbix Server本机以zabbix用户身份测试su - zabbix -s /bin/bash -c /usr/lib/zabbix/alertscripts/zabbix_mail.py testexample.com 测试 内容这一步实测能排查掉九成的环境问题。邮件正文里的中文乱码问题也要提前处理。脚本里已经用MIMEText(body, plain, utf-8)设置编码但如果Zabbix传到脚本的中文字符被系统locale影响变成??可以在脚本开头加import os os.environ[LANG] en_US.UTF-84.2 告警内容优化按严重级别分流某公司的告警体系里我用脚本方式做了严重级别分流紧急告警灾难/严重发送到全员运维邮箱普通告警警告/一般只发到值班负责人。实现方式不是在脚本里判断而是在Zabbix动作里配置两个操作操作1发送给A同学条件为触发器严重性在严重灾难操作2发送给B同学条件为触发器严重性在警告一般。这样逻辑清晰、配置直观也避免了脚本写太多分支判断导致维护复杂。4.3 配置告警升级与恢复通知Zabbix的动作里支持配置步骤Steps步骤之间的间隔可以设置。举个例子触发器触发后不做处理会按照步骤顺序执行操作这就是升级机制。在动作操作里可以设置步骤1-1间隔1分钟步骤2-2间隔30分钟步骤3-0间隔60分钟。这样告警产生后第1分钟发邮件给值班人员如果问题没解决30分钟后再发一次1小时后重复。次数填0表示无限重复。恢复通知也应配置操作里再添加恢复消息勾选恢复操作这样问题恢复后运维人员会收到确认邮件形成完整闭环。这一步看似简单但对工单闭环管理帮助很大。5. 常见问题与排查技巧实录5.1 问题清单与速查表以下是我在多次部署和日常运维中遇到的高频问题整理成速查表症状可能原因排查方法Zabbix告警动作已触发但没收到邮件脚本没有执行权限检查/etc/zabbix/zabbix_server.conf的AlertScriptsPath路径同上SELinux阻断临时setenforce 0验证同上SMTP服务器拒绝连接telnet smtp.example.com 465日志显示认证失败密码错误或邮箱开启了安全验证用同样的账号在邮件客户端测试日志显示发送成功但收不到被对方邮件服务商当垃圾邮件检查发件域名SPF记录、发信频率中文乱码系统locale问题脚本内设置LANG环境变量参数顺序错误脚本参数与声明的值不对应检查告警媒介里的三个参数顺序脚本执行成功但退出码非0sys.exit(1)被触发查看日志里的错误前缀5.2 排查过程中最实用的两条经验经验一先手工跑脚本再看Zabbix日志。很多人一上来就翻zabbix_server.log但Zabbix日志只会记录执行脚本失败不会告诉你Python报了什么错。正确顺序是手工以zabbix用户执行脚本脚本自己写的smtp日志会记录详细错误脚本通了但Zabbix依然不执行时再查Zabbix日志。经验二用strace追踪脚本的真实执行情况。偶发性的告警丢失很难排查但用strace可以看到脚本进程是否有网络连接、是否被信号打断strace -f -e tracenetwork -p zabbix_server_pid实际操作中这个层级比较深了适合所有常规手段都试过仍然无解的场景。大多数情况用日志就能定位。5.3 一个让我记忆深刻的坑脚本执行超时某次生产环境升级后告警邮件频繁延迟。查了所有环节都没问题最后发现原因SMTP服务器在同一时刻并发连接数超过了阈值Zabbix的脚本执行超时时间默认是3秒脚本还在等待SMTP响应就被Zabbix杀掉产生告警丢失。处理办法有两个在zabbix_server.conf里把Timeout3改为Timeout10同时优化脚本把SMTP连接超时从默认值改为可配的timeout10避免脚本无限等待。生产环境务必把这两个超时时间协调好并且监控Zabbix Server本机的SMTP连接状态防患于未然。6. 个人实践体会整个方案落地之后最大的感受是Zabbix脚本告警的难点不在于写Python代码而在于把Zabbix参数传递机制和邮件发送链路上的阻点摸清楚。参数传递机制决定了脚本能不能拿到正确的收件人和内容邮件链路决定了脚本能不能顺利把信发出去。二者缺一不可。我个人的习惯是给每一个脚本文件都写日志并且每季度检查一次SMTP账号和密码是否过期——很多邮箱账号密码设置了定期重置过期后告警邮件会全部打回而如果不看脚本日志几乎无从发现。最后分享一个小技巧脚本里可以加一个依赖检测启动时检查/tmp/zabbix_mail_check文件是否存在如果存在则直接输出Maintenance Mode并退出。配合定时任务可以在变更窗口期主动抑制告警邮件避免大量误报打扰值班人员。这个小改动实测下来场景价值非常高。这套方案已经稳定运行了一段时间后续如果邮件服务商调整了安全策略也只需要改脚本里的SMTP配置前端和动作配置完全不需要动扩展和维护的灵活性正是我选择脚本方案的根本原因。
RELATED

相关推荐

A*寻路算法从原理到实战:启发函数、性能调优与避坑指南

A*寻路算法从原理到实战:启发函数、性能调优与避坑指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

📅 2026/10/16 5:16:40
嵌入式实时噪声估计:三层递进式鲁棒算法设计

嵌入式实时噪声估计:三层递进式鲁棒算法设计

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

📅 2026/10/16 5:16:40
恭介的法则:研发团队如何将踩坑经验固化为可执行规则

恭介的法则:研发团队如何将踩坑经验固化为可执行规则

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

📅 2026/10/16 5:16:40
MORE NEWS

更多资讯

📰

Flink算子链深度解析:原理、调优与实战避坑指南

1. 算子链到底解决了什么问题第一次接触 Flink 的算子链(Operator Chaining)机制,是在一个实时计算任务里。当时任务逻辑并不复杂,从数据源读取、做一次 map 清洗、再 filter 掉无效记录、最后 keyBy 后做窗口聚合输出。但打开 Fl…

📰

技术参考资源整理指南:从分层筛选到知识库搭建

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

📰

揭秘 vm2api 0 提示词注入机制:为什么不用再篡改 System 提示词

【免费下载链接】vm2api vm2api 使用虚拟机完全拟真方案的订阅转api 项目地址: https://gitcode.com/gh_mirrors/vm/vm2api 点击查看 免费下载 vm2api 是一个使用虚拟机完全拟真方案做 AI 订阅转 API 的开源网关,它的核心卖点之一,就是不用向…

📰

两串电池主动均衡:MP2642GR-Z+TM4C1294硬件与固件方案

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

📰

红队、CTF、企业评估:PentAGI 三种打开方式催生的新玩法

红队、CTF、企业评估:PentAGI 三种打开方式催生的新玩法 【免费下载链接】pentagi Fully autonomous AI Agents system capable of performing complex penetration testing tasks 项目地址: https://gitcode.com/GitHub_Trending/pe/pentagi 一句话下指令&a…

📰

WelcomeCoordinator 架构全景图:核心组件协作与数据流深度解读

【免费下载链接】welcome-coordinator Welcome Coordinator for Android 项目地址: https://gitcode.com/gh_mirrors/we/welcome-coordinator 点击查看 免费下载 WelcomeCoordinator 是一款来自 Redbooth 开源团队的 Android 引导页库(Welcome Wizard /…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬