Transactional Emails: What They Are and How to Send Them with Node.js
Sooner or later, every software product needs to send emails.
Are you a founder, a SaaS builder, or a software maintainer?
No matter what you build, if you work with software long enough, there will come a day when you need to send transactional emails.
Password resets, email verification, login alerts, invoices, OTP codes. These emails are everywhere. Users rarely notice them when they work, but when they fail, your product immediately feels broken.
So what exactly are transactional emails, and how should developers handle them?
What Are Transactional Emails?
Transactional emails are automatic, one-to-one messages triggered by a user action or a system event.
They are not marketing emails.
They are part of your product’s core functionality.
Common examples include:
- Account verification emails
- Password reset emails
- Login or security alerts
- Payment confirmations and invoices
- OTP and two-factor authentication emails
These emails must be delivered fast, reliably, and to the inbox. If a password reset email lands in spam or arrives too late, users lose trust instantly.
That is why transactional emails are not just “emails”.
They are part of your authentication flow, security layer, and user experience.
Why Developers Should Care About Deliverability
Transactional emails usually have low volume but high importance.
You are not sending newsletters.
You are sending critical system messages.
This means:
- Timing matters
- Inbox placement matters
- Reputation matters
Many teams separate transactional and marketing emails entirely. Different domains, different infrastructure, and stricter sending rules help protect deliverability.
Ignoring this early often leads to painful problems later.
Installing the Metigan SDK
To send transactional emails with Metigan, start by installing the SDK.
Using npm:
npm install metigan or yarn add metigan
Initializing Metigan
After installation, initialize Metigan with your API key.
import Metigan from 'metigan';
const metigan = new Metigan({
apiKey: "sp_63ace7496fb7692b6cace7496fb7692b6cace8f77d3d1bf8bc0db95cd944d498cbfc7679a1d5987b"
});
This instance will be used to send emails and manage contacts.
Sending a Basic Email
Here is a simple example of sending an email to one or more recipients.
export const sendMail = async (recipients: string[]) => {
try {
const result = await metigan.email.sendEmail({
from: "Oi <oi@metigan.com>",
recipients,
subject: "Message for API key test",
content: "Hello buddy, this message is from the Metigan Node.js SDK"
});
return result;
} catch (error) {
throw new Error(error as string);
}
};
This type of email can be used for system notifications or internal messages.
Creating Contacts Programmatically
Many products need to store users or customers for lifecycle communication.
export const createContacts = async (email: string, audienceId: string) => {
try {
const contact = await metigan.contacts.create({
email: email,
firstName: 'John',
lastName: 'Doe',
phone: '+1234567890',
tags: ['customer', 'premium'],
customFields: {
company: 'Acme Corp',
jobTitle: 'Software Engineer'
},
audienceId: audienceId
});
console.log('Contact created:', contact._id);
return contact;
} catch (error) {
console.error('Error creating contact:', error);
return error;
}
};
This is useful for onboarding flows and future communication.
Sending Transactional Emails
Now the most important part.
export const sendTransactionalEmail = async () => {
try {
const result = await metigan.email.sendTransactional({
from: 'Francisco Inoque APP <hello@franciscoinoque.com>',
to: 'jaimeinoque20@gmail.com',
subject: 'Welcome to Metigan!',
content: '<p>This is your password reset link: <a href="link_to_reset">Reset Password</a></p>'
});
console.log('Transactional email sent successfully!');
return result;
} catch (error) {
console.error('Error sending transactional email:', error);
return error;
}
};
j
This pattern applies to password resets, account verification, and security notifications.
If these emails fail, users are blocked from using your product.
Sending OTP Emails
One very common transactional use case is sending One-Time Passwords (OTP).
const sendOtpEmail = async () => {
try {
await metigan.email.sendOtp({
from: 'hello@example.com',
recipients: ['user@gmail.com'],
subject: 'Your OTP Code',
content: '<p>Your OTP code is: <strong>123456</strong></p>',
expiry: 300
});
console.log('OTP email sent successfully!');
} catch (error) {
console.error('Error sending OTP email:', error);
}
};
sendOtpEmail();
OTP emails are time-sensitive and should expire quickly. In this example, the OTP expires after 5 minutes, which is a common and safe default.
This is typically used for:
Login verification
Password reset confirmation
Sensitive account actions
Email-based two-factor authentication
Final Thoughts
Transactional emails are not optional. They are a core part of any serious software product.
As developers, treating them with the same importance as authentication, database reliability, or security pays off in the long run.
Users will never thank you when transactional emails work perfectly.
But they will complain loudly when they don’t.
If you are building a product today, start thinking about transactional emails early.
Full Documentation
For more advanced use cases and API references, check the full documentation:
Top comments (0)