Embed images in e-mail’s body using Microsoft Flow
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! 🙂
so what do i writein the body email then : s
Hi! You can write whatever HTML you want. My approach just replaces images in the HTML body contents with their base64 definitions.
i am new to using expression on microsoft flow.
Could you please tell me more how can i extract image using expression?
Hi, sure! I’m doing it in less straightforward way. First, I split the whole message body using the ‘src=”‘ token:
split(variables('var_Body_Str'), 'src="'). Then, for each token (split creates an array), I am extracting substring from its beginning until the quote char, what should always return a full image path:
substring(item(), 0, indexOf(item(), '"')). Then, I am building an absolute path to the image and using action “Get file content using path” I am getting file contents which then I am transforming to the right base64 structure.
Could you help me?
on a flow, i need to first get an embed image (or more than one) from an e-mail body then i need to send it on an another e-mail but now as an attachment.
It is very similar to what you already do.
I have a hard time following what needs to be done. Would you give me a step by step for what I need?
Well, it might be similar, but mustn’t 🙂 First, are you sure the images inside your e-mail are added as references to an asset stored elsewhere? So that in e-mail’s body HTML you can find “ October 25, 2018 at 8:21 am
Looks great! Just a request, can you post screenshots of your steps. I am really new to Flow, so I keep getting lost.
I think the post itself is very descriptive. Where are you getting stuck exactly?
Thank you for the solution. Will be possible for you to send screenshots of the steps. Looks like I am not getting the steps correctly.
this works only for OUtlook web not the native desktop version
I’m nearly sure I checked it also for desktop clients, however that is possible it only works for online client 🙂 Nevertheless this way of embedding images into e-mails, using base64 strings, used to be working for desktop clients for sure! 🙂
Hello Tomasr! I need a help with this.
Hi, what kind of help? Please reach me out via the contact form 😀
We had the same issue and found out that it is blocked by Outlook completely: https://blog.mailtrap.io/embedding-images-in-html-email-have-the-rules-changed/
We ended up getting it to work in the web version of Outlook, but not the desktop version. It worked intermittently on Mobile.
Hi! Thanks for sharing. Good to know.
Hi Tomasz, can you assist in adding image to email body for desktop client. Specific steps would be helpful! Thanks.
Hi, what exactly are you missing? Where are you stuck?
Thanks for the posts, I am having issue with this hope you can help!
I am using OneDrive Get file content
That gives me this output!
Then I get base64 by using the function in a compose action:
Then I use a second compose to add the extra bits:
Finally, I just the output of the second compose in the email body:
However, the image does not show up I get empty image tag in the email!
I have tried this as well:
Still no luck!
Where are you trying to display it? What application?
Hello Tomasz, Could you share screenshots an the code for this clever solution?
I have an email coming with a signature included in a cid attachment, when converting to HTML the signature is gone so I wanted to find and encode the image, I’m new to MS Flow.
Thank you in advance.
Hey! Honestly speaking I don’t have it anymore. It turned out to be not that very much usable, since this approach was only supported by Outlook. So eg. when sending to Gmail it was not working. But what you should do is to simply get the attachment and then use dataUri expression. Check out this post to get a bigger picture: https://poszytek.eu/en/microsoft-en/office-365-en/powerautomate-en/powerapps-hand-written-signature/ (starting from “Microsoft Flow” header).
Hello Tomasz, i followed the logic in the post above and managed to embed the image using Base64 encoding. The image shows in outlook desktop and doesnt render in outlook web or the app.
That’s the limit of the technology. The image this way will not be displayed in Gmail either. To avoid it you must store images somewhere publicly (like Azure Storage) and reference to them.
I was trying to send a mail with variable text on top of image by using base 64 image as background for table on it. It looks perfect in browser but when I send mail the background disappears in outlook . If I open the mail in browser it works. Is there a way to get it work in outlook
Hi, this approach might not work in Outlook. You can consider other ways of embedding images: https://www.campaignmonitor.com/blog/email-marketing/embedded-images-in-html-email/.
I am looking for the same solution.
when I receive mail from someone that mail has a PNG attachment. I want to forward it to someone I can do using simple flow.
I first use trigger with receive mail and then send to someone in the next step,
only thing is I want that next step png file to be going as an attachment but I want that to be in body mail. can you help me with it?
Well… since you do have the contents of the files already, I think you should be able to simply follow the steps describe in the post.