Код NodeJS для создания черновика электронного письма Gmail с вложением из Google Диска с учетом FileID

Мне нужно составить черновик электронного письма с использованием API-интерфейсов GMail с вложением с идентификатором файла из Google Диска с использованием API-интерфейсов Google Диска.

У меня есть рабочий вызов API GMail, который создает черновик электронного письма (без вложения):

const res = await gmail.users.drafts.create({
    userId: user.email,
    requestBody: {
        message: {
            raw: await createRawMessage(to, subject, htmlBody),
        },
    },
});

Вот код моей функции createRawMessage:

export async function createRawMessage(recipientEmail, subject, body) {
    const message = [
        `Content-Type: text/html; charset = "UTF-8"`,
        `to: ${recipientEmail}`,
        `subject: ${subject}\n`,
        body,
    ].join("\n");
    return Buffer.from(message)
        .toString("base64")
        .replace(/\+/g, "-")
        .replace(///g, "_")
        .replace(/=+$/, "");
}

Есть ли способ просто добавить fileId с Google Диска? Я бы предпочел не загружать файл в Base64Encode, так как он уже находится на Google Диске, и у меня есть значок fileId.

Кроме того, я не хочу использовать другую библиотеку, например NodeMailer.

Я рассмотрел, как отправлять электронные письма с вложениями (не создавая черновики), чтобы ссылаться на этот код в моей функции черновика, но мне не удалось найти образец, который извлекает файл с Google Диска. Единственные примеры требуют загрузки файла с Google Диска и последующего включения его в свойство raw параметра requestBody.message API gmail.users.drafts.create.

У меня это работает в скрипте Google Apps, но теперь я пытаюсь перенести эту функциональность в NodeJS.

ОБНОВЛЯТЬ: Вот код, который работает со скриптом Google Apps:

    var attachments = [];
    var file = DriveApp.getFileById(appDetails.resume_file_id);

    attachments.push(file.getAs(file.getMimeType()));

    var draft = GmailApp.createDraft(
      `${contactDetails.contact_name} <${contactDetails.contact_email}>`, 
      `${appDetails.job_title} role @ ${appDetails.company}`, 
      textBody,
      {
        htmlBody: htmlBody,
        attachments: attachments,
      }
    );```
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
1
0
78
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

В качестве простого подхода, как насчет следующей модификации? В этой модификации в htmlBody вашего скрипта добавляется ссылка webViewLink файла на Google Диске. Для получения webViewLink используется Drive API.

Конечно, если вы уже знаете значения webViewLink и name файла, вы можете использовать их напрямую. В настоящее время использование Drive API не требуется.

Важным моментом является то, что в этом случае, чтобы открыть файл на стороне пользователя, необходимо поделиться файлом с пользователем. Пожалуйста, будьте осторожны.

Модифицированный скрипт:

Если вы тестируете этот скрипт, включите Drive API и добавьте область https://www.googleapis.com/auth/drive.metadata.readonly к своим текущим областям.

const gmail = google.gmail({ version: "v1", auth }); // Please set your client
const drive = google.drive({ version: "v3", auth }); // Please set your client

// Please set your values.
const fileId = "###";
const user = { email: "###" };
const to = "###";
const subject = "sample subject";
const htmlBody = "sample HTML body.";


const { data: { name, webViewLink } } = await drive.files.get({ fileId, fields: "name,webViewLink" });
const res = await gmail.users.drafts.create({
  userId: user.email,
  requestBody: {
    message: {
      raw: await createRawMessage(
        to,
        subject,
        htmlBody + `<div><a href = "${webViewLink}" target = "_blank"><span>${name}</span></a></div>`
      ),
    },
  },
});
console.info(res.data);

Примечание:

  • В этой модификации используется webViewLink. Но если вы хотите прикрепить файл в виде двоичных данных, если файл не является файлом Документов Google (документы, таблицы, слайды и т. д.), вы можете прикрепить файл напрямую. Но если файл представляет собой файл Документов Google, его необходимо преобразовать в другой тип mimeType, поскольку на текущем этапе файлы Документов Google невозможно напрямую экспортировать с исходным типом mimeType. Пожалуйста, будьте осторожны с этим. Но по вашему вопросу я предположил, что это может быть не тот результат, которого вы ожидали.

  • Если этот подход не дает ожидаемого результата, укажите текущий сценарий this working in a Google Apps Script из I have this working in a Google Apps Script, but now trying to migrate this functionality to NodeJS..

Ссылка:

  • Метод: files.get

Добавлен:

Из ответа ОП:

Я думал просто поместить webViewLink в тело, но на самом деле мне хотелось бы добавить вложение.

Я заметил, что ОП хотел прикрепить содержимое файла, не являющееся файлами Google Docs. В этом случае пример сценария выглядит следующим образом. В этом случае содержимое файла можно загрузить напрямую.

В этой модификации добавьте https://www.googleapis.com/auth/drive.readonly для загрузки содержимого файла.

function getData(drive, fileId) {
  return new Promise((resolve, reject) => {
    drive.files.get(
      { fileId, alt: "media", supportsAllDrives: true },
      { responseType: "stream" },
      function (err, { data }) {
        if (err) {
          return reject("The API returned an error: " + err);
        }
        let buf = [];
        data.on("data", function (e) {
          buf.push(e);
        });
        data.on("end", function () {
          const buffer = Buffer.concat(buf);
          resolve(buffer.toString("base64"));
        });
      }
    );
  });
}

async function createRawMessage(recipientEmail, subject, body, drive, fileId) {
  const { data: { name, mimeType } } = await drive.files.get({ fileId, fields: "name,mimeType" });
  const fileContent = await getData(drive, fileId);

  // Ref: This is my answer. https://stackoverflow.com/a/53891937
  const message = [
    "MIME-Version: 1.0",
    `to: ${recipientEmail}`,
    `subject: ${subject}`,
    "Content-Type: multipart/mixed; boundary=boundary_mail1\n",
    "--boundary_mail1",
    "Content-Type: multipart/alternative; boundary=boundary_mail2\n",
    "--boundary_mail2",
    "Content-Type: text/html; charset=UTF-8",
    "Content-Transfer-Encoding: quoted-printable\n",
    `${body}\n`,
    "--boundary_mail2--",
    "--boundary_mail1",
    `Content-Type: ${mimeType}`,
    `Content-Disposition: attachment; filename = "${name}"`,
    "Content-Transfer-Encoding: base64\n",
    fileContent,
    "--boundary_mail1--",
  ].join("\n");

  return Buffer.from(message)
    .toString("base64")
    .replace(/\+/g, "-")
    .replace(///g, "_")
    .replace(/=+$/, "");
}


const gmail = google.gmail({ version: "v1", auth }); // Please set your client
const drive = google.drive({ version: "v3", auth }); // Please set your client

// Please set your values.
const fileId = "###";
const user = { email: "###" };
const to = "###";
const subject = "sample subject";
const htmlBody = "sample HTML body.";

const res = await gmail.users.drafts.create({
  userId: user.email,
  requestBody: { message: { raw: await createRawMessage(to, subject, htmlBody, drive, fileId) } },
});
console.info(res.data);
  • В этой модификации файл fileId не является файлом Google Docs (Документы, Таблицы, Слайды и т. д.). Пожалуйста, будьте осторожны с этим.
  • При запуске этого сценария содержимое файла загружается, и загруженное содержимое файла используется в качестве вложения. И создается черновик электронного письма.

Спасибо, что ответили мне по этому поводу. Я думал просто поместить webViewLink в тело сообщения, но мне хотелось бы добавить вложение. Я обновил исходное сообщение, добавив пример кода, который работает в скрипте Google Apps.

Deep Trikannad 21.05.2024 03:25

@Deep Trikannad Спасибо за ответ. Из вашего ответа я добавил еще один пример сценария. Пожалуйста, подтвердите это.

Tanaike 21.05.2024 04:01

Спасибо @Tanaike за быстрый ответ. Я знаю, что могу загрузить его и закодировать, чтобы прикрепить к электронному письму, но я пытался избежать этого шага и вместо этого заставил API Gmail извлекать его напрямую с Google Диска через FileId.

Deep Trikannad 21.05.2024 05:30

@Deep Trikannad Спасибо за ответ. По поводу but I was trying to avoid that step and instead have the Gmail API pull it directly from Google Drive via the FileId., итак, я предложил 1-й подход. Но, скажете вы but I'd like to actually add the attachment. И, судя по I have this working in a Google Apps Script, but now trying to migrate this functionality to NodeJS. и добавленному вами скрипту Google Apps, я подумал, что вы хотите преобразовать отображаемый скрипт Google Apps в Node.js. Итак, я предложил второй подход. Я думаю, что мой второй сценарий даст тот же результат, что и ваш.

Tanaike 21.05.2024 06:34

Спасибо @Tanaike. Я также обратился по этому поводу в службу поддержки Google, и они сказали то же самое, что вы предложили. Таким образом, я принял ваш ответ. Еще раз спасибо!

Deep Trikannad 27.05.2024 19:03

@Deep Trikannad Спасибо за ответ. Я понимаю ваш ответ. И тебе спасибо.

Tanaike 28.05.2024 02:22

Другие вопросы по теме