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:
- Using the Firebase console: Install the Firestore Trigger Email extension
- Using the CLI: Run the following command:
firebase ext:install firebase/firestore-send-email --project=projectId-or-alias
Basic configuration
The extension is quick and easy to set up. To get started, you will need to do a couple of things.
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
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 pickedmail
.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.
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:
- Go to myaccount.google.com
- Go to Security (from the left/right panel)
- Scroll down to Signing in to Google
- 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
- From the dropdown menu, choose “**Other (custom name)**”
- Provide a name for this password, for example,
Firebase Trigger Email Extension
- A dialog will show with a random password, make sure to copy it, then click Done
- 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",
}
}
This should trigger a new email sent to the address specified in to
the field.
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:
- Go to the extension configurations in the Firebase console, and set the name of the Firestore collection where your templates will live.
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.
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:
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 Twitter, Linkedin, 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.