使用 Firebase 云功能实现发送电子邮件

2024-02-20

对于我们的网络应用程序,我们目前使用 Firebase 的免费计划,并且需要发送有关各种事件/触发器的电子邮件。问题是,我认为 Mailgun 及其云功能可以完美地完成此任务,但看起来只能将其 API 与 Firebase 的付费计划一起使用,而当我们的应用程序仍在开发时,我们现在不打算使用该计划。因此,我们有点陷入困境,不知道如何用 Firebase 用最少的钱实现电子邮件功能(当我们稍微清楚我们的应用程序是否会盈利时,我们总是可以支付或支付更多费用)。 ..任何人都可以帮助我。目前以(几乎)免费的方式进行此操作 - 我们可以在以后随时升级?

谢谢! 皮尤什·索尼


我在我的个人投资组合网站中使用 firebase 托管和云功能。我创建了一个云函数(http 事件)来从联系表单部分发送电子邮件,我尚未启用计费选项,但免费报价(云函数执行)仍然足以满足我当前的需求。我通过以下方式发送电子邮件:

云功能:

const functions = require('firebase-functions');
const nodemailer = require('nodemailer');
const rp = require('request-promise');

//google account credentials used to send email
const mailTransport = nodemailer.createTransport(
    `smtps://[email protected] /cdn-cgi/l/email-protection:[email protected] /cdn-cgi/l/email-protection`);

exports.sendEmailCF = functions.https.onRequest((req, res) => {

  //recaptcha validation
  rp({
        uri: 'https://recaptcha.google.com/recaptcha/api/siteverify',
        method: 'POST',
        formData: {
            secret: 'your_secret_key',
            response: req.body['g-recaptcha-response']
        },
        json: true
    }).then(result => {
        if (result.success) {
            sendEmail('[email protected] /cdn-cgi/l/email-protection', req.body).then(()=> { 
              res.status(200).send(true);
            });
        }
        else {
            res.status(500).send("Recaptcha failed.")
        }
    }).catch(reason => {
        res.status(500).send("Recaptcha req failed.")
    })

});

// Send email function
function sendEmail(email, body) {
  const mailOptions = {
    from: `<[email protected] /cdn-cgi/l/email-protection>`,
    to: email
  };
  // hmtl message constructions
  mailOptions.subject = 'contact form message';
  mailOptions.html = `<p><b>Name: </b>${body.rsName}</p>
                      <p><b>Email: </b>${body.rsEmail}</p>
                      <p><b>Subject: </b>${body.rsSubject}</p>
                      <p><b>Message: </b>${body.rsMessage}</p>`;
  return mailTransport.sendMail(mailOptions);
}

更新包括联系表格和脚本:

<form class="rsForm" action="/sendEmailCF" method="post">
    <div class="input-field">
        <label>Name</label>
        <input type="text" name="rsName" value="">
        <span class="line"></span>
    </div>

    <div class="input-field">
        <label>Email</label>
        <input type="email" name="rsEmail" value="">
        <span class="line"></span>
    </div>

    <div class="input-field">
        <label>Subject</label>
        <input type="text" name="rsSubject" value="">
        <span class="line"></span>
    </div>

    <div class="input-field">
        <label>Message</label>
        <textarea rows="4" name="rsMessage"></textarea>
        <span class="line"></span>
    </div>

    <input type="hidden" name="rsLang" value="en" />

    <span class="btn-outer btn-primary-outer ripple">
        <input class="formSubmitBtn btn btn-lg btn-primary" type="submit" data-recaptcha="global" value="Send">
    </span>
    <div id="recaptcha-global"></div>
</form>

处理表单提交的脚本:

$('.formSubmitBtn').on('click', function (e) {
    glForm = $(this).closest('.rsForm');
    var recaptchaId = 'recaptcha-' + $(this).data('recaptcha');
    var rsFormErrors = false;
    glFormAction = glForm.attr('action');
    var rsFormFields = glForm.find('.input-field');
    var rsFormName = glForm.find("[name='rsName']");
    var rsFormEmail = glForm.find("[name='rsEmail']");
    var rsFormMessage = glForm.find("[name='rsMessage']");

    // Button ripple effect
    ripple($(this).parent(), e.pageX, e.pageY);

    // Reset form errors
    rsFormFields.removeClass('error');
    rsFormErrors = false;

    // Validate form fields
    if(!rsFormName.val()) {
        rsFormErrors = true;
        rsFormName.parent().addClass('error');
    }

    if(!rsFormEmail.val() || !isValidEmail(rsFormEmail.val())) {
        rsFormErrors = true;
        rsFormEmail.parent().addClass('error');
    }

    if(!rsFormMessage.val()) {
        rsFormErrors = true;
        rsFormMessage.parent().addClass('error');
    }

    if(rsFormErrors) {
        // if has errors - do nothing
        return false;
    } else {

        if(rca[recaptchaId] === undefined){
            rca[recaptchaId] = grecaptcha.render(recaptchaId, {
                'sitekey' : 'sitekey',
                'callback' : onExecutedCaptcha,
                'size' : 'invisible',
                'badge':'inline'
            });

        } else {
            grecaptcha.reset(rca[recaptchaId]);
        }

        grecaptcha.execute(rca[recaptchaId]);
        return false;
    }
});

处理验证码响应和表单发布的脚本:

function onExecutedCaptcha(token) {

  var sendingMsg = null, textMsg = null, textErr = null;
  var lang = glForm.find("[name='rsLang']").val();

  if(lang == 'es') {
      sendingMsg = 'Enviando mensaje...';
      textMsg = 'Tu mensaje se ha enviado con \u00e9xito!';
      textErr = 'Algo ha salido mal. Intenta mas tarde';
  } else {
      textMsg = 'Your email was sent successfully!';
      textErr = 'Oops! Something went wrong. Please try again.';
      sendingMsg = 'Sending email...';
  }

  swal({
    text: sendingMsg,
    button: false,
    closeOnClickOutside: false,
    closeOnEsc: false,
  });

    $.post( glFormAction,
        glForm.serialize(),
        function (response) {
            grecaptcha.reset();
            var data = jQuery.parseJSON( response );
            swal.close();

            if(data){
                swal({
                  text: textMsg,
                  icon: "success",
                });
                 glForm.find("input[type=text], input[type=email], textarea").val("");
            } else {
                swal({
                  text: textErr,
                  icon: "error",
                });
            }
        }
    );
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 Firebase 云功能实现发送电子邮件 的相关文章

随机推荐

  • Spark 连接速度呈指数级缓慢

    我正在尝试连接两个 Spark RDD 我有一个链接到类别的事务日志 我已将交易 RDD 格式化为以类别 id 作为键 transactions cat take 3 u 707 u 86246 u 205 u 7 u 707 u 1078
  • 为什么我的 d3 力导向图不显示边缘?

    我使用 d3 创建了一个简单的力导向图 http goo gl afHTD http goo gl afHTD 为什么图表的边缘不显示 这是我的整个 HTML 文件 当然 您也可以通过在我的链接页面上查看源代码来查看它并修改它 它基于 d3
  • 使用错误的表别名生成查询的原则

    我正在尝试做一个简单的 gt find 使用原则 规则 2 5 1 查询非常简单 this gt get order repository gt find 10 但这会生成一个复杂的查询 选择 s0 number AS number 0 s
  • SYSTEM_HANDLE_INFORMATION结构

    这个结构从何而来 我知道它是在著名的 ntdll h 中声明的 并且是未记录的 Windows API 的一部分 但不同版本的windows之间不是有差异吗 有没有办法从工作系统中转储这个结构 我在 Windbg 中尝试了 dt SYSTE
  • 如何复制内存

    说我有 unsigned char varA varB varC varA malloc 64 varB malloc 32 varC malloc 32 我怎样才能把first将 32 字节的 varA 放入 varB 中last32字节
  • 编写带有垂直标题的 HTML 表格的最常见方法? [关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 您编写具有垂直标题的 HTML 表格的首选方式是什么 通过垂直标题我的意思是表格有标题 th 标签位于左侧 通常 Header 1数据数据数据
  • 最大连续数

    我正在练习两个指针技术来解决最大连续数 LeetCode https leetcode com problems max consecutive ones 给定一个二进制数组 找出该数组中连续 1 的最大数量 示例1 Input 1 1 0
  • Html-Webpack-Plugin 模板:模块构建失败:SyntaxError:意外的标记

    当我尝试使用 index ejs 模板文件使用 html webpack plugin 进行构建时 会引发以下错误 即使我尝试加载为 html 文件或安装 ejs loader 仍然失败 我不确定 ejs loader 是否与 html w
  • mysql 错误 2002 (HY000): 无法通过套接字 '/var/run/mysqld/mysqld.sock' 连接到本地 MySQL 服务器 (2)

    我使用 在 Ubuntu 13 上 安装了 MYSQL sudo apt get install mysql 但跑完之后 mysql u root p 然后输入密码就会出现错误 ERROR 2002 HY000 无法通过套接字连接到本地 M
  • 在Python中初始化二维数组

    我在 python 中初始化二维数组时遇到问题 我想要一个 6x6 阵列 我做到了 arr None 6 6 但是当我这样做时 gt gt gt arr 1 2 10 gt gt gt arr None None 10 None None
  • 电子邮件中的 URL 是否已被搜索引擎索引,以便可以公开搜索?

    我在这里阅读了一些有关电子邮件客户端预取电子邮件中的 URL 的问题 对此的答案似乎是添加一个新的确认页面 用户必须在其中单击按钮来确认所需的操作 But this https stackoverflow com a 42147812 11
  • 外键到底是什么?

    好的 所以我知道数据库中的主键是什么 如果数据库中有一个表 则主键是表中每一行唯一的单个值 例如 id name whatever 1 Alice 2 Bob 45 Eve 988 所以我需要一个好的 简单的例子来解释外键到底是什么 因为我
  • 仅使用单精度浮点近似 [0,pi] 上的余弦

    我目前正在研究余弦的近似值 由于最终的目标设备是自行开发的 32 位浮点 ALU LU 并且有专门的 C 编译器 因此我无法使用 C 库数学函数 cosf 我的目标是编写在准确性和指令 周期数量方面有所不同的各种方法 我已经尝试过很多不同的
  • 空对象的条件类型

    是否有可能有一个条件类型可以测试可以为空的对象 例如 function test
  • 如何将我自己的代码/函数和外部java库添加到azure函数应用程序

    我编写了一些代码来在代码运行时创建一个文件 我的计划是按照定期计划将其放在 Microsoft Azure 函数应用程序上 因此它每小时或每天运行一次 我将使用计时器触发器并在那里也有一个 HTTP 请求触发器进行测试 但是 我不知道在哪里
  • 计算 C 中一致字符串的数量

    所以这是 leetcode 的一个问题 我遇到了一些问题 我已经看到解决这个问题的代码发布到 leetcode 的讨论部分 但我想知道是否有人可以帮助我解决这个问题我已经写过的代码 这就是问题所在 给你一个字符串allowed由不同的字符和
  • Visual Studio:针对私有和内部成员缺少 XML 文档发出警告

    我正在使用 Visual Studio 2005 VS 8 0 并且我希望强制执行所有类成员 而不仅仅是公共成员 都被记录的要求 虽然设置 Visual Studio 在公共 受保护或内部受保护成员未记录时生成警告很简单 但我正在寻找一种方
  • Cygwin 中的 .seh_savexmm 寄存器无效

    制作 我曾使用 cygwin 但遇到编译错误 我不确定 seh savexmm 的无效寄存器是什么 请帮我 我在谷歌上搜索了这个问题但没有找到 问题很多 但没有灵魂 请帮我 perl generate functions pl file o
  • 如何在 VSCode 中使用 yapf(或 black)

    我使用以下命令安装了 yapf conda install yapf 并在我的中添加下一行 vscode settings json file python linting pylintEnabled true python linting
  • 使用 Firebase 云功能实现发送电子邮件

    对于我们的网络应用程序 我们目前使用 Firebase 的免费计划 并且需要发送有关各种事件 触发器的电子邮件 问题是 我认为 Mailgun 及其云功能可以完美地完成此任务 但看起来只能将其 API 与 Firebase 的付费计划一起使