Leveraging Firebase functions with Sendgrid integration

I'm still learning about Firebase functions and I've been working on setting up an onCreate() trigger, but I'm having trouble getting it to work.

Could the issue be with how I am handling the promise for Sendgrid? I'm not sure what I'm missing

const functions = require("firebase-functions");
const admin = require("firebase-admin");
const sendGrid = require("@sendgrid/mail");
admin.initializeApp();

const database = admin.database();
const API_KEY = '';
const TEMPLATE_ID = '';
sendGrid.setApiKey(API_KEY);

const actionCodeSettings = {
  ...
};

exports.sendEmailVerify = functions.auth.user().onCreate((user) => {
  admin
    .auth()
    .generateEmailVerificationLink(user.email, actionCodeSettings)
    .then((url) => {
      const msg = {
        to: user.email,
        template_id: TEMPLATE_ID,
        dynamic_template_data: {
          subject: "test email",
          name: name,
          link: url,
        },
      };
      return sendGrid.send(msg);
    })
    .catch((error) => {
      console.log(error);
    });
});

Event logs from firebase functions

sendEmailVerify
Function execution started

sendEmailVerify
Function returned undefined, expected Promise or value

sendEmailVerify
Function execution took 548 ms, finished with status: 'ok'

sendEmailVerify
{ Error: Forbidden

sendEmailVerify
at axios.then.catch.error (node_modules/@sendgrid/client/src/classes/client.js:133:29)

sendEmailVerify
at process._tickCallback (internal/process/next_tick.js:68:7)

sendEmailVerify
code: 403, 

sendEmailVerify
message: 'Forbidden', 

Answer №1

Your Cloud Function is not properly handling the Promises chain. To correct this, ensure that your function returns the promises in the following manner:

exports.sendEmailVerify = functions.auth.user().onCreate((user) => {
  return admin // <- Make sure to include a return statement
    .auth()
    .generateEmailVerificationLink(user.email, actionCodeSettings)
    .then((url) => {
      const msg = {
        to: user.email,
        template_id: TEMPLATE_ID,
        dynamic_template_data: {
          subject: "test email",
          name: name,
          link: url,
        },
      };
      return sendGrid.send(msg);
    })
    .catch((error) => {
      console.log(error);
      return null;
    });
});

Answer №2

Here lies a couple of programming challenges waiting to be solved.

  1. The function must return a promise that resolves once all asynchronous operations are complete; simply using then and `catch isn't enough. You must explicitly return a promise from the function handler.

  2. You're invoking sendGrid.send(email), but the variable email is not defined in your code. Without defining it, you're passing an undefined value to sendgrid.

Additionally, if your project is not on a payment plan, any call to sendgrid will fail due to restrictions on outbound networking for free plans. Upgrading to a paid plan is necessary for this functionality to work properly.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

WebDriverIO effortlessly converts the text extracted using the getText() command

One of my webpage elements contains the following text: <span class="mat-button-wrapper">Sicherheitsfrage ändern</span> However, when I attempt to verify this text using webdriver, it indicates that it is incorrect assert.strictEqual($(.mat ...

Click on a button to completely remove all JavaScript from your website using jQuery

I'm currently experiencing some difficulties with my website Concept Studio. On a specific page, I have a typing animation within a form and I'd like to include a button that allows users to skip the animation. However, I'm unsure of how to ...

Mobile device scrolling glitch

I'm currently working on my website, which can be found at . After testing it on mobile devices, I came across an issue that I just can't seem to fix. For instance, when viewing the site on a device with 768px width, you can scroll to the righ ...

Change the class of the div when the first div is selected

My goal is to switch the class of the #klapp element (from .klapp to .klappe) whenever a click event happens inside the #label-it container, including when the #klapp element itself is clicked. The challenge is that I am not able to use unique IDs for each ...

Steps for verifying the presence of an element in Selenium using JavaScript

I'm facing an issue with a Jest and Selenium test. I'm trying to verify if an element is removed from the DOM after being clicked. Here's what I've attempted: test('User removes button after clicking on it', async (done) =& ...

Prevent right-clicking on links from a particular domain

Looking to prevent right-clicking on a link? Check out this code snippet: <script type="text/javascript" language="javascript> $(document).ready(function() { $('body').on('contextmenu', 'a', function(e){ ...

Unfortunately, IE8 does not support binding with underscores

In my code, I am utilizing _.bind from underscore.js but unfortunately, it is not functioning properly in IE8/9. I have come across a workaround on MDN (MDN Polyfill), however, I am uncertain if this can be implemented with the underscore library. I am al ...

How do I access values in my factory after the deviceready event in AngularJS/Cordova?

I am currently utilizing the Cordova Device plugin to retrieve information about the device being used by the user. According to the documentation, it can only be invoked AFTER the deviceready function. Therefore, in my .run function, I have implemented th ...

Displaying data on the number of vertices and triangles in the editor interface

Can anyone provide guidance on how to incorporate a legend displaying the number of Vertices and Triangles, as well as a 3 axes helper legend, in Three.js rendering within the example editor? I have attached a screenshot of the scene with these legends for ...

Svelte user interface fails to update correctly after editing a writable array type

Currently, I am working on developing a crew creator tool for a rowing club to provide some context. The Writable container that holds the array is defined as follows import { writable, Writable } from 'svelte/store'; import type { CrewMember } ...

What is the best method for individually toggling multiple displays in React?

Currently, I am pulling multiple posts from an API request and I want each post to have a toggle option. The issue is that when you click on the "Show More" toggle, it expands all the posts at once. I am using the NPM react-toggle-display package for this ...

Utilizing Sentiment Analysis API with Ionic 2 Angular and handling CORS restrictions

Currently, I am in the process of developing a mobile application that can analyze an individual's thoughts using the Aylien Sentiment Analysis API. The technology stack I am utilizing includes Ionic 2 and Angular 4. While I have successfully integrat ...

Javascript recursive method for fetching data entries

Seeking a solution to retrieve interconnected records based on a parent column, where the relation can be one or many on both ends. After attempting a recursive function without success, I found my code became overly complex and ineffective. Is there a st ...

Different types of arrays suitable for the useState hook

I have a scenario where I am utilizing setState to assign an array of objects. Here is the code snippet: const [friendList, setFriendList] = useState<any>(); const _onCompleted = (data: any) => { let DATA = data.me.friends.map( (item ...

various arbitrary visuals on an HTML5 canvas

I am attempting to randomly draw multiple images from an array on a canvas, but I'm struggling with iterating through the array and drawing them when the draw() function is called within a for loop. Here's my current code: // Call Draw particle ...

Struggling with web scraping using Selenium due to persistent "NoSuchElementException" errors. I have exhausted all possible solutions to resolve this issue

I am currently attempting to extract all the climbers' names, countries, and points from the IFSC website using BeautifulSoup. However, I encountered several issues with BeautifulSoup and decided to switch to Selenium. Unfortunately, I am encountering ...

Sorting objects in an array according to their prices: A guide

Suppose we have the following data structure: var lowestPricesCars = { HondaC: { owner: "", price: 45156 }, FordNew: { owner: "", price:4100 }, HondaOld: { owner: "", price: 45745 }, FordOld: { owner: "", ...

Convert the Date FR and Date US formats to ISO date format

There is a function in my code that accepts dates in different formats. It can handle two formats: 2022-06-04 or 04/06/2022 I want all dates to be in the format: 2022-06-04 For instance: public getMaxduration(data: object[]): number { data.forEach((l ...

Transmit information from the server and retrieve data using PHP, AJAX, JavaScript, JSON, and the POST method

I am seeking clear examples of sending data from a server and receiving data by the server using PHP, Ajax, JavaScript, JSON, and post requests. Thank you in advance! ...

What is the best way to paginate a dynamically updated data table using AJAX in Laravel?

I'm currently facing an issue with rendering a Blade template in Laravel. The template includes an HTML table populated with data fetched via AJAX, and I need to implement manual pagination using Laravel's LengthAwarePaginator. The main Blade fi ...