API GMail с использованием запроса POST, код ошибки: 400, требуется адрес получателя - PullRequest
2 голосов
/ 17 июня 2019

Я пытаюсь отправить электронное письмо с помощью запроса POST, используя только стандартные модули Node в NodeJS v8.10 через API GMail. Пример кода приведен ниже.

Я получаю ошибку:

{
 "error": {
  "errors": [
   {
    "domain": "global",
    "reason": "invalidArgument",
    "message": "Recipient address required"
   }
  ],
  "code": 400,
  "message": "Recipient address required"
 }
}

В нем говорится, что адрес получателя требуется, но в соответствии с тем, что я думаю (я могу ошибаться), мое преобразование base64url выполнено правильно, так как я проверил его в Google API Explorer, но моя проблема заключается в передаче данных, я делаю это правильно, так как сказано в руководстве, то есть внутри тела с «сырым» ключом, но он все еще не работает, и это то, где моя проблема должна быть. Может быть, я что-то упускаю, может, я не знаю правильную структуру.

Да, есть несколько сообщений по этому поводу, но ни одно из них не предоставило решения. Я сослался на руководство по https://developers.google.com/gmail/api/v1/reference/users/messages/send но данный пример с использованием клиентской библиотеки.

Я пробовал все, передавая «сырые» данные с кодировкой base64url в функцию записи запроса, передавая их как параметр данных в параметрах, передавая их через параметры тела в параметрах, все, что я могу придумать.

Я что-то упустил? Куда я иду не так?

Я новичок в nodejs, поэтому, пожалуйста, объясните, и, если возможно, примерная структура решения будет очень кстати.

Base64url работает нормально, я думаю. Я скопировал строку, созданную преобразованием, и попробовал ее на https://developers.google.com/gmail/api/v1/reference/users/messages/send?apix=true Он работает нормально и отправляет мне письмо, но не работает с моим кодом.

var email = (
          "Content-Type: text/plain; charset=\"UTF-8\"\n" +
          "Content-length: 5000\n" +
          "MIME-Version: 1.0\n" +
          "Content-Transfer-Encoding: message/rfc2822\n" +
          "to: something@something.com\n" +
          "from: \"Some Name\" <something@gmail.com>\n" +
          "subject: Hello world\n\n" +

          "The actual message text goes here"
            );

async function sendMail(token,resp) {

    return new Promise((resolve,reject) => {

      var base64EncodedEmail = Buffer.from(email).toString('base64'); 
      var base64urlEncodedEmail = base64EncodedEmail.replace(/\+/g, '-').replace(/\//g, '_');

      var params = {
        userId: 'me',
        resource: {
          'raw': base64urlEncodedEmail
        }
      };

      var body2 = {
          "raw": base64urlEncodedEmail,
        }

      var options = {
        hostname: 'www.googleapis.com',
        path:'/upload/gmail/v1/users/me/messages/send',
        headers: {
          'Authorization':'Bearer '+token,
          'Content-Type':'message/rfc822',
        },
        body: {
          "raw": base64urlEncodedEmail,
          'resource': {
            'raw': base64urlEncodedEmail,
          }
        },
        data: JSON.stringify({
          'raw': base64urlEncodedEmail,
          'resource': {
            'raw': base64urlEncodedEmail,
          }
        }),
        message: {
          'raw': base64urlEncodedEmail,
        },
        payload: {
          "raw": base64urlEncodedEmail, //this is me trying everything I can think of
        },
        // body: raw,
        // }
        userId: 'me',
        // resource: {
        //   'raw': base64urlEncodedEmail
        // },
        method: 'POST',
      };

    var id='';
    console.log(base64urlEncodedEmail);
    const req = https.request(options, (res) => {

        var body = '';

        res.on('data', (d) => {
            body += d;
        });
        res.on('end', () => {
            var parsed = body;
            console.log(parsed);
        })
      });

      req.on('error', (e) => {
        console.error(e);
      });
      req.write(JSON.stringify(body2));
      req.end();
  });
};

Спасибо за ваше время и ответы.

1 Ответ

0 голосов
/ 18 июня 2019

Я нашел решение.

Везде говорится, что нужно преобразовать строку в формате rfc822 в Base64url для отправки и присоединить ее к свойству raw в теле сообщения POST, но я не знаю, что изменилось, и вам больше не нужно это делать.

Перво-наперво, Content-Type в заголовке должен быть

'Content-Type':'message/rfc822'

Теперь, поскольку мы указываем тип содержимого как message / rfc822, нам больше не нужно преобразовывать данные, которые мы хотим отправить, в формат base64url, я думаю (не уверен в причине, потому что у меня очень мало знание об этом.) Только передавая "To :thing@any.com" как тело работает.

Вот полный код того, как это сделать для того, кто борется за ту же проблему.

function makeBody(to, from, subject, message) {
    let str = [
        "to: ", to, "\n",
        "from: ", from, "\n",
        "subject: ", subject, "\n\n",
        message,
    ].join('');
    return str;
}


async function getIdAsync(token,resp) {

    return new Promise((resolve,reject) => {

      let raw = makeBody("something@gmail.com", "something@gmail.com", "Subject Here", "blah blah blah");

      var options = {
        hostname: 'www.googleapis.com',
        path:'/upload/gmail/v1/users/me/messages/send',
        headers: {
          'Authorization':'Bearer '+token,
          'Content-Type':'message/rfc822'
        },
        method: 'POST',
      };

    const req = https.request(options, (res) => {

        var body = '';

        res.on('data', (d) => {
            body += d;
        });
        res.on('end', () => {
            var parsed = body;
            console.log(parsed);
        })
      });

      req.on('error', (e) => {
        console.error(e);
      });
      req.write(raw);
      req.end();
  });
};

Happy Coding:)

...