Botframework-sdk: MS Teams attachments fail for Bots.

Created on 13 Apr 2018  路  6Comments  路  Source: microsoft/botframework-sdk

Bot Info

  • SDK Platform: .NET
  • SDK Version: 4.7.1
  • Bot Framework 3.14.1.1
  • Active Channels: MS Teams, Test Chat
  • Deployment Environment: Azure Bot Service/Azure App Service

Issue Description

No attachments from MS Teams to our Bot come through correctly.

  • Attached file messages (images/pdf/dc/xls) on Android MS Teams come through with zero attachments
  • Attached file messages (images) on iOS MS Teams come through with 2 attachments (count), but neither have a file name, one has no contentURL and the other contains a contentURL to a location we cannot access (https://smba.trafficmanager.net/apac-client-ss.msg/v3/attachments/ .....etc). We get a 401 status.
  • Shared file messages (images) on Android MS Teams come through with 2 attachments (count), but neither have a file name, one has no contentURL and the other contains a contentURL to a location we cannot access (https://smba.trafficmanager.net/apac-client-ss.msg/v3/attachments/ .....etc). We get a 401 status
  • Shared file messages (images/pdf/doc/xls) on iOS MS Teams come through with zero attachments

Code Example

private async Task MessageReceivedAsync(IDialogContext context, IAwaitable result)
{
var activity = await result as Activity;
for (int i=0;i < activity.Attachments.Count; i++)
{
log.DebugFormat("Attachment URL: {0}", activity.Attachments[i].ContentUrl);
log.DebugFormat("Attachment Name: {0}", activity.Attachments[i].Name);
}
}

Reproduction Steps

  1. We deployed our bot service. We have been using this successfully with Slack Channel
  2. In the Bot Service, we added the MS Teams channel (there is no configuration to do)
  3. We have tested with Android, iOS (iPad), Windows MS Teams App and Web Browser

MS Team behaviour is a bit inconsistent across devices, but the attachment-to-bot issues seem universal.

Expected Behavior

Attachments come through in the activity object with name and contentURL filled in, and useable.

Actual Results

In MS Teams, it looks like attachments attach correctly, however for a bot, the attachments are failing. There is no screenshot for this.

Most helpful comment

Hi @DigitalSa1nt

The request for the file should have an Authentication Header with Bearer token. Here is a C# example:

var attachment = turnContext.Activity.Attachments.First();
using (HttpClient httpClient = new HttpClient())
{
    // Skype & MS Teams attachment URLs are secured by a JwtToken, so we need to pass the token from our bot.
    if (turnContext.Activity.ChannelId.Equals("skype", StringComparison.InvariantCultureIgnoreCase) || turnContext.Activity.ChannelId.Equals("msteams", StringComparison.InvariantCultureIgnoreCase))
    {
        var token = await new MicrosoftAppCredentials().GetTokenAsync();
        httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
    }

    var responseMessage = await httpClient.GetAsync(attachment.ContentUrl);
    var contentLenghtBytes = responseMessage.Content.Headers.ContentLength;
    await turnContext.SendActivityAsync($"Attachment of {attachment.ContentType} type and size of {contentLenghtBytes} bytes received.");
}

All 6 comments

Are you sending attachments to the bot within a group channel, or one-on-one?

hi @nodeomega . This is a one-on-one conversation with the bot.

I've recently tested using the Windows desktop version (which now includes a paperclip icon for attaching files in one-on-one bot chats from what I'm seeing), and I tried on the iOS version (though in one-on-one I was only able to send a GIF or an image, not any other type). I do not have access to an Android device in order to test on that at this moment.

I was able to access the files through the URLs given (although I had to copy and paste the entire URL, as the hyperlink broke at the first space in the given URL in my case), so perhaps there was a recent change in at least the Windows desktop version. In my case, the text file I uploaded was also directed to a sharepoint URL, not the other type of URL you had referenced. Perhaps there is an environmental variance I am not familiar with. The file I uploaded from the desktop version was retrievable from the iOS version. Again, I am not certain if this was a recent change in functionality.

For the iOS version, the shared GIF files do seem to have clickable or tappable URL's (at least in the way I shared it to my test bot chat). They did show as having a type of "image/*", however. But... when I uploaded an image from my iPhone I was testing with, I did replicate the URL that returned a 401 error when followed.

Based on the linked issue, I believe this to be a limitation more with Teams than with Botbuilder. As I am not aware of any resolution to this issue, and given the age of the issue, I am closing this issue at this time. If there are any other questions, don't hesitate to open a new issue!

It's worth noting that there is no adequate documentation on how to consume In-Line images in Teams or Skype, a content url like:

https://smba.trafficmanager.net/emea/v3/attachments/{Id}]/views/original

Is provided, but throws an authentication error when trying to access it. Does anyone here know the process to access this image?

Hi @DigitalSa1nt

The request for the file should have an Authentication Header with Bearer token. Here is a C# example:

var attachment = turnContext.Activity.Attachments.First();
using (HttpClient httpClient = new HttpClient())
{
    // Skype & MS Teams attachment URLs are secured by a JwtToken, so we need to pass the token from our bot.
    if (turnContext.Activity.ChannelId.Equals("skype", StringComparison.InvariantCultureIgnoreCase) || turnContext.Activity.ChannelId.Equals("msteams", StringComparison.InvariantCultureIgnoreCase))
    {
        var token = await new MicrosoftAppCredentials().GetTokenAsync();
        httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
    }

    var responseMessage = await httpClient.GetAsync(attachment.ContentUrl);
    var contentLenghtBytes = responseMessage.Content.Headers.ContentLength;
    await turnContext.SendActivityAsync($"Attachment of {attachment.ContentType} type and size of {contentLenghtBytes} bytes received.");
}

Hi @DigitalSa1nt

The request for the file should have an Authentication Header with Bearer token. Here is a C# example:

var attachment = turnContext.Activity.Attachments.First();
using (HttpClient httpClient = new HttpClient())
{
    // Skype & MS Teams attachment URLs are secured by a JwtToken, so we need to pass the token from our bot.
    if (turnContext.Activity.ChannelId.Equals("skype", StringComparison.InvariantCultureIgnoreCase) || turnContext.Activity.ChannelId.Equals("msteams", StringComparison.InvariantCultureIgnoreCase))
    {
        var token = await new MicrosoftAppCredentials().GetTokenAsync();
        httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
    }

    var responseMessage = await httpClient.GetAsync(attachment.ContentUrl);
    var contentLenghtBytes = responseMessage.Content.Headers.ContentLength;
    await turnContext.SendActivityAsync($"Attachment of {attachment.ContentType} type and size of {contentLenghtBytes} bytes received.");
}

Thank you this was exactly what I was after. Out of interest was there documentation out there about this do you know? Because I couldn't find it.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

kenyeung128 picture kenyeung128  路  3Comments

akakoychenko picture akakoychenko  路  3Comments

hailiang-wang picture hailiang-wang  路  3Comments

peterbozso picture peterbozso  路  3Comments

Vigneshramkumar picture Vigneshramkumar  路  3Comments