Skip to content
Open
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ ms.localizationpriority: medium
author: akjo
ms.topic: overview
ms.owner: vishachadha
ms.date: 12/15/2022
ms.date: 03/24/2026
---

# Send proactive installation messages
Expand Down Expand Up @@ -191,51 +191,94 @@ The following code provides an example of sending proactive messages:

# [C#](#tab/dotnet)

* [SDK reference](/dotnet/api/microsoft.bot.builder.cloudadapterbase.continueconversationasync?view=botbuilder-dotnet-stable&preserve-view=true#microsoft-bot-builder-cloudadapterbase-continueconversationasync(system-string-microsoft-bot-schema-activity-microsoft-bot-builder-botcallbackhandler-system-threading-cancellationtoken))
* [SDK reference](/microsoftteams/platform/teams-sdk/essentials/sending-messages/proactive-messaging?tabs=minimal&pivots=csharp)

* [Sample code reference](https://github.com/OfficeDev/Microsoft-Teams-Samples/blob/main/samples/graph-meeting-notification/csharp/MeetingNotification/Controllers/NotificationController.cs#L112)

```csharp
public async Task<int> SendNotificationToAllUsersAsync(ITurnContext<IMessageActivity> turnContext, CancellationToken cancellationToken)
{
int msgSentCount = 0;
using Microsoft.Teams.Api;
using Microsoft.Teams.Apps;
Comment thread
AjayJ12-MSFT marked this conversation as resolved.

// Send notification to all the members.
foreach (var conversationReference in _conversationReferences.Values)
{
await turnContext.Adapter.ContinueConversationAsync(_configuration["MicrosoftAppId"], conversationReference, BotCallback, cancellationToken);
msgSentCount++;
}
// Store conversation IDs (e.g., during install event)

return msgSentCount;
}
var conversationStorage = new Dictionary<string, string>();
app.OnInstall(async context =>
{
Comment thread
AjayJ12-MSFT marked this conversation as resolved.
var userId = context.Activity.From.AadObjectId;
var conversationId = context.Activity.Conversation.Id;
conversationStorage[userId] = conversationId;
await context.Send("Hi! I will send you proactive notifications.");
});

private async Task BotCallback(ITurnContext turnContext, CancellationToken cancellationToken)
{
// Sends an activity to the sender of the incoming activity.
await turnContext.SendActivityAsync("Proactive hello.");
}
// Send proactive message from anywhere

public static async Task SendProactiveNotification(string userId)
{
var conversationId = conversationStorage.GetValueOrDefault(userId);
if (conversationId is null) return;

await app.Send(conversationId, "Proactive hello.");
}
```

# [Node.js](#tab/nodejs)

* [SDK reference](/javascript/api/botbuilder/cloudadapter?view=botbuilder-ts-latest&preserve-view=true#botbuilder-cloudadapter-continueconversationasync)
* [SDK reference](/microsoftteams/platform/teams-sdk/essentials/sending-messages/proactive-messaging?tabs=minimal&pivots=typescript)
* [Sample code reference](https://github.com/OfficeDev/Microsoft-Teams-Samples/blob/main/samples/bot-initiate-thread-in-channel/nodejs/bots/teamsStartNewThreadInChannel.js#L20)

```javascript
server.get('/api/notify', async (req, res) => {
for (const conversationReference of Object.values(conversationReferences)) {
import { MessageActivity } from '@microsoft/teams.api';
import { App } from '@microsoft/teams.apps';

// Sends a proactive message to a conversation.
await adapter.continueConversationAsync(process.env.MicrosoftAppId, conversationReference, async context => {
await context.sendActivity('proactive hello');
});
}
res.setHeader('Content-Type', 'text/html');
res.writeHead(200);
res.write('<html><body><h1>Proactive messages have been sent.</h1></body></html>');
res.end();
});
const app = new App();

// Store conversation IDs
const conversationStorage = new Map<string, string>();


// Capture conversation ID when app is installed
app.on('install.add', async ({ activity, send }) => {
conversationStorage.set(activity.from.aadObjectId!, activity.conversation.id);
await send('Hi! I will send you proactive notifications.');
});

// Send proactive message from anywhere
const sendProactiveNotification = async (userId: string) => {
Comment thread
AjayJ12-MSFT marked this conversation as resolved.
const conversationId = conversationStorage.get(userId);
if (!conversationId) return;
const activity = new MessageActivity('Proactive hello.');
await app.send(conversationId, activity);
};
```

# [Python](#tab/python)

* [SDK reference](/microsoftteams/platform/teams-sdk/essentials/sending-messages/proactive-messaging?tabs=minimal&pivots=typescript)
Comment thread
AjayJ12-MSFT marked this conversation as resolved.
Outdated

```python
from microsoft_teams.api import MessageActivityInput
from microsoft_teams.apps import App
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The PR imports App but never uses it. The correct import per official docs is ActivityContext (and InstalledActivity for the typed handler). Please correct the imports.

Update -
from microsoft_teams.api import InstalledActivity, MessageActivityInput
from microsoft_teams.apps import ActivityContext

DOC Link - https://microsoft.github.io/teams-sdk/python/essentials/sending-messages/proactive-messaging/


app = App()


# Store conversation IDs
conversation_storage: dict[str, str] = {}


@app.on_install_add
async def handle_install(ctx):
user_id = ctx.activity.from_property.aad_object_id
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

conversation_storage[user_id] = ctx.activity.conversation.id
await ctx.send("Hi! I will send you proactive notifications.")

# Send proactive message from anywhere
async def send_proactive_notification(user_id: str):
conversation_id = conversation_storage.get(user_id, "")
if not conversation_id:
return
activity = MessageActivityInput(text="Proactive hello.")
await app.send(conversation_id, activity)
```

---
Expand Down
Loading