Updates from: 02/05/2021 04:15:00
Service Microsoft Docs article Related commit history on GitHub Change details
platform https://docs.microsoft.com/en-us/microsoftteams/platform/bots/how-to/conversations/send-proactive-messages https://github.com/MicrosoftDocs/msteams-docs/commits/master/msteams-platform/bots/how-to/conversations/send-proactive-messages.md
@@ -1,9 +1,9 @@
Title: Send proactive messages-
-description: How to send proactive messages with your Microsoft Teams bot.
+ Title: send proactive messages
+description: describes how to send proactive messages with your Microsoft Teams bot.
+Keywords: send a message get user ID channel ID conversation ID
# Send proactive messages
@@ -15,9 +15,9 @@ A proactive message is any message sent by a bot that is not in direct response
* Notifications * Scheduled messages
-In order for your bot to send a proactive message, it must have access to the user, group chat, or team that you wish to send the message to. For a group chat or team, this means the app that contains your bot must first be installed to that location. You can [proactively install your app using Graph](#proactively-install-your-app-using-graph) in a team if necessary, or use an [app policy](/microsoftteams/teams-custom-app-policies-and-settings) to push apps out to teams and users in your tenant. For users, your app either needs to be installed for that user, or your user needs to be part of a team where your app is installed.
+For your bot to send a proactive message, it must have access to the user, group chat, or team that you want to send the message to. For a group chat or team, this means the app that contains your bot must be installed to that location first. You can [proactively install your app using Graph](#proactively-install-your-app-using-graph) in a team, if required or use an [app policy](/microsoftteams/teams-custom-app-policies-and-settings) to push apps out to teams and users in your tenant. For users, your app either must be installed for the user or your user must be part of a team where your app is installed.
-Sending a proactive message is different than sending a regular message in that you won't have an active `turnContext` to use for a reply. You may also need to create the conversation (for example a new one-to-one chat, or a new conversation thread in a channel) before sending the message. You cannot create a new group chat or a new channel in a team with proactive messaging.
+Sending a proactive message is different than sending a regular message. In that, there is no active `turnContext` to use for a reply. You may also need to create the conversation before sending the message. For example, a new one-to-one chat or a new conversation thread in a channel. You cannot create a new group chat or a new channel in a team with proactive messaging.
At a high level the steps you'll need to complete to send a proactive message are:
@@ -26,119 +26,111 @@ At a high level the steps you'll need to complete to send a proactive message ar
1. [Get the conversation ID](#get-the-conversation-id). 1. [Send the message](#send-the-message).
-The code snippets in the [examples](#examples) section below are for creating a one-to-one conversation, see the [references](#references) section for links to complete working samples for both one-to-once conversations and group/channels.
+The code snippets in the [examples](#examples) section are for creating a one-to-one conversation. For links to complete working samples for both one-to-one conversations and group or channels , see [code samples](#code-samples).
## Get the user ID or team/channel ID
-If you need to create a new conversation or conversation thread in a channel you'll first need the right ID to create the conversation. You can receive/retrieve this ID in multiple ways:
+To create a new conversation or conversation thread in a channel, you need the correct ID. You can receive or retrieve this ID in multiple ways:
1. When your app is installed in any particular context, you'll receive a [`onMembersAdded` Activity](~/bots/how-to/conversations/subscribe-to-conversation-events.md). 1. When a new user is added to a context where your app is installed, you'll receive a [`onMembersAdded` Activity](~/bots/how-to/conversations/subscribe-to-conversation-events.md). 1. You can retrieve the [list of channels](~/bots/how-to/get-teams-context.md) in a team your app is installed. 1. You can retrieve the [list of members](~/bots/how-to/get-teams-context.md) of a team your app is installed.
-1. Every Activity your bot receives will contain the necessary information.
+1. Every Activity your bot receives must contain the required information.
-Regardless of how you gain the information, you'll need to store the `tenantId` and either the `userId` or `channelId` in order to create a new conversation. You can also use the `teamId` to create a new conversation thread in the general/default channel of a team.
+Regardless of how you gain the information, you'll need to store the `tenantId` and either the `userId` or `channelId` to create a new conversation. You can also use the `teamId` to create a new conversation thread in the general or default channel of a team.
-The `userId` is unique to your bot Id and a particular user, you cannot re-use them between bots. The `channelId` is global, however your bot _must_ be installed in the team before you can send a proactive message to a channel.
+The `userId` is unique to your bot Id and a particular user, you cannot re-use them between bots. The `channelId` is global, however, your bot must be installed in the team before you can send a proactive message to a channel.
## Create the conversation
-Once you have the user/channel information, you'll need to create the conversation if it doesn't already exist (or you don't know the `conversationId`). You should only create the conversation once; make sure you store the `conversationId` value or `conversationReference` object to use in the future.
+After you have the user or channel information, you need to create the conversation if it doesn't already exist or you don't know the `conversationId`. You must only create the conversation once and make sure you store the `conversationId` value or `conversationReference` object to use in the future.
## Get the conversation ID
-Once the conversation has been created, you will use either the `conversationReference` object or the `conversationId` and the `tenantId` to send the message. You can get this Id by either creating the conversation, or storing it from any Activity sent to you from that context. Make certain that you store this Id.
+After the conversation is created, use either the `conversationReference` object or `conversationId` and `tenantId` to send the message. You can get this ID by either creating the conversation or storing it from any Activity sent to you from that context. Make certain that you store this ID.
## Send the message
-Now that you have the right address information, you can send your message. If you're using the SDK, you'll do so using the `continueConversation` method,and the `conversationId` and `tenantId` to make a direct API call. You'll need to set the `conversationParameters` correctly to successfully send your message - see the [examples](#examples) below or use one of the samples listed in the [references](#references) section.
+Now that you have the right address information, you can send your message. If you're using the SDK, you'll do so using the `continueConversation` method, and the `conversationId` and `tenantId` to make a direct API call. You must set the `conversationParameters` correctly to successfully send your message. See the [examples](#examples) section or use one of the samples listed in the [code samples](#code-samples) section.
## Best practices for proactive messaging
-Sending proactive messages to users can be a very effective way to communicate with your users. However, from their perspective this message can appear completely unprompted and, in the case of welcome messages, it will be the first time they've interacted with your app. As such, it is very important to use this functionality sparingly (don't spam your users) and to provide enough information to let users understand why they are being messaged.
+Sending proactive messages to users is a very effective way to communicate with your users. However, from their perspective, this message can appear completely unprompted, and in the case of welcome messages, it is the first time they have interacted with your app. Therefore, it is very important to use this functionality sparingly, don't spam your users, and to provide enough information to let users understand why they are being messaged.
### Welcome messages
-When using proactive messaging to send a welcome message to a user you must keep in mind that, for most people receiving the message, there will be no context for why they are receiving it. This is also the first time they will have interacted with your app; it is your opportunity to create a good first impression. The best welcome messages will include:
+When using proactive messaging to send a welcome message to a user you must keep in mind that, for most people receiving the message, there is no context for why they are receiving it. This is also the first time they have interacted with your app. It is your opportunity to create a good first impression. The best welcome messages must include:
-* **Why a user is receiving the message.** It should be very clear to the user why they are receiving the message. If your bot was installed in a channel and you sent a welcome message to all users, let them know what channel it was installed in and potentially who installed it.
+* **Why a user is receiving the message.** It must be very clear to the user why they are receiving the message. If your bot was installed in a channel and you sent a welcome message to all users, let them know what channel it was installed in and potentially who installed it.
* **What do you offer.** What can they do with your app? What value can you bring to them? * **What should they do next.** Invite them to try out a command, or interact with your app in some way.
-Remember, poor welcome messages can lead to users blocking your bot. You should spend plenty of time crafting your welcome messages, and iterate on them if they are not having the desired effect.
+Remember, poor welcome messages can lead to users blocking your bot. Spend plenty of time crafting your welcome messages, and iterate on them if they are not having the desired effect.
### Notification messages
-When using proactive messaging to send notifications you need to make sure your users have a clear path to take common actions based on your notification and a clear understanding of why the notification occurred. Good notification messages will generally include:
+When using proactive messaging to send notifications you must ensure your users have a clear path to take common actions based on your notification and a clear understanding of why the notification occurred. Good notification messages generally include:
* **What happened.** A clear indication of what happened to cause the notification.
-* **What was the result.** It should be clear what item/thing was updated to cause the notification.
+* **What was the result.** It must be clear what item or thing was updated to cause the notification.
* **Who/what triggered it.** Who or what took action that caused the notification to be sent. * **What can users do in response.** Make it easy for your users to take actions based on your notifications.
-* **How can users opt out.** You need to provide a path for users to opt out of additional notifications.
+* **How can users opt out.** You must provide a path for users to opt out of additional notifications.
## Proactively install your app using Graph > [!Note] > Proactively installing apps using the Microsoft Graph is currently in beta.
-Occasionally it may be necessary to proactively message users that have not installed or interacted with your app previously. For example, you want to use the [company communicator](~/samples/app-templates.md#company-communicator) to send messages to your entire organization. For this scenario you can use the Graph API to proactively install your app for your users, then cache the necessary values from the `conversationUpdate` event your app will receive upon install.
+Occasionally it may be necessary to proactively message users that have not installed or interacted with your app previously. For example, you want to use the [company communicator](~/samples/app-templates.md#company-communicator) to send messages to your entire organization. For this scenario you can use the Graph API to proactively install your app for your users, then cache the necessary values from the `conversationUpdate` event your app receives upon installation.
-You can only install apps that are in your organizational app catalogue, or the Teams app store.
+You can only install apps that are in your organizational app catalog or the Teams app store.
-See [Install apps for users](/graph/teams-proactive-messaging) in the Graph documentation and [Proactive bot installation and messaging in Teams with Microsoft Graph](../../../graph-api/proactive-bots-and-messages/graph-proactive-bots-and-messages.md). There is also a [Microsoft .NET framework sample](https://github.com/microsoftgraph/contoso-airlines-teams-sample/blob/283523d45f5ce416111dfc34b8e49728b5012739/project/Models/GraphService.cs#L176) on the GitHub platform.
+See [Install apps for users](/graph/api/userteamwork-post-installedapps) in the Graph documentation and [Proactive bot installation and messaging in Teams with Microsoft Graph](../../../graph-api/proactive-bots-and-messages/graph-proactive-bots-and-messages.md). There is also a [Microsoft .NET framework sample](https://github.com/microsoftgraph/contoso-airlines-teams-sample/blob/283523d45f5ce416111dfc34b8e49728b5012739/project/Models/GraphService.cs#L176) on the GitHub platform.
## Examples # [C#/.NET](#tab/dotnet) ```csharp
-private async Task MessageAllMembersAsync(ITurnContext<IMessageActivity> turnContext, CancellationToken cancellationToken)
+[Route("api/notify")]
+[ApiController]
+public class NotifyController : ControllerBase
{
- var teamsChannelId = turnContext.Activity.TeamsGetChannelId();
- var serviceUrl = turnContext.Activity.ServiceUrl;
- var credentials = new MicrosoftAppCredentials(_appId, _appPassword);
- ConversationReference conversationReference = null;
+ private readonly IBotFrameworkHttpAdapter _adapter;
+ private readonly string _appId;
+ private readonly ConcurrentDictionary<string, ConversationReference> _conversationReferences;
- //Get the set of member IDs to send the message to
- var members = await GetPagedMembers(turnContext, cancellationToken);
-
- foreach (var teamMember in members)
+ public NotifyController(IBotFrameworkHttpAdapter adapter, IConfiguration configuration, ConcurrentDictionary<string, ConversationReference> conversationReferences)
{
- var proactiveMessage = MessageFactory.Text($"Hello {teamMember.GivenName} {teamMember.Surname}. I'm a Teams conversation bot.");
+ _adapter = adapter;
+ _conversationReferences = conversationReferences;
+ _appId = configuration["MicrosoftAppId"] ?? string.Empty;
+ }
- var conversationParameters = new ConversationParameters
+ public async Task<IActionResult> Get()
+ {
+ foreach (var conversationReference in _conversationReferences.Values)
{
- IsGroup = false,
- Bot = turnContext.Activity.Recipient,
- Members = new ChannelAccount[] { teamMember },
- TenantId = turnContext.Activity.Conversation.TenantId,
+ await ((BotAdapter)_adapter).ContinueConversationAsync(_appId, conversationReference, BotCallback, default(CancellationToken));
+ }
+
+ // Let the caller know proactive messages have been sent
+ return new ContentResult()
+ {
+ Content = "<html><body><h1>Proactive messages have been sent.</h1></body></html>",
+ ContentType = "text/html",
+ StatusCode = (int)HttpStatusCode.OK,
};
- //create the new one-to-one conversations
- await ((BotFrameworkAdapter)turnContext.Adapter).CreateConversationAsync(
- teamsChannelId,
- serviceUrl,
- credentials,
- conversationParameters,
- async (t1, c1) =>
- {
- //Get the conversationReference
- conversationReference = t1.Activity.GetConversationReference();
- //Send the proactive message
- await ((BotFrameworkAdapter)turnContext.Adapter).ContinueConversationAsync(
- _appId,
- conversationReference,
- async (t2, c2) =>
- {
- await t2.SendActivityAsync(proactiveMessage, c2);
- },
- cancellationToken);
- },
- cancellationToken);
}
- await turnContext.SendActivityAsync(MessageFactory.Text("All messages have been sent."), cancellationToken);
+ private async Task BotCallback(ITurnContext turnContext, CancellationToken cancellationToken)
+ {
+ // If you encounter permission-related errors when sending this message, see
+ // https://aka.ms/BotTrustServiceUrl
+ await turnContext.SendActivityAsync("proactive hello");
+ }
} ```
@@ -241,21 +233,17 @@ You must supply the user ID and the tenant ID. If the call succeeds, the API ret
-## References
-
-The official proactive messaging samples are listed below.
+## Code samples
-| No. | Sample Name | Description | .NET | JavaScript | Python |
-|:--:|:-|:|:--|:-|:--|
-|57|Teams Conversation Basics | Demonstrates basics of conversations in Teams, including sending one-to-one proactive messages.|[.NET&nbsp;Core](https://github.com/microsoft/BotBuilder-Samples/blob/master/samples/csharp_dotnetcore/57.teams-conversation-bot)|[JavaScript](https://github.com/microsoft/BotBuilder-Samples/tree/master/samples/javascript_nodejs/57.teams-conversation-bot) | [Python](https://github.com/microsoft/BotBuilder-Samples/blob/master/samples/python/57.teams-conversation-bot)|
-|58|Start new thread in a channel | Demonstrates creating a new thread in a channel. |[.NET&nbsp;Core](https://github.com/microsoft/BotBuilder-Samples/blob/master/samples/csharp_dotnetcore/58.teams-start-new-thread-in-channel)|[JavaScript](https://github.com/microsoft/BotBuilder-Samples/blob/master/samples/javascript_nodejs/58.teams-start-new-thread-in-channel)|[Python](https://github.com/microsoft/BotBuilder-Samples/blob/master/samples/python/58.teams-start-thread-in-channel) |
+The official proactive messaging samples are as follows:
-The sample below demonstrates the minimal amount of information needed to send a proactive message (without using a `conversationReference` object). This sample can be useful if you're using REST API calls directly, or haven't been storing full `conversationReference` objects.
+| Sample Name | Description | .NET | JavaScript | Python |
+|:-|:|:--|:-|:--|
+|Teams Conversation Basics | Demonstrates basics of conversations in Teams, including sending one-to-one proactive messages.|[.NET&nbsp;Core](https://github.com/microsoft/BotBuilder-Samples/blob/master/samples/csharp_dotnetcore/57.teams-conversation-bot)|[JavaScript](https://github.com/microsoft/BotBuilder-Samples/tree/master/samples/javascript_nodejs/57.teams-conversation-bot) | [Python](https://github.com/microsoft/BotBuilder-Samples/blob/master/samples/python/57.teams-conversation-bot)|
+|Start new thread in a channel | Demonstrates creating a new thread in a channel. |[.NET&nbsp;Core](https://github.com/microsoft/BotBuilder-Samples/blob/master/samples/csharp_dotnetcore/58.teams-start-new-thread-in-channel)|[JavaScript](https://github.com/microsoft/BotBuilder-Samples/blob/master/samples/javascript_nodejs/58.teams-start-new-thread-in-channel)|[Python](https://github.com/microsoft/BotBuilder-Samples/blob/master/samples/python/58.teams-start-thread-in-channel) |
-* [Teams Proactive Messaging](https://github.com/clearab/teamsProactiveMessaging)
-
-## View additional code
+## View additional code samples
> > [!div class="nextstepaction"] > [**Teams proactive messaging code samples**](/samples/officedev/msteams-samples-proactive-messaging/msteams-samples-proactive-messaging/)
->
+>