Comparisons
Firebase Trigger Email vs EmailsDone
Firebase Trigger Email and EmailsDone can both be used to send email from Firebase apps, but they are not trying to solve the same problem.
Firebase Trigger Email is a Firebase extension that sends emails from Firestore documents using an SMTP provider you configure.
EmailsDone is a template-first transactional email API for common app emails such as welcome, verification, password reset, login code, notification and billing messages.
The simple difference is this:
Firebase Trigger Email helps you trigger email from Firebase.
EmailsDone helps you avoid building the email layer yourself.
Quick comparison
| Feature | Firebase Trigger Email | EmailsDone |
|---|---|---|
| Main purpose | Send email from Firestore documents | Send common app emails from backend code |
| Firebase-native | Yes, as an extension | Used from Firebase Functions or backend code |
| Sending method | SMTP provider you configure | SES-backed transactional email API |
| Requires SMTP setup | Yes | No |
| Templates included | You manage templates/content | Built-in app email templates |
| Custom HTML | You can provide your own | Not the core model |
| Best for | Firestore-to-SMTP workflows | App emails without template faff |
| Developer model | Create mail documents | Call a template method |
| Flexibility | Higher | Lower by design |
| Operational ownership | More on you | More handled for you |
Neither option is universally better.
The right choice depends on whether you want email infrastructure flexibility or finished app email flows.
What Firebase Trigger Email is
Firebase Trigger Email is best thought of as a Firestore-to-SMTP bridge.
Your app writes an email document to a Firestore collection. The extension watches that collection, reads the document, then sends the message through the SMTP provider you configured.
The flow looks like this:
Firebase app
↓
Firestore mail document
↓
Firebase Trigger Email extension
↓
Configured SMTP provider
↓
Recipient inbox
That is a useful Firebase pattern.
It lets email sending fit into a Firestore-driven workflow, and it keeps the actual send out of the frontend.
A simple mail document might contain the recipient, subject and HTML body:
{
to: ["user@example.com"],
message: {
subject: "Welcome to Acme",
html: "<p>Thanks for signing up...</p>"
}
}
The extension then takes care of sending that message through SMTP.
What EmailsDone is
EmailsDone takes a different approach.
Instead of asking your app to provide the full email content, EmailsDone gives you common transactional app emails as built-in templates.
Your Firebase app calls EmailsDone from trusted backend code, usually a Firebase Cloud Function.
The flow looks like this:
Firebase app
↓
Firebase Function
↓
EmailsDone template API
↓
Recipient inbox
For example:
await emailsDone
.authentication()
.welcome("https://app.example.com/get-started")
.send("user@example.com");
Or:
await emailsDone
.authentication()
.passwordReset(resetUrl)
.send("user@example.com");
The function is still yours.
The API key still stays server-side.
The email template is already done.
Implementation shape
With Firebase Trigger Email, the main action is creating a Firestore document.
That can be nice if your app already uses Firestore as a queue or event log.
For example:
await addDoc(collection(db, "mail"), {
to: ["user@example.com"],
message: {
subject: "Your report is ready",
html: "<p>Your report is ready to download.</p>"
}
});
With EmailsDone, the main action is calling a template from backend code:
await emailsDone
.notifications()
.notification({
subject: "Your report is ready",
heading: "Your report is ready",
intro: "The report you requested has finished processing.",
actionButton: {
label: "View report",
url: reportUrl
}
})
.send("user@example.com");
The difference is subtle but important.
Trigger Email asks you to describe the whole email.
EmailsDone asks you to describe the app event.
Sender setup
Firebase Trigger Email sends through the SMTP provider you configure.
That means you still need to decide what SMTP service to use, configure credentials, and understand the limits and behaviour of that provider.
That is fine if you already have a provider and know how you want to send.
EmailsDone avoids SMTP setup from your app’s perspective. It uses a transactional email API model, with sending backed by SES and sender/domain setup handled through DNS verification.
The practical difference is:
Trigger Email:
Bring SMTP credentials and your own templates.
EmailsDone:
Verify your sending domain and call app email templates.
You should not need to buy inbox hosting just to send transactional app emails from your own domain.
Template ownership
This is the biggest difference.
Firebase Trigger Email gives you a way to send email, but the email content is still yours to create and maintain.
You need to decide:
- subject lines
- HTML
- text content
- layout
- variables
- fallback links
- wording
- consistency across all app emails
That gives you flexibility.
It also gives you work.
EmailsDone is template-first. Common app emails are already structured, so your app passes the data needed by the template.
For example, a password reset email becomes:
await emailsDone
.authentication()
.passwordReset(resetUrl)
.send("user@example.com");
Most apps do not need a unique password reset layout.
They need a clear, safe, production-ready password reset email that works.
That is the trade-off.
Developer ergonomics
Firebase Trigger Email fits developers who like configuration and Firestore-driven flows.
It can be a good mental model:
Create document → extension sends email
EmailsDone fits developers who want email to be a small app integration:
Call template → email queued
Neither is wrong.
But they feel different to work with.
With Trigger Email, email becomes a document format you maintain.
With EmailsDone, email becomes a small method call attached to an app event.
Flexibility vs finished
The comparison comes down to this:
Do you want flexibility, or do you want finished?
Firebase Trigger Email is more flexible. You can send the content you want, using your chosen SMTP provider, from a Firestore-based workflow.
EmailsDone is more constrained. You choose from app email templates and pass the required data.
That constraint is deliberate.
It removes decisions:
- no HTML to write
- no template layout to design
- no SMTP credentials to manage
- no separate email template system to invent
- no need to ask a coding agent to create a password reset email from scratch
If you need complete creative control, Firebase Trigger Email or a general email provider may be the better fit.
If you want production app emails without turning email into another project, EmailsDone is the simpler fit.
When Firebase Trigger Email is better
Use Firebase Trigger Email if:
- you want an official Firebase extension
- you prefer Firestore-based workflows
- you already have an SMTP provider
- you want full control over email content
- you want to maintain your own templates
- you need unusual or highly customised emails
- you are comfortable owning the delivery setup around SMTP
It is a good fit when you want Firebase-native email plumbing and do not mind owning the email layer.
When EmailsDone is better
Use EmailsDone if:
- you want common app emails working quickly
- you do not want to write HTML templates
- you do not want to configure SMTP
- you are using Firebase Functions or trusted backend code
- you want consistent transactional emails
- you want a small API/SDK call
- you prefer template-first over blank-canvas email sending
It is a good fit when your app needs email, but email is not the product.
Example Firebase Function with EmailsDone
A safe Firebase setup keeps the EmailsDone API key server-side and sends from a Cloud Function:
import { onCall, HttpsError } from "firebase-functions/v2/https";
import { defineSecret } from "firebase-functions/params";
import { EmailsDone } from "emailsdone";
const emailsDoneApiKey = defineSecret("EMAILSDONE_API_KEY");
export const sendWelcomeEmail = onCall(
{
secrets: [emailsDoneApiKey],
enforceAppCheck: true,
},
async (request) => {
if (!request.auth?.token.email) {
throw new HttpsError("unauthenticated", "You must be signed in.");
}
const emailsDone = EmailsDone.fromApiKey(emailsDoneApiKey.value());
await emailsDone
.authentication()
.welcome("https://app.example.com/get-started")
.send(request.auth.token.email);
return { queued: true };
}
);
The Firebase Function handles the trusted backend concerns:
- authentication
- App Check
- validation
- secrets
EmailsDone handles the email template and sending layer.
Final recommendation
Firebase Trigger Email is useful if you want Firestore-to-SMTP email sending and are happy managing your own email content.
EmailsDone is useful if you want common transactional app emails already packaged and callable from Firebase backend code.
The real comparison is not just:
Firestore document vs API call.
It is:
Do you want to build and maintain the email layer yourself?
If the answer is yes, Firebase Trigger Email gives you a Firebase-native way to do that.
If the answer is no, EmailsDone gives you the app email templates and sending layer so you can move on.
Some tools help you send any email.
EmailsDone helps you avoid building the boring ones.