首页 > 解决方案 > 在 firestore 错误时使用 sendgrid 发送电子邮件

问题描述

我目前正在为一个朋友开发一个网站,他有一家代客公司。我正在为他创建一个网站,以便人们可以上网并为他们的位置请求私人活动,例如家庭聚会或聚会。

请求部分已经完成,但现在他问我是否可以让网站在每次有新请求时向他发送电子邮件,而不是去网站登录然后从那里继续。

我了解到您可以使用 sendgrid 发送电子邮件。我正在为我的项目使用 firebase/firestore。我已经安装了@sendgrid/mail 并创建了一个 JS 文件来查看电子邮件服务是否有效。

我创建只是为了看看我是否可以发送电子邮件。如果我用节点和终端运行它的代码,它工作得很好

我继续将代码添加到客户端的 JS 文件中。我做了一些研究,发现我不能在客户端使用 require 并且看到如果我安装 require.js 它将允许我这样做。

然后我安装了 requirejs 并继续将相同的代码添加到包含客户端 html 的新 JS 文件中。

我一开始遇到了这个错误

" 模块名称 "@sendgrid/mail" 尚未加载上下文:_。使用 require([] )"

然后我阅读了错误并尝试添加“[]”。这把我带到了我现在卡住的地方这显示了所有添加了“[]”的代码。我现在收到一个新错误,类似于此代码图片 这是我现在遇到的错误

这是我的 JS 文件,它位于客户端,带有 sendgrid/mail。

const sgMail = require(['@sendgrid/mail']);
const API_KEY = '';
sgMail.setApiKey(API_KEY);

(function(){ 
//configuration file for firebase. The way we acess the app location in the database
 var firebaseConfig = {
 apiKey: "",
 authDomain: "",
 projectId: "",
 storageBucket: "",
 messagingSenderId: "",
 appId: "",
 measurementId: ""
 };

 //firebase initialiaztion. The way we initialize
  firebase.initializeApp(firebaseConfig);
  var db = firebase.firestore();

const email = document.getElementById('emailTxt');
const firstName = document.getElementById('firstNameTxt');
const lastName = document.getElementById('lastNameTxt');
const firstPhone = document.getElementById('numberTxtArea'); 
const secondPhone = document.getElementById('numberTxtMiddle');
const thirdPhone = document.getElementById('numberTxtEnd');
const location = document.getElementById('locationTxt');
const numberOfCars = document.getElementById('carCount');
const numberOfPeople = document.getElementById('peopleCount'); 
const startTime = document.getElementById('starTime');
const endTime = document.getElementById('endTime'); 
const parking = document.getElementById('availability'); 
const details = document.getElementById('details'); 
const submitQuoteBtn = document.getElementById('requestQuoteBtn');
const succesfullySubmited = document.getElementById('requestConfirm');




submitQuoteBtn.addEventListener('click', e=>{ 


  const emailValue = email.value;
  const firstNameValue = firstName.value;
  const lastNameValue = lastName.value;
  const firstPhoneValue = firstPhone.value;
  const secondPhoneValue = secondPhone.value;
  const thirdPhoneValue = thirdPhone.value;
  const phoneNumber = firstPhoneValue + "-" + secondPhoneValue + "-" + thirdPhoneValue;
  const locationValue = location.value;
  const numberOfCarsValue = numberOfCars.value;
  const numberOfPeopleValue = numberOfPeople.value;
  const startTimeValue = startTime.value;
  const endTimeValue = endTime.value;
  const parkingValue = parking.value;
  const detailsValue = details.value;
  var datePlaced = new Date();
  var dd = datePlaced.getDate();
  var mm = datePlaced.getMonth() +1;
  var yyyy =  datePlaced.getFullYear();
  var fullDate = (mm + "-" + dd + "-" + yyyy);

const message  = {
  to: '',
  from: '',
  subject: 'New Private EVENT',
  text: "hi",
  html: "hello",
};


sgMail.send(message)
.then((response) => console.log('Email sent'))
.catch((error) => console.log(error.message));
 db.collection("Manager").doc("Quote").collection("Quotes").doc((firstNameValue + " " + 
lastNameValue)).set({

  email: emailValue,
  firstName: firstNameValue,
  lastName: lastNameValue,
  phone: phoneNumber,
  location: locationValue,
  numberOfCars: numberOfCarsValue,
  numberOfPeople: numberOfPeopleValue,
  startTime: startTimeValue,
  endTime: endTimeValue,
  parking: parkingValue,
  details: detailsValue,
  date: fullDate,




 }).then(() =>{
    console.log("i am here 6");
 console.log("document written successfully");

 succesfullySubmited.style = "visible";

 }).catch((error) => {
    console.log(error);
})   
});

})()

这是我连接到js文件的html文件

<!DOCTYPE html>
<html lang="en">
<head>
 <link rel = "stylesheet" href="RCMA.css" >
 <meta charset="UTF-8">
 <meta http-equiv="X-UA-Compatible" content="IE=edge">
 <meta name="viewport" content="width=device-width, initial-scale=1.0">
 <meta name="description" content="Providing proffesional valet services around the Cleveland 
Area. Restaurants, Private events, and more">
    <title></title>

</head>

<body>


    <script src="https://www.gstatic.com/firebasejs/8.3.1/firebase-app.js"></script>
    <script src="https://www.gstatic.com/firebasejs/8.3.1/firebase-firestore.js"></script>
    <script src="scripts/require.js"></script>






    <div class= "banner">

        <div class="navbar">
            <img src="pictures/rcmalogo.jpeg" class= "logo">
                    <ul>
                        <li><a href="index.html">Home</a></li>
                        <li><a href="contact.html">Contact</a></li>
                        <li><a href="Quote.html">Get a Quote</a></li>
                        <li><a href="AboutUs.html">About Us</a></li>
                        <li><a href="SignIn.html">Sign In</a></li>
                    </ul>
                
            </div>
            
            <div class="inputBoxes">
                                    
                <input  type="email" id="emailTxt" class="emailTxt" placeholder="Email..." /> <br>
                <input type="textfield" id="firstNameTxt" class="firstNameTxt" placeholder="First Name..." /> 
                <input type="textfield" id="lastNameTxt" class="lastNameTxt" placeholder="Last Name..." /><br>
                <input type="textfield" id="numberTxtArea" class="numberTxtArea" placeholder="###" /> 
                <input type="textfield" id="numberTxtMiddle" class="numberTxtMiddle" placeholder="###" />
                <input type="textfield" id="numberTxtEnd" class="numberTxtEnd" placeholder="####" /> <br>
                <input type="textfield" id="locationTxt" class="locationTxt" placeholder="Location..." /><br>
                <input type="textfield" id="carCount" class="carCount" placeholder="Estimated # of Cars..." /><br>
                <input type="textfield" id="peopleCount" class="peopleCount" placeholder="Estimated # of People..." /><br>
                <input type="textfield" id="starTime" class="starTime" placeholder="Event Start time..." />
                <input type="textfield" id="endTime" class="endTime" placeholder="Event End Time..."/><br>
                <input type="textfield" id="availability" class="availability" placeholder="Parking Availability..."/> <br>
                <input type="textfield" id="details" class="details" placeholder="Details / Questions..."/><br> <br> <br>
                <button id="requestQuoteBtn"> Request Quote</button>
                <h1 id="requestConfirm" style="display: none;" >Submited Succesfully! </h1>
            </div>
            
            
        </div>
        



</body>

<script type="module" src="scripts/quote.js"></script>



</html>

标签: javascriptfirebasefunctionsendgrid

解决方案


您需要从您控制的后端(Node.js 服务器,或者更简单的云函数)执行此操作。并且您需要为 Node.js 使用 Sendgrid APi

此外,您不应在前端代码中共享您的 Sendgrid API 密钥,因为可以轻松阅读源代码。

因此,发送电子邮件的简单云函数将是这样的:

const functions = require('firebase-functions');

const admin = require('firebase-admin');
admin.initializeApp();

const sgMail = require('@sendgrid/mail');
sgMail.setApiKey(functions.config().sendgrid.apikey);
// See the doc for the config: https://firebase.google.com/docs/functions/config-env
// The API key is securely stored as a Cloud Function configuration item

exports.createUser = functions.firestore
    .document('requests/{requestId}')
    .onCreate((snap, context) => {
        const newValue = snap.data();

        // access a particular field as you would any JS property
        const requestName = newValue.name;

        const msg = {
            to: 'recipient@whatevermail.com',
            from: '....', // Change to your verified sender
            subject: '',
            html: 'Here is the name: ' + requestName  // Adapt that with HTML code
        }

        return sgMail.send(msg)
        .catch(error => {
          console.log(JSON.stringify(error));
          return null;
        })

    });

每次创建新的请求文档时,都会发送一封电子邮件。


另一种可能性是使用“触发电子邮件”Firebase 扩展。您可以在 Medium 上的“Firebase Tips & Tricks”出版物中找到,该文章解释了如何使用 Sendgrid 配置扩展。


推荐阅读