Ошибка Nodemailer при использовании gmail в функциях firebase - PullRequest
0 голосов
/ 01 декабря 2018

Я использую облачные функции Firebase.У меня настроена следующая настройка.Хотя это работает совершенно нормально на моей локальной машине, это вызывает проблемы при работе на серверах.Я пробовал gazillion обходных путей в Интернете, но не повезло.Что не так с этим?

'use strict'
const functions = require('firebase-functions');
var admin = require('firebase-admin');
const express = require('express');
const nodemailer = require('nodemailer');
const app = express()

var emailRecepient;
var userName;


const smtpTransport = nodemailer.createTransport({
service: "gmail",
host: 'smtp.gmail.com',
port: 587, // tried enabling and disabling these, but no luck
secure: false, // similar as above
auth: {
  user: '<emailid>',
  pass: '<password>'
    },
        tls: {
        rejectUnauthorized: false
    }
});

var mailOptions = {
  from: 'test <hello@example.com>',
  to: emailRecepient,
  subject: 'Welcome to test',
  text: 'welcome ' + userName + ". did you see the new things?"
};

function sendmail() {
smtpTransport.sendMail(mailOptions, function (error, info) {
    if (error) {
        console.log(error);
    }
    else {
        console.log('Email sent: ' + info.response);
    }
});
};

exports.sendEmails = functions.database.ref('/users/{userID}/credentials').onCreate((snap, context) => {

  const userID = context.params.userID;
  const vals = snap.val()

  userName = vals.name;
  emailRecepient = vals.email;

  smtpTransport.sendMail(mailOptions, function (error, info) {
  if (error) {
      console.log("Error sending email ---- ",error);
  }
  else {
      console.log('Email sent: ' + info.response);
  }
  });

  return true;

});

Ошибка, которую я получил во всех случаях:

        Error sending email 2 ----  { Error: Invalid login: 534-5.7.14 <https://accounts.google.com/signin/continue?sarp=1&scc=1&plt=AKgnsbsi
    534-5.7.14 qRQLfD9YlFZDsPj7b8QQACro9c41PjhSVo0NZ4i5ZHNlyycFi_FyRp8VdZ_dH5ffWWAABQ
    534-5.7.14 8rH2VcXkyZBFu00-YHJUQNOqL-IqxEsZqbFCwCgk4-bo1ZeDaKTdkEPhwMeIM2geChH8av
    534-5.7.14 0suN293poXFBAk3TzqKMMI34zCvrZlDio-E6JVmTrxyQ-Vn9Ji26LaojCvdm9Bq_4anc4U
    534-5.7.14 SpQrTnR57GNvB0vRX1BihDqKuKiXBJ5bfozV1D1euQq18PZK2m> Please log in via
    534-5.7.14 your web browser and then try again.
    534-5.7.14  Learn more at
    534 5.7.14  https://support.google.com/mail/answer/78754 t2sm3669477iob.7 - gsmtp
        at SMTPConnection._formatError (/user_code/node_modules/nodemailer-smtp-transport/node_modules/smtp-connection/lib/smtp-connection.js:528:15)
        at SMTPConnection._actionAUTHComplete (/user_code/node_modules/nodemailer-smtp-transport/node_modules/smtp-connection/lib/smtp-connection.js:1231:30)
        at SMTPConnection.<anonymous> (/user_code/node_modules/nodemailer-smtp-transport/node_modules/smtp-connection/lib/smtp-connection.js:319:22)
        at SMTPConnection._processResponse (/user_code/node_modules/nodemailer-smtp-transport/node_modules/smtp-connection/lib/smtp-connection.js:669:16)
        at SMTPConnection._onData (/user_code/node_modules/nodemailer-smtp-transport/node_modules/smtp-connection/lib/smtp-connection.js:493:10)
        at emitOne (events.js:96:13)
        at TLSSocket.emit (events.js:188:7)
        at readableAddChunk (_stream_readable.js:176:18)
        at TLSSocket.Readable.push (_stream_readable.js:134:10)
        at TLSWrap.onread (net.js:559:20)
      code: 'EAUTH',
      response: '534-5.7.14 <https://accounts.google.com/signin/continue?sarp=1&scc=1&plt=AKgnsbsi\n534-5.7.14 qRQLfD9YlFZDsPj7b8QQACro9c41PjhSVo0NZ4i5ZHNlyycFi_FyRp8VdZ_dH5ffWWAABQ\n534-5.7.14 8rH2VcXkyZBFu00-YHJUQNOqL-IqxEsZqbFCwCgk4-bo1ZeDaKTdkEPhwMeIM2geChH8av\n534-5.7.14 0suN293poXFBAk3TzqKMMI34zCvrZlDio-E6JVmTrxyQ-Vn9Ji26LaojCvdm9Bq_4anc4U\n534-5.7.14 SpQrTnR57GNvB0vRX1BihDqKuKiXBJ5bfozV1D1euQq18PZK2m> Please log in via\n534-5.7.14 your web browser and then try again.\n534-5.7.14  Learn more at\n534 5.7.14  https://support.google.com/mail/answer/78754 t2sm3669477iob.7 - gsmtp',
      responseCode: 534,
      command: 'AUTH PLAIN' }

Я даже повернул allow secure apps in the google settings.Но по какой-то причине это, похоже, не работает.Любая помощь очень ценится.

В соответствии с рекомендациями Renaud, я попытался firebase-samples/email-confirmation, и у меня появляется следующая ошибка:

TypeError: snapshot.changed is not a function
at exports.sendEmailConfirmation.functions.database.ref.onWrite (/user_code/index.js:38:17)
at Object.<anonymous> (/user_code/node_modules/firebase-functions/lib/cloud-functions.js:112:27)
at next (native)
at /user_code/node_modules/firebase-functions/lib/cloud-functions.js:28:71
at __awaiter (/user_code/node_modules/firebase-functions/lib/cloud-functions.js:24:12)
at cloudFunction (/user_code/node_modules/firebase-functions/lib/cloud-functions.js:82:36)
at /var/tmp/worker/worker.js:758:24
at process._tickDomainCallback (internal/process/next_tick.js:135:7)

Cheers

Ответы [ 2 ]

0 голосов
/ 27 июля 2019

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

1) function.ts (написано на TypeScript)

import * as admin from 'firebase-admin';
import * as functions from 'firebase-functions';
import * as nodemailer from 'nodemailer';

admin.initializeApp();

// I'm taking all these constants as secrets injected dynamically (important when you make `git push`), but you can simply make it as a plaintext.
declare const MAIL_ACCOUNT: string; // Declare mail account secret.
declare const MAIL_HOST: string; // Declare mail account secret.
declare const MAIL_PASSWORD: string; // Declare mail password secret.
declare const MAIL_PORT: number; // Declare mail password secret.

const mailTransport = nodemailer.createTransport({
  host: MAIL_HOST,
  port: MAIL_PORT, // This must be a number, important! Don't make this as a string!!
  auth: {
    user: MAIL_ACCOUNT,
    pass: MAIL_PASSWORD
  }
});

exports.sendMail = functions.https.onRequest(() => {
  const mailOptions = {
    from: 'ME <SENDER@gmail.com>',
    to: 'RECEIVER@gmail.com',
    subject: `Information Request from ME`,
    html: '<h1>Test</h1>'
  };
  mailTransport
    .sendMail(mailOptions)
    .then(() => {
      return console.log('Mail sent'); // This log will be shown in Firebase Firebase Cloud Functions logs.
    })
    .catch(error => {
      return console.log('Error: ', error); // This error will be shown in Firebase Cloud Functions logs.
    });
});

При этом вы должны получить электронное письмо от SENDER@gmail.com до RECEIVER@gmail.com, конечно, измените его для своих собственных нужд.

Примечание. У меня возникла та же проблема с отправкой почты правильно на localhost, но при развертывании - нет.Похоже, проблема в моем случае заключалась в том, что я не использовал port и host в createTransport, вместо этого у меня было:

const mailTransport = nodemailer.createTransport({
  service: 'gmail',
  auth: {
    user: MAIL_ACCOUNT,
    pass: MAIL_PASSWORD
  }
});

Кроме того, не забудьте включить Менее безопасный доступ к приложению до ON .Также https://accounts.google.com/DisplayUnlockCaptcha может быть полезным.

0 голосов
/ 01 декабря 2018

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

Это очень хорошо объяснено в официальной серии видеороликов Firebase здесь: https://firebase.google.com/docs/functions/video-series/. В частности, посмотрите три видеоролика под названием «Изучите обещания JavaScript» (части 2 и 3 посвящены в основном фоновым облачным функциям,но это действительно стоит посмотреть Часть 1 прежде).

Поэтому вы должны изменить свой код следующим образом:

exports.sendEmails = functions.database.ref('/users/{userID}/credentials').onCreate((snap, context) => {

  const userID = context.params.userID;
  const vals = snap.val()

  userName = vals.name;
  emailRecepient = vals.email;

  return smtpTransport.sendMail(mailOptions);
});

Если вы хотите вывести на консоль результат отправки электронного письма, выможно сделать следующим образом:

  return smtpTransport.sendMail(mailOptions)
    .then((info) => console.log('Email sent: ' + info.response))
    .catch((error) => console.log("Error sending email ---- ", error));
});

На самом деле существует официальный образец Cloud Functions, который делает именно это, см. https://github.com/firebase/functions-samples/blob/master/email-confirmation/functions/index.js

...