在Firebase函数中使用gmail时出现Nodemailer错误

时间:2018-12-01 06:03:35

标签: node.js firebase smtp google-cloud-functions nodemailer

我正在使用Firebase云功能。我配置了以下设置。尽管这在我的本地计算机上可以正常工作,但是在服务器上运行时却给了我一个问题。我在互联网上尝试了数以千计的工作,但是没有运气。怎么了?

import csv, itertools

age_50 = {39: 66, 40: 83, 42: 217, 43: 53, 23: 33, 21: 28} 
age50_80 = {59: 397, 65: 408, 61: 120, 67: 241, 68: 372, 78: 424, 76: 635 } 
age_80 = {80: 93, 88: 425, 83: 165, 84: 58, 91: 88} 

f = open("test.csv", "w", newline='')
cf = csv.writer(f)

cf.writerows(
    itertools.zip_longest(
        ['Age_Under50'] + [age_50[k] for k in age_50],
        ['Between_50_80']+[age50_80[k] for k in age50_80],
        ['Greater_80']+[age_80[k] for k in age_80],
        fillvalue=0
    )
)

f.close()

我在所有情况下遇到的错误都是:

'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' } 。但是由于某种原因,这似乎不起作用。任何帮助都非常感谢。

根据Renaud的建议,我尝试了allow secure apps in the google settings,但遇到以下错误:

firebase-samples/email-confirmation

欢呼

3 个答案:

答案 0 :(得分:1)

当您在后台触发的Cloud Function中执行异步操作时,您必须返回一个Promise,即Cloud Function等待该Promise解析以便终止。

在以下官方Firebase视频系列中对此进行了很好的解释:https://firebase.google.com/docs/functions/video-series/。尤其要观看三个名为“学习JavaScript的承诺”的视频(第2和第3部分特别关注后台触发的Cloud Functions,但之前确实值得观看第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

答案 1 :(得分:0)

我看到这是一个漫长的讨论,让我分享一些代码片段,这些代码片段对于其他遇到类似问题的人来说很有效,因此更容易弄清楚。

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.comRECEIVER@gmail.com收到一封电子邮件,当然可以根据自己的需要进行修改。

注意:我在localhost上正确发送邮件时遇到了相同的问题,但在部署时却没有。看来我的问题是我没有在port中使用hostcreateTransport,而是使用了:

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

除此之外,请不要忘记启用Less secure app access ON

答案 2 :(得分:0)

检查上面列出的所有内容是否都在我的代码中完成之后,我解决了在Google帐户(使用我与Proyect使用的帐户)中登录的问题。我必须从另一个来源识别该活动(谷歌检测到Firebase试图访问该帐户),仅此而已。 之后,我尝试从Firebase Cloud发送另一封电子邮件,但工作正常