How to Send Zabbix 4.2 Alerts with Embedded Images via Email and WeChat Using Python
This guide shows how to use Python 2.7 to extend Zabbix 4.2 alerts by attaching the current graph image to email and WeChat notifications, covering environment setup, script details, Zabbix media type configuration, and testing the final result.
1. Python implementation for Zabbix 4.2 email alerts with images
Implementation idea
The first line of the alert must contain the
itemid. The script extracts the
itemidwith a regular expression, creates a Zabbix session, fetches the graph image, saves it locally, converts the text field to HTML, and sends an email that embeds the image.
Environment preparation
Python 2.7.5 runtime
Required libraries:
requestsScript implementation
<code>#!/usr/bin/python
#coding=utf-8
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.image import MIMEImage
import smtplib, sys, os, time, re, requests
from smtplib import SMTP
user = 'Admin' # Zabbix username
password = 'zabbix' # Zabbix password
graph_path = '/usr/lib/zabbix/alertscripts/graph'
graph_url = 'http://192.168.73.133/chart.php'
loginurl = 'http://192.168.73.133/index.php'
host = '192.168.73.133'
to_email = sys.argv[1]
subject = sys.argv[2].decode('utf-8')
mail_pass = 'xxx'
smtp_host = 'smtp.163.com'
from_email = '[email protected]'
def get_itemid():
itemid = re.search(r'监控ID:(\d+)', sys.argv[3]).group(1)
return itemid
def get_graph(itemid):
session = requests.Session()
loginheaders = {"Host": host, "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8"}
payload = {"name": user, "password": password, "autologin": "1", "enter": "Sign in"}
session.post(url=loginurl, headers=loginheaders, data=payload)
graph_params = {"from": "now-10m", "to": "now", "itemids": itemid, "width": "400"}
graph_req = session.get(url=graph_url, params=graph_params)
time_tag = time.strftime("%Y%m%d%H%M%S", time.localtime())
graph_name = os.path.join(graph_path, 'baojing_' + time_tag + '.png')
with open(graph_name, 'wb') as f:
f.write(graph_req.content)
return graph_name
def text_to_html(text):
lines = text.splitlines()
html_text = ''
for line in lines:
html_text += line + '<br>\n'
return html_text
def send_mail(graph_name):
msg = MIMEMultipart('related')
with open(graph_name, 'rb') as f:
graph = MIMEImage(f.read())
graph.add_header('Content-ID', 'imgid1')
text = text_to_html(sys.argv[3])
html_body = """<html><body>%s<br><img src='cid:imgid1'></body></html>""" % text
html = MIMEText(html_body, 'html', 'utf-8')
msg.attach(html)
msg.attach(graph)
msg['Subject'] = subject
msg['From'] = from_email
try:
server = SMTP(smtp_host, "587")
server.starttls()
server.login(from_email, mail_pass)
server.sendmail(from_email, to_email, msg.as_string())
server.quit()
except smtplib.SMTPException as e:
print(e)
def run():
itemid = get_itemid()
graph_name = get_graph(itemid)
send_mail(graph_name)
if __name__ == '__main__':
run()
</code>Define Zabbix media type
In Zabbix Web UI, go to Administration → Media types, create a new script type, set the script name to
zabbix_email_pic.py, and configure the script parameters.
Define alert action
Create an action in Configuration → Actions, and use the following default message template (variables are Zabbix macros):
<code>默认标题 Zabbix告警:服务器:{HOSTNAME}发生: {TRIGGER.NAME}故障!
监控ID:{ITEM.ID}
告警主机:{HOST.NAME}
告警主机:{HOST.IP}
告警时间:{EVENT.DATE} {EVENT.TIME}
告警等级:{TRIGGER.SEVERITY}
告警信息: {TRIGGER.NAME}
告警项目:{TRIGGER.KEY}
问题详情:{ITEM.NAME}:{ITEM.VALUE}
当前状态:{TRIGGER.STATUS}:{ITEM.VALUE}
事件ID:{EVENT.ID}
</code>2. Python implementation for Zabbix 4.2 WeChat alerts with images
Implementation idea
Create a corporate WeChat application to obtain
agentId,
secretand department ID. Extract
itemidfrom the alert, fetch the graph image via a Zabbix session, upload the image as temporary media to WeChat, and send an
mpnewsmessage that includes the image and alert details.
Environment preparation
Python 2.7.5 runtime
Required libraries:
requestsScript implementation
<code>#!/usr/bin/python
#coding=utf-8
import requests, json, urllib3, smtplib, sys, os, time, re
from email.mime.image import MIMEImage
urllib3.disable_warnings()
class WechatImage(object):
def get_token(self, corpid, secret):
r = requests.get('https://qyapi.weixin.qq.com/cgi-bin/gettoken', params={"corpid": corpid, "corpsecret": secret}, verify=False)
return r.json()['access_token']
def get_image_url(self, token, path):
files = {"media": open(path, 'rb')}
r = requests.post('https://qyapi.weixin.qq.com/cgi-bin/media/upload?access_token=%s&type=image' % token, files=files)
return r.json()['media_id']
def get_messages(self, subject, content, path, corpid, secret):
token = self.get_token(corpid, secret)
media_id = self.get_image_url(token, path)
content_html = text_to_html(content) + "<br/> <img src='https://qyapi.weixin.qq.com/cgi-bin/media/get?access_token=%s&media_id=%s'>" % (token, media_id)
return {"articles": [{"title": subject, "digest": content, "content": content_html, "thumb_media_id": media_id}]}
def send_news_message(self, corpid, secret, to_user, agentid, subject, content, path):
token = self.get_token(corpid, secret)
messages = self.get_messages(subject, content, path, corpid, secret)
data = {"toparty": to_user, "agentid": agentid, "msgtype": "mpnews", "mpnews": messages, "safe": "0"}
headers = {'content-type': 'application/json'}
r = requests.post('https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token=%s' % token, headers=headers, data=json.dumps(data, ensure_ascii=False).encode('utf-8'))
return r.text
def text_to_html(text):
return '<br>'.join(text.splitlines())
def get_itemid():
return re.search(r'监控ID:(\d+)', sys.argv[3]).group(1)
def get_graph(itemid):
session = requests.Session()
# login similar to email script (omitted for brevity)
graph_params = {"from": "now-10m", "to": "now", "itemids": itemid, "width": "290", "height": "40"}
r = session.get('http://192.168.73.133/chart.php', params=graph_params)
name = os.path.join('/usr/lib/zabbix/alertscripts/graph/', 'baojing_' + time.strftime('%Y%m%d%H%M%S') + '.png')
with open(name, 'wb') as f:
f.write(r.content)
return name
if __name__ == '__main__':
user = 'Admin'
password = 'zabbix'
graph_path = '/usr/lib/zabbix/alertscripts/graph/'
graph_url = 'http://192.168.73.133/chart.php'
loginurl = 'http://192.168.73.133/index.php'
host = '192.168.73.133'
itemid = get_itemid()
path = get_graph(itemid)
to_user = sys.argv[1]
subject = sys.argv[2]
content = sys.argv[3]
corpid = 'xxxxx'
secret = 'xxxxxxx'
agentid = '1000002'
wechat = WechatImage()
wechat.send_news_message(corpid, secret, to_user, agentid, subject, content, path)
</code>Define WeChat media type
In Zabbix, create a new script media type named
zabbix_weixin_pic.pyand set the appropriate script parameters.
Define alert action
Configure an action in Zabbix similar to the email case, using the new media type to trigger the WeChat script.
Testing
Manually trigger an alert; the recipient receives a WeChat message with the embedded graph image and can view the historical chart by clicking the message.
Ops Development Stories
Maintained by a like‑minded team, covering both operations and development. Topics span Linux ops, DevOps toolchain, Kubernetes containerization, monitoring, log collection, network security, and Python or Go development. Team members: Qiao Ke, wanger, Dong Ge, Su Xin, Hua Zai, Zheng Ge, Teacher Xia.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.