For the past couple of weeks, I’ve been struggling with sending emails with Firebase, but I’ve finally done it.
So, if you’re like me and you keep searching for “firebase send emails” on Google, search no more, because you’ve come to the right place.
I’ll walk you through the whole process in this article, and show you how to integrate email functionalities into your app with Mailtrap and Nodemailer.
Let’s jump straight into it!
Before sending emails: Setting up the project
Before we dive in, you’ll need to set up the following:
- Firebase
- Mailtrap – As Firebase doesn’t have an in-built email service, we’ll need one to send emails, and, for this, I chose Mailtrap due to its conventionality and ease of use.
- Nodemailer – A module for Node.js applications to send emails easily, Nodemailer handles the complexities of email protocols and allows you to implement email-sending functionality.
Setting up Firebase
1. Create a Firebase Project
The first thing you need to do is to create a new Firebase project by visiting the Firebase Console. Simply click on ‘Create a project’ and follow the rest of the setup wizard.
After you’ve entered your project name and agreed to the terms, you can decide whether you want to enable Google Analytics for your project.
2. Connect Firebase authentication
Go to the ‘Authentication’ section in your Firebase project dashboard and click on ‘Get started’ to set up the sign-in methods you need, such as email, password, Google, etc.
3. Connect Firestore
Initialize Firestore by going to the ‘Firestore Database’ section and clicking on ‘Create database.’
For initial setup, choose ‘Start in test mode’ and remember to configure security rules (e.g., authentication, validation, etc.) before deploying your app.
Lastly, define your collections and documents as needed for your application.
4. Install Firebase CLI
The Firebase CLI is a versatile utility that provides you with an easy way to manage, view, and deploy code and assets to your Firebase project.
You can install the utility on your development environment using a method that matches your preferences and use cases. Regardless of how you install it, you’ll still get the same functionalities.
For this tutorial, we’ll use the following command in our Windows Command Prompt to install the CLI globally:
npm install -g firebase-tools
Note that you’ll need to have Node.js installed on your system before running the above command.
After installing it, you can create a new directory that will contain the code for this Firebase project.
Then, go to the directory and run the following command to sign in to your Firebase account:
firebase login
Then, you’ll need to follow the ensuing prompts so that you can be authenticated into the Firebase platform. This way, you’ll be granted the right to access your Firebase projects locally, as your local machine will be connected to Firebase.
5. Initialize Firebase SDK for Cloud Functions
Cloud Functions allow you to access Firebase events directly in your application. This way, you can easily integrate with the Firebase platform and accomplish a wide range of tasks.
Initializing Firebase SDK for Cloud Functions allows you to create an empty project that contains some dependencies you can use to build the rest of your application.
After logging in successfully, you can initialize a Firebase project in your local directory by following these steps:
- Run the firebase init functions command.
- Follow the ensuing prompts to associate the project on your local machine with an existing Firebase project.
- The command gives you two language options for writing Cloud Functions: TypeScript and JavaScript. For this tutorial, choose JavaScript.
- If you want to use ESLint for catching bugs and enforcing style, you can accept that option. For this tutorial, just decline it.
- If you want to install dependencies with npm, you can accept that option. For this tutorial, just accept it.
After the installation is complete, the structure of your new directory will look something like this:
And here’s what it all means:
- functions – Directory that has all your functions code
- node_modules – Directory that has dependencies
- .gitignore – A list of rules to let Git know what files to ignore
- index.js – Main source file for your Cloud Functions code
- package.json – npm package file that has Cloud Functions code
- firebaserc – Hidden file you can use to switch between projects easily
- firebase.json – Has the properties for your project
For the rest of this tutorial, we’ll only make use of the functions directory. And, we’ll use the index.js file for all our code.
6. Install Firebase Admin SDK
The Admin SDK allows you to access Firebase from privileged environments and carry out various tasks, such as sending Firebase Cloud Messaging messages programmatically.
To install it, on the Command Prompt, navigate to your functions folder and run the following command:
npm install firebase-admin --save
Then, go to your index.js file and import and initialize the Admin SDK.
Here is the code:
const admin = require("firebase-admin");
admin.initializeApp();
Setting up Mailtrap
Setting it up Mailtrap is quick and easy. Just go to the signup page and register for a free account.
Then, go to the SMTP settings tab in your inbox and copy the details for host, port, username, and password. We’ll use these details in the next section of this tutorial.
Mailtrap also offers an NPM package to integrate Mailtrap with its official API. This allows you to add the email-sending functionality to your Node.js app much faster.
Notes:
- The version 3 of the package (as linked above) is a completely new package. The previous versions were an unofficial client. However, the new package doesn’t support Mailtrap Email Testing.
- Nodemailer is needed as a dependency, and we assume you already have it set up.
- Those who use Typescript, need to install @types/nodemailer as a devDependency.
- When using the Node.js client, you can add special keys such as ‘customVariables’, ‘category’, ‘templateVariables’, and ‘templateUuid’.
Now, let’s see how to install and use the package.
1. Install package
You can use the npm or yarn to complete the installation. Here are the code snippets:
npm install mailtrap
yarn add mailtrap
2. Use the package
Please find the script for minimal usage below:
import { MailtrapClient } from "mailtrap"
/**
* For this example to work, you need to set up a sending domain,
* and obtain a token that is authorized to send from the domain.
*/
const TOKEN = "<YOUR-TOKEN-HERE>";
const SENDER_EMAIL = "<SENDER@YOURDOMAIN.COM>";
const RECIPIENT_EMAIL = "<RECIPIENT@EMAIL.COM>";
const client = new MailtrapClient({ token: TOKEN });
const sender = { name: "Mailtrap Test", email: SENDER_EMAIL };
client
.send({
from: sender,
to: [{ email: RECIPIENT_EMAIL }],
subject: "Hello from Mailtrap!",
text: "Welcome to Mailtrap Sending!",
})
.then(console.log)
.catch(console.error);
If you’d like to see full usage, you can refer to the script in the official GitHub documentation.
3. Send from a Mailtrap email template
To send from a Mailtrap email template, use the following script:
import { MailtrapClient } from "mailtrap"
/**
* For this example to work, you need to set up a sending domain,
* and obtain a token that is authorized to send from the domain.
*/
const TOKEN = "<YOUR-TOKEN-HERE>";
const SENDER_EMAIL = "<SENDER@YOURDOMAIN.COM>";
const RECIPIENT_EMAIL = "<RECIPIENT@EMAIL.COM>";
const client = new MailtrapClient({ token: TOKEN });
client
.send({
from: { name: "Mailtrap Test", email: SENDER_EMAIL },
to: [{ email: RECIPIENT_EMAIL }],
template_uuid: "813e39db-c74a-4830-b037-0e6ba8b1fe88",
template_variables: {
user_name: "John Doe",
},
})
.then(console.log)
.catch(console.error);
Make sure to replace the following with your own credentials:
- “<YOUR-TOKEN-HERE>”
- “<SENDER@YOURDOMAIN.COM>”
- “<RECIPIENT@EMAIL.COM>”
- template_uuid:
Setting up Nodemailer
Nodemailer is a simple module for sending email with Node.js applications. It comes with a wide range of features that allow you to send emails quickly, efficiently, and securely.
To install Nodemailer, go to your functions directory and run the following command:
npm install nodemailer
Then, go to your index.js file and import it into your project.
Here is the code:
const nodemailer = require('nodemailer');
1. Creating a Nodemailer transporter
Next, create a reusable Nodemailer transporter object using your Mailtrap’s SMTP information.
Here is the code:
let transporter = nodemailer.createTransport({
host: "live.smtp.mailtrap.io",
port: 587,
auth: {
user: "71b312d8f1a983", // generated by Mailtrap
pass: "e7a8f2287183dd" // generated by Mailtrap
}
});
In this case, the transporter will be an object that can be used to send emails.
Notice that is the same code available in your Mailtrap inbox—if you select Nodemailer, under the Integrations section.
2. Creating a Firebase Cloud Function
For this tutorial, we’ll create a Firebase HTTP Cloud Function, which will be triggered whenever its URL is executed in the browser.
Here is its syntax:
exports.emailSender = functions.https.onRequest((req, res) => {...});
As you can see on the code above, we named the function emailSender (you can call it any name). Then, we used the functions library with the https API and the onRequest event to register the function.
The callback event handler function accepts two parameters: req and res. While the req object provides you with access to the properties of the initial HTTP request sent by the client, the res object allows you to send a response back to the client.
Send emails from Firebase Functions
To send emails from Firebase functions using Nodemailer and Mailtrap’s service, use the following code snippet:
// The Cloud Functions for Firebase SDK to create Cloud Functions and triggers.
const functions = require('firebase-functions');
const nodemailer = require('nodemailer');
// The Firebase Admin SDK to access Firestore.
const {initializeApp} = require("firebase-admin/app");
initializeApp();
//Creating Nodemailer transporter using your Mailtrap SMTP details
let transporter = nodemailer.createTransport({
host: "live.smtp.mailtrap.io",
port: 587,
auth: {
user: "username",
pass: "password"
}
});
exports.sendEmail = functions.region('asia-south1').https.onRequest(async (req, res) => {
//Defining mailOptions
const mailOptions = {
from: 'from@gmail.com', //Adding sender's email
to: "to@gmail.com", //Getting recipient's email by query string
subject: 'Email Sent via Firebase', //Email subject
html: 'This is a test Email from Firebase' //Email content
};
//Returning result
return transporter.sendMail(mailOptions, (err, info) => {
if(err){
return res.send(err.toString());
// return false;
}
return res.send('Email sent succesfully');
// return true;
});
});
Additionally, you can also send emails from Firebase Functions by using Mailtrap email API.
Here’s how to do it:
const functions = require('firebase-functions');
const fetch = require('node-fetch');
exports.sendEmailAPIFunction = functions.https.onCall(async (data, context) => {
const apiUrl = 'https://send.api.mailtrap.io/api/send';
const response = await fetch(apiUrl, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Api-Token': 'your_mailtrap_api_token'
},
body: JSON.stringify({
to: [{ email: data.to }],
from: { email: 'your_email@example.com' },
subject: data.subject,
text: data.text
})
});
return response.json();
});
Essentially, I set up a function that makes an HTTP POST request to Mailtrap’s API endpoint.
Note that you should:
- Ensure you have the ‘note-fetch’ package installed in your Firebase project to use fetch for API calls.
- Replace the placeholders like ‘username’ or ‘password’ with your actual Mailtrap credentials and API token.
Sending emails using Firebase Trigger Email Extension
The Firebase Trigger Email extension automatically sends emails based on the changes in a Cloud Firestore collection. This can be useful if you want to automate email workflows directly from your Firebase project.
Keep in mind that it’s designed to work with SMTP and does not natively support sending emails via an API.
So, to use it, you need to:
- Install the extension from the official Firebase Extension docs page.
- Upgrade your project to the paid Blaze plan as the extension requires the pay-as-you-go pricing plan.
- Configure the extension with Mailtrap’s SMTP settings.
- Make sure to input the SMTP URL, username, password, host URL, and port into the extension’s configuration settings.
- Set up a Firestore collection to trigger the email setting.
- Define a Firestore collection (e.g., ‘mail’ or ‘users’) that the extension will monitor.
Here’s an example:
```javascript
// The Cloud Functions for Firebase SDK to create Cloud Functions and triggers.
const functions = require('firebase-functions');
// The Firebase Admin SDK to access Firestore.
const {initializeApp} = require("firebase-admin/app");
const admin = require(‘firebase-admin’);
initializeApp();
admin.firestore().collection('mail').add({
to: 'someone@example.com',
message: {
subject: 'Hello from Firebase!',
html: 'This is an <code>HTML</code> email body.',
},
});
Send HTML emails
To send HTML emails, simply specify the HTML content in mailOptions variable:
let html = `<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Welcome Card</title>
<style>
body {
font-family: Arial, sans-serif;
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
margin: 0;
background-color: #f7f7f7;
}
.card {
box-shadow: 0 4px 8px 0 rgba(0,0,0,0.2);
transition: 0.3s;
width: 40%;
min-width: 300px;
border-radius: 5px;
background-color: white;
padding: 2em;
text-align: center;
}
.card:hover {
box-shadow: 0 8px 16px 0 rgba(0,0,0,0.2);
}
.welcome-text {
color: #333;
font-size: 24px;
margin-top: 0;
}
</style>
</head>
<body>
<div class="card">
<p class="welcome-text">Welcome to Our Site!</p>
<p>Enjoy exploring the features we have to offer.</p>
</div>
</body>
</html>
`;
exports.sendEmail = functions.region('asia-south1').https.onRequest(async (req, res) => {
//Defining mailOptions
const mailOptions = {
from: 'from@gmail.com', //Adding sender's email
to: "to@gmail.com", //Getting recipient's email by query string
subject: 'Email Sent via Firebase', //Email subject
html: html
};
//Returning result
return transporter.sendMail(mailOptions, (err, info) => {
if(err){
return res.send(err.toString());
// return false;
}
return res.send('Email sent succesfully');
// return true;
});
});
The finishing result should look something like this:
Send emails with attachments
To send documents, images, and other types of files with Nodemailer, simply use the following code:
const mailOptions = {
from: 'you@example.com',
to: user.email,
subject: 'Here’s your requested document',
text: 'Please find the attached document.',
attachments: [
{
filename: 'document.pdf',
path: 'path/to/document.pdf'
}
]
};
//Return result
return transporter.sendMail(mailOptions, (err, info) => {
if (err) {
return res.send(err.toString());
}
return res.send('Email sent successfully');
})
In the example above, ‘attachments’ is an array where each element represents a file to be attached, with properties such as ‘filename’ and ‘path.’
Test emails and email sending in a staging environment
When sending emails from your app, a lot can go wrong. Your HTML might not render correctly, your personalization variables might be off, etc.
To avoid these issues and improve your email deliverability, all you have to do is test your emails. A tool that will help you do this is Mailtrap Email Testing, which allows you to inspect and debug your emails in a safe environment.
Apart from allowing you to test the email-sending capabilities of your app in staging, Email Testing can help you inspect HTML/CSS. This way, you’ll see all the faulty lines of code so you can easily fix them.
On top of that, Email Testing will also check your spam score, which, if you keep under 5, will prevent any deliverability issues when your app moves to production. Essentially, you can ensure your email lands in the recipient’s inbox, instead of their spam folder.
With that said, here’s how it works.
SMTP
First, you need to install Jest, a testing framework for JavaScript, by running ‘npm install jest’ in your project directory.
Then, use the following code snippet in your ‘index.js’ for SMTP testing:
const syncSendMailSMTP = async (testData) => {
// Defining email options
const mailOptions = {
from: 'from@gmail.com',
to: "to@gmail.com",
subject: 'Email Sent via Firebase',
html: '<b>Sending emails with Firebase is easy!</b>'
};
// You can use testData or mailOptions here
return new Promise((resolve, reject) => {
transporter.sendMail(mailOptions, (err, info) => {
if (err) reject(false);
else resolve(true);
})
})
}
exports.sendEmailSMTP = async () => {
return await syncSendMailSMTP();
};
API
To automate testing, simply add the following code to your ‘email.test.js.’ file:
const { sendEmailSMTP, sendEmailAPI } = require('./index'); // Import your Cloud Function
describe('Email Sending Function Tests', () => {
it('should send an email successfully', async () => {
const testData = {
to: 'test@example.com',
subject: 'Test Subject',
text: 'This is a test email',
};
const result = await sendEmailAPI(testData);
expect(result).toBe(true);
});
// Add more tests as needed
});
Lastly, make sure to configure Jest in your ‘package.json’:
"test": "jest"
npm run test
Wrapping up
And that’s about it!
Hopefully, now you understand how to send emails with Firebase and can incorporate Mailtrap and Nodemailer to make it even better.
If you’re looking for more content about emails and sending them from different programming languages and frameworks, make sure to check out the Mailtrap blog, where you can read articles on sending emails with:
If you’re a visual learner, you can visit our YouTube channel and see how to send emails with Nodemailer, for example.