2

I've been successfully getting the list of mails in inbox using microsoft graph rest api but i'm having tough time to understand documentation on how to download attachments from mail.

enter image description here

For example : This question stackoverflow answer speaks about what i intend to achieve but i don't understand what is message_id in the endpoint mentioned : https://outlook.office.com/api/v2.0/me/messages/{message_id}/attachments

UPDATE

i was able to get the details of attachment using following endpoint : https://graph.microsoft.com/v1.0/me/messages/{id}/attachments and got the following response.

enter image description here

I was under an impression that response would probably contain link to download the attachment, however the response contains key called contentBytes which i guess is the encrypted content of file.

4
  • Is the value of the body property the data that you are trying to download? Commented Feb 22, 2019 at 6:02
  • There is a PDF attachment in the mail. i want to download that. HasAttachment flag is also true in the resulting json Commented Feb 22, 2019 at 6:12
  • Have not tried MS-grapgh. What property value of the object is a PDF file? Commented Feb 22, 2019 at 7:01
  • @guest271314 : I was able to get the details of the attachment using api endpoint : https://graph.microsoft.com/v1.0/me/messages/{id}/attachments Commented Feb 22, 2019 at 7:45

3 Answers 3

1

For attachment resource of file type contentBytes property returns

base64-encoded contents of the file

Example

The following Node.js example demonstrates how to get attachment properties along with attachment content (there is a dependency to request library):

const attachment = await getAttachment(
    userId,
    mesasageId,
    attachmentId,
    accessToken
);
const fileContent = new Buffer(attachment.contentBytes, 'base64');
//...

where

const requestAsync = options => {
  return new Promise((resolve, reject) => {
    request(options, (error, res, body) => {
      if (!error && res.statusCode == 200) {
        resolve(body);
      } else {
        reject(error);
      }
    });
  });
};

const getAttachment = (userId, messageId, attachmentId, accessToken) => {
  return requestAsync({
    url: `https://graph.microsoft.com/v1.0/users/${userId}/messages/${messageId}/attachments/${attachmentId}`,
    method: "GET",
    headers: {
      Authorization: `Bearer ${accessToken}`,
      Accept: "application/json;odata.metadata=none"
    }
  }).then(data => {
    return JSON.parse(data);
  });
};

Update

The following example demonstrates how to download attachment as a file in a browser

try {
  const attachment = await getAttachment(
    userId,
    mesasageId,
    attachmentId,
    accessToken
  );

  download("data:application/pdf;base64," +  attachment.contentBytes, "Sample.pdf","application/pdf");
} catch (ex) {
  console.log(ex);
}

where

async function getAttachment(userId, messageId, attachmentId, accessToken){
    const res = await fetch(
      `https://graph.microsoft.com/v1.0/users/${userId}/messages/${messageId}/attachments/${attachmentId}`,
      {
        method: "GET",
        headers: {
          Authorization: `Bearer ${accessToken}`,
          Accept: "application/json;odata.metadata=none"
        }
      }
    );
    return res.json();
 }

Dependency: download.js library

Sign up to request clarification or add additional context in comments.

5 Comments

I've been able to get the contentBytes property. I'm looking for solution to use it and save the attachment
@ifranharun, save to local file in Node.js?
No, I'm using a simple web-page with only Jquery. I can use other libraries as well. But No NodeJs
@ifranharun, could you update your question then with a minimal example which demonstrates what is not working?
@irfanharun, the answer has been updated (see update section)
1

I had the same problem. This is the function I used to solve it. Please notice that the 'contentBytes' are already base64 encoded, so you have to decode them to be written. You do this with base64.b64decode. If you don't do this, your files will be saved but they will be unreadable.

def save_attachments(self, message_id):
        """ Saves the email attachments obtained from MS Graph REST API.       
        """
        # Set the API endpoint. This will give all the attachments for a given email (message_id provided)
        url = f"https://graph.microsoft.com/v1.0/me/messages/{message_id}/attachments"
        
        # using the MS Graph client to make the call as this is a 'delegated' email authorization
        # this will create a flow with a URL and a code for the owner of the email account
        # to authorize its use. You can use requests instead if you have the access in AAD. (Application scenario)
        response = self.user_client.get(url)

        # gets the 'value' part of the json response, which contains all the attachment details
        attachments = response.json()['value']
        
        counter = 0
        # Save the attachment content to a file
        for attachment in attachments:
            counter+=1
            file_name = attachment["name"]        
            content_bytes = attachment["contentBytes"]

            full_file_name = os.path.join(file_path, file_name)
            with open(full_file_name, "wb") as f:
                # converts text to base64 encoded bytes
                # remember to add the import from base64 import b64decode
                decoded_content = b64decode(content_bytes)
                f.write(decoded_content)
            print(f"{counter}. {file_name}.")

Comments

0

I don't know if this would help but you just have to add /$value at the end of your request :

https://graph.microsoft.com/v1.0/me/messages/{message_id}/attachments/{attachment_id}/$value

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.