如何在Firebase Storage上的hbs模板和onCreate触发函数中的数据库中的nodemailer-express-handlebars一起使用?

时间:2018-12-23 04:20:19

标签: firebase firebase-realtime-database firebase-authentication google-cloud-functions nodemailer

当尝试在实时数据库节点上触发onCreate函数时,我尝试使用通过nodemailer上传到我的Firebase项目存储(appId.appspot.com/templates/testTemplate.hbs)的车把模板文件发送电子邮件。 / p>

我可以使用html格式的字符串成功发送电子邮件,但实际上需要使用模板将动态数据添加到电子邮件中。

这是我的功能:

import * as functions from "firebase-functions";
const admin = require("firebase-admin");
const hbs = require("nodemailer-express-handlebars");
const nodemailer = require("nodemailer");

const smtpConfig = {
  host: "mailHost",
  port: 465,
  secure: true,
  auth: {
    user: "xxxxxxxx",
    pass: "xxxxxxxx"
  }
};

const transporter = nodemailer.createTransport(smtpConfig);

exports.sendEmail = functions.database
  .ref("/databasePath/{pushId}")
  .onCreate(async (snapshot, context) => {
    const userData = snapshot.val();
    admin.initializeApp({
      storageBucket: "appId.appspot.com"
    });
    const bucket = admin.storage().bucket();
    const templatesFolder = bucket.name + "/templates/"; // path to storage folder with templates

    transporter.use(
      "compile",
      hbs({
        viewPath: templatesFolder,
        extName: ".hbs"
      })
    );
    const uniqueCode = "generated by a function";
    const uniqueLink = "https://appId.firebaseapp.com/?id=" + uniqueCode;
    const message = {
      from: "fromEmail",
      to: "toEmail",
      subject: "Subject",
      template: "testTemplate", // name of the template file
      context: {
        user: "User name",
        link: uniqueLink
      }
    };

    try {
      await transporter.sendMail(message);
      console.log("Email sent to:", "toEmail");
    } catch (error) {
      console.error("Error sending email:", error);
    }
    return null;
  });

触发该功能时,我在日志中收到以下错误:

发送电子邮件时出错:{错误:ENOENT:没有此类文件或目录,请打开'/user_code/appId.appspot.com/templates/testTemplate.hbs'     错误(本机)   errno:-2,   代码:“ ENOENT”,   syscall:“打开”,   路径:'/user_code/appId.appspot.com/templates/testTemplate.hbs'}

bucket.name开头有'/ user_code',因此hbs找不到模板。如何获得正确的模板文件夹路径?

2 个答案:

答案 0 :(得分:0)

您似乎尚未实际编写任何可从Cloud Storage下载文件的代码。您不仅可以在Cloud Storage中构建文件的路径,将其传递给其他组件,还希望它知道如何处理该路径。您所要做的就是将不存在的本地文件的名称传递给它。您必须实际将文件下载到temp文件夹中,才能在本地使用它。

或者更好的是,只需跳过Cloud Storage并随功能一起部署模板。您可以直接从磁盘上读取文件,而无需额外费用。 (每个Cloud Storage下载都需要付费。)

答案 1 :(得分:0)

这是更新的功能:

import * as functions from "firebase-functions";
const admin = require("firebase-admin");
const hbs = require("nodemailer-express-handlebars");
const nodemailer = require("nodemailer");

const smtpConfig = {
  host: "mailHost",
  port: 465,
  secure: true,
  auth: {
    user: "xxxxxxxx",
    pass: "xxxxxxxx"
  }
};

const transporter = nodemailer.createTransport(smtpConfig);

exports.sendEmail = functions.database
  .ref("/databasePath/{pushId}")
  .onCreate(async (snapshot, context) => {
    const userData = snapshot.val();
    const templatesFolder = __dirname + "/templates"; // <--

    transporter.use(
      "compile",
      hbs({
        viewPath: templatesFolder,
        extName: ".handlebars"
      })
    );
    const uniqueCode = "generated by a function";
    const uniqueLink = "https://appId.firebaseapp.com/?id=" + uniqueCode;
    const message = {
      from: "fromEmail",
      to: userData.email, // from the snapshot
      subject: "Subject",
      template: "testTemplate", // name of the template file
      context: {
        user: userDate.name, // from the snapshot
        link: uniqueLink
      }
    };

    try {
      await transporter.sendMail(message);
      console.log("Email sent to:", userData.email);
    } catch (error) {
      console.error("Error sending email:", error);
    }
    return null;
  });

将模板文件添加到“ functions / lib / templates / testTemplate.handlebars”