How to retrieve contents of an itemAttachment via the Microsoft Graph API
Asked Answered
G

3

10

I'm currently developing a solution which is retrieving e-mails via the Microsoft Graph API. In november 2015 Microsoft stated it is ready for production and I've read in another forum post that if you start now on developing using a Microsoft API, you should use the Graph API, since it is the future.

Everything is going well except for one thing and that is the following.

I must retrieve e-mails. Inside these e-mails there are of course attachments. These attachments come in some variaties. fileAttachment (images, documents etc.), referenceAttachments and itemAttachments (outlook-item). The issue here is with the itemAttachments. An itemAttachment can be anything from an appointment to another message. The problem here is that I'm not able to get and retrieve the contentBytes in some way which is working for fileAttachments. A related object to itemAttachment is outlookItem. There is also a page with a description made for this outlookItem, but the examples and the details are missing. The user rights are set to Mail.Read and Mail.ReadWrite.

Links: General overview: http://graph.microsoft.io/docs/overview/overview Get outlookItem (empty?):

Example call and response I get. Please note the types of the attachments. https://graph.microsoft.com/v1.0 /users/ /messages/ /attachments

{
  "@odata.context": "link",
  "value": [
    {
      "@odata.type": "#microsoft.graph.fileAttachment",
      "id": "AAMkAGU2NmIwMTcxLTljYzUtNGRiMi1hZjczLTllNzhiZDRiNWZlZABGAAAAPAD_Lx_gimDGRqSr98J_O_e6BwDcWyYHlO7rS5_XpLHCx6NSAAIMC0V-AADcWyYHlO7rS5_XpLHCx6NSAAIMC6RgAAABEgAQAGhN_vm1RlBPt7V4N9a89UY=",
      "lastModifiedDateTime": "2016-01-13T14:25:33Z",
      "name": "image001.png",
      "contentType": "image/png",
      "size": 5077,
      "isInline": true,
      "contentId": "[email protected]",
      "contentLocation": null,
      "contentBytes": "iVBORw0KGgoAAAANSUhEUgAAAKAAAACCCAIAAABOyVRHAAAAAXNSR0IArs4c6QAAEndJREFUeF7tXQ1QFFe2bkbU... (truncated)"
    },
    {
      "@odata.type": "#microsoft.graph.fileAttachment",
      "id": "AAMkAGU2NmIwMTcxLTljYzUtNGRiMi1hZjczLTllNzhiZDRiNWZlZABGAAAAPAD_Lx_gimDGRqSr98J_O_e6BwDcWyYHlO7rS5_XpLHCx6NSAAIMC0V-AADcWyYHlO7rS5_XpLHCx6NSAAIMC6RgAAABEgAQAFnSLgIC5wZOosmLtBWK8gE=",
      "lastModifiedDateTime": "2016-01-13T14:25:34Z",
      "name": "image002.png",
      "contentType": "image/png",
      "size": 3722,
      "isInline": true,
      "contentId": "[email protected]",
      "contentLocation": null,
      "contentBytes": "iVBORw0KGgoAAAANSUhEUgAAAPoAAABSCAYAAAB9o8m+AAAAGXRFWHRTb... (truncated)"
    },
    {
      "@odata.type": "#microsoft.graph.fileAttachment",
      "id": "AAMkAGU2NmIwMTcxLTljYzUtNGRiMi1hZjczLTllNzhiZDRiNWZlZABGAAAAPAD_Lx_gimDGRqSr98J_O_e6BwDcWyYHlO7rS5_XpLHCx6NSAAIMC0V-AADcWyYHlO7rS5_XpLHCx6NSAAIMC6RgAAABEgAQANOuw7m8sW1Ot3MivYQ5OYU=",
      "lastModifiedDateTime": "2016-01-13T14:25:24Z",
      "name": "Knipsel.PNG",
      "contentType": null,
      "size": 7641,
      "isInline": false,
      "contentId": null,
      "contentLocation": null,
      "contentBytes": "iVBORw0KGgoAAAANSUhEUgAAAKAAAACCCAYAAADBq8MQAAA... (truncated)"
    },
    {
      "@odata.type": "#microsoft.graph.itemAttachment",
      "id": "AAMkAGU2NmIwMTcxLTljYzUtNGRiMi1hZjczLTllNzhiZDRiNWZlZABGAAAAPAD_Lx_gimDGRqSr98J_O_e6BwDcWyYHlO7rS5_XpLHCx6NSAAIMC0V-AADcWyYHlO7rS5_XpLHCx6NSAAIMC6RgAAABEgAQAPEUC740tjtAlNTe8NpopUI=",
      "lastModifiedDateTime": "2016-01-14T15:55:07Z",
      "name": "RE: Test met plaatje",
      "contentType": null,
      "size": 36972,
      "isInline": false
    }
  ]
}

I've tried to change the GET-statement by pasting the attachment id with or without the messages path and the expand feature (which is only supported one level deep), but I can't seem te find the solution. Something I've found is this question, which is kind of the same, however it is for the office365 unified API. How to retrieve ItemAttachment contents from Office 365 REST API?.

So, the question: How can I retrieve the contents of an outlookItem via the Microsoft Graph API? And how do I know what to expect? Can anybody help me getting past this obstacle.

Gillard answered 22/1, 2016 at 10:16 Comment(4)
Does no one has any clue, hint or solution for me?Gillard
no,unfortunately there is no solutionLunik
Hmmm, I still can't believe that Microsoft stated it is production ready(!) :-(Gillard
to get the attachments list you need to know message Id. When you have message Id you can easily call graph.microsoft.com/beta/me/messages/[ message Id ]/attachments with valid Bearer authentication !!!! using valid access code. Also, make sure that you have assigned enough permissions for this action on the Azure management portal. Content of an attachment is base64 encoded string, which is present in the contentBytes field. If you have attachmentId you can usd it. Please check this doc: graph.microsoft.io/en-us/docs/api-reference/beta/api/… . Its wokring fineLunik
T
6

Use $expand option:

GET https://graph.microsoft.com/v1.0/me/messages('AAMkADA1M-zAAA=')/attachments('AAMkADA1M-CJKtzmnlcqVgqI=')/?$expand=microsoft.graph.itemattachment/item 

Response:

HTTP/1.1 200 OK
Content-type: application/json

{
  "@odata.context":"https://graph.microsoft.com/v1.0/$metadata#users('d1a2fae9-db66-4cc9-8133-2184c77af1b8')/messages('AAMkADA1M-zAAA%3D')/attachments/$entity",
  "@odata.type":"#microsoft.graph.itemAttachment",
  "id":"AAMkADA1MCJKtzmnlcqVgqI=",
  "lastModifiedDateTime":"2017-07-21T00:20:34Z",
  "name":"Reminder - please bring laptop",
  "contentType":null,
  "size":32005,
  "isInline":false,
  "[email protected]":"https://graph.microsoft.com/v1.0/$metadata#users('d1a2fae9-db66-4cc9-8133-2184c77af1b8')/messages('AAMkADA1M-zAAA%3D')/attachments('AAMkADA1M-CJKtzmnlcqVgqI%3D')/microsoft.graph.itemAttachment/item/$entity",
  "item":{
    "@odata.type":"#microsoft.graph.message",
    "id":"",
    "createdDateTime":"2017-07-21T00:20:41Z",
    "lastModifiedDateTime":"2017-07-21T00:20:34Z",
    "receivedDateTime":"2017-07-21T00:19:55Z",
    "sentDateTime":"2017-07-21T00:19:52Z",
    "hasAttachments":false,
    "internetMessageId":"<BY2PR15MB05189A084C01F466709E414F9CA40@BY2PR15MB0518.namprd15.prod.outlook.com>",
    "subject":"Reminder - please bring laptop",
    "importance":"normal",
    "conversationId":"AAQkADA1MzMyOGI4LTlkZDctNDkzYy05M2RiLTdiN2E1NDE3MTRkOQAQAMG_NSCMBqdKrLa2EmR-lO0=",
    "isDeliveryReceiptRequested":false,
    "isReadReceiptRequested":false,
    "isRead":false,
    "isDraft":false,
    "webLink":"https://outlook.office365.com/owa/?ItemID=AAMkADA1M3MTRkOQAAAA%3D%3D&exvsurl=1&viewmodel=ReadMessageItem",
    "body":{
      "contentType":"html",
      "content":"<html><head>\r\n</head>\r\n<body>\r\n</body>\r\n</html>"
    },
    "sender":{
      "emailAddress":{
        "name":"Adele Vance",
        "address":"[email protected]"
      }
    },
    "from":{
      "emailAddress":{
        "name":"Adele Vance",
        "address":"[email protected]"
      }
    },
    "toRecipients":[
      {
        "emailAddress":{
          "name":"Alex Wilbur",
          "address":"[email protected]"
        }
      }
    ],
    "ccRecipients":[
      {
        "emailAddress":{
          "name":"Adele Vance",
          "address":"[email protected]"
        }
      }
    ]
  }
}

Source: https://developer.microsoft.com/en-us/graph/docs/api-reference/v1.0/api/attachment_get#request-2

Tilburg answered 18/1, 2018 at 1:34 Comment(5)
Hi Dave, Thanks for your answer! That looks exactly what I was looking for. Now I can make the customer a very happy customer since now a complete e-mail import functionality can be created. Again thanks and I will definitely will try this!! KR, BartGillard
Yeah it's most of the way there. An outstanding problem for me is to just get the bytes of the itemAttachment. I have my doubts that graph supports nested attachments in that itemAttachment as well.Tilburg
I've tested and tried it and I'm very pleased that it works now. Thanks again!Gillard
I searched high and low for this answer. Thank-you @DaveMoten For reference, once you have contentID you need to decode it. In powershell: [System.Text.Encoding]::ASCII.GetString([System.Convert]::FromBase64String($attachID.contentBytes))Skolnik
as of microsoft-graph version 5.34.0 it no longer needs to be decoded. In Java I check if the .oDataType equals "#microsoft.graph.itemAttachment" and then I cast the response to ((ItemAttachment) responseObject or, going deeper to ((Message) ((ItemAttachment) responseObject.item)Fronia
L
0

The official documentation: https://graph.microsoft.io/en-us/docs/api-reference/beta/api/attachment_get.htm . Use valid Bearer authentication access code, and check for appropriate Graph API permissions on the Azure management portal. Attachment is based64 encoded string, coming in the contentBytes field. Correct Uri for loading list of a message attachments is: https://graph.microsoft.com/beta/me/messages/[ message Id ]/attachments. Sample code to call attachments endpoint is below:

using (var client = new HttpClient())
{
    using (var request = new HttpRequestMessage(HttpMethod.Get, 
        "https://graph.microsoft.com/beta/me/messages/..id../attachments"))
    {
        request.Headers.Authorization = 
            new AuthenticationHeaderValue("Bearer", "...valid access token...");

        using (HttpResponseMessage response = await client.SendAsync(request))
        {
            if (response.StatusCode == HttpStatusCode.OK)
            {
                result = await response.Content.ReadAsStringAsync();
                var json = JObject.Parse(result);
            }
        }
    }
}
Lunik answered 8/12, 2016 at 23:17 Comment(1)
Hi Semen, Thanks for looking into the issue. However, your answer is regarding attachments in general and that is not the issue here. The question is about getting de contents of an itemAttachment. To simulate this you can use the outlook client and forward an e-mail message as attachment to another e-mail message. You'll notice that the Outlook client identifies it as an Outlook-Item. Exactly this kind of attachment are the ones I cannot get the contentBytes from. Did you managed to? Is the API version 1.0 a little more functional right now? PS: Do not use Beta in production solutionsGillard
D
0

Get attachment using MS Graph API for Java:
First build the graph client. Sample code

ClientSecretCredential clientSecretCredential = new ClientSecretCredentialBuilder()
                .clientId(yourClientId).clientSecret(yourClientSecret)
                .tenantId(yourTenantId).build();

TokenCredentialAuthProvider tokenCredAuthProvider = new TokenCredentialAuthProvider(clientSecretCredential);
GraphServiceClient<Request> gClient = GraphServiceClient.builder().authenticationProvider(tokenCredAuthProvider)
                .buildClient();

Either get all the attachments for a message-
FileAttachment fa = (FileAttachment) graphClient.users(id).messages(messageId).attachments().buildRequest().get();

Or get a particular attachment by passing the attachment id:

FileAttachment fa = (FileAttachment) graphClient.users(id).messages(messageId).attachments(attachmentId).buildRequest().get();

//Copy file attachment into a File from byte stream using FileUtils.
FileUtils.writeByteArrayToFile(new File(yourFileLocation), fa.contentBytes);

You can also similarly either get all users, messages or attachments or pass particular id to get a unique result for these entities.

Doriadorian answered 1/8, 2022 at 10:0 Comment(1)
Does not answer the question: OP asked about ItemAttachment - these are not FileAttachmentsKansas

© 2022 - 2025 — McMap. All rights reserved.