主动邮件

主动消息是由代理发送但未响应用户请求的任何消息。 此消息可以包括以下内容:

  • 欢迎消息
  • Notifications
  • 计划的消息

要向用户、群聊或团队发送主动消息,您的代理必须具有发送消息所需的访问权限。 对于群组聊天或团队,必须首先在该位置安装包含代理的应用程序。

如有必要,可以在团队中使用 Microsoft Graph 主动安装应用 ,或使用 自定义应用策略 在团队和组织用户中安装应用。 对于某些方案,你必须使用 Graph 主动安装应用。 若要让用户接收主动消息,请为用户安装应用或使用户成为安装该应用的团队的一员。

发送主动消息与发送常规消息不同。 主动消息通过应用发送。在活动处理程序外部发送 () 。 当你呼叫应用时,SDK 会自动创建对话。发送 () 。 需要 conversationId,SDK 会自动解析服务 URL。 例如,频道中新的一对一聊天或新的对话线程。 你不能在具有主动消息传递的团队中创建新的群聊或新频道。

若要发送主动邮件,请按照以下步骤操作:

  1. 如有必要,获取 Microsoft Entra 用户 ID、用户 ID、团队 ID 或频道 ID。
  2. 创建对话(如果必要)。
  3. 获取对话 ID。
  4. 发送消息.

示例部分中的代码片段用于创建一对一对话。 有关一对一对话以及组或频道消息示例的链接,请参阅 代码示例。 若要有效地使用主动消息,请参阅 主动消息的最佳实践。

获取 Microsoft Entra 用户 ID、用户 ID、团队 ID 或频道 ID

可以与频道中的用户或对话线程创建新对话,并且必须具有正确的 ID。 可以使用以下任一方式接收或检索此 ID:

  • 在特定上下文中安装应用后,你会收到一个onMembersAdded活动。
  • 将新用户添加到安装应用的上下文时,你会收到活动 onMembersAdded 。
  • 代理收到的每个事件都包含所需的信息,您可以从代理上下文 (活动上下文) 获取这些信息。
  • 你可以在已安装应用的团队中检索频道列表。
  • 你可以检索已安装应用的团队的成员列表。

无论如何获取信息,都可存储 tenantId 然后存储 userId或 channelId 创建新对话。 你还可以使用 teamId 在团队的常规频道或默认频道中创建新的对话线程。 请确保在团队中安装了代理,然后才能向频道发送主动消息。

  • 该信息对用户是唯一的, aadObjectId 可以使用 图形 API 检索它,以便在个人聊天中创建新对话。 请确保在个人作用域中安装代理,然后才能发送主动消息。 如果代理未安装在个人作用域中,则在使用 发送aadObjectId主动消息时,代理将返回带有403消息的错误。ForbiddenOperationException

  • 对于您的代理 ID 和特定用户是唯一的。userId 不能重复使用 userId 代理之间的

  • channelId 是全局 ID。

获取用户或频道信息后创建对话。

注意

仅在个人范围内支持使用 发送 aadObjectId 主动消息。

创建对话

注意

如果代理已 supportsSessions 在应用清单中设置为 true ,则调用创建对话 API 以开始一对一对话将创建新会话。 返回 conversationId 的对象限定为该会话,可用于会话内的后续消息传递操作。 有关详细信息,请参阅 使用会话管理多个用户对话。

如果对话不存在或 conversationId不知道,则可以创建对话。 仅创建一次对话,并存储结果 conversationId 以备将来的主动消息使用。

若要创建对话,需要一个 aadObjectId 或 userId、 tenantId和 serviceUrl。

注意

若要创建对话,请传递 aadObjetId 参数中的 Id 值。

对于 serviceUrl,请使用触发流的传入活动或全局服务 URL 之一中的值。 如果从 serviceUrl 触发主动方案的传入活动中不可用,请使用以下全局 URL 终结点:

  • 公共: https://smba.trafficmanager.net/teams/
  • GCC: https://smba.infra.gcc.teams.microsoft.com/teams
  • GCC High: https://smba.infra.gov.teams.microsoft.us/teams
  • DoD: https://smba.infra.dod.teams.microsoft.us/teams

警告

  • 这些 URL 仅用于主动消息。 避免对其进行硬编码。 请改为从 serviceUrl 传入的活动或对话引用中使用。 如果不可用,请使用基于区域和云的全局 URL。

  • 对于对邮件的任何回复,请使用 serviceURL 传入请求中的邮件。 有关详细信息,请参阅 Activity.ServiceUrl 属性。

首次安装应用时,可以获取对话。 创建对话后, 获取对话 ID。 会话更新事件中提供了 conversationId。

对话 ID 对于特定渠道中的每个代理都是唯一的,即使在多租户环境中也是如此。 此 ID 可确保代理的消息被定向到适当的频道,并且不会与同一或不同组织内的其他代理或频道中断。

如果没有 conversationId,则可以使用 Graph 主动安装应用 ,以获取 conversationId.

获取对话 ID

使用 conversationReference 对象或 conversationId 和 tenantId 发送消息。 你可以通过以下方式获取此 ID,即通过从该上下文发送给你的任何活动创建对话或存储对话。 存储此 ID 以供参考。

获取相应的地址信息后,你可以发送消息。

发送邮件

现在,你已拥有正确的地址信息,因此可以发送消息。 如果使用的是 SDK,则必须使用 app.Send() 该方法和 来 conversationId 进行直接 API 调用。 若要发送邮件,请设置 conversationParameters. 请参阅 示例 部分,或使用 代码示例 部分中列出的示例之一。

若要主动发送消息作为对频道中线程的回复,请同时使用 app.Reply() 对话 ID 和线程根消息的 ID。

注意

Teams 不支持使用电子邮件或用户主体名称 (UPN) 发送主动消息。

现在您已经发送了主动消息,您必须在发送主动消息时遵循这些最佳实践,以便用户和代理之间更好地交换信息。

了解谁阻止、静音或卸载了代理

作为开发人员,你可以创建一个报告来了解组织中哪些用户阻止、静音或卸载了代理。 此信息可能有助于组织的管理员广播组织范围内的消息或推动应用使用。

使用 Teams,可以向代理发送主动消息,以验证用户是否已阻止或卸载代理。 如果代理被阻止或卸载,Teams 会返回带有 403subCode: MessageWritesBlocked. 此响应表示代理发送的消息未传递给用户。

响应代码是按用户发送的,并包含用户的标识。 您可以编译每个用户的响应代码及其身份,以创建阻止代理的所有用户的报告。

以下代码示例是一个 403 响应代码的示例:

HTTP/1.1 403 Forbidden
Cache-Control: no-store, must-revalidate, no-cache
Pragma: no-cache
Content-Length: 196
Content-Type: application/json; charset=utf-8
Server: Microsoft-HTTPAPI/2.0
Strict-Transport-Security: max-age=31536000; includeSubDomains
MS-CV: NXZpLk030UGsuHjPdwyhLw.5.0
ContextId: tcid=0,server=msgapi-canary-eus2-0,cv=NXZpLk030UGsuHjPdwyhLw.5.0
Date: Tue, 29 Mar 2022 17:34:33 GMT

{"errorCode":209,"message":"{\n  \"subCode\": \"MessageWritesBlocked\",\n  \"details\": \"Thread is blocked from message writes.\",\n  \"errorCode\": null,\n  \"errorSubCode\": null\n}"}

主动消息传递的最佳做法

向用户发送主动消息是一种与用户沟通的有效方式。 但是,从用户的角度来看,该消息似乎是未经提示的。 如果有欢迎消息,则标志着他们与你的应用的首次交互。 使用此功能并向用户提供完整信息以了解该消息的用途非常重要。

欢迎消息

当使用主动消息传递向用户发送欢迎消息时,没有关于用户为什么收到该消息的上下文。 此外,这是用户与应用的首次交互。 这是创造良好第一印象的好机会。 良好的用户体验可确保更好地采用应用程序。 糟糕的欢迎消息可能会导致用户阻止您的应用程序。 编写一条清晰的欢迎消息,如果欢迎消息没有达到预期的效果,请对它进行迭代。

好的欢迎信息可以包括以下信息:

  • 消息的原因 - 用户必须清楚他们收到消息的原因。 如果您的代理已安装在频道中,并且您向所有用户发送了欢迎消息,请让他们知道它的安装在哪个频道以及安装人员。

  • 你的产品/服务 - 用户必须能够确定他们可以使用你的应用做什么,以及你可以为他们带来什么价值。

  • 后续步骤 - 用户应了解后续步骤。 例如,邀请用户试用命令或与您的应用交互。

通知消息

若要使用主动消息传递发送通知,请确保用户具有清晰的路径来根据你的通知执行常见操作。 如果在选项卡应用中需要用户操作,请使用活动源通知而不是代理。 确保用户清楚地了解他们收到通知的原因。 好的通知消息包括以下内容:

  • 发生了什么? 明确指出发生了什么情况才导致发送通知。

  • 结果是什么? 必须明确指出哪些项目更新导致发送通知。

  • 谁或什么触发了它? 谁或什么执行了导致发送通知的操作。

  • 用户可以在响应中执行哪些操作? 让用户能够轻松地根据通知执行操作。

  • 用户如何选择退出? 必须为用户提供选择退出更多通知的路径。

若向大量用户发送消息,例如向你的组织发送消息,请使用 Graph 主动安装你的应用。

要更新或删除由仅通知代理发送的主动消息:

  1. 通过在发送主动消息时存储消息 ID 或对话引用来跟踪已发送的消息。

  2. 使用 context.Api.Conversations.Activities.UpdateAsync(conversationId, activityId, updatedActivity) OR context.Api.Conversations.Activities.DeleteAsync(conversationId, activityId) 方法更新或删除原始消息。

计划的消息

使用主动消息传递向用户发送计划的消息时,请验证你的时区是否已更新为其所在的时区。 这可确保在相关时间将消息传递给用户。 计划消息包括:

  • 为什么用户接收到了消息? 让用户轻松了解他们收到消息的原因。

  • 用户接下来可以做什么? 用户可以根据消息内容执行所需的操作。

使用 Graph 主动安装应用

可以使用图形 API 主动为用户安装应用。 缓存应用在安装时收到的 conversationUpdate 事件中的必要值。

只能安装组织应用目录或 Microsoft Teams 应用商店中的应用。

请参阅 Graph 文档中的“ 为用户安装应用 ”以及使用 Graph 在 Teams 中主动安装代理和消息传递。

示例

在使用 REST API 创建新对话之前,请确保进行身份验证并拥有 持有者令牌 。 以下是用于在不同上下文中创建对话的 REST API:

  • REST API 在一对一聊天中创建对话。

  • REST API 来在频道中创建对话。

  • 用于更新对话中的消息的 REST API:若要更新对话中的现有活动,请在请求终结点中包括 conversationId 和 activityId。 若要完成此方案,必须缓存原始 post 调用返回的活动 ID。

    PUT {Service URL of your agent}/v3/conversations/{conversationId}/activities/{activityId}
    
    
    {
        "type": "message",
        "text": "This message has been updated"
    }
    

    若要更新对话中的现有活动,请在请求端点中包含 conversationId 和 activityId。 若要完成此方案,必须缓存 activity ID 原始 post 调用返回的 。 如果调用成功,API 将返回以下响应对象。

    {
        "id": "{{activityID}}"
    }
    

示例

以下代码演示如何使用 Teams SDK (Teams AI 库) 发送主动消息:

// Save the conversation ID and schedule a proactive reminder on install
teams.OnInstall(async (context, cancellationToken) =>
{
    context.Storage.Set(context.Activity.From.AadObjectId!, context.Activity.Conversation.Id);
    await context.Send("Hi! I am going to remind you to say something to me soon!", cancellationToken);
    notificationQueue.AddReminder(context.Activity.From.AadObjectId!, Notifications.SendProactive, 10_000);
});
 
// Send proactive message using stored conversation ID
public static class Notifications
{
    public static async Task SendProactive(string userId)
    {
        var conversationId = (string?)storage.Get(userId);
        if (conversationId is null) return;
        await app.Send(conversationId, "Hey! It's been a while. How are you?");
    }
}

代码示例

下表提供的代码示例使用 Teams SDK 将基本对话流和主动消息传递合并到 Teams 应用程序中:

示例名称 说明 .NET Node.js Python 清单
Teams 对话基础知识 此示例应用演示如何使用适用于个人和团队范围的 Teams SDK v2 中提供的不同代理对话事件。 View View View View
机器人主动消息 此示例演示如何从安装活动捕获和存储对话 ID,并使用它向用户发送即时和延迟的主动消息。 View View View 不适用

后续步骤

另请参阅