Using e-mail to reach users who haven’t read CC messages in Teams

Recently my team got an interesting request from a customer with a frontline worker scenario. They are rolling out Teams to all their frontline workers, but at this moment the vast majority is still not running Teams in their mobile phones. They are working on the activation and change management aspects, but that population is still too focused on email (and phone!).

Then they asked for a way to fallback Company Communicator messages to e-mail. Here is the request:

“Author composes a message and send a Teams notification using Company Communicator to all front-line workers. After a few days, the author notices that just 35% of the users actually read the message in Teams, the other 65% need to be notified by other means (email for example). Can we create an option to fall back on email and send the exact message sent with teams to those users?”

Of course! 🙂

The solution

There are multiple ways to implement.

We can change CC code to go over each sent message record and send an email message to users with read status equal false. But the idea here is to create something without making big changes to company communicator code. We decided to leverage Azure Logic Apps and just create a new option on CC to activate the workflow.

For the specific version that implements this feature, there is a new option on the list of sent notifications saying, “Email who haven’t read messages”. Authors can click that option on any sent notification and CC will activate the Azure Logic App workflow. The flow will go over the database, check for who haven’t read the message and compose an email message with the exact same adaptive card sent originally by Company Communicator.

The picture below shows the option to activate the Azure Logic App workflow. Just below the duplicate option we will be including an additional menu option to trigger the flow. When authors select that option, an HTTP POST is done to the workflow passing the id of the notification as parameter.

Of course, the tracking mechanism also needs to work. It doesn’t matter where users read messages, the reposts need to be updated with the reading status, so subsequent executions of the flow can pick-up only the delta.

On the Azure side, there is a HTTP trigger for the Azure logic app with the POST method. When the option is selected, that trigger is activated, and the notification id is passed in the body of the request.

We also have two new variables for the App Service that control (1) if the feature is active, and (2) where is the Azure Log App workflow endpoint. Those variables need to be defined with the true/false and the workflow endpoint/url that you get when the flow is saved (you get that value in the workflow HTTP trigger).

The “Get Notification Id” action creates a new variable with the value received by the workflow activation trigger. We will use that value to filter the appropriate notification and then collect all messages sent with the unread status.

As you can see in the picture below, when the trigger is pulled by the CC menu option, we get the notification id from the parameter list, and then use that value to recover the specific database entity that represents that notification. We need that to collect the AdaptiveCard we use as the message in Teams.

With the adaptive card in hand, we filter all messages sent for that specific notification and which the reading status is false. That means we will recover all messages that users haven’t read. For each message we send the adaptive card now by email.

Adaptive cards in an E-mail

Trust me, I spent a few hours trying to figure out why when sending an adaptive card in an e-mail, Outlook doesn’t get it rendered right away. Turned out that administrators need to authorize that feature in your tenant.

You can easily check if Outlook is blocking the adaptive card rendering using an Outlook plug-in called Actionable Messages Debugger. If you are trying to use those adaptive cards with Outlook, install that plug in and run it to analyze messages. You will get crucial troubleshooting information.

In the case below you see cards are not enabled and there is no “originator” on the card.

To enable cards and create the originator, you need to access and create a request to your admin. Just go ahead, click New Provider and fill out the form. You will need to provide the e-mail address of the user sending messages and the URL that will be used to process responses from the cards.

Make sure you select Organization as the scope of submission. That will route the request to the tenant administrators.

The administrator will receive an e-mail and need to go to the same website to approve.

Then you need to include the originator information on the adaptive card. You can collect the ID of the originator from the request page and use the addProperty function to include that value on the adaptive card inside the Log App flow.

In my flow I’m using a variable called Originator to host the ID I captured from the form and then on the Get AdaptiveCard action I’m adding the property to the JSON I collect from the Notification entity.

Here is the complete function I’m using


That’s all. In this specific branch I have in my github you can trigger azure logic apps from the authors interface. In this article you see one application which is send emails in fallback to all users who haven’t read messages.

Stay safe…

Disclaimer – The information contained in this blog post doesn’t represent the official Microsoft guidance or best practices. It is just the view of the author on current alternatives, implementations and workarounds for common issues and/or business needs. Please refer to official Microsoft documentation and evaluate carefully any steps, code or procedures documented herein. The author doesn’t offer any warranty. Use this information at your own risk.