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 itemid with 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
#!/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>
'
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()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):
默认标题 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}2. Python implementation for Zabbix 4.2 WeChat alerts with images
Implementation idea
Create a corporate WeChat application to obtain agentId, secret and department ID. Extract itemid from the alert, fetch the graph image via a Zabbix session, upload the image as temporary media to WeChat, and send an mpnews message that includes the image and alert details.
Environment preparation
Python 2.7.5 runtime
Required libraries:
requestsScript implementation
#!/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)Define WeChat media type
In Zabbix, create a new script media type named zabbix_weixin_pic.py and 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.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
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.
