使用 SMTP 的 Firebase 功能在模拟器中工作,但在部署时超时

Firebase function using SMTP is working in emulator but time outs when deployed

目前我正在 Firebase 中编写一个云函数来使用 nodemailer 发送电子邮件,其中包括一个二维码。

如果我在 Firebase 模拟器中模拟项目,一切正常,邮件发送正确。

但是,当我将代码上传到 Firebase 时,函数总是在 60 秒后超时。我已经尝试将超时设置得更高,但它仍然发生。

我的代码是:

exports.emailSender = functions.https.onRequest(async (req, res) => {
  var { name, code, hash, dest } = req.body;
  let transporter = nodemailer.createTransport({
    host: "smtp.test.com",
    port: 25,
    auth: {
      user: "username", 
      pass: "password",
    },
  });

  try {
    let qr = await create_qrcode(code+":"+hash,250,50);
    let qrBig = await create_qrcode(code+":"+hash,500,100);

    const mailOptions = {
      from: "no-reply@test.de",
      to: dest,
      subject: "Email Sent via Firebase",
      html: `<img src="${qr}" />`,
      attachments: [
        {
          filename: "QR-Code",
          path: qrBig,
        },
      ],
    };

    await transporter.sendMail(mailOptions, (err, info) => {
      if (err) {
        console.log(err);
        res.send({ error: err.message });
      } else {
        console.log(info);
        res.send("Erfolgreich");
      }
    });
  } catch (error) {
    res.send({ error: error.message });
  }
});

创建二维码的函数是:

async function create_qrcode(dataForQRcode, width, cwidth {
  // grab data you want on qrcode here
  const cvs = createCanvas(1, 1);
  const url = await QRCode.toCanvas(cvs, dataForQRcode, {
    errorCorrectionLevel: "H", // LMQH
    margin: 1,
    color: {
      dark: "#000000", // black pixels
      light: "#ffffff", // white background
    },
  });
  const canvas = createCanvas(width, width);
  const ctx = canvas.getContext("2d");
  const img = await loadImage("./icon.png");
  ctx.drawImage(url, 0, 0, width, width);
  const center = (width - cwidth) / 2;
  ctx.drawImage(img, center, center, cwidth, cwidth);
  return canvas.toDataURL("image/png");
};

似乎函数在 sendMail() 处冻结,因此没有触发 res.send(),并且在 60 秒后达到超时。

知道为什么这适用于模拟器而不适用于真正的云功能吗?

作为抵制滥用的一种方式,GCP entirely blocks outbound port 25 适用于 Compute Engine,而且几乎可以肯定,同样的事情也发生在 Cloud Functions 上。

您必须尝试另一种不使用出站端口 25 的方法。例如,您可以使用邮件服务器上的 SMTP 提交端口 587(而不是端口 25)来提交出站电子邮件。这将起作用,因为端口 587(和 465,用于 smtps)未被 GCP 阻止。