Friday, 13 March 2020

How to send an email to multiple recipients using an Email Template

In my last WTF episode I shared how to send an email using an Email Template defined in Dynamics 365 or CDS. The constraint of that method is that it is valid for the use case of sending to a single recipient. When multiple recipients are required in the email, the SendTemplate unbound action is not suitable because of how you need to explicitly add the the recipient by clicking on "+ Add new item" within the action.

In today's WTF episode I share a different method in my flow in Power Automate for the use case of sending an email to multiple recipients dynamically using an email template.

Replicating sending an email with multiple recipients using an Email Template in Power Automate

The thing is, today in classic workflows it's not possible to achieve this out-of-the-box. You can elect to send to multiple recipients by selecting values from lookup fields when configuring the send email step and applying the "Use Template" option. However this is an explicit reference as it requires someone to reference those lookup fields within the send email step.


Another option is to add records directly through the To field in the send email step but again, this is an explicit reference.


You're not dynamically adding recipients to the send email step, and you definitely cannot do this without a custom workflow activity in the scenario where you want to send an email to contacts based on associated records from a 1:N relationship. It is common to come across a business process where an email is required to be sent based on Contacts that live in related records. Refer to the use case.

Use Case

I'm referring to a use that is relates to the insurance industry.

"As an insurance advisor,

I want to send Trustees an email reminder that their policy is due to expire,

so that their policy can be renewed."

Using a flow in Power Automate, this is achievable 😊💙

Process

The process will be that a Case is created and an insurance advisor will update a field to trigger the Power Automate. This can be automated where a scheduled Power Automate runs daily but for the purpose of this WTF episode I am triggering it manually. Once triggered an email is sent to all Trustees associated to the Trust using an Email Template.

Sounds like a piece of cake right? 😅

The data model in Dynamics 365 or CDS

I am using the out-of-the-box entity of Connections which is used to link a record to another record in Dynamics 365 or CDS. You can associate a connection role which represents the relationship of a record to another. What I have done is used Connections to link a Contact to an Account where the role associated to the Contact is "Trustee" and role associated to the Account is "Trust."


This is because Trustees can exist as contacts but are associated to their primary account already. To prevent duplicate contact records, connections is a good way to link a Trustee to a Trust which may also be an existing account record.

I have chosen to send the email to the Trustees where they are Bcc'd so that I can show you that my flow in Power Automate is flexible to cater for any activity party types that Dynamics 365 or CDS supports.

What my flow in Power Automate looks like

It has more actions than the previous flow you saw in my last WTF episode however don't forget that we can't do this out-of-the-box in a classic workflow today. My flow in Power Automate enables emails to be sent to multiple recipients that are dynamically referenced. You can have 30 Trustees or 5 Trustees, my flow in Power Automate will handle the recipients dynamically.


The last three actions in my flow is a result of AK's investigation and the core part of it is from my method that I figured out on how to form the email activity parties array and the recipient + sender objects dynamically. Combining our findings resulted in my pretty cool flow. Thanks AK.

This flow was created within a solution and I am using the CDS current environment connector.

1.0 Trigger - when a Case field is updated

I created a custom Two Option field called Send Trust policy renewal in the Case entity and placed it on the Case entity form so that I can update it to trigger my Power Automate. I set the filtering attribute to this field.


I have also configured the trigger condition where the field must equal Yes.

1.1 Get Account record

Using the CDS Get record action, retrieve the account record based on the Customer lookup value of the Case.

1.2 Retrieve connection records

Using the CDS List records action a FetchXml query can be applied which is defined using Advanced Find in Dynamics 365 or CDS. My FetchXml query will display all connections that have a connection role of Trustee and is associated to a specific account. The following is a screenshot of what my query looks like in Advanced Find.


The following is a screenshot of what my FetchXml looks like when downloaded.


Copy and paste this into the FetchXml query of the CDS List records action and replace the explicit references of account name and the account ID with the dynamic content values from the Get Account record. This is ensure that my Power Automate will work for any Trust and its associated Trustees that are represented by connections.

1.3 Temporary - Body of list

This is a Compose action where I am referencing the output of the CDS List records action. Currently as of writing this blog post there is a known issue where a status reason of 200 will display without an output of the JSON response. I am using the Compose action to verify that the correct connections records are returned since I don't have visibility in the CDS List records action while this issue is occurring. This is an optional action.

1.10 odata.type workaround + 1.11 Email target + 1.12 Perform an unbound action

I'm going to jump to two actions later in my flow because to understand the core part of my flow, I need to explain AK's method.

AK pointed out that there is another unbound action called SendEmailFromTarget. The part that tripped us up was the Target payload. It's documented how to define this through the SDK but as JSON, well that's another challenge which AK figured out. AK figured out the JSON payload for the Email Target from another fellow Microsoft MVP's blog post, Andrew Butenko. You can read Andrew Butenko's blog post here

AK figured out that he needed to serialize the @odata.type in order for it to be applicable in the Initialize Variable action that forms the Email Target object in the JSON payload. The Email Target object is an array of the email activity parties and the odata.type of email.

In my action 1.10 odata.type workaround, I'm using AK's method where Initialize Variable is used to form the @odata property.


This is then referenced in the Initialize Variable to form the Email Target object.

Problem solving time

While AK was investigating, I too was doing the exact same thing and found a different forum post from our community. When I was reviewing the screenshot in the bottom of the forum post I studied the email_activity_party array in the Target object.

  • I knew that the each of the rows in the array represented an email activity party. 
  • I knew that I also had to dynamically loop through the connections to identify the contact that would be used as the Bcc recipients.

Essentially when you study the JSON payload in the screenshot there's three elements (errr not sure if this is the right word but I'll go with it):

  1. The array which is the email activity parties.
  2. The object that represents the sender including the activity party type value.
  3. The object that represents the recipient including the activity party type value.

Since it is an array, I figured there can be more than one recipient which would be represented by multiple rows in the array where the type of recipient is defined by the ActivityParty.ParticipationTypeMask attribute.

The technique that I've applied is to use the following actions

  1. Initialize Variables
  2. Append to array variable
  3. Set Variable
I'll explain the core of my Power Automate in the next few sections.

1.4 Email activity parties

To form the array the Initialize Variable action is used where Type is equal to array.

1.5 Recipients

To form the row in each array the Initialize Variable action is used where Type is equal to Object.

1.6 Apply to each Trustee

Since connections are retrieved from my FetchXml query in the CDS List records action, I needed to loop through each record to reference the contact ID which would be used in the email activity parties array.


1.7 Set Recipients Variable

To form the row for the contact to be used in the email activity parties array, the Set Variable action is used where I'm referencing my recipients variable from my action 1.5 Recipients. I am also forming the object that will represent the row in the array by the following,
  1. Reference the contact using the contact ID from the CDS List records action. This is defined by the Connected To field in the Connection entity.
  2. Reference the activity party type. Since the activity party type is Bcc, the value of 4 is used.

My expression to reference the contact ID in No.1 is
item()?['_record2id_value']

1.8 Append to activity parties array variable

The final action within the Apply to each control is to append the recipients variable defined in 1.7 Set Recipients Variable to the array variable in 1.4 Email activity parties. The Append to array variable action is used.


This action is important because it will dynamically form the row in the email activity parties array. Essentially when all connections have been looped through, all of the recipients will be appended to the activity parties array.

1.7 Sender

**note this should be named as 1.9 but I only noticed my mistake in the naming convention for the later half of my flow in Power Automate after filming. To keep it consistent with the vlog I'll keep it as-is in case you're creating your own flow by watching my vlog and reading this blog post at the same time**

Now that the recipients have been taken care of, the sender needs some TLC. It's essentially the same technique as 1.5 Recipients where an Initialize Variable action is used to form the Sender object but this time we define the JSON payload for the object since we do not need to loop through records. There is always going to be one sender whereas the number of recipients can be dynamic.

1.8 Append Sender to array variable

Using an Append to array variable action, the sender variable is appended to the array variable in 1.4 Email activity parties.

1.9 Email activity parties array

This action is optional, you do not need this at all. I have this Compose action that's referencing the array variable output for two reasons,
  1. To check that my array that was from the appended variables of recipients and senders was correct.
  2. To show you in the vlog what the array variable looks like to validate that it is in fact correctly structured and defined.

1.10 odata.type workaround

As mentioned earlier this was a hack AK originally came up with to serialize the @odata.type.

**💡 BUT WAIT 💡**

Since filming another Microsoft community person, Ryan Maclean, tweeted an issue about his unbound action and I commented to share AK's method which then also led to Andrew Butenko chipping in to solve it.

Then came the question of why from Matt, why does flow behave like this?

Whenever the flow life gives me lemons 🍋🍋🍋 I turn to the Flow Ninja, John Liu 🐱‍👤. John is a supreme flow being (no joke) cause he's super intelligent when it comes to Logic Apps or flow in Power Automate. John shared this microsoft.com article with me (scroll down) which I then shared in Ryan's thread. He takes it one step further by sharing a hack. Ryan also came up with a hack too.
  1. John Liu's Hack
  2. Ryan Maclean's Hack
Go follow these two on Twitter if you haven't already done so! Do it.

So you can now skip action 1.10 odata.type workaround by following John or Ryan's hack.

1.11 Email target

Now that we have the email activity parties array from the appended variables of recipients and senders, it can now be referenced in the overall JSON payload. I am using an Initialize Variable to honour AK's method but you could probably define this directly in the final action.


This is based on AK's investigation and my investigation where I studied the JSON payload from the Dynamics 365 Community Forum post I provided earlier.

1.12 Perform an unbound action

The final action is to use the CDS perform an unbound action where the SendEmailFromTemplate action is used.

The information required by this action are
  1. The action which is SendEmailFromTemplate
  2. The ID of the email template. This can be found in the URL of your email template record (refer to vlog)
  3. Regarding which is the Case record
  4. Target which is the JSON payload defined in my 1.11 Email target action

Woo hoo, we are ready to automate! #LetsAutomate

Power Automate in action

Good to go, update the Send Trust policy renewal field in my Case record and away it goes!

Summary

What previously couldn't be achieved using out-of-the-box classic workflows can be achieved with flow in Power Automate - sending emails to multiple recipients (dynamically) using an Email Template. This excites me because it takes Dynamics 365 and CDS to the next level as use cases can be met using flows in Power Automate.

Thanks for checking out this WTF episode and catch you in my next one.

Toodles.

Thursday, 5 March 2020

How to send an email using an Email Template with Power Automate

Sending an email using an email template in Dynamics 365 and CDS is straight forward in a classic workflow. It's simply a send email step and applying the "Use Template" option. If you want to replicate it via flows in Power Automate, there is an action available called SendTemplate for the Common Data Service Web API.

This Part 1 WTF episode came about as a result of another Microsoft MVP in our community, Sara Lagerquist. She was trying to figure out how to send an email using an email template through Power Automate. Initially I thought it couldn't be done but then chances are if it can be done in a classic workflow, it CAN be done in Power Automate using a different method. We know that there are APIs available and Power Automate plays well with APIs so I investigated it further. At the same time another Microsoft MVP in our community Aung Khaing, who is more known as AK, also investigated and beat me to it. Well, what you see in Part 2 originates from mine and AK's investigation.

In this WTF episode I share what AK came across and also outline the constraint of this method.

What is an email template?

It's self explanatory - it's a template you create for an email and you can associate it to an email activity record in Dynamics 365 or CDS. I am referring to the native email functionality of Dynamics 365 and CDS, this is different to an Outlook email.

When you create an email template, the template type is defined which is the entity the email template is associated to. A list of out-of-the-box entities will be available for you to select when creating an email template.

Replicating sending an email using an Email Template in Power Automate

Use Case

I'm referring to a use case that is common across all organisations that have a customer service centre.

"As a customer,

I want to receive an email confirming my request has been created as a Case,

so that I have acknowledgement from Company ABC of my request."

An email is required to be automatically send to an individual who has engaged with the organisation. The email usually provides details of the request and a reference ID. 

What my flow in Power Automate looks like

It's straight forward (except for the constraint) in Power Automate as an unbound action is used where you provide the details required by the action. Not exactly the same steps as a classic workflow but it works.

1.0 Trigger - when a Case is created

In my Power Automate the trigger is when a Case is created. Whenever a Case is created, send an email to the contact associated to the account in the Customer field.

1.1 Perform an unbound action

The unbound action will only be available if you have created your Power Automate in a solution and you are selecting CDS actions from the CDS current environment connector.


If you don't create your Power Automate in a solution you won't be able to use this particular action so make sure it is in a solution.

The information required by this action are
  1. The action which is SendTemplate
  2. The ID of the email template. This can be found in the URL of your email template record (refer to vlog)
  3. The Sender which I've made as the Owner of the Case
  4. The Recipient which I've made as the Customer of the Case. If an account is the customer value, the primary contact will be the recipient.
The following are optional
  1. The regarding value can be left blank where the email will not be associated to a record.
  2. The deliveryprioritycode which I have set to 1 which represents Normal. By default if you leave this blank Power Automate will set it to 0 which is Low.

Side note

When using the CDS current environment connector, make sure you enclose your dynamic content value with brackets and reference the entity as plural. Sara Lagerquist has a blog post on this.

Power Automate in action

Good to go, trigger Power Automate and away it goes.


If you have attached a file to the email template, this will also be included in the email.

Constraint

Using the SendTemplate action is useful when you have a single recipient to send to. In the use case where you have multiple recipients and it can vary based on the scenario, this action is not valid because of how you need to explictly add the the recipient by clicking on "+ Add new item". Ideally the recipients should be added dynamically so that it's 100% automated.

Stay tuned cause I'll share what you need to do in Power Automate when you want to send an email using an email template to multiple recipients.

Summary

The SendTemplate unbound action can be used when you have created your Power Automate in a solution. 

I also want to point out that it respects the design principles of email templates in Dynamics 365 (or CDS). If you are sending an email where the recipient is not of the same entity as the defined template type of the email template, an error will be thrown in the Power Automate run history. For example, if you want to send an email template related to a Case, the recipient must be defined using the Case entity. If you try referencing the Contact entity an error will be thrown because of how the email template is for the Case entity and not the Contact entity.

Credit goes to AK and cheers to Sara's question that sparked all of this.

Wednesday, 15 January 2020

How to avoid Apply to Each from appearing

As a Power Automate maker you are happily building your flows in Power Automate and then suddenly after selecting dynamic content as a value in one of your actions, the Apply To Each appears. You think you’ve done something wrong so you delete the action and try again. The Apply To Each still appears!

Well my friend, you’ve come to the right place because in this WTF episode I can help you understand why this occurs and when you can avoid the Apply to Each from appearing. The first half of this episode is from the perspective of a CDS action however is applicable to the equivalent SharePoint action as well. In case you aren't aware, my background is with Dynamics 365 and my experiences with the Apply to Each has arisen from developing solutions for business use cases in Power Automate with flow.

Why or How does it appear

I have experienced the Apply To Each appearing when I select dynamic content from a CDS List Records action or an HTTP action. This is due to the JSON response as it is in the form of an array.

The way I like to explain an array to an everyday person is to think of it as a structured collection of data. Think of a table in an Excel worksheet. A table is structured where there are columns and rows of data. Each row would be an index and in each row there will be property values associated as reflected by the columns.

When a property is referenced from an array in an action, flow in Power Automate recognizes it is associated to an array and therefore the Apply to Each appears automatically. Flow in Power Automate will have the Apply to Each cocoon your action as it thinks the action is for each array.

In this WTF episode I’ll refer to the two common causes, in my opinion. There can be different causes but these are the two I tend to come across.

CDS List Records action – Cause No.1

There are times when a CDS List Records action is used and only a single record is expected to be returned. When using a List Records action there are multiple records expected to be returned in the result so the structure of the JSON response accommodates this in the form of an array.

An example is from a previous WTF episode where a CDS List Records action (the action in my Power Automate with flow is the 1.5 Get Time Zone Name of User) is used against the Time Zone Definitions entity that contains the time zone information used by CDS/Dynamics 365. Each array in the response will represent the different time zones. One of the properties in each array is standardname which is a value that can be referenced in expressions that require a time zone value, such as the Convert Time Zone action.

In my action I used a filter query to only return the time zone definition record that is equal to the time zone code of the CDS/Dynamics 365 user. This was so that only one record is returned rather than all time zone definitions as I’m only after the standardname property to identify the time zone name of the CDS/Dynamics 365 user to use downstream.

When you try use dynamic content to reference the standardname property in a subsequent action, the Apply to Each will appear which is what was seen in the Convert Time Zone action.


When you review the output of a List Records action it will be in the form of an array. The clue is from the square brackets [] that you’ll see in the output.

Parse JSON action – Cause No.2

Sometimes the Parse JSON action is used after an HTTP action in order to reference properties downstream. I’ll refer to my Power Automate with flow from this WTF episode as an example.

In my Power Automate with flow the goal is to reference the windowsTimeZoneId property downstream. The JSON response of the HTTP action is structured in the form of an array, similar to a CDS List Records action.

If we use the Parse JSON technique, we have to jump through a number of Apply to Each records to get to the windowsTimeZoneId because this property is buried within arrays.

Assess and choose a technique

I’m going to separate this section into two explanations in reference to the previous examples provided.
  • The first part will be in regards to a simple property where it is not buried in arrays.
  • The second part will be in regards to a complex property where it is buried in arrays.

When a simple property is to be referenced

Option one

When a single record is expected to be returned in the CDS List Records action or even an HTTP action, an expression can be used either directly in a field within an action or can be used in a Compose action. I'll use the Flow in my previous WTF episode as an example where the standardname property is to be referenced from a CDS List Records action that retrieves the time zone details of a user.

The key here is to use the first function in the expression. It will look something like this,


To explain this expression I’ll describe it in the way that my friend John Liu did when he helped me understand for my learning.

1.Start with outlining the array that is to be referenced. This is selected through the dynamic content Flow builder using the value output from the CDS List Records action - 1.5 Get Time Zone Name of User from the action (from my previous WTF episode).

body('1.5_Get_Time_Zone_Name_of_User')?['value']

2. Since we are only expecting one record to be returned in the List Records action, the next part of the expression is to wrap the first function around the output. If I go back to the Excel example from the beginning of this blog post, we are only going to reference the first row.

first(body('1.5_Get_Time_Zone_Name_of_User')?['value'])

3.The final part in the expression is the property to be referenced from the first row/record in the array which is standardname. This will be at the end of the expression.

first(body('1.5_Get_Time_Zone_Name_of_User')?['value'])?['standardname']

Bonus tip

The ? makes each property in the expression optional. For example if standardname is missing, the expression will return null and will not cause the flow in Power Automate to crash.
Using an expression either directly in an action or referencing from a compose action is suitable when you are only referencing a single property/field or let’s say two properties downstream in the Flow.

Option Two

Another way of writing an expression is the following

outputs('1.5_Get_Time_Zone_Name_of_User')?['body']?['value'][0]?['standardname']

This will retrieve the first row in the array of the JSON response from the [0] and the standardname property.

When would these options not be suitable

If you are going to be referencing a properties that aren't as straight forward, refer to the next section for another method.

When a complex property is to be referenced

Below is a screenshot of the JSON response in the HTTP action that I referenced earlier in the “Parse JSON action – Cause No.2” section. This is where we want to reference the windowsTimeZoneId downstream in my flow with Power Automate and the property is buried in arrays. To help with your understanding of the issue refer to the following screenshot.


You can see the windowsTimeZoneId property is buried in arrays. I’ll work backwards to help you with your understanding. The windowsTimeZoneId is within the timeZone array, which lives within the timeZoneAtLocation array, which lives in the resources array, which lives in the resourceSets array. Therefore Power Automate thinks the proceeding action is for each of the arrays within the output of the HTTP action.

The expression to use will be the following as per the above explanation where the first row in each array is represented by [0]

Summary

When you have a property to reference downstream and it’s in a simple structure within the JSON response, such as a CDS List Records action, use an expression that will either use the first function in the expression or has a reference to the row in the array. Otherwise if you're referencing a property that is not as straight forward where it may be buried in an array Option Two is better. These are the most two common scenarios I come across as a Power Automate maker working with Dynamics 365/CDS.

You can also check out John Liu’s blog post that mentions the Apply to Each appearing phenomenon, refer to Problem 2 - the array - item object and auto apply-each wrapping.