Using email templates when sending emails with PowerApps
Using templates for sending emails has several advantages:
- A more consistent look and feel.
- App creators spent less time on email creation.
- Future updates to the look and feel are more easily implemented.
- Maintaining the look and feel can be delegated.
- Reuse of "code".
- Configurable settings are put outside the app.
Creating emails with a good look and feel is a specialty. Something an app creator not always possesses. Being able to separate the creation of an app and the creation of the look and feel of an email is therefor useful.
Canvas apps do not have native support for email templates but with some help of a data source, we can have this functionality nevertheless.
Data sources
Several data sources could be needed to store the email templates based on how email templates are used and based on the email content. Functional reasons are:
- The usage of company wide settings.
- The usage of app specific settings.
- Images.
A SharePoint Online list is an obvious choice for the first two reasons, though with PowerApps, several other options are possible too. The third reason could be more difficult when sending emails externally. The companies external website often make a good choice.
The SharePoint Online list for company wide settings must be accessible for all employees. For app specific settings, the SharePoint Online list needs to be accessible for all users of the app as a minimum. Yes, a more fine-grained setup is possible if only a subset of the app users in fact sent emails via the app, but it is left to the reader to decide how useful that really is.
Email templates
An email template could be as simple as one text block with one variable, but things get more complex when using company wide settings and when an email can contain multiple items. Both situations are shown in this blog post.
Both the simple and complex example use a SharePoint Online list called “Demo_Settings” containing two columns:
- Title
- MLoT
The first column (Title) contains unique names for the text blocks which are put in the second column (MLoT). The second column is of type “Multiple Lines of Text” (Plain text).
Simple example
In this example, only one text block is used. The text block is shown below and contains the variables {{User}} and {{Title}}. Using the double accolades is something I use to identify a variable. You can use your own implementation ofcourse.
Hi {{User}}, Your request with name "{{Title}}" has been submitted successfully. Kind regards, Your PowerApps Team
The variables are substituted with real values in the app just before sending the email. In this example, {{User}} is substituted with the name of the app user and {{Title}} is substituted with a value entered in a text input control. The text block is saved in the SharePoint list item where the field "Title" has the value "Email 1".
UpdateContext({emailBody: LookUp('Demo_Settings', Title="Email 1", MLoT)}); UpdateContext({emailBody: Substitute(emailBody, "{{User}}", User().FullName)}); UpdateContext({emailBody: Substitute(emailBody, "{{Title}}", DataCardValue1.Text)}); Office365.SendEmail(User().Email, "Your request has been submitted", emailBody)
Complex example
In this example, a HTML email is sent containing information about requested items. Five text blocks are used:
- Company wide header.
- Company wide footer.
- App specific header.
- App specific footer.
- Item.
The company wide header contains the css to style the email. To make this blog post not to long, this is omitted. Just sent me a private message if you are interested in the css.
Text block - Company wide header
<!DOCTYPE html> <html> <head> <style></style> </head> <body> <div id="header"> <img src="https://www.contoso.com/images/PowerApps.png"> </div>
Text block - Company wide footer
<div id="footer"></div> </body> </html>
Text block - App specific header
<p>Dear {{User}},</p> <p> You have just ordered the following devices: </p>
Text block - App specific footer
<p>Kind regards,<br />Your PowerApps team</p>
Text block - Item
<table id="tableItem"> <tr> <td><img src="{{VAR1}}"></td> <td class="Content"> <table id="tableContent"> <tr><td>Property 1</td><td>{{VAR2}}</td></tr> <tr><td>Property 2</td><td>{{VAR3}}</td></tr> <tr><td>Property 3</td><td>{{VAR4}}</td></tr> </table>
</td> </tr> </table>
The variables are substituted with real values in the app just before sending the email. The logic to do this is as expected more complex than the simple example. In this example, {{User}} is substituted with the name of the app user, {{VAR1}} is substituted with the url of the image of the item, {{VAR2}} is substituted with the values of property “Property 1”, {{VAR3}} is substituted with the values of property “Property 2” and {{VAR4}} is substituted with the values of property “Property 3”.
To better understand the low-code below, one must know that the app has a collection called “itemsCollection” with the following columns:
- ID
- VAR1
- VAR2
- VAR3
- VAR4
This collection contains all the items which should be shown in the email.
A new collection, called “itemsCollectionBody”, is created based on the collection “itemsCollection”. This new collection gets an extra column containing the text block “item” for all records. Using the ForAll function, the collection “itemsCollectionBody” is processed meaning that the remaining variables are substituted with real values. Then, again a new collection is created: itemsBody. This is a single column collection containing only the items. This collection is concatinated into a string, which is placed with the other 4 text blocks into a new variable. This variable is used when sending the email.
In this example, an email is sent when a button is clicked.
Property OnVisible of screen
UpdateContext({header: LookUp('Demo_Settings', Title="Header", MLoT)}); UpdateContext({footer: LookUp('Demo_Settings', Title="Footer", MLoT)}); UpdateContext({emailHeader: LookUp('Demo_Settings', Title="Email 2 - Header", MLoT)}); UpdateContext({emailFooter: LookUp('Demo_Settings', Title="Email 2 - Footer", MLoT)}); UpdateContext({item: LookUp('Demo_Settings', Title="Email 2 - Item", MLoT)}); UpdateContext({emailHeader: Substitute(emailHeader, "{{User}}", User().FullName)})
Property OnSelect of a button on same screen as mentioned above.
ClearCollect(itemsCollectionBody, AddColumns(itemsCollection, "Body", item)); ForAll(itemsCollection, UpdateIf(itemsCollectionBody, ID=ID, {Body: Substitute(Body, "{{VAR1}}", VAR1)}); UpdateIf(itemsCollectionBody, ID=ID, {Body: Substitute(Body, "{{VAR2}}", VAR2)}); UpdateIf(itemsCollectionBody, ID=ID, {Body: Substitute(Body, "{{VAR3}}", VAR3)}); UpdateIf(itemsCollectionBody, ID=ID, {Body: Substitute(Body, "{{VAR4}}", VAR4)}) ); Collect(itemsBody, ForAll(itemsCollectionBody, Body)); Set(body, header & emailHeader & Concat(itemsBody, Value & "") & emailFooter & footer); Office365.SendEmail(User().Email, "Your request has been submitted", body, {IsHtml:true, Importance:Normal})
A visualization of the sent email is shown below:
Comments
-
Using email templates when sending emails with PowerApps
Hi @alsabea,
Please check my latest blog post in the PowerApps community blog: https://powerusers.microsoft.com/t5/PowerApps-Community-Blog/Using-an-email-to-approve-or-decline-an-approval-request-using/ba-p/138619.
Rick
-
Using email templates when sending emails with PowerApps
That was soo nice to know, i wish you explain how to include button with the Email to finish task or some things.
*This post is locked for comments