KartikTalwar / gmail.js

Gmail JavaScript API
MIT License
3.74k stars 455 forks source link

Issue downloading attachment(s) from compose view #716

Closed GTP95 closed 2 years ago

GTP95 commented 2 years ago

Greetings,

I'm failing to download an attachment (for now I tried only with one, but my code should work with any number of attachments) from the compose view. Here is how I'm trying to do this. First I get a list of the attachments like this

const emailAttachments = compose_ref.attachments();
console.log("Attachments: ", emailAttachments);

And indeed in the console I get a list with an object containing information about the attachment. Then I try to get the promises to download the attachments like this:

const listOfAttachmentPromises = [];
          for (const attachment in emailAttachments) {
            listOfAttachmentPromises.push(
              // @ts-ignore
              gmail.tools.make_request_download_promise(attachment.url, true)
            );
          }

I'm using JS with added type checking by the TS compiler, in the code above the error I'm ignoring is about attachment.url being a string and so not having the url property, but I think it is a false positive due to me not having set up types for this library correctly. Then I print that list to the console and I indeed get a fulfilled promise:

console.log(
            "List of attachment promises: ",
            listOfAttachmentPromises
          );

promise But if I later try to use that, seems that the promise turned into a string:

for (const attachment in listOfAttachmentPromises) {
            console.log("attachment: ", attachment);
            console.log("Reported type of attachment: ", typeof attachment);
}

string

How can I get the Uint8Array representing the attachment?

Thank you for your help,

GTP

josteink commented 2 years ago

Without doing any "deep" debugging, I can see that you are simultaneously downloading all attachments (you iterate and generate promises) without awaiting them.

This effectively means you are trying to download all in parallel and I have no idea if that works at all.

Try downloading them one by one?

const attachments = [];
// use "of" not "in" to iterate over an array/collection-type object
// for (const attachmentInfo in attachmentInfos) {
for (const attachmentInfo of attachmentInfos) {
    // note use of "await" in loop. this causes one download at a time.
    const attachmentData = await  gmail.tools.make_request_download_promise(attachmentInfo.url, true);
    attachments.push(attachmentData)
}
josteink commented 2 years ago

As for the actual attachment-result... I've been able to post that as is to other REST-endpoints without loss of data or fidelity.

It might be the browser is trying to be helpful and tries to convert it into a string if you try to access it as one (like you do with console.log? No idea, honestly.

GTP95 commented 2 years ago

Following your suggestions it now works, thank you!