【问题标题】:Nodemailer error while using gmail in firebase functions在 Firebase 函数中使用 gmail 时出现 Nodemailer 错误
【发布时间】:2019-05-03 05:45:25
【问题描述】:

我正在使用 firebase 云功能。我配置了以下设置。虽然这在我的本地机器上运行良好,但在服务器上运行时给我带来了问题。我已经在互联网上尝试了无数的解决方法,但没有运气。这有什么问题?

'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)

干杯

【问题讨论】:

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


    【解决方案1】:

    当您在后台触发的 Cloud Function 中执行异步操作时,您必须返回一个 Promise,这样 Cloud Function 会等待该 Promise 解决才能终止。

    这在官方 Firebase 视频系列中有很好的解释:https://firebase.google.com/docs/functions/video-series/。特别是观看名为“学习 JavaScript Promises”的三个视频(第 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

    【讨论】:

    • 原来gmail安全规则需要24-48小时才能生效。我想,在那之后我就可以知道了。我什至从 firebase 团队那里听说过,但它没有用。我检查他们过去提出的问题。建议等待。嗯是的。我会及时通知你。
    • 感谢您的反馈。仅供参考,使用 Sendgrid 效果很好。每月有 12000 封邮件的免费套餐。
    • 请参阅此 SO 响应中的“讨论”(即 cmets):stackoverflow.com/questions/53481773/…
    • 嘿,只是一个快速更新。现在运行良好!虽然我选择 sendgrid 只是为了节省模板邮件的时间。为帮助干杯。
    • @AshishYadav 抱歉,回复晚了!我不得不从我的所有帐户中注销,并从不同的浏览器登录。只需再次遵循所有协议。我不知道为什么,但在那种情况下它开始了。这就是 Firebase 团队的回答。甚至尝试清除缓存或历史记录
    【解决方案2】:

    我看到这是一个很长的讨论,让我分享一下代码 sn-ps,它为我解决了类似问题的其他人,这样会更容易弄清楚。

    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 上正确发送邮件时遇到了同样的问题,但在部署时却没有。看起来我的问题是我没有在createTransport中使用porthost,而是我有:

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

    除此之外,不要忘记将Less secure app access 启用为ONhttps://accounts.google.com/DisplayUnlockCaptcha 也可能会有所帮助。

    【讨论】:

      【解决方案3】:

      在检查了上面列出的所有事情都在我的代码中完成后,我解决了登录 Google 帐户的问题(使用我在项目中使用的帐户)。我必须从另一个来源识别活动(谷歌检测到 Firebase 试图访问该帐户),就是这样。 之后我尝试从 firebase cloud 发送另一封电子邮件,它工作正常

      【讨论】:

        猜你喜欢
        • 2021-06-18
        • 1970-01-01
        • 1970-01-01
        • 2020-08-08
        • 2018-02-25
        • 2018-02-04
        • 2022-09-26
        • 2020-02-10
        • 2021-07-17
        相关资源
        最近更新 更多