microsoft / botframework-sdk

Bot Framework provides the most comprehensive experience for building conversation applications.
MIT License
7.5k stars 2.44k forks source link

[MS Teams] ChannelAccount only works with internal user ID #4518

Closed andyroz closed 6 years ago

andyroz commented 6 years ago

Bot Info

Issue Description

Documentation and SDK hints for ChannelAccount indicate that a Channel id for the user or bot can be a account name, a chat handle, or an internal id. image However, using anything other than the internal user id results in a error ('BadRequest') when trying to initiate a conversation with a user.

Code Example

public static async Task NotifyUser(MessageModel msg, JobModel job)
{
            string conversationId = "";
            var userAccount = new ChannelAccount('joe@example.com', 'Joe');
            var botAccount = new ChannelAccount(job.BotRecipientId, job.BotReceipentName);

            var connector = new ConnectorClient(new Uri(job.BotServiceUrl));
            try
            {
                // Create a new message.
                IMessageActivity message = Activity.CreateMessageActivity();
                message.ChannelId = job.BotChannelId;

                await connector.HttpClient.AddAPIAuthorization(myMicrosoftAppId, myMicrosoftAppPassword);

                var response = connector.Conversations.CreateOrGetDirectConversation(botAccount, userAccount, myTenantId);
                message.Conversation = new ConversationAccount(id: response.Id);
           } catch(Exception ex) {
           }

...etc
}

Reproduction Steps

  1. Use a non-userId Code, ie; @joe or joe@example.com etc for the user ChannelAccount
  2. Try to start a conversation with the user.

Expected Behavior

That the user handle @joe or AD name joe@example.com would be sufficient to start a conversation with the user. It does not seem possible to know the MSTeams userId (28:jjwej99we-wewer-werweq-etc) when a bot initiates a new conversation with a new user. This makes it impossible for a bot to start a new conversation with a MS Teams user.

Actual Results

Microsoft.Bot.Connector.ErrorResponseException: Operation returned an invalid status code 'BadRequest'
   at Microsoft.Bot.Connector.Conversations.<CreateConversationWithHttpMessagesAsync>d__6.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.Bot.Connector.ConversationsExtensions.<CreateConversationAsync>d__3.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.Bot.Connector.ConversationsExtensions.CreateConversation(IConversations operations, ConversationParameters parameters)
   at fj_pabot.MessagesController.<NotifyUser>d__3.MoveNext() in D:\xxxxxxx\mybot\Controllers\MessagesController.cs:line 103

In the Azure Channels view there are 'Issues' like this: image

JasonSowers commented 6 years ago

What it sounds like you are trying to accomplish here, a bot starting a conversation with a user without having previously talked to the bot, is not a supported scenario in bot framework. It is intentionally like this to prevent spambots. However, if this is not what you are trying to accomplish and you would like to send a proactive message to a user that has previously interacted with your bot please see this doc about proactive messages.

As far as user IDs, the channels themselves determine the user ID. You would have to be able to change the user ID at the channel level to make it say an Email address. Which would make something like this only possible where you have full control of the channel ie webchat and directline.

andyroz commented 6 years ago

Thanks @JasonSowers . Your initial impression was correct, and that sounds like something we can't do. I'm thinking then, that when a user adds the bot to their chat, we will get a notification containing the user id (I've seen welcome messages, so I'm assuming this is possible), and we can store this for future conversations.

For context, what we are trying to do is notify a user via MS Teams chat about a file they drop in a O365/OneDrive folder (which has a webhook). Although MS Teams & OneDrive are part of the same O365/AD account, MS Teams has this user ID requirement that stops our bot initiating a connection with the user. So, we'll try the bot-added notification (ActivityTypes.ContactRelationUpdate?) thing, and if that doesn't work, I guess we'll have to get users to initiate the bot conversation.

JasonSowers commented 6 years ago

You could also keep a map or a table to translate the Id teams generates to some other ID you would rather use (ex. an email address). You should be able to do what you are trying via the ContactRelationUpdate. The link I shared should help you accomplish this, let us know if you have any more questions.