diff --git a/LibreNMS/Alert/Transport/Mail.php b/LibreNMS/Alert/Transport/Mail.php
index 324578fd17..76ff0660a9 100644
--- a/LibreNMS/Alert/Transport/Mail.php
+++ b/LibreNMS/Alert/Transport/Mail.php
@@ -46,7 +46,7 @@ class Mail extends Transport
$msg = preg_replace("/(?config['attach-graph'] ?? null);
}
public static function configTemplate()
@@ -59,6 +59,13 @@ class Mail extends Transport
'descr' => 'Email address of contact',
'type' => 'text',
],
+ [
+ 'title' => 'Include Graphs',
+ 'name' => 'attach-graph',
+ 'descr' => 'Include graph image data in the email. Will be embedded if html5, otherwise attached. Template must use @signedGraphTag',
+ 'type' => 'checkbox',
+ 'default' => true,
+ ],
],
'validation' => [
'email' => 'required|email',
diff --git a/LibreNMS/Data/Store/Rrd.php b/LibreNMS/Data/Store/Rrd.php
index b732fffb19..92dae88252 100644
--- a/LibreNMS/Data/Store/Rrd.php
+++ b/LibreNMS/Data/Store/Rrd.php
@@ -559,7 +559,6 @@ class Rrd extends BaseDatastore
* @param string $options
* @return string
*
- * @throws \LibreNMS\Exceptions\FileExistsException
* @throws \LibreNMS\Exceptions\RrdGraphException
*/
public function graph(string $options): string
@@ -568,9 +567,13 @@ class Rrd extends BaseDatastore
$process->setTimeout(300);
$process->setIdleTimeout(300);
- $command = $this->buildCommand('graph', '-', $options);
- $process->setInput($command . "\nquit");
- $process->run();
+ try {
+ $command = $this->buildCommand('graph', '-', $options);
+ $process->setInput($command . "\nquit");
+ $process->run();
+ } catch (FileExistsException $e) {
+ throw new RrdGraphException($e->getMessage(), 'File Exists');
+ }
$feedback_position = strrpos($process->getOutput(), 'OK ');
if ($feedback_position !== false) {
@@ -584,6 +587,9 @@ class Rrd extends BaseDatastore
$position += strlen($search);
throw new RrdGraphException(
substr($process->getOutput(), $position),
+ null,
+ null,
+ null,
$process->getExitCode(),
substr($process->getOutput(), 0, $position)
);
@@ -591,7 +597,7 @@ class Rrd extends BaseDatastore
// only error text was returned
$error = trim($process->getOutput() . PHP_EOL . $process->getErrorOutput());
- throw new RrdGraphException($error, $process->getExitCode(), '');
+ throw new RrdGraphException($error, null, null, null, $process->getExitCode());
}
private function getImageEnd(string $type): string
diff --git a/LibreNMS/Exceptions/RrdGraphException.php b/LibreNMS/Exceptions/RrdGraphException.php
index 3317ac6ff9..3c55e1cd5c 100644
--- a/LibreNMS/Exceptions/RrdGraphException.php
+++ b/LibreNMS/Exceptions/RrdGraphException.php
@@ -26,19 +26,48 @@
namespace LibreNMS\Exceptions;
use Exception;
+use LibreNMS\Util\Graph;
class RrdGraphException extends Exception
{
+ /** @var string */
protected $image_output;
+ /** @var string|null */
+ private $short_text;
+ /** @var int|string|null */
+ private $width;
+ /** @var int|string|null */
+ private $height;
- public function __construct($error, $exit_code, $image_output)
+ /**
+ * @param string $error
+ * @param string|null $short_text
+ * @param int|string|null $width
+ * @param int|string|null $height
+ * @param int $exit_code
+ * @param string $image_output
+ */
+ public function __construct($error, $short_text = null, $width = null, $height = null, $exit_code = 0, $image_output = '')
{
parent::__construct($error, $exit_code);
+ $this->short_text = $short_text;
$this->image_output = $image_output;
+ $this->width = $width;
+ $this->height = $height;
}
- public function getImage()
+ public function getImage(): string
{
return $this->image_output;
}
+
+ public function generateErrorImage(): string
+ {
+ return Graph::error(
+ $this->getMessage(),
+ $this->short_text,
+ empty($this->width) ? 300 : (int) $this->width,
+ empty($this->height) ? null : (int) $this->height,
+ );
+ }
}
diff --git a/LibreNMS/Util/Graph.php b/LibreNMS/Util/Graph.php
index 74e390195b..c40256c99d 100644
--- a/LibreNMS/Util/Graph.php
+++ b/LibreNMS/Util/Graph.php
@@ -25,12 +25,147 @@
namespace LibreNMS\Util;
+use App\Facades\DeviceCache;
use App\Models\Device;
+use Illuminate\Support\Facades\Auth;
use LibreNMS\Config;
+use LibreNMS\Exceptions\RrdGraphException;
+use Rrd;
class Graph
{
- public static function getTypes()
+ const BASE64_OUTPUT = 1; // BASE64 encoded image data
+ const INLINE_BASE64 = 2; // img src inline base64 image
+ const COMMAND_ONLY = 4; // just print the command
+
+ /**
+ * Fetch a graph image (as string) based on the given $vars
+ * Optionally, override the output format to base64
+ *
+ * @param array|string $vars
+ * @param int $flags Flags for controlling graph generating options.
+ * @return string
+ *
+ * @throws \LibreNMS\Exceptions\RrdGraphException
+ */
+ public static function get($vars, int $flags = 0): string
+ {
+ define('IGNORE_ERRORS', true);
+ chdir(base_path());
+
+ include_once base_path('includes/dbFacile.php');
+ include_once base_path('includes/common.php');
+ include_once base_path('includes/html/functions.inc.php');
+ include_once base_path('includes/rewrites.php');
+
+ // handle possible graph url input
+ if (is_string($vars)) {
+ $vars = Url::parseLegacyPathVars($vars);
+ }
+
+ [$type, $subtype] = extract_graph_type($vars['type']);
+
+ $graph_title = '';
+ if (isset($vars['device'])) {
+ $device = device_by_id_cache(is_numeric($vars['device']) ? $vars['device'] : getidbyname($vars['device']));
+ DeviceCache::setPrimary($device['device_id']);
+
+ //set default graph title
+ $graph_title = DeviceCache::getPrimary()->displayName();
+ }
+
+ // variables for included graphs
+ $width = $vars['width'] ?? 400;
+ $height = $vars['height'] ?? $width / 3;
+ $title = $vars['title'] ?? '';
+ $vertical = $vars['vertical'] ?? '';
+ $legend = $vars['legend'] ?? false;
+ $output = $vars['output'] ?? 'default';
+ $from = parse_at_time($vars['from'] ?? '-1d');
+ $to = empty($vars['to']) ? time() : parse_at_time($vars['to']);
+ $period = ($to - $from);
+ $prev_from = ($from - $period);
+ $graph_image_type = $vars['graph_type'] ?? Config::get('webui.graph_type');
+ Config::set('webui.graph_type', $graph_image_type); // set in case accessed elsewhere
+ $rrd_options = '';
+ $rrd_filename = null;
+
+ $auth = Auth::guest(); // if user not logged in, assume we authenticated via signed url, allow_unauth_graphs or allow_unauth_graphs_cidr
+ require base_path("/includes/html/graphs/$type/auth.inc.php");
+ if (! $auth) {
+ // We are unauthenticated :(
+ throw new RrdGraphException('No Authorization', 'No Auth', $width, $height);
+ }
+
+ if (is_customoid_graph($type, $subtype)) {
+ $unit = $vars['unit'];
+ require base_path('/includes/html/graphs/customoid/customoid.inc.php');
+ } elseif (is_file(base_path("/includes/html/graphs/$type/$subtype.inc.php"))) {
+ require base_path("/includes/html/graphs/$type/$subtype.inc.php");
+ } else {
+ throw new RrdGraphException("{$type}_$subtype template missing", "{$type}_$subtype missing", $width, $height);
+ }
+
+ if ($graph_image_type === 'svg') {
+ $rrd_options .= ' --imgformat=SVG';
+ if ($width < 350) {
+ $rrd_options .= ' -m 0.75 -R light';
+ }
+ }
+
+ // command output requested
+ if ($flags & self::COMMAND_ONLY) {
+ $cmd_output = "
";
+ $cmd_output .= "
RRDTool Command
";
+ $cmd_output .= "
";
+ $cmd_output .= escapeshellcmd('rrdtool ' . Rrd::buildCommand('graph', Config::get('temp_dir') . '/' . strgen(), $rrd_options));
+ $cmd_output .= '
';
+ try {
+ $cmd_output .= Rrd::graph($rrd_options);
+ } catch (RrdGraphException $e) {
+ $cmd_output .= "
RRDTool Output
";
+ $cmd_output .= "
";
+ $cmd_output .= $e->getMessage();
+ $cmd_output .= '
';
+ }
+ $cmd_output .= '
';
+
+ return $cmd_output;
+ }
+
+ if (empty($rrd_options)) {
+ throw new RrdGraphException('Graph Definition Error', 'Def Error', $width, $height);
+ }
+
+ // Generating the graph!
+ try {
+ $image_data = Rrd::graph($rrd_options);
+
+ // output the graph int the desired format
+ if (Debug::isEnabled()) {
+ return '
';
+ } elseif ($flags & self::BASE64_OUTPUT || $output == 'base64') {
+ return base64_encode($image_data);
+ } elseif ($flags & self::INLINE_BASE64 || $output == 'inline-base64') {
+ return 'data:' . self::imageType($graph_image_type) . ';base64,' . base64_encode($image_data);
+ }
+
+ return $image_data; // raw data
+ } catch (RrdGraphException $e) {
+ // preserve original error if debug is enabled, otherwise make it a little more user friendly
+ if (Debug::isEnabled()) {
+ throw $e;
+ }
+
+ if (isset($rrd_filename) && ! Rrd::checkRrdExists($rrd_filename)) {
+ throw new RrdGraphException('No Data file' . basename($rrd_filename), 'No Data', $width, $height, $e->getCode(), $e->getImage());
+ }
+
+ throw new RrdGraphException('Error: ' . $e->getMessage(), 'Draw Error', $width, $height, $e->getCode(), $e->getImage());
+ }
+ }
+
+ public static function getTypes(): array
{
return ['device', 'port', 'application', 'munin', 'service'];
}
@@ -42,7 +177,7 @@ class Graph
* @param Device $device
* @return array
*/
- public static function getSubtypes($type, $device = null)
+ public static function getSubtypes($type, $device = null): array
{
$types = [];
@@ -79,7 +214,7 @@ class Graph
* @param string $subtype
* @return bool
*/
- public static function isMibGraph($type, $subtype)
+ public static function isMibGraph($type, $subtype): bool
{
return Config::get("graph_types.$type.$subtype.section") == 'mib';
}
@@ -98,4 +233,70 @@ class Graph
return Config::get("os_group.$os_group.over", Config::get('os.default.over'));
}
+
+ /**
+ * Get the http content type of the image
+ *
+ * @param string $type svg or png
+ * @return string
+ */
+ public static function imageType(string $type): string
+ {
+ return $type === 'svg' ? 'image/svg+xml' : 'image/png';
+ }
+
+ /**
+ * Create image to output text instead of a graph.
+ *
+ * @param string $text Error message to display
+ * @param string|null $short_text Error message for smaller graph images
+ * @param int $width Width of graph image (defaults to 300)
+ * @param int|null $height Height of graph image (defaults to width / 3)
+ * @param int[] $color Color of text, defaults to dark red
+ * @return string the generated image
+ */
+ public static function error(string $text, ?string $short_text, int $width = 300, ?int $height = null, array $color = [128, 0, 0]): string
+ {
+ $type = Config::get('webui.graph_type');
+ $height = $height ?? $width / 3;
+
+ if ($short_text !== null && $width < 200) {
+ $text = $short_text;
+ }
+
+ if ($type === 'svg') {
+ $rgb = implode(', ', $color);
+
+ return <<
+SVG;
+ }
+
+ $img = imagecreate($width, $height);
+ imagecolorallocatealpha($img, 255, 255, 255, 127); // transparent background
+
+ $px = (int) ((imagesx($img) - 7.5 * strlen($text)) / 2);
+ $font = $width < 200 ? 3 : 5;
+ imagestring($img, $font, $px, ($height / 2 - 8), $text, imagecolorallocate($img, ...$color));
+
+ // Output the image
+ ob_start();
+ imagepng($img);
+ $output = ob_get_clean();
+ ob_end_clean();
+ imagedestroy($img);
+
+ return $output;
+ }
}
diff --git a/LibreNMS/Util/Mail.php b/LibreNMS/Util/Mail.php
index ff1406e328..738af32c18 100644
--- a/LibreNMS/Util/Mail.php
+++ b/LibreNMS/Util/Mail.php
@@ -27,6 +27,7 @@ namespace LibreNMS\Util;
use Exception;
use LibreNMS\Config;
+use LibreNMS\Exceptions\RrdGraphException;
use PHPMailer\PHPMailer\PHPMailer;
class Mail
@@ -70,7 +71,7 @@ class Mail
* @param bool $html
* @return bool|string
*/
- public static function send($emails, $subject, $message, bool $html = false)
+ public static function send($emails, $subject, $message, bool $html = false, ?bool $embedGraphs = null)
{
if (is_array($emails) || ($emails = self::parseEmails($emails))) {
d_echo("Attempting to email $subject to: " . implode('; ', array_keys($emails)) . PHP_EOL);
@@ -89,8 +90,11 @@ class Mail
$mail->CharSet = 'utf-8';
$mail->WordWrap = 76;
$mail->Body = $message;
+ if ($embedGraphs ?? Config::get('email_attach_graphs')) {
+ self::embedGraphs($mail);
+ }
if ($html) {
- $mail->isHTML(true);
+ $mail->isHTML();
}
switch (strtolower(trim(Config::get('email_backend')))) {
case 'sendmail':
@@ -124,4 +128,41 @@ class Mail
return 'No contacts found';
}
+
+ /**
+ * Search for generated graph links, generate them, attach them to the email and update the url to a cid link
+ */
+ private static function embedGraphs(PHPMailer $mail): void
+ {
+ $body = $mail->Body;
+
+ // search for generated graphs
+ preg_match_all('/ class=\"librenms-graph\" src=\"(.*?)\"/', $body, $match);
+
+ foreach (array_values(array_unique($match[1])) as $attachment_id => $url) {
+ try {
+ $cid = "graph$attachment_id";
+
+ // fetch image, do not debug as it will return the wrong format.
+ $prev = Debug::isEnabled();
+ Debug::set(false);
+ $image = Graph::get(Url::parseLegacyPathVars($url));
+ Debug::set($prev);
+
+ // attach image
+ if (Config::get('webui.graph_type') == 'svg') {
+ $mail->addStringEmbeddedImage($image, $cid, "$cid.svg", PHPMailer::ENCODING_BASE64, 'image/svg+xml');
+ } else {
+ $mail->addStringEmbeddedImage($image, $cid, "$cid.png", PHPMailer::ENCODING_BASE64, 'image/png');
+ }
+
+ // update image tag to link to attached image
+ $body = str_replace($url, "cid:$cid", $body);
+ } catch (RrdGraphException|\PHPMailer\PHPMailer\Exception $e) {
+ report($e);
+ }
+ }
+
+ $mail->Body = $body;
+ }
}
diff --git a/app/Http/Controllers/GraphController.php b/app/Http/Controllers/GraphController.php
index 52833b513e..a73d06e283 100644
--- a/app/Http/Controllers/GraphController.php
+++ b/app/Http/Controllers/GraphController.php
@@ -5,39 +5,38 @@ namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use LibreNMS\Config;
+use LibreNMS\Exceptions\RrdGraphException;
use LibreNMS\Util\Debug;
+use LibreNMS\Util\Graph;
use LibreNMS\Util\Url;
class GraphController extends Controller
{
+ /**
+ * @throws \LibreNMS\Exceptions\RrdGraphException
+ */
public function __invoke(Request $request, string $path = ''): Response
{
- define('IGNORE_ERRORS', true);
-
- include_once base_path('includes/dbFacile.php');
- include_once base_path('includes/common.php');
- include_once base_path('includes/html/functions.inc.php');
- include_once base_path('includes/rewrites.php');
-
- $auth = \Auth::guest(); // if user not logged in, assume we authenticated via signed url, allow_unauth_graphs or allow_unauth_graphs_cidr
$vars = array_merge(Url::parseLegacyPathVars($request->path()), $request->except(['username', 'password']));
+ $vars['graph_type'] = $vars['graph_type'] ?? Config::get('webui.graph_type');
+
if (\Auth::check()) {
// only allow debug for logged in users
Debug::set(! empty($vars['debug']));
}
- // TODO, import graph.inc.php code and call Rrd::graph() directly
- chdir(base_path());
- ob_start();
- include base_path('includes/html/graphs/graph.inc.php');
- $output = ob_get_clean();
- ob_end_clean();
+ $headers = [
+ 'Content-type' => Graph::imageType($vars['graph_type']),
+ ];
- $headers = [];
- if (! Debug::isEnabled()) {
- $headers['Content-type'] = (Config::get('webui.graph_type') == 'svg' ? 'image/svg+xml' : 'image/png');
+ try {
+ return response(Graph::get($vars), 200, Debug::isEnabled() ? [] : $headers);
+ } catch (RrdGraphException $e) {
+ if (Debug::isEnabled()) {
+ throw $e;
+ }
+
+ return response($e->generateErrorImage(), 500, $headers);
}
-
- return response($output, 200, $headers);
}
}
diff --git a/app/Providers/AppServiceProvider.php b/app/Providers/AppServiceProvider.php
index 95334dc4d1..63b69a967b 100644
--- a/app/Providers/AppServiceProvider.php
+++ b/app/Providers/AppServiceProvider.php
@@ -80,8 +80,8 @@ class AppServiceProvider extends ServiceProvider
return "'; ?>";
});
- Blade::directive('graphImage', function ($vars, $base64 = false) {
- return "";
+ Blade::directive('graphImage', function ($vars, $flags = 0) {
+ return "";
});
}
diff --git a/doc/Alerting/Transports.md b/doc/Alerting/Transports.md
index 66adf8d6d8..410f51a1d0 100644
--- a/doc/Alerting/Transports.md
+++ b/doc/Alerting/Transports.md
@@ -381,8 +381,18 @@ LibreNMS database.
## Mail
-The E-Mail transports uses the same email-configuration like the rest of LibreNMS.
-As a small reminder, here is it's configuration directives including defaults:
+The E-Mail transports uses the same email-configuration as the rest of LibreNMS.
+As a small reminder, here is its configuration directives including defaults:
+
+Emails will attach all graphs included with the @signedGraphTag directive.
+If the email format is set to html, they will be embedded.
+To disable attaching images, set email_attach_graphs to false.
+
+!!! setting "alerting/email"
+```bash
+lnms config:set email_html true
+lnms config:set email_attach_graphs false
+```
**Example:**
diff --git a/html/mix-manifest.json b/html/mix-manifest.json
index 5c089fa24f..439f47be48 100644
--- a/html/mix-manifest.json
+++ b/html/mix-manifest.json
@@ -5,12 +5,12 @@
"/css/app.css": "/css/app.css?id=bd093a6a2e2682bb59ef",
"/js/vendor.js": "/js/vendor.js?id=c5fd3d75a63757080dbb",
"/js/lang/de.js": "/js/lang/de.js?id=613b5ca9cd06ca15e384",
- "/js/lang/en.js": "/js/lang/en.js?id=6b3807ebe10e3fa9fa40",
+ "/js/lang/en.js": "/js/lang/en.js?id=b4dc5539b25bf7a31718",
"/js/lang/fr.js": "/js/lang/fr.js?id=982d149de32e1867610c",
"/js/lang/it.js": "/js/lang/it.js?id=e24bb9bad83e288b4617",
"/js/lang/ru.js": "/js/lang/ru.js?id=f6b7c078755312a0907c",
+ "/js/lang/sr.js": "/js/lang/sr.js?id=388e38b41f63e3517506",
"/js/lang/uk.js": "/js/lang/uk.js?id=34f8698ff09b869db2f5",
"/js/lang/zh-CN.js": "/js/lang/zh-CN.js?id=4e081fbac70d969894bf",
- "/js/lang/zh-TW.js": "/js/lang/zh-TW.js?id=ed26425647721a42ee9d",
- "/js/lang/sr.js": "/js/lang/sr.js?id=17585a0e001293ade0e1"
+ "/js/lang/zh-TW.js": "/js/lang/zh-TW.js?id=ed26425647721a42ee9d"
}
diff --git a/includes/html/functions.inc.php b/includes/html/functions.inc.php
index 58407da339..929f516cb9 100644
--- a/includes/html/functions.inc.php
+++ b/includes/html/functions.inc.php
@@ -11,7 +11,6 @@
*/
use LibreNMS\Config;
-use LibreNMS\Util\Debug;
use LibreNMS\Util\Number;
use LibreNMS\Util\Rewrite;
@@ -439,44 +438,7 @@ function generate_port_image($args)
*/
function graph_error($text, $color = [128, 0, 0])
{
- global $vars;
-
- $type = Config::get('webui.graph_type');
- if (! Debug::isEnabled()) {
- header('Content-type: ' . get_image_type($type));
- }
-
- $width = (int) ($vars['width'] ?? 150);
- $height = (int) ($vars['height'] ?? 60);
-
- if ($type === 'svg') {
- $rgb = implode(', ', $color);
- echo <<
-SVG;
- } else {
- $img = imagecreate($width, $height);
- imagecolorallocatealpha($img, 255, 255, 255, 127); // transparent background
-
- $px = ((imagesx($img) - 7.5 * strlen($text)) / 2);
- $font = $width < 200 ? 3 : 5;
- imagestring($img, $font, $px, ($height / 2 - 8), $text, imagecolorallocate($img, ...$color));
-
- // Output the image
- imagepng($img);
- imagedestroy($img);
- }
+ echo \LibreNMS\Util\Graph::error($text, null, 300, null, $color);
}
/**
@@ -1035,7 +997,7 @@ function eventlog_severity($eventlog_severity)
*/
function get_image_type(string $type)
{
- return $type === 'svg' ? 'image/svg+xml' : 'image/png';
+ return \LibreNMS\Util\Graph::imageType($type);
}
function get_oxidized_nodes_list()
diff --git a/includes/html/graphs/application/nginx_req.inc.php b/includes/html/graphs/application/nginx_req.inc.php
index 7b44cb469d..e4d13e2d99 100644
--- a/includes/html/graphs/application/nginx_req.inc.php
+++ b/includes/html/graphs/application/nginx_req.inc.php
@@ -16,6 +16,4 @@ if (Rrd::checkRrdExists($rrd_filename)) {
$rrd_options .= " GPRINT:a:LAST:'%6.2lf %s'";
$rrd_options .= " GPRINT:a:AVERAGE:'%6.2lf %s'";
$rrd_options .= " GPRINT:a:MAX:'%6.2lf %s\\n'";
-} else {
- $error_msg = 'Missing RRD';
}
diff --git a/includes/html/graphs/graph.inc.php b/includes/html/graphs/graph.inc.php
index 21f6dea89c..2de8b81602 100644
--- a/includes/html/graphs/graph.inc.php
+++ b/includes/html/graphs/graph.inc.php
@@ -42,13 +42,6 @@ if ($auth && is_customoid_graph($type, $subtype)) {
// Graph Template Missing");
}
-if (! empty($error_msg)) {
- // We have an error :(
- graph_error($error_msg);
-
- return;
-}
-
if ($auth === null) {
// We are unauthenticated :(
graph_error($width < 200 ? 'No Auth' : 'No Authorization');
@@ -83,13 +76,6 @@ if (! empty($command_only)) {
return;
}
-// graph sent file not found flag
-if (! empty($no_file)) {
- graph_error($width < 200 ? 'No Data' : 'No Data file ' . $no_file);
-
- return;
-}
-
if (empty($rrd_options)) {
graph_error($width < 200 ? 'Def Error' : 'Graph Definition Error');
diff --git a/misc/config_definitions.json b/misc/config_definitions.json
index 6ae7182f84..0cd182425b 100644
--- a/misc/config_definitions.json
+++ b/misc/config_definitions.json
@@ -1427,6 +1427,13 @@
"value": "smtp"
}
},
+ "email_attach_graphs": {
+ "default": true,
+ "group": "alerting",
+ "section": "email",
+ "order": 4,
+ "type": "boolean"
+ },
"email_backend": {
"default": "mail",
"group": "alerting",
diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon
index adc501dd7c..0b1a711817 100644
--- a/phpstan-baseline.neon
+++ b/phpstan-baseline.neon
@@ -2740,31 +2740,6 @@ parameters:
count: 1
path: LibreNMS/Exceptions/JsonAppWrongVersionException.php
- -
- message: "#^Method LibreNMS\\\\Exceptions\\\\RrdGraphException\\:\\:__construct\\(\\) has parameter \\$error with no type specified\\.$#"
- count: 1
- path: LibreNMS/Exceptions/RrdGraphException.php
-
- -
- message: "#^Method LibreNMS\\\\Exceptions\\\\RrdGraphException\\:\\:__construct\\(\\) has parameter \\$exit_code with no type specified\\.$#"
- count: 1
- path: LibreNMS/Exceptions/RrdGraphException.php
-
- -
- message: "#^Method LibreNMS\\\\Exceptions\\\\RrdGraphException\\:\\:__construct\\(\\) has parameter \\$image_output with no type specified\\.$#"
- count: 1
- path: LibreNMS/Exceptions/RrdGraphException.php
-
- -
- message: "#^Method LibreNMS\\\\Exceptions\\\\RrdGraphException\\:\\:getImage\\(\\) has no return type specified\\.$#"
- count: 1
- path: LibreNMS/Exceptions/RrdGraphException.php
-
- -
- message: "#^Property LibreNMS\\\\Exceptions\\\\RrdGraphException\\:\\:\\$image_output has no type specified\\.$#"
- count: 1
- path: LibreNMS/Exceptions/RrdGraphException.php
-
-
message: "#^Method LibreNMS\\\\Exceptions\\\\UnserializableRouteCache\\:\\:__construct\\(\\) has parameter \\$cli_php_version with no type specified\\.$#"
count: 1
@@ -5616,7 +5591,12 @@ parameters:
path: LibreNMS/Util/Graph.php
-
- message: "#^Method LibreNMS\\\\Util\\\\Graph\\:\\:getTypes\\(\\) has no return type specified\\.$#"
+ message: "#^Result of && is always false\\.$#"
+ count: 1
+ path: LibreNMS/Util/Graph.php
+
+ -
+ message: "#^Variable \\$rrd_filename in isset\\(\\) always exists and is always null\\.$#"
count: 1
path: LibreNMS/Util/Graph.php
diff --git a/resources/lang/en/settings.php b/resources/lang/en/settings.php
index f3d98bab5f..a1c7c4d2f7 100644
--- a/resources/lang/en/settings.php
+++ b/resources/lang/en/settings.php
@@ -625,6 +625,10 @@ return [
'description' => 'Auto TLS support',
'help' => 'Tries to use TLS before falling back to un-encrypted',
],
+ 'email_attach_graphs' => [
+ 'description' => 'Attach graph images',
+ 'help' => 'This will generate a graph when the alert is raised and attach it and embed it in the email.',
+ ],
'email_backend' => [
'description' => 'How to deliver mail',
'help' => 'The backend to use for sending email, can be mail, sendmail or SMTP',