William Holmes
William Holmes

Reputation: 109

Retrieving a mail message's attachments with Microsoft GraphServiceClient API & C#

I have the following code:

var graphServiceClient = GraphClientFactory.GetGraphServiceClient(config.ClientId, config.Authority, config.Scopes);

MailMessagePage = await graphServiceClient.Me.MailFolders.Inbox.Messages
    .Request()
        .Expand("attachments")
    .GetAsync();

foreach (var mm in MailMessagePage)
{
    foreach (var a in mm.Attachments)
    {

    }
}

This code is successfully downloading the Inbox Messages and the Inner foreach loop is enumerating through the attachments collection. Here is a example:

Watch of a

What is not included is the actual attachment data. Does anyone have an example of downloading the actual attachment data?

Thanks

Based on the suggestions from Darrel I implemented the following.

var outlookItem = await builder.Request().GetAsync();

Is returning the Metadata for the attachment bu not the attachment itself. I am after the data.

MailMessagePage = await graphServiceClient.Me.MailFolders.Inbox.Messages
    .Request()
    .Expand("attachments")
    .GetAsync();

foreach (var mm in MailMessagePage)
{
    foreach (var itemAttachment in mm.Attachments)
    {
        if(itemAttachment is ItemAttachment)
        {
            var builder = new ItemAttachmentRequestBuilder(graphServiceClient.Me.Messages[mm.Id].Attachments[itemAttachment.Id].RequestUrl, graphServiceClient);
            var outlookItem = await builder.Request().GetAsync(); 
        }
    }
}

Watch showing itemAttachnment vs outlookItem

Upvotes: 1

Views: 4070

Answers (2)

Darrel Miller
Darrel Miller

Reputation: 142044

The challenge here is that Attachment is actually an abstract type and there are multiple different concrete types. FileAttachment has a ContentBytes property, but ItemAttachment has a navigation property Item that points to an OutlookItem. This means that you need to do a separate request to retrieve the OutlookItem. There doesn't appear to be a request builder for that particular Item.

            if (attachment is ItemAttachment)
            {
                var requestUrl = graphClient.Me.Messages[message.Id].Attachments[attachment.Id].RequestUrl + "/item"; 
                var request = new HttpRequestMessage() {
                    RequestUri = new Uri(requestUrl)
                };
                var outlookItemResponse = graphClient.HttpProvider.SendAsync(request);
               var outlookItem = new ResponseHandler(new Serializer()).HandleResponse<OutlookItem>(outlookItemResponse);
            }

We acknowledge that this is not intuitive. We will be investigating how we can make accessing these derived types easier.

Upvotes: 2

Shoejep
Shoejep

Reputation: 4839

Have you tried the below? Taken from here.

var attachments = await graphServiceClient.Me.Messages[messageId]
   .Attachments
   .Request()
   .GetAsync();

You can then check if they're a FileAttachment which has a ContentBytes property that contains the actual attachment data.

Upvotes: 3

Related Questions