Embed images not working on IOS devices

Hi,

Currently i’m busy with getting the template working by attaching a graph image to an email.
The thing is that when i’m at home and see a CPU alert in my inbox, it would be great if i can see a CPU graph.

So I after searching on the interweb, i came across this post: https://community.librenms.org/t/feature-request-embed-images-into-email/. When reading it, i saw that Dohald and Chas make it work; i then went to GitHub and looked at the specific PR 8646, i attached the code from here: https://github.com/librenms/librenms/pull/8646/files#diff-f81f3dff36bf04b7a070d642c858e883 into the functions.php.

 $mail->Body = $message;
        if ($html) {
            $mail->isHTML(true);
            //Addding functionality to support cid embedded graphs
            $arrContextOptions=array(
                "ssl"=>array(
                "verify_peer"=>false,
                "verify_peer_name"=>false,
                "timeout" => 1200,
                ),
                );
            preg_match_all('/ alt=\"(.*?)\"/', $mail->Body, $match);
            $countcheck = 0;
            $newcidhtml = $mail->Body;
            foreach ($match[1] as $item) {
                $newcidhtml=preg_replace("/\bembedimage\b/i", $countcheck, $newcidhtml, 1);
                $image = file_get_contents($item, false, stream_context_create($arrContextOptions));
                if ($config['webui']['graph_type'] == 'svg') {
                    $mail->addStringEmbeddedImage($image, $countcheck, 'graph.svg', 'base64', 'image/svg+xml');
                } else {
                    $mail->addStringEmbeddedImage($image, $countcheck, 'graph.png', 'base64', 'image/png');
                }
                $countcheck++;
            }
            $mail->Body = $newcidhtml;
        }
        switch (strtolower(trim($config['email_backend']))) {
            case 'sendmail':

So far so good.

I then added this code to my template, based on the input from Dohald; that didn’t work either at first: <img width="700" height="300" src="cid:embedimage" alt="http://myserver/graph.php?&type=device_processor&lazy_w=805&device=%hostname&?=yes&height=486&width=1656&from=end-1h">

I had to change the link in the alt; replacing the ampersand with slashes and i had to replace the cid:embedimage with cid:graph.png; after this, i could see the graph in my Outlook 2016 client.

<img src="cid:graph.png" alt="https://monitor.domain.nl/graph.php/device={{ $alert->device_id }}/type=device_processor/width=800/height=300/lazy_w=552/from=end-1h">

But now i wanted also it viewable in my native IOS mail app, and there i’m stuck; the graph doesnt show; it is just a blank square; i even can’t see the alt text within it; so it looks like it is loaded, but on the otherhand it is not.

Anybody idea’s how to fix this?

Thanks for checking out my pull request :slight_smile:

Unfortunately it didn’t get merged, and i’ve since moved to a different alert transport. The code has updated a lot since nearly exactly 1 year ago. :smiley: so there is probably something that needs updating.

Your rather on your own here, and remember modifying core files like functions.php will break future LibreNMS upgrades. To restore the old file you will need to run ./scripts/github-remove -d which removes all custom files in your librenms directory.

By all means have a play around, firstly it followed the same concept as current html embedded images, I think as you say the embed URL may have changed and maybe you don’t right click copy image address, and you copy the main graph page URL instead. According to example with img src in the docs #https://docs.librenms.org/Alerting/Templates/#examples-html

Also i noticed “%hostname” is using old format from old templating, so bare that in mind. You could try replace using the new format as per docs {{ $alert->hostname }} then maybe the ampersand method does work.

Ensure you can see that link unauthenticated using that config parameter in the PR.

Now as you changed to cid:graph.png, this shouldn’t work, the logic i added specifically finds “embedimage” and this part should not have been changed. I think you broke it if there are multiple images into the alert by making that change.

It should work on IOS mail app, maybe check your General Settings -> WebUI settings -> and change from svg to png or vice-versa, as some mail clients do not support svg embeds.

Also check on IOS

  1. Open the settings app.
  2. Select “Mail, Contacts, Calendars.”
  3. Set the “Load Remote Images” to ON .

Good luck!

Hi Chas,

Ok, understood :slight_smile:

So I will ditch the custom functions.php, and go for the Laravel approach; that being said; i’ve done the following so far:

created a new PHP file under /opt/librenms/resources/views/alerts/templates. The file i named is cpu.blade.php.

The cpu.blade.php is filled with the following code:

<html>
	<head>
	<meta http-equiv="content-type" content="multipart/alternative; charset=UTF-8">
	</head>
<div style="font-family:Helvetica;">
	<h2> @if ($alert->state == 1) <span style="color:red;">Warning @endif 
	 @if ($alert->state == 2) <span style="color:goldenrod;">Planned load @endif </span>
	 @if ($alert->state == 3) <span style="color:green;">It is recovering @endif </span>
	 @if ($alert->state == 0) <span style="color:green;">Recovered @endif </span>
	</h2>
    <body>
        <div class="container">
            @yield('content')
        </div>
    </body>
</html>

After this i created a new alert template and filled it with:

@extends('alerts.templates.cpu')

@section('content')
 <b>Hostname:</b> {{ $alert->hostname }}<br>
 <b>Limit:</b> 90 %<br>
 <b>CPU Load Length:</b> {{ $alert->elapsed }}<br>
 <br>
 <br>
 <br>
 <br>
 <b>Faults:</b><br>
  @if ($alert->faults)                                                                                     
  @foreach ($alert->faults as $key => $value)#{{ $key }}: {{ $value['string'] }}<br>
  @endforeach                                                                                                              
  @endif 
@endsection

But now the million dollar question; how can i fit in a embeded image here?
I’ve found so far this link https://laravel.com/docs/5.1/mail#inline-attachments and it says that i must use this code for inline attachments:

<body>
    Here is an image:

    <img src="<?php echo $message->embed($pathToFile); ?>">
</body>

But where and how must i fit this is in? I tried in the alert template; but i would go further due to a error.

Also i have no clue where and what i must do to get a inline image in the mail.

The thing is, is that i want to see on my phone when i’m not in office what is going on via a graph that is embedded :slight_smile:

Thanks in advance!

Interesting! Looks like you got quite far already, didn’t know laravel has something for it. Looks like it might not work though with markdown emails, i see some workarounds, how about the asset approach? https://stackoverflow.com/questions/42503168/laravel-5-4-embed-image-in-mail

Hi Chas,

I’ve taken a look at the code provided via your link and found the following code that works, but more in a way “close but no sigar”

<img src="data:image/png;base64,{{base64_encode(file_get_contents('https://monitor.host.nl/graph.php/device=2/type=device_processor/width=800/height=300/lazy_w=552/from=end-1h'))}}" alt="">

This code provides a base64 encoded html line in the mail; both my Outlook 2016 and my native iOS Mail app show the picture now (jeej! :star_struck:).

But now the final part; the device you see is device id=2; this can be done dynamically. Normal way to do this is via {{ $alert->device-id}} ; but when i try this in the following code:

<img src="data:image/png;base64,{{base64_encode(file_get_contents('https://monitor.host.nl/graph.php/device={{ $alert->device_id }}/type=device_processor/width=800/height=300/lazy_w=552/from=end-1h'))}}" alt="">

It can’t save the alert template in LibreNMS; it error’s out that there is a error. :exploding_head:

I suspect that I can’t do a {{}} within in {{ }} .

Any idea’s how to fix this? I’ve got the feeling i’m almost there…

I thought that might be the better answer on there, i remember specifying image/png and encoding with base64 was very important for mail clients.

I think its {{ $value['device_id'] }} you could try without the brackets too as they are already used. (although i don’t really know)

and also , you might want to check out using {!! !!} not sure if it may be useful

Found it!

The working code is as follows:

 @foreach ($alert->faults as $key => $value)
 Graph for the last hour:<br>
 <img src="data:image/png;base64,{{base64_encode(file_get_contents('https://monitor.local/graph.php/device=' . $value['device_id'] . '/type=device_processor/width=800/height=300/lazy_w=552/from=end-1h'))}}" alt=""><br> 
 @endforeach

I had to to make sure it fiddled in the code : @foreach ($alert->faults as $key => $value) and had to make sure the variable for the device started with a SPACE and DOT and SPACE; the same for after the variable and all of this between two quotation marks. That’s it!

Now only if MS Webmail could show the image; only my iOS device and Outlook 2016 can show it (while this is enough for now); it would also be a nice to have to let MS Webmail show the image. Anybody ideas on this ?

Cool that you got it working by using templating.

Did you check the top of the email in office365, sometimes it gets blocked.

Try;

Specify Width & Height

switch to SVG in librenms the change your type image/svg+xml

I got only empty (0KB size large) Base64 converted SVG to png images in email attachments and it will not display CID attachments :thinking:

Example: graph.zip

I followed all the above steps with that result.
Can anyone help me out?

Kindly regards.
Chris,

Hi @CircumFlex_sigma
Could you start a new PR (or continue the existing one) with your code so we can review it and merge it for the community ?
Thanx

Hi PipoCanaja,

Sure no problem, sorry for the late delay, but this is the code i use in my template that alerts me.

Please look carefully in the ; the FQDN should be set correctly :slight_smile:

Kind regards,
David

@extends('alerts.templates.default')

@section('content')
 <b>Hostname:</b> {{ $alert->hostname }} ({{ $alert->sysName }})<br>
 <b>System:</b> {{ $alert->sysDescr }}<br>
 <b>Uptime:</b> {{ $alert->uptime_short }}<br>
 <b>Limit:</b> {{ $alert->name }}<br>
 <b>Time elapsed:</b> {{ $alert->elapsed }}<br>
 <br>
 @foreach ($alert->faults as $key => $value)
 <b>Physical Interface:</b> {{ $value['ifDescr'] }}<br>
 <b>Interface Description:</b> {{ $value['ifAlias'] }}<br>
 <b>Interface Speed:</b> {{ ($value['ifSpeed']/1000000000) }} Gbs<br>
 <b>Inbound Utilization:</b> @php echo number_format(((($value['ifOutOctets_rate']*8)/$value['ifSpeed'])*100*100),1); @endphp Mbps<br>
 <b>Outbound Utilization:</b> @php echo number_format(((($value['ifInOctets_rate']*8)/$value['ifSpeed'])*100*100),1); @endphp Mbps<br>
 <br>
 @endforeach
 <br>
 @foreach ($alert->faults as $key => $value)
 <b>Graph for the last hour for interface {{ $value['ifDescr'] }}:</b><br>
 <img src="data:image/png;base64,{{base64_encode(file_get_contents('https://FQDN.ofyour.librenms-server/graph.php/id=' . $value['port_id'] . '/type=port_bits/width=800/height=300/lazy_w=552/from=end-1h'))}}" alt=""><br>
 <br>
 @endforeach
 <br>
 <br>
 <b>Faults:</b><br>
  @if ($alert->faults)
  @foreach ($alert->faults as $key => $value)#{{ $key }}: {{ $value['string'] }}<br>
  @endforeach
  @endif
@endsection
1 Like

HI, CircumFlex_sigma I am trying your code and unfortunately, the images do not show up on the email only a blank space if I do a view source of the email this is what I get. I validated and the FQDN is correct. please let me know what I am doing wrong.

have the same problem with embed images in the Company Mails, an explanation for the empty/broken graph src=“data:image/png;base64,” and the base64_encode → (oh, we use MS Outlook :sweat_smile:)

Some bad news about base64 encoded images:

  • totally blocked by Outlook