Firebase Extension — Trigger Email

Myrick Chow
Jan 23 · 12 min read
Image for post
Image for post

Sending emails is a common digital marketing technique. However, setting up your own SMTP server and maintaining its security can be a difficult task for many business parties. In addition, you have to make sure to keep your servers up-to-date to keep them secure and take a lot of other steps to prevent your emails from being classified as spam.

Firebase provides a simple to use extension — Trigger Email for handling email delivery. Developers just need to register for an SMTP service provider and create a document with specific fields (e.g. to, subject and text). The Trigger Email Extension will then handle the rest for you.

Image for post
Image for post

The Trigger Email Extension is one of the official Firebase extensions built by the Firebase team. It is a packaged and ready-to-use solution. It is mostly driven by a Cloud Function that observes a collection in your Cloud Firestore instance for document creation and updates. Once there is a new email document created, or the state of the delivery field is updated, this Cloud Function will produce an email according to the document fields and send a request to the SMTP service provider through Nodemailer, which is a third-party library.

The Trigger Email process usually doesn’t take more than 2s, and the email is delivered to recipients within 15s depending on the chosen SMTP service provider. This article will include step-by-step setup procedures for setting up the extension and some practical tricks on using this extension.

Why do we need an SMTP service provider?

Image for post
Image for post

First of all, we have to understand that there is a limit on sending out emails from ordinary email service providers, such as Google, Microsoft and Yahoo every day. Take Gmail as an example, the limit is 2000 emails per 24 hours. Two thousand emails are only enough for personal use but not for marketing advertisement. To tackle this issue, we need to find an SMTP service provider which allows you to increase the quota to a few million per month or even unlimited depending on the chosen plan.

In the big picture, we delegate the SMTP service provider to send emails on behalf of us. Therefore, we will not hit the daily quota easily. There are many SMTP service providers in the market, e.g. SendGrid, MailGun and Mailchimp, etc. In this tutorial, I decided to choose SendGrid as an example.

Setup SendGrid (SMTP Service Provider)

Image for post
Image for post

Step 1) Create an account at SendGrid

Step 2) Verify a sender identity

Image for post
Image for post
Image for post
Image for post

You can either verify a single sender identity or a domain identity depending on your needs. A verification email is sent to your email account. After verifying your email address, SendGrid will whitelist your email address and send emails on your behalf.

Step 3) Generate an API key for the Extension setup

Image for post
Image for post

Go to the “Integration Guide” in the “Email API” tab at the navigation drawer. Select the “SMTP Relay” option.

Image for post
Image for post
Image for post
Image for post

The steps are straight forward. An API key, which is also named as Password”, is finally generated. Keep it as secret as possible to prevent any security issue!

Setup the Trigger Email Extension

Image for post
Image for post
  1. Visit the Firebase Extensions website and install the Trigger Email Extension. Make sure your project is in Blaze plan.

2. Configure the Trigger Email Extension

Image for post
Image for post
  • Cloud Functions location: Should be as close as possible to your target customer’s region in order to minimise the latency
  • SMTP connection URI: The format shown at the placeholder is:
smtps://{username}:{password}@{smtp.hostname.com}:465
Image for post
Image for post

❗️We should NOT mix up the username and password field with those used for login SMTP service provider. They are two sets of data. The username is “apikey” and password is the actual API key according to the SendGrid configuration. Below is a sample URI:

smtp://apikey:SG.IH8vUS.................QzZ1N0@smtp.sendgrid.net:465
  • Default FROM and REPLY-TO address: This must be a verified email address at the SMTP service provider. Otherwise, the 550 error code will be returned from SendGrid.
Image for post
Image for post

Moreover, we can add a user-friendly display name to the email address in the format of displayName <sample@demo.com>. For example, Firebase Myrick Chow <myrickchow32@gmail.com>.

  • Email documents collection: Cloud Functions observes the document creation and the update in this collection and triggers email delivery according to the document fields.
  • Users collection: Developers can save the users’ profile with an email address into this collection and refer to this document ID at toUids, ccUids and bccUids fields in the email document. The extension can then fetch the recipients’ profile and send email to them accordingly.
  • Templates collection: Developers can save some parts of the message details into this collection and reuse them in the future. However, the template does not support the attachments field, and you need to set it whenever you want to add attachments manually.

Basic Email

Image for post
Image for post

After setting up the Trigger Email extension, we can now try to send out a simple email, which only consists of the most common fields — recipients, subject and content.

Let’s create the following document at the email_collection (or the one you configured at the previous session) in the Cloud Firestore.

Image for post
Image for post

Cloud Functions would observe the document creation at the email_collection and compose an email based on the document fields. The extension supports 11 fields, and the following are 7 of them:

  1. to, cc & bcc: The recipients’ email address. They can be in a type of String or Array of String.

2. from & replyTo: Custom sender’s and reply-to email address. Please make sure the email addresses are verified at the SMTP service provider. Otherwise, SendGrid will return the 550 error code with the following details:

Message failed: 550 The from address does not match a verified Sender Identity. Mail cannot be sent until this error is resolved. Visit https://sendgrid.com/docs/for-developers/sending-email/sender-identity/ to see the Sender Identity requirements

3. header: A Map with key-value pair. It should only be used for advanced purposes, e.g. authorisation and email categorisation. In typical cases, we do not need to customise this value.

By the way, to view the header field in macOS Mail app, you have to enable View> Message > Default Headers or simply press [Command + Shift + H].

Image for post
Image for post

4. message: in the type of nodemailer.SendMailOptions consists of many fields, e.g. subject, text, html, amp and attachments, etc. If you look carefully at the Nodemailer documentation, it also contains from, replyTo, to, cc and bcc. According to the open-source code, these settings will be overridden by the 1st level document field. Therefore, we should ignore these fields.

Send email according to user profile

Image for post
Image for post
Image for post
Image for post

It is common for an application to have a list of users. Developers can save the user profile to the users_collection (or the one you configured at the “Setup the Trigger Email Extension” session) and the email address to the email field.

After that, we can specify the user id (document ID in users_collection) to the toUids, ccUids or bccUids in the email document. The extension will then fetch the email addresses according to the document ID and send emails directly.

An email with attachments — Cloud Storage

Attachments provide supplementary information to the email content, for instance, PDF and Zip files. Nodemailer supports adding attachments to emails. We can first upload the attachment to Cloud Storage.

Image for post
Image for post

After that, copy the file link and add the following attachments field at the email document. Finally, you can see your attachment shown in the email:

Image for post
Image for post
Image for post
Image for post

Email with HTML

Image for post
Image for post
Image for post
Image for post
Image for post
Image for post

Email supports three types of format — plain text, HTML and AMP format. HTML can have a fancier UI than the plain text. There are many HTML template providers on the Internet, such as Stripo, BEE Free and Envato Elements, etc. After getting the HTML code of the email template, you can add it to the html field of the message field in email document:

Image for post
Image for post

AMP Email

Image for post
Image for post
Example AMP email at this link

AMP is a new generation of email with many interactive UI components, such as carousel and expanding accordions. Sending it out is similar to the HTML email. We just need to insert the AMP code to the amp field.

Image for post
Image for post

However, email service providers typically block AMP emails by default due to safety issues. Take Gmail as an example, it throws an error when the sender is not a registered one in the Gmail server.

Image for post
Image for post

The sender has to register at Google server first and pass the Google test to send AMP emails to Gmail recipients. You can find the registration form here.

Email Templates

The message field, which is in the type of nodemailer.SendMailOptions, has a lot of configurable fields. Are you annoyed by setting the fields repeatedly? The Trigger Email Extension allows developers to save the message field settings into the template_collection (or the one you configured at the “Setup The Trigger Email Extension” session) and reuse it later.

However, according to the open-source code, not all fields are supported. Only subject, html, text and amp are handled. In other words, you cannot save the attachment setting in attachments field in the template document and need to add it every time you construct an email.

By specifying the template with the name field, the Trigger Email extension will fetch the template details from the template_collection and override those corresponding fields at the email document, see the copy of source code above.

Image for post
Image for post
Image for post
Image for post

Email with Handlebars

The extension can also support Handlebars which is a template language and can dynamically render both text and HTML content according to the user inputs. The most common use case is the recipient’s name at the start of the email, i.e. “Dear XXX”.

Image for post
Image for post
Image for post
Image for post

Developers have to add {{variableName}} at the subject, text, html or amp fields and input the parameters at the template’s data field.

An email with multiple partial templates

Multiple templates probably have several common UI components, such as the header and footer. Developers can define them as a partial template and embed it into another template. The syntax of inserting a partial template is {{> templateDocumentId}}.

Image for post
Image for post
Image for post
Image for post

Delivery status

Image for post
Image for post

Once the Cloud Function runs, it updates the delivery status continuously until the process is completed. There are five main states — RETRY, PENDING, PROCESSING, SUCCESS and ERROR. At first, Cloud Functions updates the state field to PENDING once the document is created and then PROCESSING while preparing and sending a payload to the SMTP service provider. Finally, the state is changed to SUCCESS or ERROR depending on the SMTP service provider’s response. To monitor the email delivery status, we can add a document snapshot listener at the client-side and show the latest status once there is an update.

We can also manually change the state to RETRY to resend the email again.

What is the "info" field?

Image for post
Image for post

At first glance, some developers think that the info field is the actual delivery state to the end recipients. However, the info field represents how the SMTP service provider handles the email request. For example, “abcd123NonExistingEmailAddress@nonExisingDomain.com” is a non-existing email address. The email address is shown inside the accepted field, although the email cannot be delivered. So, how to check the actual delivery status to the end recipient? We have to visit the console of the SMTP service provider and filter the specific email address:

Image for post
Image for post
Image for post
Image for post

Therefore, the overall debug procedure would be:

  1. Checking if there is an error message shown at the delivery.error field. The sample error messages are:
  • Failed to deliver email. Expected at least 1 recipient.
  • Must specify a users collection to send using uids.
  • Template object is missing a ‘name’ parameter.
  • Message processing lease expired.
  • 550 The from address does not match a verified Sender Identity. Mail cannot be sent until this error is resolved. Visit https://sendgrid.com/docs/for-developers/sending-email/sender-identity/ to see the Sender Identity requirements

2. Visit the SMTP provider console and search for the delivery result of the specific email address.

Maintenance

Image for post
Image for post

The project owner can change the SMTP service provider or any extension configuration in practice. It requires 3–5 minutes for the new configuration to be deployed. Although the email handling function is still shown at the “Functions” tab, it does not carry out any operation in this period with the old configurations. In other words, there is a maintenance window when clients can still create an email document, but no email requests are handled.

To tackle this short period of maintenance, we can have two approaches:

  1. Edit the security rule to temporarily suspend the email document creation and show an error message at the client-side to notify a temporary service suspension. Re-enable it after the configuration is deployed.
  2. Execute a cloud function to filter those email documents created during this maintenance period and re-create them to trigger the email requests again.

Summary

  1. The Trigger Email extension reduces the developer’s workload on sending emails to target clients and composes email according to the new document in email collection.
  2. The SMTP connection URL format is quite tricky. Do not mix up the one for logging in the SMTP service provider with those generated with the API key.
  3. The email consists of recipients’ addresses (to, cc & bcc), header, subject and content.
  4. The extension supports email templates for only subject, text, HTML and AMP, but not attachments. Template settings override those identical fields at the top level of the document.
  5. AMP is the most elegant email format and can encourage clients’ motivation. However, you must register your sender’s email address with Google to send AMP emails to Gmail addresses.
  6. Delivery status shown in the email document only represents the handling status at the SMTP service provider. It does not represent the actual delivery status. We have to visit the SMTP service provider console to view the actual one.

Firebase Developers

Tutorials, deep-dives, and random musings from Firebase…

Sign up for The Firebase Developers Quarterly

By Firebase Developers

A summary of what has happened on the Firebase Developers publication in the past quarter. Sent once a quarter. Take a look.

By signing up, you will create a Medium account if you don’t already have one. Review our Privacy Policy for more information about our privacy practices.

Check your inbox
Medium sent you an email at to complete your subscription.

Myrick Chow

Written by

🇭🇰 _Hong Kong App Developer; Android, iOS & Firebase lover; Sharing & Writing can strengthen my knowledges!

Firebase Developers

Tutorials, deep-dives, and random musings from Firebase developers all around the world. Views expressed are those of the authors and don’t necessarily reflect those of Firebase or its parent companies.

Myrick Chow

Written by

🇭🇰 _Hong Kong App Developer; Android, iOS & Firebase lover; Sharing & Writing can strengthen my knowledges!

Firebase Developers

Tutorials, deep-dives, and random musings from Firebase developers all around the world. Views expressed are those of the authors and don’t necessarily reflect those of Firebase or its parent companies.

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store