From 57975385196f4ee65fc4148aed9ac6fe7655061f Mon Sep 17 00:00:00 2001
From: Mark Oudsen <mark.oudsen@puzzl.nl>
Date: Fri, 5 Mar 2021 11:57:01 +0100
Subject: [PATCH] Several enhancements and bugfixes - getting ready for v1.20
 release (v1.19)

---
 config/config.json.template    |   2 +-
 javascript/zabbix.mailGraph.js |  57 ++++++++++++++
 mailGraph.php                  | 136 ++++++++++++++++++---------------
 mailGraph.xml                  | 125 +++++++++++++-----------------
 4 files changed, 183 insertions(+), 137 deletions(-)
 create mode 100644 javascript/zabbix.mailGraph.js

diff --git a/config/config.json.template b/config/config.json.template
index 6887cc2..ffe15a4 100644
--- a/config/config.json.template
+++ b/config/config.json.template
@@ -6,7 +6,7 @@
     "cli_eventValue": 0,
     "cli_duration": 0,
     "cli_recipient": "recipient@domain.com",
-    "cli_subject": "{{ HOST_NAME|raw }}:  ({{ EVENT_SEVERITY }}) {{ EVENT_NAME|raw }}",
+    "cli_subject": "[CLI TEST] {{ HOST_NAME|raw }}:  ({{ EVENT_SEVERITY }}) {{ EVENT_NAME|raw }}",
     "cli_baseURL": "https:\/\/domain.com\/zabbix\/",
     "zabbix_user": "alogicalusername",
     "zabbix_user_pwd": "astrongpassword",
diff --git a/javascript/zabbix.mailGraph.js b/javascript/zabbix.mailGraph.js
new file mode 100644
index 0000000..caa831e
--- /dev/null
+++ b/javascript/zabbix.mailGraph.js
@@ -0,0 +1,57 @@
+try {
+    // Pickup parameters
+    params = JSON.parse(value),
+        req = new CurlHttpRequest(),
+        fields = {},
+        resp = '',
+        result = { tags: {} };
+
+    // Set HTTP proxy if required
+    if (typeof params.HTTPProxy === 'string' && params.HTTPProxy.trim() !== '') { req.setProxy(params.HTTPProxy); }
+
+    // Declare output type
+    req.AddHeader('Content-Type: application/json');
+
+    // Must have fields
+    fields.itemId = params.itemId;
+    fields.triggerId = params.triggerId;
+    fields.eventId = params.eventId;
+    fields.eventValue = params.eventValue;
+    fields.recipient = params.recipient;
+    fields.baseURL = params.baseURL;
+    fields.duration = params.duration;
+
+    // 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; }
+
+    // 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] Receiving response:' + resp);
+
+    // If there was an error, report it
+    if (req.Status() != 200) { throw JSON.parse(resp).errors[0]; }
+
+    // We expect the message id back from the processing script
+    resp = JSON.parse(resp);
+    result.tags.__message_id = resp.messageId;
+
+    // Pass the result back to Zabbix
+    return JSON.stringify(result);
+}
+catch (error)
+{
+    // In case something went wrong in the processing, pass the error back to Zabbix
+    Zabbix.Log(127, 'MailGraph notification failed : '+error);
+    throw 'MailGraph notification failed : '+error;
+}
\ No newline at end of file
diff --git a/mailGraph.php b/mailGraph.php
index 8426a4d..9ee4718 100644
--- a/mailGraph.php
+++ b/mailGraph.php
@@ -21,8 +21,9 @@
     // 1.16 2021/03/02 - Mark Oudsen - Found issue with graph.get not returning graphs to requested item ids
     //                                 Workaround programmed (fetch host graphs, search for certain itemids)
     // 1.17 2021/03/02 - Mark Oudsen - Added ability to specify period of time displayed in the graph
-    // 1.18 2021/03/04 - Mark Oudsen - Added ability to specify a deviating period of time per trigger
-    //                                 Added ability to specify different graph to be embedded
+    // 1.18 2021/03/04 - Mark Oudsen - Added ability to specify Tags per trigger
+    //                                 Shorten long "lastvalue" or "prevvalue"
+    // 1.19 2021/03/05 - Mark Oudsen - Added ability to pass Zabbix 'infoXXX' parameters for TWIG template
     // ------------------------------------------------------------------------------------------------------
     //
     // (C) M.J.Oudsen, mark.oudsen@puzzl.nl
@@ -45,7 +46,7 @@
 
     // CONSTANTS
 
-    $cVersion = 'v1.18';
+    $cVersion = 'v1.19';
     $cCRLF = chr(10).chr(13);
     $maskDateTime = 'Y-m-d H:i:s';
 
@@ -346,7 +347,7 @@
     _log('# Data passed from Zabbix'.$cCRLF.json_encode($problemData,JSON_PRETTY_PRINT|JSON_NUMERIC_CHECK));
 
     // --- CHECK AND SET P_ VARIABLES ---
-    // FROM POST OR CLI DATA ---
+    // FROM POST OR CLI DATA
 
     if (!isset($problemData['itemId'])) { echo "Missing ITEM ID?\n"; die; }
     $p_itemId = intval($problemData['itemId']);
@@ -384,6 +385,13 @@
     $p_period = '48h';
     if (isset($problemData['period'])) { $p_period = $problemData['period']; }
 
+    // DYNAMIC VARIABLES FROM ZABBIX
+
+    foreach($problemData as $aKey=>$aValue)
+    {
+        if (substr($aKey,0,4)=='info') { $mailData[$aKey] = $aValue; }
+    }
+
     // FROM CONFIG DATA
 
     $p_smtp_server = 'localhost';
@@ -501,16 +509,32 @@
 
     foreach($thisTrigger['result'][0]['tags'] as $aTag)
     {
-        if ($aTag['tag']=='mailGraph.period')
+        switch ($aTag['tag'])
         {
-            $p_period = $aTag['value'];
-            _log('+ Graph display period override = '.$p_period);
-        }
+            case 'mailGraph.period':
+                $p_period = $aTag['value'];
+                _log('+ Graph display period override = '.$p_period);
+                break;
 
-        if ($aTag['tag']=='mailGraph.graph')
-        {
-            $forceGraph = intval($aTag['value']);
-            _log('+ Graph ID to display = '.$forceGraph);
+            case 'mailGraph.graph':
+                $forceGraph = intval($aTag['value']);
+                _log('+ Graph ID to display = '.$forceGraph);
+                break;
+
+            case 'mailGraph.showLegend':
+                $p_showLegend = intval($aTag['value']);
+                _log('+ Graph display legend override = '.$p_showLegend);
+                break;
+
+            case 'mailGraph.graphWidth':
+                $p_graphWidth = intval($aTag['value']);
+                _log('+ Graph height override = '.$$p_graphWidth);
+                break;
+
+            case 'mailGraph.graphHeight':
+                $p_graphHeight = intval($aTag['value']);
+                _log('+ Graph height override = '.$$p_graphHeight);
+                break;
         }
     }
 
@@ -543,6 +567,10 @@
     if (substr($mailData['ITEM_LASTVALUE'],0,5)=='<?xml') { $mailData['ITEM_LASTVALUE'] = '[record]'; }
     if (substr($mailData['ITEM_PREVIOUSVALUE'],0,5)=='<?xml') { $mailData['ITEM_PREVIOUSTVALUE'] = '[record]'; }
 
+    // Catch long elements
+    if (strlen($mailData['ITEM_LASTVALUE'])>50) { $mailData['ITEM_LASTVALUE'] = substr($mailData['ITEM_LASTVALUE'],0,50).' ...'; }
+    if (strlen($mailData['ITEM_PREVIOUSVALUE'])>50) { $mailData['ITEM_PREVIOUSVALUE'] = substr($mailData['ITEM_PREVIOUSVALUE'],0,50).' ...'; }
+
     // --- GET HOST INFO ---
 
     _log('# Retrieve HOST information');
@@ -712,63 +740,45 @@
 
     // If we have any matching graph, make the embedding information available
 
-    if ($forceGraph>0)
+    if ((sizeof($matchedGraphs) + sizeof($otherGraphs) + $forceGraph)>0)
     {
-        _log('# Adding FORCED graph #'.$forceGraph);
-        $graphFile = GraphImageById($forceGraph,
+        if ($forceGraph>0)
+        {
+            $theGraph = $forceGraphInfo;
+            $theType = 'Forced';
+        }
+        else
+        {
+            if (sizeof($matchedGraphs)>0)
+            {
+                $theGraph = $matchedGraphs[0];
+                $theType = 'Matched';
+            }
+            else
+            {
+                if (sizeof($otherGraphs)>0)
+                {
+                    $theGraph = $otherGraphs[0];
+                    $theType = 'Other';
+                }
+            }
+        }
+
+        $mailData['GRAPH_ID'] = $theGraph['graphid'];
+        $mailData['GRAPH_NAME'] = $theGraph['name'];
+        $mailData['GRAPH_MATCH'] = $theType;
+
+        _log('# Adding '.strtoupper($theType).' graph #'.$mailData['GRAPH_ID']);
+
+        $graphFile = GraphImageById($mailData['GRAPH_ID'],
                                     $p_graphWidth,$p_graphHeight,
-                                    $forceGraphInfo['result'][0]['graphtype'],
+                                    $theGraph['graphtype'],
                                     $p_showLegend,$p_period);
 
         _log('> Filename = '.$graphFile);
 
-        $mailData['GRAPH_ID'] = $forceGraph;
-        $mailData['GRAPH_NAME'] = $forceGraphInfo['result'][0]['name'];
         $mailData['GRAPH_URL'] = $z_url_image . $graphFile;
-        $mailData['GRAPH_MATCH'] = 'Forced';
-    }
-    else
-    {
-        if ((sizeof($matchedGraphs)+sizeof($otherGraphs))>0)
-        {
-            // Exact match goes first
-
-            if (sizeof($matchedGraphs)>0)
-            {
-                _log('# Adding MATCHED graph #'.$matchedGraphs[0]['graphid']);
-                $graphFile = GraphImageById($matchedGraphs[0]['graphid'],
-                                            $p_graphWidth,$p_graphHeight,
-                                            $matchedGraphs[0]['graphtype'],
-                                            $p_showLegend,$p_period);
-
-                _log('> Filename = '.$graphFile);
-
-                $mailData['GRAPH_ID'] = $matchedGraphs[0]['graphid'];
-                $mailData['GRAPH_NAME'] = $matchedGraphs[0]['name'];
-                $mailData['GRAPH_URL'] = $z_url_image . $graphFile;
-                $mailData['GRAPH_MATCH'] = 'Exact';
-            }
-            else
-            {
-                if (($p_graph_match!='exact') && (sizeof($otherGraphs)>0))
-                {
-                    _log('# Adding OTHER graph #'.$otherGraphs[0]['graphid']);
-                    $graphFile = GraphImageById($otherGraphs[0]['graphid'],
-                                                $p_graphWidth,$p_graphHeight,
-                                                $otherGraphs[0]['graphtype'],
-                                                $p_showLegend);
-
-                    _log('> Filename = '.$graphFile);
-
-                    $mailData['GRAPH_ID'] = $otherGraphs[0]['graphid'];
-                    $mailData['GRAPH_NAME'] = $otherGraphs[0]['name'];
-                    $mailData['GRAPH_URL'] = $z_url_image . $graphFile;
-                    $mailData['GRAPH_MATCH'] = 'Other';
-                }
-            }
-
-            $mailData['GRAPH_ZABBIXLINK'] = $z_server.'/graphs.php?form=update&graphid='.$mailData['GRAPH_ID'];
-        }
+        $mailData['GRAPH_ZABBIXLINK'] = $z_server.'/graphs.php?form=update&graphid='.$mailData['GRAPH_ID'];
     }
 
     // Prepare HTML LOG content
@@ -917,4 +927,4 @@
         file_put_contents($z_log_path.$logName,$content);
 	_log('= Log stored to '.$z_log_path.$logName);
     }
-?>
+?>
\ No newline at end of file
diff --git a/mailGraph.xml b/mailGraph.xml
index 4eb846d..b6669ba 100755
--- a/mailGraph.xml
+++ b/mailGraph.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <zabbix_export>
     <version>5.0</version>
-    <date>2021-02-28T20:27:03Z</date>
+    <date>2021-03-05T10:51:39Z</date>
     <media_types>
         <media_type>
             <name>MailGraph</name>
@@ -9,7 +9,7 @@
             <parameters>
                 <parameter>
                     <name>baseURL</name>
-                    <value>https://domain.com/zabbix/</value>
+                    <value>https://mydomain.com/zabbix/</value>
                 </parameter>
                 <parameter>
                     <name>duration</name>
@@ -35,6 +35,10 @@
                     <name>HTTPProxy</name>
                     <value/>
                 </parameter>
+                <parameter>
+                    <name>infoGiveMeAName</name>
+                    <value>A generic value you want to pass to MailGraph</value>
+                </parameter>
                 <parameter>
                     <name>itemId</name>
                     <value>{ITEM.ID}</value>
@@ -57,58 +61,65 @@
                 </parameter>
                 <parameter>
                     <name>URL</name>
-                    <value>https://domain.com/mailGraph.php</value>
+                    <value>https://mydomain.com/mailGraph.php</value>
                 </parameter>
             </parameters>
             <script>try {&#13;
-  // Pickup parameters&#13;
-  params = JSON.parse(value),&#13;
-           req = new CurlHttpRequest(),&#13;
-           fields = {},&#13;
-           resp = '',&#13;
-           result = { tags: {} };&#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;
+    // 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;
+    // 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;
+    // 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;
+    // 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;
+    // Add generic fields&#13;
+    Object.keys(params).forEach(function(key) {&#13;
+        if (key.substring(0, 4) == 'info') {&#13;
+            fields[key] = params[key];&#13;
+        }&#13;
+    });&#13;
 &#13;
-  // If there was an error, report it&#13;
-  if (req.Status() != 200) { throw JSON.parse(resp).errors[0]; }&#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;
-  // We expect the message id back from the processing script&#13;
-  resp = JSON.parse(resp);&#13;
-  result.tags.__message_id = resp.messageId;&#13;
+    // If there was an error, report it&#13;
+    if (req.Status() != 200) { throw JSON.parse(resp).errors[0]; }&#13;
 &#13;
-  // Pass the result back to Zabbix&#13;
-  return JSON.stringify(result);&#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;
+    // 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.&#13;
@@ -120,38 +131,7 @@ Customization:&#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;
-{{ GRAPH_ZABBIXLINK }} - URL to the graph item in Zabbix
-{{ LOG_HTML }} - script log in HTML format&#13;
-{{ LOG_PLAIN }} - script log in PLAIN text format</description>
+More details are available at https://github.com/moudsen/mailGraph</description>
             <message_templates>
                 <message_template>
                     <event_source>TRIGGERS</event_source>
@@ -202,4 +182,3 @@ itemId: {ITEM.ID]</message>
         </media_type>
     </media_types>
 </zabbix_export>
-