Compare commits

..

No commits in common. "main" and "v1.11-2" have entirely different histories.

25 changed files with 653 additions and 2098 deletions

View File

@ -1,49 +0,0 @@
# Contributor Covenant Code of Conduct
## Our Pledge
In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body
size, disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, religion, or sexual identity and orientation.
## Our Standards
Examples of behavior that contributes to creating a positive environment include:
* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members
Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery and unwelcome sexual attention or advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a professional setting
## Our Responsibilities
Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate,
threatening, offensive, or harmful.
## Scope
This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at abuse@puzzl.nl. All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
[homepage]: https://www.contributor-covenant.org
For answers to common questions about this code of conduct, see https://www.contributor-covenant.org/faq

181
README.md
View File

@ -1,62 +1,165 @@
## Introduction ##
Over the years I've been using Zabbix as both personal and business solution for monitoring. One of the missing features in Zabbix itself was the ability to have graphs generated and associated to monitoring messages as well as an easy way to jump back into Zabbix when searching for monitoring information for specific events, problems or to have a direct link to the associated Zabbix item or host.
# mailGraph
Zabbix Media module and scripts for sending e-mail alerts with graphs.
This initiated the development of mailGraph v1 in Zabbix 5.4 delivering an elementary solution for sending HTML enriched messages from Zabbix including graphs.
To facilitate in a very flexible way to setup and format messages including the graphs, Twig made its introduction towards mailGraph v2, the current release branch of mailGraph.
[![](images/Example-mail-message.png?raw=true)](images/Example-mail-message.png)
The below message is just an example of what MailGraph is capable of. The template engine in Twig allows for a fully customized message creation to your needs! It is also possible to add more Zabbix fields as any field is passed to Twig when accessible in Zabbix through the macro mechanism.
# WORK IN PROGRESS
Although still under development (consider the current releases "beta"), I need feedback and interaction with other users of Zabbix that are looking for the functionality I've developed hence I'm releasing my code to the world.
Note that all Zabbix host, item or screen related information is made available to Twig automatically.
**List of item to-do**
1. Resolve macro information => _DROPPED_: Found out during development and testing this may expose sensitive information over the e-mail hence decided to drop this; clicking the EVENT DETAILS link takes any receiver to the corresponding Zabbix page.
2. Passing dynamic parameters via the Webhook for template/output usage => WORK IN PROGRESS, release 1.20
3. Finding "beta testers" to assist me in further enhancing the use cases => awaiting the first users/feedback!
4. Adding parameters to configure SwitftMailer configuration. Currently mailGraph assumes you have a localhost capable of processing the mail. => WORK IN PROGRESS, release 1.20
Example message:
# Zabbix enhancements
https://support.zabbix.com/browse/ZBXNEXT-6534
Main ticket asking how to get this Media type onboarded in the Media type section of the manual and the associated Zabbix GitHub directory.
![Example image](https://github.com/moudsen/mailGraph/assets/16045332/0cb671d9-464f-493b-b250-15dd550fd84a)
https://support.zabbix.com/browse/ZBXNEXT-6535
One of the major items that needs to be tackled is to resolve Macros that are in names, descriptions, etc. As this does work for the Trigger and TriggerPrototype I've examined the Zabbix source code and from here I would say it's quite "easy" to add the "expandXXX" flags to other types as well (found many existing functions to perform this).
I'm adding this to my testlab setup for Item and ItemPrototype and will share the outcome. If it is succesfull I will also arrange for other types (like Host) eventually giving back the additional code lines to Zabbix for incorporation into a release.
mailGraph is capable of adding several series of graphs into a single message delivering a unique experience when and how groups of graph images per the requested periods of time are added.
Currently mailGraph supports hosts, (one or more related) items and screens (applicable to Zabbix 5.4 only).
# Installation pre-requisites
The suggested installation path of this script is on the same host where Zabbix lives but outside the actual Zabbix directory, although it is possible to run the script entirely somewhere else (the code is webhook based, picking up information from Zabbix is via the front-end login and API).
More information can be found in the Wiki.
I've tested my code with Zabbix 5.0.5 (LTS). Not sure if it can/will run in any versions under 5.
## Installation ##
Please refer to the Wiki how to get mailGraph installed and configured on your system.
# I'm assuming
- You are familiar with "composer"
- You know how to configure and secure a webserver/virtual host
- That you have CURL and PHP installed
## Reference websites ##
[Extensive GERMAN installation from scratch](https://znil.net/index.php?title=Zabbix_mailGraph_installieren_-_Trigger_Alerts_Emails_mit_Grafiken) - nice work from Bernard Linz
# Prepare the installation
- Download or clone this repository
- Pick a directory within a (virtual) host of your webserver
- Create the directories "config", "images", "log", "templates" and "tmp" inside this directory
- Copy .htaccess to the main directory _(if not using Apache make sure your webserver denies http access to /config!)_
- Copy mailGraph.php to the main directory
- Install SwiftMailer: `composer require swiftmailer/swiftmailer`
- Install TWIG: `composer require twig/twig`
- Copy config/config.php to your /config directory
- Copy config/config.json.template to your /config/ directory and rename to "config.json" (we will configure in the next step)
- Copy templates/html.template and templates/plain.template to your templates directory
- Copy mailGraph.xml to a location where you can upload the Media Type to Zabbix (we will load into / configure in Zabbix in the next steps)
## Announcements ##
_(2025/02/04)_
# Configuration
- Goto your /config directory
- Two ways to configure the config.json file: 1) with config.php or 2) with your favorite text editor (note that you must have knowledge of JSON format to use this option)'
- List the available configuration options with "php config.php config.json list"
- Change any option with "php config.php config.json replace 'key_name' 'new_value'" (note the usage of the single quotes from the command-line!)
Started on coding and testing mailGraph v3.
**"script_baseurl"** should point to the URL of your directory where MailGraph is installed (ie. "https://mydomain.com/"). Note the ending '/'!
_(2025/01/26)_
**"zabbix_user"** and **zabbix_user_pwd** must be a Zabbix SuperAdmin user/password you need to have/create to login to Zabbix (this is for grabbing the images via the regular Zabbix routines).
mailGraph v2.20 now supporting Zabbix 7.0 (LTS) and Zabbix 7.2 (in particular the new API bearer token authentication method).
**"zabbix_user_api"** and **zabbix_user_pwd** must also be a Zabbix SuperAdmin user/password you need to have/create to login to the Zabbix API (this is for grabbing the information of the event via the Zabbix API).
_(2024/12/01)_
**"mail_from"** must be a valid e-mail address which represents the 'from' address in the mails that are sent (ie. "zabbix.mailgraph.noreply@domain.com") that is acceptable by your mail server.
As per December 2024 PHP 7 and older is no longer supported. Please upgrade to a supported PHP 8 version.
Note that mailGraph is expected to function in older PHP versions.
# Load the Media Type "MailGraph" into Zabbix
- Login to your Zabbix instance
- Goto "Administration" => "Media yypes"
- Import the "mailGraph.xml" file
- Edit the new media type
- Configure some of the macros associated
_(2023/11/01)_
"baseURL" must contain your Zabbix URL (ie. "https://mydomain.com/zabbix/"). Note the ending '/'!
As per November 2023 the maintenance on mailGraph v2.x for Zabbix 5.x will stop in conjunction with the Zabbix lifecycle policy (https://www.zabbix.com/life_cycle_and_release_policy) as Zabbix 5 is nearing it's end of life.
You can set your custom "graphWidth" and "GraphHeight" to your convenience.
Principal bug fixing on mailGraph v2.x (logic failure or similar) will continue but only for Zabbix 6.x onwards.
You can switch the graph legend on/off with "showLegend" (0=off,1=on).
## Ideas and improvements ##
You can change the "subject" of the e-mail that is sent (note that the markup can be a combination of Zabbix MACRO or TWIG notation!).
I'm open to new feature requests - please raise an issue for this in this Github space.
"URL" is the url to the mailGraph script (ie. "https://mydomain.com/mailGraph.php").
[#50 - Docker support](https://github.com/moudsen/mailGraph/issues/50) - Docker support inserted shortly after testing; will be pushed into release 3 shortly.
_Please refer to the `docker` directory for the first release of the docker image on Docker Hub (hoppa66/zabbix-mailgraph)_
# Actions configuration
At this point the Media type is ready for configuration under "actions" as per the regular way of Zabbix alert processing. Please refer to the manual how to configure.
## Special thank you ##
I would like to express my gratitude to the following people that have actively contributed to bring bugs and improvements to my attention:
- [pqvindesland](https://github.com/pqvindesland)
- [BernardLinz](https://github.com/BernhardLinz)
- [WMP](https://github.com/WMP)
- [dima-online](https://github.com/dima-online)
- [tadeuszkura](https://github.com/tadeuszkura)
# Template adjustments
I've picked TWIG as the template processor, where the following macros are available for your convenience. Feel free to adjust the html.template and plain.template files as you see fit for your situation!
## IMPORTANT NOTE for users of mailGraph v2 and older and Zabbix versions under 6.0 ##
As per November 2023, mailGraph is no longer maintained for Zabbix 5 and older.
Values available:
{{ baseURL }} - base url of the Zabbix system (use for references to API and login)
{{ TRIGGER_ID }} - id of the applicable trigger
{{ TRIGGER_DESCRIPTION }} - raw trigger description (note: macros are not parsed!)
{{ TRIGGER_COMMENTS }} - comments of the trigger
{{ TRIGGER_URL }} - url of the trigger form
{{ ITEM_ID }} - id of the associated item to the trigger
{{ ITEM_KEY }} - key of the item
{{ ITEM_NAME }} - item name
{{ ITEM_DESCRIPTION }} - description of the item
{{ ITEM_LASTVALUE }} - last value of the item
{{ ITEM_PREVIOUSVALUE }} - the value of the before LASTVALUE
{{ ITEM_URL }} - url of the item form
{{ HOST_ID }} - id of the associated host to the item
{{ HOST_NAME }} - name of the host
{{ HOST_ERROR }} - last error state of the applicable host
{{ HOST_DESCRIPTION }} - description of the host
{{ HOST_URL }} - url of the host form
{{ EVENT_ID }} - id of the associated event
{{ EVENT_NAME }} - name of the event (note: macros are parsed!)
{{ EVENT_OPDATA }} - associated operational data of the vent
{{ EVENT_VALUE }} - event state (0=Recovered, 1=Triggered/Active)
{{ EVENT_SEVERITY }} - severity of the event
{{ EVENT_STATUS }} - status of the event
{{ EVENT_URL }} - url of the event details
{{ GRAPH_ID }} - id of the (first) associated graph that contains the item
{{ GRAPH_NAME }} - name of this graph
{{ GRAPH_URL }} - URL to this graph (assuming script produces to an accessible location)
{{ GRAPH_CID }} - IMG embed string (<img src="{{ GRAPH_CID }}" />)
{{ LOG_HTML }} - script log in HTML format
{{ LOG_PLAIN }} - script log in PLAIN text format
# Troubleshooting
In general if something goes wrong (no output), use the following sequence to identify where the error has occured (and raise an issue in this repository so I can take a look at it):
- Goto Zabbix => Reports => Action Log and search for events with Status "Failed"
- Note the itemId, triggerId and eventId from this event for testing the Media Type manually
- If the popup message says "Syntax Error" something went wrong with the processing during the script. In this case you have to investigate a bit more what is happening.
The easiest way to test what is happening is to now goto Administration => Media types and hit the "Test" at the right hand side for MailGraph.
- Replace relevant macros with information (eventId, triggerId, itemId, recipient, baseUrl and URL) and hit "Test"
- The last line in the result will tell you what the problem is (most likely an access or connectivity issue)
- Fix accordingly and retry
To facilitate troubleshooting, you can (at code level):
- switch on $cDebugMail to receive processing logs as attachment of an e-mail message
- store logs in the /log directory when $cDebug is switched on
In case of an issue that happens before an e-mail is sent, you can also perform a CLI based test:
- php mailGraph.php test
Note that you have to set the configuration items starting with "cli" in config.json with actual values from a previous message to make this work!
Last resort is to raise an issue in this repository and I will try to assist as soon as possible to fix it.

View File

@ -1,32 +1,16 @@
{
"script_baseurl": "https:\/\/mydomain.com\/",
"script_baseurl": "https:\/\/domain.com\/",
"cli_itemId": 0,
"cli_triggerId": 0,
"cli_eventId": 0,
"cli_eventValue": 0,
"cli_duration": 0,
"cli_recipient": "recipient@mydomain.com",
"cli_subject": "[TEST] {{ HOST_NAME|raw }}: ({{ EVENT_SEVERITY }}) {{ EVENT_NAME|raw }}",
"cli_baseURL": "https:\/\/mydomain.com\/zabbix\/",
"cli_period": "30m",
"cli_period_header": "Last 30 minutes",
"cli_debug": 1,
"cli_proxy": "",
"cli_recipient": "recipient@domain.com",
"cli_subject": "\"{{ HOST_NAME }}\": ({{ EVENT_SEVERITY }}) {{ EVENT_NAME }}"
"cli_baseURL": "https:\/\/domain.com\/zabbix\/",
"zabbix_user": "alogicalusername",
"zabbix_user_pwd": "astrongpassword",
"zabbix_api_user": "alogicalusername",
"zabbix_api_pwd": "astrongpassword",
"subject": "{{ HOST_NAME|raw }}: ({{ EVENT_SEVERITY }}) {{ EVENT_NAME|raw }}",
"smtp_server": "localhost",
"smtp_port": 25,
"smtp_security": "none",
"smtp_strict": "yes",
"smtp_from_address": "mailgraph@mydomain.com",
"smtp_from_name": "mailGraph",
"smtp_reply_address": "feedback@mydomain.com",
"smtp_reply_name": "mailGraph response mailbox",
"graph_match": "any",
"item_value_truncate": 50,
"period": "20m",
"period_header": "Last 20 minutes",
"retention_images": 7,
"retention_logs": 14,
"debug": 0
"mail_from": "sender@domain.com"
}

View File

@ -1,31 +0,0 @@
{
"script_baseurl": "https:\/\/mydomain.com\/",
"cli_eventId": 0,
"cli_duration": 0,
"cli_recipient": "recipient@mydomain.com",
"cli_subject": "[TEST] {{ HOST_NAME|raw }}: ({{ EVENT_SEVERITY }}) {{ EVENT_NAME|raw }}",
"cli_baseURL": "https:\/\/mydomain.com\/zabbix\/",
"cli_period": "30m",
"cli_period_header": "Last 30 minutes",
"cli_debug": 1,
"cli_proxy": "",
"zabbix_user": "alogicalusername",
"zabbix_user_pwd": "astrongpassword",
"zabbix_api_token": "TheTokenGeneratedInZabbix",
"subject": "{{ HOST_NAME|raw }}: ({{ EVENT_SEVERITY }}) {{ EVENT_NAME|raw }}",
"smtp_server": "localhost",
"smtp_port": 25,
"smtp_security": "none",
"smtp_strict": "yes",
"smtp_from_address": "mailgraph@mydomain.com",
"smtp_from_name": "mailGraph",
"smtp_reply_address": "feedback@mydomain.com",
"smtp_reply_name": "mailGraph response mailbox",
"graph_match": "any",
"item_value_truncate": 50,
"period": "20m",
"period_header": "Last 20 minutes",
"retention_images": 7,
"retention_logs": 14,
"debug": 0
}

View File

@ -1,30 +0,0 @@
{
"script_baseurl": "https:\/\/mydomain.com\/",
"cli_eventId": 0,
"cli_duration": 0,
"cli_recipient": "recipient@mydomain.com",
"cli_subject": "[TEST] {{ HOST_NAME|raw }}: ({{ EVENT_SEVERITY }}) {{ EVENT_NAME|raw }}",
"cli_baseURL": "https:\/\/mydomain.com\/zabbix\/",
"cli_periods": "10m,4h,2d,7d",
"cli_periods_headers": "Last 10 minutes,Last 4 hours,Last 2 days,Last 7 days",
"cli_debug": 1,
"cli_proxy": "",
"zabbix_user": "alogicalusername",
"zabbix_user_pwd": "astrongpassword",
"zabbix_api_user": "alogicalusername",
"zabbix_api_pwd": "astrongpassword",
"subject": "{{ HOST_NAME|raw }}: ({{ EVENT_SEVERITY }}) {{ EVENT_NAME|raw }}",
"smtp_server": "localhost",
"smtp_port": 25,
"smtp_security": "none",
"smtp_strict": "yes",
"smtp_from_address": "mailgraph@mydomain.com",
"smtp_from_name": "mailGraph",
"smtp_reply_address": "feedback@mydomain.com",
"smtp_reply_name": "mailGraph response mailbox",
"graph_match": "any",
"item_value_truncate": 50,
"periods": "10m,4h,2d,7d",
"periods_headers": "Last 10 minutes,Last 4 hours,Last 2 days,Last 7 days",
"debug": 0
}

View File

@ -27,7 +27,7 @@
$content = file_get_contents($argv[1]);
$data = json_decode($content,TRUE);
if (($data==NULL) && (sizeof($content)>2))
if ($data==NULL)
{
echo 'Invalid JSON format in config file?!'.$cCRLF;
die;

View File

@ -1 +0,0 @@
RESTART_POLICY=unless-stopped

View File

@ -1,88 +0,0 @@
FROM ubuntu:latest
#########################################################################################################
#########################################################################################################
##
## ZABBIX-MAILGRAPH (Dockerfile)
## =============================
## Dockerfile to builld and configure the zabbix-mailgraph image.
##
## -----------------------------------------------------------------------------------------------------
## v0.9.1 2025/05/05 - Mark Oudsen - First public beta - Pending documentation
## v0.9.0 2025/05/05 - Mark Oudsen - Internal test release
## v0.1.0 2025/05/05 - Mark Oudsen - Initial build, based on idea from "dima-online
## "https://github.com/moudsen/mailGraph/issues/50
##
## -----------------------------------------------------------------------------------------------------
##
## (C) M.J.Oudsen, mark.oudsen@puzzl.nl
## MIT License
## Credits: "demi-online" (https://github.com/dima-online)
##
#########################################################################################################
#########################################################################################################
# Disable interactive functions
ENV DEBIAN_FRONTEND=noninteractive
# Install Apache, PHP and supplimentary programs
RUN apt-get update && \
apt-get install -y apache2 \
libapache2-mod-php \
php-curl \
php-zip \
curl \
git
# Clean out APT files
RUN rm -rf /var/lib/apt/lists/*
RUN apt-get clean -y
# Install Composer for PHP dependencies
RUN cd /tmp && curl -sS https://getcomposer.org/installer | php && mv composer.phar /usr/local/bin/composer
# Enable Apache modules
RUN a2enmod php8.3
RUN a2enmod rewrite
# Update the PHP.ini file, enable <? ?> tags and quieten logging.
RUN sed -i "s/short_open_tag = Off/short_open_tag = On/" /etc/php/8.3/apache2/php.ini
RUN sed -i "s/error_reporting = .*$/error_reporting = E_ERROR | E_WARNING | E_PARSE/" /etc/php/8.3/apache2/php.ini
# Manually set up the apache environment variables
ENV APACHE_RUN_USER=www-data
ENV APACHE_RUN_GROUP=www-data
ENV APACHE_LOG_DIR="/var/log/apache2"
ENV APACHE_LOCK_DIR="/var/lock/apache2"
ENV APACHE_PID_FILE="/var/run/apache2.pid"
# Copy the Github code into Apache site directory (run fetch_mailgraph.sh before building!)
ADD www /var/www/site/public
# Copy the cleanup script into local bin
ADD cleanup.sh /usr/local/bin/cleanup
RUN chmod +x /usr/local/bin/cleanup
# Fetch dependencies via Composer
RUN composer require phpmailer/phpmailer
RUN composer require twig/twig
# Move into the site directory
RUN mv /composer* /var/www/site/public/.
RUN mv /vendor /var/www/site/public/.
# Create some directories not existing yet
RUN mkdir /var/www/site/public/log
RUN mkdir /var/www/site/public/tmp
# Fix ownership
RUN chown www-data.www-data -R /var/www/site/public
# Update(/overwrite) the default apache site with the config we created
ADD apache-config.conf /etc/apache2/sites-enabled/000-default.conf
# Expose the HTTP port to external
EXPOSE 80
# By default, simply start apache
ENTRYPOINT ["/usr/sbin/apache2ctl", "-D", "FOREGROUND"]

View File

@ -1,44 +0,0 @@
## Introduction ##
With the following instructions, mailGraph can be run in a Docker container.
Every new version of mailGraph will also be deployed to Docker Hub.
WORK-IN-PROGRESS
## Instructions - Plain vanilla deployment ##
- Create a directory structure on your system as follows:
```
mkdir /opt/Zabbix-Mailgraph
mkdir /opt/Zabbix-Mailgraph/config
mkdir /opt/Zabbix-Mailgraph/templates
```
- Create a new `config.json` in the above `config` directory and configure accordingly (refer to the wiki for more detailed instructions or use the `config.json.template` as a boilerplate).
- Copy the `plain.template` and `html.template` into the above `templates` directory.
- Deploy the mailGraph container, preferably using `docker-compose`:
-- Adopt and configure the `docker-compose.yml` file to your needs;
-- Configure `RESTART_POLICY=unless-stopped` in a file name `.env` (same directory as `docker-compose`).
- Start the container: `docker-compose -D up`.
- Follow best-practices on your applicable Linux version to ensure the container is started after a reboot.
When running:
- mailGraph is exposed on port `9080` (point the Zabbix webhook to this location).
- Apache logging is exposed on `/opt/Zabbix-Mailgraph/apache.log`.
## Testing and Debugging ##
- Display currently running containers `docker ps`.
- Execute `docker exec -it <container name> sh` for a shell into the container.
- Following the instructions in the Wiki on troubleshooting and debugging, i.e.:
-- `cd /var/www/site/public`
-- `php mailGraph.test test`
- When done testing, `exit` the container.
## Periodic cleanup of images and logs ##
The following command must be run on a regular basis to clean up images and logs (add to cron for example):
- `docker exec -it <container name> cleanup`
## Custom deployment ##
In case you like to adjust the container to your needs, you can adopt and modiyfy the provisioned scripts and files in this directory.
Please do not forget to modify the repository name in `build.sh` and `docker-compose.yml`.
## Special thank you ##
I would like to express my gratitude to the following people that have actively contributed to bring bugs and improvements to my attention with regards for mailGraph on Docker:
- [dima-online](https://github.com/dima-online)

View File

@ -1,18 +0,0 @@
ServerName mailgraph.mydomain.com
<VirtualHost *:80>
ServerAdmin me@mydomain.com
DocumentRoot /var/www/site/public
<Directory /var/www/site/public>
Options Indexes FollowSymLinks MultiViews
AllowOverride All
Order deny,allow
Allow from all
</Directory>
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>

View File

@ -1,2 +0,0 @@
#!/bin/bash
docker build -t hoppa66/zabbix-mailgraph .

View File

@ -1,3 +0,0 @@
#!/bin/bash
cd /var/www/site/public
php mailGraph.php cleanup

View File

@ -1,13 +0,0 @@
version: '2.1'
services:
webhook:
image: hoppa66/zabbix-mailgraph:latest
restart: ${RESTART_POLICY}
hostname: mailgraph
ports:
- "9080:80"
volumes:
- /opt/Zabbix-mailGraph/apache.log:/var/log/apache2:rw
- /opt/Zabbix-mailGraph/config:/var/www/site/public/config:ro
- /opt/Zabbix-mailGraph/templates:/var/www/site/public/templates:ro

View File

@ -1,3 +0,0 @@
#!/bin/bash
rm -rf www
git clone https://github.com/moudsen/mailGraph.git www

Binary file not shown.

Before

Width:  |  Height:  |  Size: 85 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 95 KiB

BIN
images/Example-mail-message.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 67 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 115 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 55 KiB

View File

@ -1 +0,0 @@
Issue #32 has been resolved. The javascript code now works for Zabbix 5.4, 6.0 LTS and 6.4.

View File

@ -1,99 +0,0 @@
// mailGraph v2.20
// Function to test string
function isJSON(str) {
try {
JSON.stringify(JSON.parse(str));
return true;
} catch (e) {
return false;
}
}
try {
// Pickup parameters
params = JSON.parse(value),
req = new HttpRequest(),
fields = {},
resp = '',
result = { tags: {} };
// Set HTTP proxy if required
if (typeof params.HTTPProxy === 'string' && params.HTTPProxy.trim() !== '') {
req.setProxy(params.HTTPProxy);
fields.HTTPProxy = params.HTTPProxy;
}
// Declare output type
req.addHeader('Content-Type: application/json');
// Pick up fields relevant for mailGraph API level call while parsing/casting fields that should be integer
fields.itemId = params.itemId * 1;
fields.eventId = params.eventId * 1;
fields.recipient = params.recipient;
fields.baseURL = params.baseURL;
fields.duration = params.duration * 1;
if (fields.recipient.charAt(0) == '{') {
throw '[MailGraph Webhook] Please define recipient for the test message!';
}
// Optional fields
if (typeof params.graphWidth === 'string') { fields.graphWidth = params.graphWidth; }
if (typeof params.graphHeight === 'string') { fields.graphHeight = params.graphHeight; }
if (typeof params.subject === 'string') { fields.subject = params.subject; }
if (typeof params.showLegend === 'string') { fields.showLegend = params.showLegend; }
if (typeof params.periods === 'string') { fields.periods = params.periods; }
if (typeof params.periods_headers === 'string') { fields.periods_headers = params.periods_headers; }
if (typeof params.debug === 'string') { fields.debug = params.debug; }
// Add generic fields
Object.keys(params).forEach(function(key) {
if (key.substring(0, 4) == 'info') {
fields[key] = params[key];
}
});
// Post information to the processing script
Zabbix.Log(4, '[MailGraph Webhook] Sending request: ' + params.URL + '?' + JSON.stringify(fields));
var resp = req.post(params.URL,JSON.stringify(fields));
Zabbix.Log(4, '[Mailgraph Webhook] Received response:' + resp);
// The response can be
// - did not receive status 200 as result (contains HTTP server response)
// - null (no response received at all)
// - empty string (likely no e-mail sent due to recipient issue)
// - not json (debugging message for troubleshooting or configuration hints)
// - json (contains the mail message ID sent)
if (req.getStatus() != 200) {
throw '[MailGraph Webhook] Processing of mailGraph.php failed: ' + resp;
}
if (resp==null) {
throw '[MailGraph Webhook] No response received from mailGraph.php? This should not occur (check URL and your webserver!)';
}
if (resp=='') {
throw '[MailGraph Webhook] No data received from mailGraph - please check recipient address or mailGraph log and retry.';
}
// Check if JSON was returned
if (!isJSON(resp)) {
throw '[MailGraph Webhook] An error has occurred during processing: ' + resp;
}
// We expect the message id back from the processing script response in JSON format
msg = JSON.parse(resp);
result.tags.__message_id = msg.messageId;
Zabbix.Log(4, '[MailGraph Webhook] Message sent with identification "' + msg.messageId + '"');
// Pass the result back to Zabbix
return JSON.stringify(result);
}
catch (error)
{
// In case something else went wrong in the processing, pass the error back to Zabbix
Zabbix.Log(127, 'MailGraph notification failed: '+error);
throw 'MailGraph notification failed : '+error;
}

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<zabbix_export>
<version>5.4</version>
<date>2023-08-16T20:38:38Z</date>
<version>5.0</version>
<date>2021-02-28T20:27:03Z</date>
<media_types>
<media_type>
<name>MailGraph</name>
@ -9,7 +9,7 @@
<parameters>
<parameter>
<name>baseURL</name>
<value>https://myzabbix.com/zabbix/</value>
<value>https://domain.com/zabbix/</value>
</parameter>
<parameter>
<name>duration</name>
@ -19,6 +19,10 @@
<name>eventId</name>
<value>{EVENT.ID}</value>
</parameter>
<parameter>
<name>eventValue</name>
<value>{EVENT.VALUE}</value>
</parameter>
<parameter>
<name>graphHeight</name>
<value>120</value>
@ -32,16 +36,8 @@
<value/>
</parameter>
<parameter>
<name>infoTest</name>
<value>Test</value>
</parameter>
<parameter>
<name>periods</name>
<value>10m,4h,1d,7d</value>
</parameter>
<parameter>
<name>periods_headers</name>
<value>Last 10 minutes,Last 4 hours,Last day,Last 7 days</value>
<name>itemId</name>
<value>{ITEM.ID}</value>
</parameter>
<parameter>
<name>recipient</name>
@ -53,163 +49,156 @@
</parameter>
<parameter>
<name>subject</name>
<value>{{ HOST_NAME|raw }}: ({{ EVENT_SEVERITY }}) {{ EVENT_NAME|raw }}</value>
<value>{{ HOST_NAME }}: ({{ EVENT_SEVERITY }}) {{ EVENT_NAME }}</value>
</parameter>
<parameter>
<name>triggerId</name>
<value>{TRIGGER.ID}</value>
</parameter>
<parameter>
<name>URL</name>
<value>https://myzabbix.com/mailGraph.php</value>
<value>https://domain.com/mailGraph.php</value>
</parameter>
</parameters>
<script>// mailGraph v2.20
// Function to test string
function isJSON(str) {
try {
JSON.stringify(JSON.parse(str));
return true;
} catch (e) {
return false;
}
}
try {
// Pickup parameters
params = JSON.parse(value),
req = new HttpRequest(),
fields = {},
resp = '',
result = { tags: {} };
// Set HTTP proxy if required
if (typeof params.HTTPProxy === 'string' &amp;&amp; params.HTTPProxy.trim() !== '') {
req.setProxy(params.HTTPProxy);
fields.HTTPProxy = params.HTTPProxy;
}
// Declare output type
req.addHeader('Content-Type: application/json');
// Pick up fields relevant for mailGraph API level call while parsing/casting fields that should be integer
fields.itemId = params.itemId * 1;
fields.eventId = params.eventId * 1;
fields.recipient = params.recipient;
fields.baseURL = params.baseURL;
fields.duration = params.duration * 1;
if (fields.recipient.charAt(0) == '{') {
throw '[MailGraph Webhook] Please define recipient for the test message!';
}
// Optional fields
if (typeof params.graphWidth === 'string') { fields.graphWidth = params.graphWidth; }
if (typeof params.graphHeight === 'string') { fields.graphHeight = params.graphHeight; }
if (typeof params.subject === 'string') { fields.subject = params.subject; }
if (typeof params.showLegend === 'string') { fields.showLegend = params.showLegend; }
if (typeof params.periods === 'string') { fields.periods = params.periods; }
if (typeof params.periods_headers === 'string') { fields.periods_headers = params.periods_headers; }
if (typeof params.debug === 'string') { fields.debug = params.debug; }
// Add generic fields
Object.keys(params).forEach(function(key) {
if (key.substring(0, 4) == 'info') {
fields[key] = params[key];
}
});
// Post information to the processing script
Zabbix.Log(4, '[MailGraph Webhook] Sending request: ' + params.URL + '?' + JSON.stringify(fields));
var resp = req.post(params.URL,JSON.stringify(fields));
Zabbix.Log(4, '[Mailgraph Webhook] Received response:' + resp);
// The response can be
// - did not receive status 200 as result (contains HTTP server response)
// - null (no response received at all)
// - empty string (likely no e-mail sent due to recipient issue)
// - not json (debugging message for troubleshooting or configuration hints)
// - json (contains the mail message ID sent)
if (req.getStatus() != 200) {
throw '[MailGraph Webhook] Processing of mailGraph.php failed: ' + resp;
}
if (resp==null) {
throw '[MailGraph Webhook] No response received from mailGraph.php? This should not occur (check URL and your webserver!)';
}
if (resp=='') {
throw '[MailGraph Webhook] No data received from mailGraph - please check recipient address or mailGraph log and retry.';
}
// Check if JSON was returned
if (!isJSON(resp)) {
throw '[MailGraph Webhook] An error has occurred during processing: ' + resp;
}
// We expect the message id back from the processing script response in JSON format
msg = JSON.parse(resp);
result.tags.__message_id = msg.messageId;
Zabbix.Log(4, '[MailGraph Webhook] Message sent with identification &quot;' + msg.messageId + '&quot;');
// Pass the result back to Zabbix
return JSON.stringify(result);
}
catch (error)
{
// In case something else went wrong in the processing, pass the error back to Zabbix
Zabbix.Log(127, 'MailGraph notification failed: '+error);
throw 'MailGraph notification failed : '+error;
<script>try {&#13;
// Pickup parameters&#13;
params = JSON.parse(value),&#13;
req = new CurlHttpRequest(),&#13;
fields = {},&#13;
resp = '',&#13;
result = { tags: {} };&#13;
&#13;
// Set HTTP proxy if required&#13;
if (typeof params.HTTPProxy === 'string' &amp;&amp; params.HTTPProxy.trim() !== '') { req.setProxy(params.HTTPProxy); }&#13;
&#13;
// Declare output type&#13;
req.AddHeader('Content-Type: application/json');&#13;
&#13;
// Must have fields&#13;
fields.itemId = params.itemId;&#13;
fields.triggerId = params.triggerId;&#13;
fields.eventId = params.eventId;&#13;
fields.eventValue = params.eventValue;&#13;
fields.recipient = params.recipient;&#13;
fields.baseURL = params.baseURL;&#13;
fields.duration = params.duration;&#13;
&#13;
// Optional fields&#13;
if (typeof params.graphWidth === 'string') { fields.graphWidth = params.graphWidth; }&#13;
if (typeof params.graphHeight === 'string') { fields.graphHeight = params.graphHeight; }&#13;
if (typeof params.subject === 'string') { fields.subject = params.subject; }&#13;
if (typeof params.showLegend === 'string') { fields.showLegend = params.showLegend; }&#13;
&#13;
// Post information to the processing script&#13;
Zabbix.Log(4, '[MailGraph Webhook] Sending request: ' + params.URL + '?' + JSON.stringify(fields));&#13;
var resp = req.Post(params.URL,JSON.stringify(fields));&#13;
Zabbix.Log(4, '[Mailgraph Webhook] Receiving response:' + resp);&#13;
&#13;
// If there was an error, report it&#13;
if (req.Status() != 200) { throw JSON.parse(resp).errors[0]; }&#13;
&#13;
// We expect the message id back from the processing script&#13;
resp = JSON.parse(resp);&#13;
result.tags.__message_id = resp.messageId;&#13;
&#13;
// Pass the result back to Zabbix&#13;
return JSON.stringify(result);&#13;
}&#13;
catch (error)&#13;
{&#13;
// In case something went wrong in the processing, pass the error back to Zabbix&#13;
Zabbix.Log(127, 'MailGraph notification failed : '+error);&#13;
throw 'MailGraph notification failed : '+error;&#13;
}</script>
<process_tags>YES</process_tags>
<description>The &quot;URL&quot; must point to the location of the processing script. If a proxy is required, define &quot;HTTPProxy&quot; for the proxy address.
Customization:
- &quot;graphWidth&quot; and &quot;graphWidth&quot; can be defined for the image size
- &quot;showLegend&quot; can be defined to show or hide the legend of the graph
- &quot;subject&quot; can be defined for a customized subject for the mail message
- &quot;periods&quot; and &quot;periods_headers&quot; can be defined for displaying multiple periods of the same graph, or
- &quot;period&quot; and &quot;period_header&quot; can be defined to display a single graph
The html.template and plain.template files can be adjusted (TWIG format).
More details are available at https://github.com/moudsen/mailGraph</description>
<description>The &quot;URL&quot; must point to the location of the processing script. If a proxy is required, define &quot;HTTPProxy&quot; for the proxy address.&#13;
&#13;
Customization:&#13;
- &quot;graphWidth&quot; and &quot;graphWidth&quot; can be defined for the image size&#13;
- &quot;showLegend&quot; can be defined to show or hide the legend of the graph&#13;
- &quot;subject&quot; can be defined for a customized subject for the mail message&#13;
&#13;
The html.template and plain.template files can be adjusted (TWIG format).&#13;
&#13;
Values available:&#13;
{{ baseURL }} - base url of the Zabbix system (use for references to API and login)&#13;
{{ TRIGGER_ID }} - id of the applicable trigger&#13;
{{ TRIGGER_DESCRIPTION }} - raw trigger description (note: macros are not parsed!)&#13;
{{ TRIGGER_COMMENTS }} - comments of the trigger&#13;
{{ TRIGGER_URL }} - url of the trigger form&#13;
{{ ITEM_ID }} - id of the associated item to the trigger&#13;
{{ ITEM_KEY }} - key of the item&#13;
{{ ITEM_NAME }} - item name&#13;
{{ ITEM_DESCRIPTION }} - description of the item&#13;
{{ ITEM_LASTVALUE }} - last value of the item&#13;
{{ ITEM_PREVIOUSVALUE }} - the value of the before LASTVALUE&#13;
{{ ITEM_URL }} - url of the item form&#13;
{{ HOST_ID }} - id of the associated host to the item&#13;
{{ HOST_NAME }} - name of the host&#13;
{{ HOST_ERROR }} - last error state of the applicable host&#13;
{{ HOST_DESCRIPTION }} - description of the host&#13;
{{ HOST_URL }} - url of the host form&#13;
{{ EVENT_ID }} - id of the associated event&#13;
{{ EVENT_NAME }} - name of the event (note: macros are parsed!)&#13;
{{ EVENT_OPDATA }} - associated operational data of the vent&#13;
{{ EVENT_VALUE }} - event state (0=Recovered, 1=Triggered/Active)&#13;
{{ EVENT_SEVERITY }} - severity of the event&#13;
{{ EVENT_STATUS }} - status of the event&#13;
{{ EVENT_URL }} - url of the event details&#13;
{{ GRAPH_ID }} - id of the (first) associated graph that contains the item&#13;
{{ GRAPH_NAME }} - name of this graph&#13;
{{ GRAPH_URL }} - URL to this graph (assuming script produces to an accessible location)&#13;
{{ GRAPH_CID }} - IMG embed string (&lt;img src=&quot;{{ GRAPH_CID }}&quot; /&gt;)&#13;
{{ LOG_HTML }} - script log in HTML format&#13;
{{ LOG_PLAIN }} - script log in PLAIN text format</description>
<message_templates>
<message_template>
<event_source>TRIGGERS</event_source>
<operation_mode>PROBLEM</operation_mode>
<subject>Problem: {EVENT.NAME}</subject>
<message>Problem started at {EVENT.TIME} on {EVENT.DATE}
Problem name: {EVENT.NAME}
Host: {HOST.NAME}
Severity: {EVENT.SEVERITY}
Operational data: {EVENT.OPDATA}
Original problem ID: {EVENT.ID}
Trigger ID (/url): {TRIGGER.ID} {TRIGGER.URL}</message>
<message>Problem started at {EVENT.TIME} on {EVENT.DATE}&#13;
Problem name: {EVENT.NAME}&#13;
Host: {HOST.NAME}&#13;
Severity: {EVENT.SEVERITY}&#13;
Operational data: {EVENT.OPDATA}&#13;
Original problem ID: {EVENT.ID}&#13;
{TRIGGER.URL}&#13;
&#13;
eventId: {EVENT.ID}&#13;
TriggerId: {TRIGGER.ID}&#13;
itemId: {ITEM.ID]</message>
</message_template>
<message_template>
<event_source>TRIGGERS</event_source>
<operation_mode>RECOVERY</operation_mode>
<subject>Resolved in {EVENT.DURATION}: {EVENT.RECOVERY.NAME}</subject>
<message>Problem has been resolved at {EVENT.RECOVERY.TIME} on {EVENT.RECOVERY.DATE}
Problem name: {EVENT.RECOVERY.NAME}
Problem duration: {EVENT.DURATION}
Host: {HOST.NAME}
Severity: {EVENT.SEVERITY}
Original problem ID: {EVENT.ID}
Trigger ID: {TRIGGER.ID} {TRIGGER.URL}</message>
<subject>Resolved in {EVENT.DURATION}: {EVENT.NAME}</subject>
<message>Problem has been resolved at {EVENT.RECOVERY.TIME} on {EVENT.RECOVERY.DATE}&#13;
Problem name: {EVENT.NAME}&#13;
Problem duration: {EVENT.DURATION}&#13;
Host: {HOST.NAME}&#13;
Severity: {EVENT.SEVERITY}&#13;
Original problem ID: {EVENT.ID}&#13;
{TRIGGER.URL}&#13;
&#13;
eventId: {EVENT.ID}&#13;
TriggerId: {TRIGGER.ID}&#13;
itemId: {ITEM.ID]</message>
</message_template>
<message_template>
<event_source>TRIGGERS</event_source>
<operation_mode>UPDATE</operation_mode>
<subject>Updated problem in {EVENT.AGE}: {EVENT.NAME}</subject>
<message>{USER.FULLNAME} {EVENT.UPDATE.ACTION} problem at {EVENT.UPDATE.DATE} {EVENT.UPDATE.TIME}.
{EVENT.UPDATE.MESSAGE}
Current problem status is {EVENT.STATUS}, age is {EVENT.AGE}, acknowledged: {EVENT.ACK.STATUS}.
Event ID: {EVENT.ID}
Trigger ID: {TRIGGER.ID}</message>
<message>{USER.FULLNAME} {EVENT.UPDATE.ACTION} problem at {EVENT.UPDATE.DATE} {EVENT.UPDATE.TIME}.&#13;
{EVENT.UPDATE.MESSAGE}&#13;
&#13;
Current problem status is {EVENT.STATUS}, age is {EVENT.AGE}, acknowledged: {EVENT.ACK.STATUS}.&#13;
&#13;
eventId: {EVENT.ID}&#13;
TriggerId: {TRIGGER.ID}&#13;
itemId: {ITEM.ID]</message>
</message_template>
</message_templates>
</media_type>
</media_types>
</zabbix_export>

View File

@ -1,209 +1,74 @@
<html lang="en"><head><meta http-equiv=Content-Type content="text/html; charset=UTF-8">
<style>
body {
font-family: Arial,sans-serif;
}
.Resolved {
background-color:#86cc89;
border:1px solid #57bd5b;
}
.Information {
background-color:#7499ff;
border:1px solid #4673f0;
}
.Warning {
background-color:#FFC859;
border:1px solid #E69F10;
}
.Average {
background-color:#FFA059;
border:1px solid #e66e15;
}
.High {
background-color:#E97659;
border:1px solid #E45959;
}
.Disaster {
background-color:#E45959;
border:1px solid #DE1E09;
}
a {
text-decoration: none;
color: #010059;
}
a:link {
text-decoration: none;
color: #010059;
}
a:visited {
text-decoration: none;
color: #010059;
}
a:active {
text-decoration: none;
color: #010059;
}
hr {
border: none;
height: 1px;
color: #333; /* old IE */
background-color: #333;
}
.MsgBody {
width: 100%;
}
#maintable {
width: 800px;
}
@media screen and (max-width: 800px;) {
#maintable {
width: 100%;
max-width: 790px;
}
#mainimage {
-ms-interpolation-mode: bicubic;
width: 100%;
max-width: 790px;
max-height: 450px;
}
}
.links {
font-size: 9px;
}
.header {
font-size: 16px;
font-weight: bold;
}
.graphHeader {
font-size: 14px;
font-weight: bold;
}
.content {
font-size: 14px;
}
.acknowledge {
font-size: 10px;
}
.Resolved {
background-color:#86cc89;
border:1px solid #57bd5b;
font-family:Tahoma,Geneva,Arial,sans-serif;font-size:14px;
}
.Information {
background-color:#7499ff;
border:1px solid #4673f0;
font-family:Tahoma,Geneva,Arial,sans-serif;font-size:14px;
}
.Warning {
background-color:#FFC859;
border:1px solid #E69F10;
font-family:Tahoma,Geneva,Arial,sans-serif;font-size:14px;
}
.Average {
background-color:#FFA059;
border:1px solid #e66e15;
font-family:Tahoma,Geneva,Arial,sans-serif;font-size:14px;
}
.High {
background-color:#E97659;
border:1px solid #E45959;
font-family:Tahoma,Geneva,Arial,sans-serif;font-size:14px;
}
.Disaster {
background-color:#E45959;
border:1px solid #DE1E09;
font-family:Tahoma,Geneva,Arial,sans-serif;font-size:14px;
}
</style>
</head>
<body>
<table style="margin: 5px;border-spacing:0 10px;border-collapse: separate;" align=center>
<tr>
<td class="{{ EVENT_SEVERITY }}" style="border-radius:10px;padding:5px 18px 5px 18px; ">
<table class="{{ EVENT_SEVERITY }}" style="border:0; text-align:left;" cellpadding="0" cellspacing="0">
<tr>
<td>
<p><span class="header">EVENT INFORMATION</span></p>
<span class="content">
Description: <b>{{ EVENT_NAME }}</b><br/>
Host: <b>{{ HOST_NAME }}</b>
<table style="margin: 10px;border-spacing:0 15px;border-collapse: separate;">
<tr>
<td class="{{ EVENT_SEVERITY }}" style="border-radius:10px;padding: 10px 36px 10px 36px; ">
<table class="{{ EVENT_SEVERITY }}" style="border:0; text-align:left;" cellpadding="0" cellspacing="0">
<tr><td>
<p><b>EVENT INFORMATION</b></p>
Description: <b>{{ EVENT_NAME }}</b><br/>
Host: <b>{{ HOST_NAME }}</b>
{% if HOST_ERROR|length > 0 %}
({{ HOST_ERROR }})
({{ HOST_ERROR }})
{% endif %}
<br/>
{% if EVENT_OPDATA|length > 0 %}
Operational data: <b>{{ EVENT_OPDATA }}</b><br/>
{% endif %}
Status: <b>{{ EVENT_STATUS }}</b><br/>
Severity: <b>{{ EVENT_SEVERITY }}</b><br/>
<br/>
Operational data: <b>{{ EVENT_OPDATA }}</b><br/>
Status: <b>{{ EVENT_STATUS }}</b><br/>
Severity: <b>{{ EVENT_SEVERITY }}</b><br/>
{% if EVENT_SEVERITY == "Resolved" %}
Duration: <b>{{ EVENT_DURATION }}</b><br/>
Duration: <b>{{ EVENT_DURATION }}</b><br/>
{% endif %}
Item: <b>{{ ITEM_NAME }}</b><br/>
Previous/Last: {{ ITEM_PREVIOUSVALUE }} ==&gt; {{ ITEM_LASTVALUE }}
</span>
</td>
</tr>
</table>
{% if ACKNOWLEDGES|length > 0 %}
<br/>
{% for anAck in ACKNOWLEDGES %}
<table style="border:0; text-align:left;" cellpadding="5" cellspacing="0">
<tr>
<td class="acknowledge">
<b>{{ anAck._clock }}</b><br/><em>({{ anAck.username }}, {{ anAck.name }} {{ anAck.surname }})</em><br/>[{{ anAck._actions }}]<br/>{{ anAck.message }}
</td>
</tr>
</table>
{% endfor %}
Item: <b>{{ ITEM_NAME }}</b><br/>
Previous/Last: {{ ITEM_PREVIOUSVALUE }} ==&gt; {{ ITEM_LASTVALUE }}
<p><a href="{{ EVENTDETAILS_URL }}">Event Details</a><br/></p>
</td></tr>
</table>
</td>
</tr>
{% if GRAPH_CID|length > 0 %}
<tr>
<td align="center"><img src="{{ GRAPH_CID }}" /></td>
</tr>
{% endif %}
</td>
</tr>
<tr>
<td class="links">
<div align=center>
Event ID: <a href="{{ EVENTDETAILS_URL }}">{{ EVENT_ID }}</a> //
Trigger ID: <a href="{{ TRIGGER_URL }}">{{ TRIGGER_ID }}</a> //
Item ID: <a href="{{ ITEM_URL }}">{{ ITEM_ID }}</a> //
Host ID: <a href="{{ HOST_URL }}">{{ HOST_ID }}</a> //
<a href="{{ HOST_PROBLEMS_URL }}">Problems</a>
{% if GRAPH_ZABBIXLINK|length > 0 %}
// Graph ID: <a href="{{ GRAPH_ZABBIXLINK }}">{{ GRAPH_ID }}</a>
{% endif %}
// <a href="{{ ACK_URL }}">Ack</a>
</div>
</td>
</tr>
{% for aGraph in GRAPHS_I %}
<tr>
<div align=justify>
<td align="center">
<span class="graphHeader">{{ aGraph.HEADER }}</span><br/>
<img id="mainimage" border=0 style="width: 100%; max-width: 790px" alt="Zabbix Graph" src="{{ aGraph.CID }}" />
</td>
</div>
</tr>
{% endfor %}
{% if TRIGGER_SCREEN > 0 %}
<tr>
<div align=justify>
<td align="center">
<span class="graphHeader">{{ GRAPHS_T_HEADER }} - {{ GRAPHS_T_PERIODHEADER }}</span>
</td>
</div>
</tr>
<tr>
<td class="links">
<div align="center">
Screen ID: <a href="{{ GRAPHS_T_LINK }}">{{ TRIGGER_SCREEN }}</a>
</div>
</td>
</tr>
{% for aGraph in GRAPHS_T %}
<tr>
<div align=justify>
<td align="center">
<img id="mainimage" border=0 style="width: 100%; max-width: 790px" alt="Zabbix Graph" src="{{ aGraph.CID }}" />
</td>
</div>
</tr>
{% endfor %}
{% endif %}
{% if HOST_SCREEN > 0 %}
<tr>
<div align=justify>
<td align="center">
<span class="graphHeader">{{ GRAPHS_H_HEADER }} - {{ GRAPHS_H_PERIODHEADER }}</span>
</td>
</div>
</tr>
<tr>
<td class="links">
<div align="center">
Screen ID: <a href="{{ GRAPHS_H_LINK }}">{{ HOST_SCREEN }}</a>
</div>
</td>
</tr>
{% for aGraph in GRAPHS_H %}
<tr>
<div align=justify>
<td align="center">
<img id="mainimage" border=0 style="width: 100%; max-width: 790px" alt="Zabbix Graph" src="{{ aGraph.CID }}" />
</td>
</div>
</tr>
{% endfor %}
{% endif %}
</table>
</table>
<p style="font-size:10px">
Event ID: <a href="{{ EVENTDETAILS_URL }}">{{ EVENT_ID }}</a> //
Trigger ID: <a href="{{ TRIGGER_URL }}">{{ TRIGGER_ID }}</a> //
Item ID: <a href="{{ ITEM_URL }}">{{ ITEM_ID }}</a> //
Host ID: <a href="{{ HOST_URL }}">{{ HOST_ID }}</a>
</p>
</body>
</html>

View File

@ -3,10 +3,10 @@ EVENT INFORMATION #{{ EVENT_ID }}
Severity: {{ EVENT_SEVERITY }}
Description: {{ EVENT_NAME }}
{% if GRAPH_CID1|length > 0 %}
GRAPH #{{ GRAPH_ID1 }}
{{ GRAPH_URL1 }}
This graph will remain available for approx. the next 2 weeks only; use HTML reader after this period to view the graph that is embedded in the attached HTML version.
{% if GRAPH_CID|length > 0 %}
GRAPH #{{ GRAPH_ID }}
{{ GRAPH_URL }}
This graph will remain available for approx. the next 2 weeks only; use HTML reader after this period to view the graph.
{% endif %}
TRIGGER #{{ TRIGGER_ID }}