Embed images in e-mail’s body using Microsoft Flow
Table of contents:
I was working on my newsletter’s solution, aimed to automatically send prepared messages hosted in my SharePoint. Naturally, newsletters often contain images. Lots of them frankly speaking. The most straightforward approach was to insert them as a URL to the physical file stored in SharePoint (described here). However, in that approach, if a recipient has no access to the site, where the file is hosted or is not yet logged in, the images won’t show up.
How to embed images into the body?
There are in fact three approaches:
- The “src” attribute pointing to the file hosted somewhere;
- The “src=cid” (Content-ID) – so the internal linking in the e-mail, if the file is physically attached to the e-mail it can be displayed inline using the “cid” (source);
- Embedding image using base64 encoded string, and the “src=data:image/jpeg;base64,<base64-encoded-image>” (or png, or gif) value of the src attribute (source).
Ad. 1 – it works like a charm, but as I mentioned above – only when user really has an access to the file.
Ad. 2 – Flow allows you to add only one attachment. You cannot add multiple (you can vote for it here). So the approach with showing images inline using the “cid method” is not very possible in case you want to show more than one file.
Ad. 3 – seemed to be feasible in Flow, however I was also aware, that unfortunately most of the e-mail clients do not support it. This old, but still up-to-date post shows support for base64 encoded images embedded in e-mails: https://www.campaignmonitor.com/blog/email-marketing/2013/02/embedded-images-in-html-email/
The base64 approach
As I wrote above, that is fairly easy to do. I managed to do it in couple of steps (having in mind that pure regular expressions are not yet available for Flow, vote for them here):
- First I processed the newsletter’s body, to extract all images paths. I did that using the “split” action using the ‘ src=” ‘ token (yes, with a quote).
- Then for each item from that array I checked, whether the string starts from “http” – if yes that meant the element is an URL to an image.
- I then extracted the image URL, using the following expression (so from its beginning to the closing quote):
substring(item(), 0, indexOf(item(), '"'))
- Then I used the action to get file contents from SharePoint using its path (split to the absolute site URL and then site-relative URL to the file).
- In return I received an object, from which I needed to get the “$contents” attribute and using it replace with the original “src” attribute’s value in my newsletter’s body. For that purpose I used the following expression:
replace(variables('var_Body_Str'), outputs('Image_Path'), concat('data:image/png;base64,', body('Get_file_content_using_path')?['$content']))
And basically that did the trick. When I previewed my Flow execution I saw that the HTML is constructed properly. When I opened sent e-mail in Outlook Web Access it also worked fine:
Thanks for reading! Do you have other ideas? Please share them! 🙂