Функция Firebase для nodemailer развернута, но нет журналов и некорректно работает с базой данных

Я установил функцию firebase с помощью nodemailer, чтобы получить входные данные из моей базы данных firebase, подключенной к моей контактной форме, и отправить их по электронной почте.

Я успешно развернул функцию и вижу, что функция отображается в моей консоли firebase, однако я не получаю никаких ошибок в консоли и не вижу никаких журналов или информации в функциональном разделе консоли. А сейчас это просто не работает.

Это первый раз, когда я делаю это, и я просмотрел почти все другие похожие вопросы по SO, но ни один из них не дал мне никаких подсказок относительно того, что я делаю неправильно.

Это мои функции package.json:

{
  "name": "functions",
  "description": "Cloud Functions for Firebase",
  "scripts": {
    "lint": "eslint .",
    "serve": "firebase serve --only functions",
    "shell": "firebase functions:shell",
    "start": "npm run shell",
    "deploy": "firebase deploy --only functions",
    "logs": "firebase functions:log"
  },
  "engines": {
    "node": "8"
  },
  "dependencies": {
    "firebase-admin": "~7.0.0",
    "firebase-functions": "^2.3.0",
    "nodemailer": "^6.1.1"
  },
  "devDependencies": {
    "eslint-plugin-promise": "^4.0.1",
    "firebase-functions-test": "^0.1.6"
  },
  "private": true
}

и это код index.js внутри папки functions:

const functions = require("firebase-functions");
const admin = require("firebase-admin");
const nodemailer = require("nodemailer");


const gmailEmail = "k****[email protected]";
const gmailPassword = functions.config().gmail.pass;

admin.initializeApp();


var goMail = function(message) {

  const transporter = nodemailer.createTransport({
    service: "gmail",
    auth: {
      user: gmailEmail,
      pass: gmailPassword
    }
  });


  const mailOptions = {
    from: gmailEmail, // sender address
    to: "****[email protected]", // list of receivers
    subject: "!", // Subject line
    text: "!" + message, // plain text body
    html: "!" + message // html body
  };


  const getDeliveryStatus = function(error, info) {
    if (error) {
      return console.log(error);
    }
    console.log("Message sent: %s", info.messageId);

  };


  transporter.sendMail(mailOptions, getDeliveryStatus);
};

exports.onDataAdded = functions.database
  .ref("/messages/{messageId}")
  .onCreate(function(snap, context) {

    const createdData = snap.val();
    var name = createdData.name;
    var email = createdData.email;
    var number = createdData.number;
    var message = createdData.message;


    goMail(name, email, number, message);
  });

Я не уверен, что моя установка неправильная или я что-то делаю не так с кодом nodemailer в index.js.

Спасибо за помощь заранее.


person Ikai Yanasaki    schedule 15.05.2019    source источник
comment
Как вы запускаете функцию?   -  person Frank van Puffelen    schedule 15.05.2019
comment
Действительно хороший вопрос, Фрэнк, извините за то, что я такой нуб, но я не уверен, выполнил ли я триггер, я просто смотрел на другой пример этого от команды firebase на github и видел раздел о том, как они запускали функция, основанная на изменениях в базе данных, но в моем собственном случае я несколько потерялся. Не могли бы вы указать мне правильное направление? Спасибо .----- Моя база данных собирает 4 разных входа в каждой коллекции, которая имеет ссылку на сообщения   -  person Ikai Yanasaki    schedule 15.05.2019
comment
Похоже, вы новичок в облачных функциях, и в этом случае взять сложный образец, подобный тому, который вы нашли, и попытаться заставить его работать, вероятно, слишком сложно сделать сразу. Функция onDataAdded запускается, когда узел узла создается в /emails, и ожидает, что этот новый узел будет иметь свойство email, которое является телом сообщения, которое вы хотите отправить людям.   -  person Frank van Puffelen    schedule 15.05.2019
comment
Вы действительно правы, и вы не знаете, насколько я ценю ваш вклад. var messageRef = firebase.database().ref("messages"); - это ссылка на коллекцию в моей базе данных, из того, что вы мне до сих пор объяснили, я думаю, вместо exports.onDataAdded = functions.database .ref("/emails/{sessionId}") мне нужно иметь exports.onDataAdded = functions.database .ref("/messages/{sessionId}")? Спасибо еще раз.   -  person Ikai Yanasaki    schedule 15.05.2019
comment
Я бы рекомендовал перезапустить на мгновение и следовать вместе с документацией Firebase для облачных функций. Сначала простое начало работы, а затем с помощью триггеры базы данных в реальном времени. Это поможет вам лучше понять скопированный код и подготовит вас к тому, чтобы изменить его в соответствии с вашими потребностями.   -  person Frank van Puffelen    schedule 15.05.2019
comment
Я так и сделаю. Вы помогли мне больше, чем я мог просить, я не знаю, как отблагодарить вас за ваше время. Ура, Фрэнк!   -  person Ikai Yanasaki    schedule 15.05.2019
comment
В дополнение к рекомендациям Фрэнка я бы добавил, что, поскольку ваша облачная функция запускается фоновым событием, вы должны вернуть обещание, чтобы указать, что асинхронные задачи завершены. В вашем случае это означает, что вы должны вернуть обещание, возвращенное transporter.sendMail() (Node Mailer вернет обещание, если обратный вызов не задан (nodemailer.com/usage)). Ключевым моментом является возврат обещания, как объясняется в трех видеороликах о обещаниях JavaScript из серии видео Firebase: firebase.google.com/docs/functions/video-series   -  person Renaud Tarnec    schedule 15.05.2019
comment
@RenaudTarnec Спасибо также за ваш вклад. Что касается обещаний, я просто смотрел те же видео, которые вы упомянули. После некоторого чтения и лучшего понимания функций я обновил свой код index.js. Я был бы очень признателен, если бы вы могли посмотреть и дать мне отзыв.   -  person Ikai Yanasaki    schedule 15.05.2019
comment
@ Mike-Selles увидеть ответ   -  person Renaud Tarnec    schedule 15.05.2019
comment
Хороший улов Рено!   -  person Frank van Puffelen    schedule 15.05.2019


Ответы (1)


Как объясняется в комментарии, поскольку ваша облачная функция запускается фоновым событием, вы должны вернуть обещание, чтобы указать, что асинхронные задачи завершены.

Итак, в функции goMail вы должны вернуть обещание, возвращаемое методом sendMail(), с помощью:

...
return transporter.sendMail(mailOptions);   //Remove the callback

И вы должны вернуть в самой облачной функции обещание, возвращаемое функцией goMail, с:

return goMail(...) 
person Renaud Tarnec    schedule 15.05.2019
comment
Спасибо, Фрэнк и Рено, вы, ребята, очень помогли. Я получил все, чтобы работать так, как хотел, и научился на высоте. - person Ikai Yanasaki; 15.05.2019