Send a notification to a Microsoft Teams user from an app

Problem

This article describes a solution for the scenario where an app needs to send a notification to a user in Microsoft Teams.

Overview of the solution

This can be accomplished by utilizing bot support in Microsoft Teams as illustrated in the diagram below.

appsnotificationsdiagram

  1. Bot Framework SDK sends an Activity object to the bot whenever a new message is received by the bot from a user.
  2. This Activity object contains a bunch of information, but of most interest to us for this scenario is the conversationId and serviceUrl. It is referred to as CallbackInfo in this diagram.
    1. conversationId: Each bot:user 1:1 chat has a unique conversationId.
    2. serviceUrl: serviceUrl informs the Bot Framework SDK where to send the HTTP request with bot’s reply.
  3. ConversationId and ServiceUrl (and bot-id + bot-secret) are enough to post a message to the conversation. So the idea is to persist the combination of ConversationId and ServiceUrl mapped to the userId of the user.
  4. When an event occurs in the system that’s of interest to a user, now it is possible to lookup the corresponding CallbackInfo and post a message to bot’s conversation with that user.
  5. The sample code below illustrates how to compactly store the CallbackInfo as a token in a webhookUrl and how to implement the webhook handler to post to the conversation of the bot with the user.

 

Sample code

Here is some code to illustrate the key parts of the solution.

First, here’s the class that captures the CallbackInfo.

public class CallbackInfo
{
    public string ConversationId { get; set; }
    public string ServiceUrl { get; set; }
}

Here is how one can construct a webhook URL that contains the encoded CallbackInfo based on the incoming activity received when a user sends a message.

 var callBackInfo = new CallbackInfo() 
 { 
     ConversationId = activity.Conversation.Id, 
     ServiceUrl = activity.ServiceUrl
 };
 var token = Convert.ToBase64String(
     Encoding.Default.GetBytes(
         JsonConvert.SerializeObject(callBackInfo)));

 var webhookUrl = host + "/v1/hook/" + token;

And finally, here’s a sample webhook controller that can post to conversation with user:

public class WebhookController : ApiController
{
    [Route("v1/hook/{token}")]
    public async Task<HttpResponseMessage> Handle([FromUri]string token, [FromBody]IncomingMessage message)
    {
        // Unpack the callback information
        var jsonString = Encoding.Default.GetString(Convert.FromBase64String(token));
        var callbackInfo = JsonConvert.DeserializeObject<CallbackInfo>(jsonString);

        // Post the message onto the conversation with the user
        ConnectorClient connector = new ConnectorClient(new Uri(callbackInfo.ServiceUrl));
 
        var newMessage = Activity.CreateMessageActivity();
        newMessage.Type = ActivityTypes.Message;
        newMessage.Conversation = new ConversationAccount(id: callbackInfo.ConversationId);
        newMessage.TextFormat = "xml";
        newMessage.Text = message.Text;

        await connector.Conversations.SendToConversationAsync(newMessage as Activity);

        return new HttpResponseMessage(HttpStatusCode.OK);
     }
 }

Using this approach in the real world

  • Securing the webhook: Use an HMAC in the webhook URL to ensure that POST to webhook is coming from the legitimate app (example).
  • Slack message schema: Is the app/service only able to send messages in Slack webhook format due to legacy reasons? Consider using classes already defined in an existing nuget package to deserialize messages coming in. Slack.Webhooks looks promising, though I have no personal experience with it.
  • Consider cards: You also have the option to post cards from your bots to get the attention of users. Take a look here.
  • Authentication: Look at AuthBot for how to utilize OAuth within bots to authenticate users (link).
  • More about activities: Read up about Activities in Bot Framework documentation here.
  • Write your first bot: Looking for a step-by-step instructions on how to create a Microsoft Teams bot? Take a look here.

Creating a bot for Microsoft Teams

Overview

This article presents step-by-step instructions for creating a new bot using Bot Framework and side-loading it into Microsoft Teams for testing.

Let’s get started…

  • Download the Bot Framework Visual Studio C# Bot project template using this link.
  • Copy this zip file over to Documents\Visual Studio 2015\Templates\ProjectTemplates\Visual C# on your machine.

Create a new bot!

  1. In Visual, click on File -> New Project
  2. Select Bot Application and hit OK.

newbotapplication

Time to wire it up!

Register your bot in Bot Framework and update your bot’s config

  1. Go to https://dev.botframework.com and select Register a bot, or simply click here.
  2. Fill out the Name, Bot handle, and Description.
  3. Leave Messaging endpoint blank for now. We’ll come back to this in a bit.
  4. Click on Create Microsoft App ID and password.
  5. In the new window that pops up, click on Generate an app password to continue.
    GenerateAppPassword.png
  6. That will cause a popup to show on the site with your app’s password. Copy it to your clipboard.
    NewPassword.png
  7. Now switch to the Visual Studio solution you created earlier and open the web.config file.
  8. Paste the password you copied into the value for MicrosoftAppPassword key.pastingapppassword
  9. Now switch back to the window where you copied the password from and hit Finish and go back to Bot Framework.
  10. Now back on Bot Framework’s bot registration page, copy the value of Microsoft App ID and paste it into the value of MicrosoftAppId key in the web.config file in your project.
  11. Copy the value of Bot handle as well and paste it as the value of BotId key in the config file.
    WebconfigFilledIn.png
  12. Double-check that you copied the values for BotId, MicrosoftAppId, and MicrosoftAppPassword correctly.
  13. Now hit F5 to start Visual Studio with debugging on.
  14. Make note of the port number used in the browser that opens up.
    PortNumber.png
  15. We are not done with registration in Bot Framework yet – we need to tell Bot Framework where to post messages meant for our bot. We will come back to that very soon.

Test your bot

  1. Download ngrok from here and extract the zip file.
  2. Launch Command Prompt and change into the directory where you extracted ngrok.
  3. Now this is where the port-number your site is running on comes in.
  4. Run the following command: ngrok http 3979 –host-header=localhost. Replace 3979 with whatever port number you saw earlier.
  5. This will start an ngrok tunnel. Copy its URL.
    ngrok
  6. Now, connect Bot Framework to this tunnel in the following manner:
    1. Go back to the Bot Framework registration page for the bot.
    2. Paste the following value for Messaging endpoint: <your_tunnel>/api/messages.
    3. In my case that is https://c5e247ac.ngrok.io/api/messages.
    4. Accept the Privacy statements, Terms of use, and Code of conduct (after you’ve read them, obviously) and click Register.
  7. Now click on the Test button under Test connection to your bot.
  8. You should see a successful POST /api/messages request received via your tunnel.
  9. That ensures that you have plugged everything in properly.

Test your bot inside Microsoft Teams

  1. Find “Microsoft Teams” under Add another channel and click on Add.
    AddMicrosoftTeams.png
  2. In the window that pops up, ensure that the channel is On and tap on I’m done configuring Microsoft Teams.
    doneaddingmicrosoftteams
  3. Now simply click on the Add to Teams button to side-load the bot into your Microsoft Teams and start a 1:1 chat with it.
    AddToTeamsButton.png
  4. This would launch Microsoft Teams if you already have it installed and bring you into a chat with the bot. If you don’t have Microsoft Teams, continue to download it, sign-in, and click on Add to Teams again.
    NewChatCreated.png
  5. Send a message to your bot and you’ll find that it responds with the number of characters in the string you sent. That’s the default logic in Bot project template.
    BotWorking.png
  6. Congratulations! You’ve got your bot working.

What to do next?

  1. Understand how everything works: Set breakpoint in MessagesController.Post method and send a message to your bot via Microsoft Teams again and step through the code so you understand what’s happening.
  2. Fiddle with it: Try modifying the bot to return something else to the user – e.g. call https://api.chucknorris.io/ to reply with a random Chuck Norris joke.
  3. Read more: Read more about utilizing cards here and capabilities of Bot Framework SDK here.
  4. Windows Azure: Deploy your Bot to Windows Azure. Once that’s done, update the bot registration in Bot Framework to have the URL of your Windows Azure website or cloud-service (depending on what you chose).