← Back to blog

Sending emails using Firestore and Firebase Extensions

Darren Ackers

Lead Developer

Mais Alheraki

Open Source Engineer

6th October, 2022

Need a custom tool? Invertase can help

Tired of investing in off-the-shelf software that doesn't quite fit your business? Invertase can build solutions tailored to your exact needs. Tell us what you're looking for here and we'll be in touch.

Introduction

Keeping users in the loop of what’s happening for their transactions is a critical requirement of most modern systems. This could be in the form of mobile apps, Push Notifications, SMS for important messages, or Emails delivered to their inbox.

In this blog, we will discover how to notify our users of important events by sending emails using Firestore efficiently and at no initial cost.

What is Firestore?

Firebase

Firestore is a real-time, highly scalable NoSQL document database. It is most often found on client-side web and mobile applications. It provides a flexible approach to storing data and easy integration with popular languages and frameworks.

Why do I need an email extension?

Most developers can and will write their own configuration or service for sending emails. However, there are many aspects to creating this type of service. A pre-written and well-tested one can save developers time and effort when trying to create a similar solution.

Here we break down the main features and advantages that this extension offers.

How do I install the extension?

💡 To use Firebase Extensions, you need to be on the Blaze Plan. This doesn’t mean you will be charged for anything until the usage exceeds the monthly complimentary limit.

Costs for this extension are associated with its services: Cloud Firestore and Cloud Functions.

To install the extension, follow the Install Firebase Extension page steps. In summary, do one of the following:

Basic configuration

The extension is quick and easy to set up. To get started, you will need to do a couple of things.

  1. Get your SMTP connection URI.

    This is the connection string for your email server, which typically comprises text in the following format:

    smtp(s)://{username}:{password}@smtp.{provider}.com:{port}

    For testing purposes you could get one by using your personal or enterprise (G Workspace) Gmail account, e.g.:.

    smtp(s)://darren@gmail.com:{appPassword}@smtp.gmail.com:465

  2. Choose your Firestore collection name

    The Firestore collection is where you would process emails from; you need to pick a name and stick by it for the rest of the setup. In this tutorial, we picked mail.
  3. Set the default “from” address

    The address will appear in the from field for the generated emails. This can be overridden when creating emails later on.
Installation configs

With the minimum configuration added, you are ready to start sending emails.

Secrets Manager

The secrets manager is a newly added feature for Firebase Extensions that provides a resource for securing sensitive data that can often appear in connection strings. In this case, the secret or password you would typically include in your credentials.

This tutorial will use the secret manager for storing secrets when configuring the extension instead of simply adding an exposed credential to the Connection URI that you configured in the previous step.

How to get the App Password for Gmail

You can’t use your regular sign-in password for an SMTP connection. Instead, you can create an App Password using your Gmail account. To do so, follow these steps:

  1. Go to myaccount.google.com
  2. Go to Security (from the left/right panel)
  3. Scroll down to Signing in to Google App password option
  4. If you don’t have 2-step verification, you must first turn it on. Once you finish, you will be able to see the “App Passwords” option
  5. From the dropdown menu, choose “**Other (custom name)**” Creating a custom password
  6. Provide a name for this password, for example, Firebase Trigger Email Extension
  7. A dialog will show with a random password, make sure to copy it, then click Done Password dialog
  8. The new password will be added to your list

Go back to your configuration in the Firebase console, then go to the Trigger Email extension, click Reconfigure extension and paste the password in SMTP password field.

Sending a basic email

The first thing to understand about sending emails through this extension is that they are sent by triggers watching the Firestore collection defined in the configuration, which in this tutorial has the name mail.

To quickly test if your setup is correct, go to the Firebase console, then create a new Firestore collection named mail, then add a new document like this:

{
  to: "someone@gmail.com",
  message: {
    subject: "This is a basic email",
    html: "That requires minimum configuration",
  }
}
Installation configs

This should trigger a new email sent to the address specified in to the field.

Installation configs

To send an email programmatically, you will need to use the firebase-admin SDK. Wherever you want to ask for the extension to send an email, add a new document to your configured Firestore collection.

/** create an instance of your configured mail collection */
const mailCollection = firestore().collection("mail");

/** add a new mail document */
await admin
  .firestore()
  .collection("mail")
  .add({
    to: ["someone@gmail.com"],
    message: {
      subject: "This is a basic email",
      html: "That requires minimum configuration",
    },
  });

Sending emails using Firebase Functions triggers

Firebase Functions have many triggers, including authentication events. If you’re using Firebase Authentication and want to send an email for newly registered users, you can use user.create trigger along with Send Email extension.

import * as admin from "firebase-admin";
import * as functions from "firebase-functions";

// Initialize the default Firebase app
admin.initializeApp();

export const sendWelcomeEmail = functions.auth.user().onCreate((user) => {
  // Don't send an email if it's an anonymous user
  if (!user.providerData || user.providerData.length == 0) return;

  firestore()
    .collection("mail")
    .add({
      to: user.email,
      message: {
        subject: "Welcome!",
        html: `
          Hey ${user.displayName || ""}! 👋

          Thank you for signing up.
        `,
      },
    });
});

Using Templates

Wouldn’t it be helpful if you could select a ready-made template with the document data already defined?

To set up your templates:

  1. Go to the extension configurations in the Firebase console, and set the name of the Firestore collection where your templates will live.
Templates collection

2. Create a template:

Suppose you have an e-commerce app in which you might have two events: subscribe and unsubscribe. You can create a template for each event.

 /** add a welcome email */
  await firestore().collection("templates").doc("subscribe").set({
    subject: "Welcome Email",
    html: "Thank you for signing up to our website.",
  });

  /** add a cancel subscription template */
  await firestore().collection("templates").doc("unsubscribe").set({
    subject: "Cancel Subscription",
    html: "As per your request, your subscription has been canceled.",
  });

Now these have been defined, you can simply name the template to send an email:

 /** add a new mail document */
  await firestore().collection("mail").add({
    to: ["someone@gmail.com"],
    template: {
      name: "subscribe",
    },
  });

Check your inbox and note that the subject and HTML content are now automatically populated.

Installation configs

Template data (Handlebars)

Handlebars

What you’ve done is excellent, but we can go one step further! This extension allows data to be added to the template object so we can customize it and make each email unique.

Update your templates:

/** add a welcome email */
await firestore().collection("templates").doc("subscribe").set({
  subject: "Welcome Email",
  html: "Thank you {{name}}, for signing up to our website.",
});

/** add a cancel subscription template */
await firestore().collection("templates").doc("unsubscribe").set({
  subject: "Cancel Subscription",
  html: "As per your request {{name}}, your subscription has been canceled.",
});

Note the new {{name}} added to the html for each template. It allows you to pass in data that can be substituted when creating the email message.

/** add a new mail document */
await firestore()
  .collection("mail")
  .add({
    to: ["someone@gmail.com"],
    template: {
      name: "subscribe",
      data: {
        name: "Darren",
      },
    },
  });

Now you should receive a message like this:

Installation configs

Attachments

The business now has a new requirement. In this scenario, you must send all users a monthly invoicing email.

First, build a new template:

/** add a monthly invoice email template */
await firestore()
  .collection("templates")
  .doc("monthly_invoice")
  .set({
    subject: "Your monthly invoice of {{amount}}",
    html: "Please find your monthly invoice attached.",
    attachments: [
      {
        content: "invoice",
        filename: "{{invoice_link}}",
      },
    ],
  });

Then, write the trigger code to send an email:

firebase
  .firestore()
  .collection("mail")
  .add({
    to: ["someone@gmail.com"],
    template: {
      name: "monthly_invoice",
      data: {
        amount: 33,
        invoice_link:
          "https://example.com/invoices/8e884ace-bee4-11e4-8dfc-aa07a5b093db.pdf",
      },
    },
  });

Conclusion

So far, you have sent an email and used a template email document to define the structure of the email. Furthermore, you learned how to send an attachment along with the email.

To learn more about Firebase Trigger Email extension, visit the official docs.

Stay tuned for more updates and exciting news that we will share in the future. Follow us on Invertase TwitterLinkedin, and Youtube, and subscribe to our monthly newsletter to stay up-to-date. You may also join our Discord to have an instant conversation with us.

Darren Ackers

Lead Developer

Mais Alheraki

Open Source Engineer

Categories

Tags