Send Email to Unresolved Recipients in Dynamics 365 using Power Automate
There are times when you need to send an email to unresolved recipients in Dynamics 365. An unresolved recipient is an email address which is not stored in the system (i.e. not stored in contact, user, queue, etc.). Dynamics 365 has an option to allow messages with unresolved email recipients to be sent from the system. This option can be used in different scenarios such as sending to a particular email address (e.g. Email Address 2) of a Contact, sending a marketing email to the list of email addresses from the spambot, or even if you are too lazy to create a Queue for an email address and use it in flow (no judgement here 🤷♂️).
Problem Statement: A Contact can be associated to one or multiple Accounts and uses a unique email address for each Account that it belongs to. Email addresses that the Contact used are stored in the following fields:
- Email Address 2
- Email Address 3
When there is an important announcement, the system must send out the announcement email to all 3 email addresses fields listed above, whichever has value.
Solution Summary: To resolve the problem statement above, we must enable the unresolved email recipients in the system settings and in the flow step of creating the email record, populate the email address as an Activity Party instead of referencing the Contact record. We need to use the Activity Party because if we use the Contact record as a reference, the announcement email will only be sent to the first email address of the Contact (Primary Email) and not to all the 3 email addresses as we want.
What we need to do first is to set the, "Allow messages with unresolved email recipients to be sent" option to Yes in System Settings. This will allow the system to send emails to unresolved recipients (obviously).
After enabling the unresolved email option, I attempted to add unresolved email recipients to a Create Email record flow step in Power Automate.
My first attempt was to add the email address in the Activity Party Attribute Value field. However, it failed with the following error and that is because the system is expecting the lookup record to have a GUID, not an email address.
My second attempt was to create the email entity first and then create the Activity Party associated with the email. But then again, it failed too and that is because the system does not allow the Create method for Activity Party entity.
Finally, in my third attempt, I managed to create the Activity Party with unresolved email recipients by entering the JSON string. To enter the JSON string as Activity Parties, click on "Switch to input entire array" at the right top corner of Activity Party section. The email address needs to be populated in "addressused" attribute.
Now let’s have a look at how I managed to make my third attempt worked and solved the problem as described in the problem statement. Here is the summary of the steps I took:
- List Contacts with Email Address
- Initialize variable Email Addresses JSON
- Clear variable Email Addresses JSON
- Append contact owner as Sender to array variable Email Addresses JSON
- Append Email 1/2/3 to array variable Email Addresses JSON
- Create a new Email and Send
When doing the above steps, you will also learn how to achieve the following using the flow in Power Automate:
- add lookup field to the Select Query of List records action
- use variable in 'Apply to each' loop control
- populate participation type integer value of the Activity Party
- build JSON array
- add unresolve recipient to the email
In this sample solution flow, it is manually triggered and retrieves all Contact records with email address. But the trigger and filter of the List records can be modified to make the solution more applicable in a real-life scenario. (e.g. to make it as an on-demand flow to send out to all contacts in the marketing list, replace the trigger with "When a record is selected" trigger from standard CDS connector and update the expand query of the flow to retrieve the Contact records which are related to the marketing list from the trigger)
It is also recommended to populate the "Select Query" parameter for "Get a record" and "List records" actions. You can find out why in my other blog post. But it is a bit tricky for the lookup field. If you just add the schema name of the lookup field (e.g. ownerid), the query would not fetch the data for that column and the value will be null if the Owner lookup value is referenced in the flow steps. If you just add the WebAPI style column name of the lookup field (e.g. _ownerid_value), the value is not available to be chosen in Dynamic content list (but the value can still be referenced using flow expression). That is why both schema name and WebAPI style column name (ownerid,_ownerid_value) are added into the Select Query of the flow above. If you are proficient with the flow expressions, you may not need to add the schema name and reference the data using flow expression. e.g.
Before we loop through the list of Contacts to send out an email, initialise an Array variable first. Variables can only be initialised outside of the array and if you try to create that step within the "Apply to each" block, you will get an error message that 'Initialize variable' can only be used at top level.
If you are using the variable in the 'Apply to each' looping control, make sure to turn off the Concurrency Control or Degree of Parallelism is 1. Otherwise, multiple instances of the looping will run at the same time and share the same variable. (which could cause a lot of problems)
The first step in the 'Apply to each' loop is to clear the variable to make sure that the variable data in the previous loop is wiped out.
In this sample solution flow, the email is being sent out from the owner of the Contact record as a sender to simplify the steps required. But in a normal real-life scenario, it would be sent from the dedicated mailbox queue. To learn more about how to use the queue and set as an email sender, check out my other blog post.
When we use the JSON value to populate the Activity Parties of an email, we cannot populate just only for unresolved recipients. We also need to populate all activity parties (Sender, To, Cc, Bcc) as a JSON object. Since we cannot choose from the list unlike in detail input view, "Activity Party Attribute Name" (participationtypemask) value needs to be set with an integer value. For sender activity party, it is 1 and the values for the other email activity parties are as in the table below. You can refer to the Microsoft Documentation about ActivityParty entity for the values of the other activity party types.
|Activity party type||Value||Description|
|Sender||1||Specifies the sender.|
|ToRecipient||2||Specifies the recipient in the To field.|
|CCRecipient||3||Specifies the recipient in the Cc field.|
|BccRecipient||4||Specifies the recipient in the Bcc field.|
The next step is to bind the owner field in the partyid of the Activity Party by concatenating the string and GUID value to form in the following format
This is the flow expression to achieve that.
concat('systemusers(', items('Apply_to_each_Contact')?['_ownerid_value'], ')')
For more details about how to set lookup field value in Common Data Service (current environment) flow connector, check out my other blog post.
After adding the Sender to the Activity Party variable, add the Email, Email Address 2, Email Address 3 fields as unresolved recipient To Activity Party. (if there is any value in the field).
In the condition control, check if Email is not equal to null and if the condition is true, append the array variable with the unresolved email recipient by adding the JSON value with participationtypemask = 2 (To Recipient) and addressused = Email.
Create the Condition steps and Append to array variable steps in the same way for Email Address 2 and Email Address 3.
When the Email is created, click on "Switch to input entire array" at the right top corner of Activity Party section and populate the entire JSON variable to the Activity Parties property. After that, "Perform a bound action" step is used to send out an email created in the previous step.
Conclusion: "Input entire array" option of the flow step is useful to populate the data when the required field is not available in "detail inputs for array item" view or when the number of items varies and depends on the number of values from the previous step.
You can download the above sample flow from my GitHub repository via this link.