Operations 16 min read

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.

Ops Development Stories
Ops Development Stories
Ops Development Stories
How to Send Zabbix 4.2 Alerts with Embedded Images via Email and WeChat Using Python

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:

requests

Script 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 + '&lt;br&gt;\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&lt;br&gt;&lt;img src='cid:imgid1'&gt;</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

,

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:

requests

Script 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) + "&lt;br/&gt; &lt;img src='https://qyapi.weixin.qq.com/cgi-bin/media/get?access_token=%s&amp;media_id=%s'&gt;" % (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.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.

MonitoringPythonAutomationWeChatZabbixemail alerts
Ops Development Stories
Written by

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.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.