Back to Blog
๐Ÿ“จ
/4 min read/By SMTPfast Team

Send Emails from Node.js in 5 Minutes with SMTPfast

No SDK, no dependencies. Just fetch() and a few lines of code to send transactional emails from your Node.js app.

tutorialnodejavascriptgetting-started
Share:๐•in

No SDK Required

0
Dependencies needed to send emails with SMTPfast from Node.js

Most email APIs require you to install an SDK. With SMTPfast, you use the built-in fetch() API that ships with Node.js 18+. No packages to install, no dependencies to maintain.

Prerequisites

  • Node.js 18 or later (for built-in fetch)
  • An SMTPfast account with a verified domain
  • An API key from the SMTPfast dashboard

Send Your First Email

Create a file called send-email.js:

async function sendEmail() {
  const res = await fetch("https://smtpfa.st/api/v1/emails", {
    method: "POST",
    headers: {
      Authorization: `Bearer ${process.env.SMTPFAST_API_KEY}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      from: "[email protected]",
      to: "[email protected]",
      subject: "Welcome to our app!",
      html: "<h1>Welcome!</h1><p>Thanks for signing up.</p>",
    }),
  });

  if (!res.ok) {
    const error = await res.json();
    throw new Error(`Email send failed: ${error.message}`);
  }

  const { id } = await res.json();
  console.log("Email sent! ID:", id);
  return id;
}

sendEmail();

Run it:

SMTPFAST_API_KEY=sf_your_api_key node send-email.js

That is it. No npm install, no configuration files.

Add Error Handling

In production, you want proper error handling and retries:

async function sendEmail(to, subject, html, retries = 3) {
  for (let attempt = 1; attempt <= retries; attempt++) {
    try {
      const res = await fetch("https://smtpfa.st/api/v1/emails", {
        method: "POST",
        headers: {
          Authorization: `Bearer ${process.env.SMTPFAST_API_KEY}`,
          "Content-Type": "application/json",
        },
        body: JSON.stringify({ from: "[email protected]", to, subject, html }),
      });

      if (res.status === 429) {
        // Rate limited - wait and retry
        const retryAfter = parseInt(res.headers.get("retry-after") || "1");
        await new Promise((r) => setTimeout(r, retryAfter * 1000));
        continue;
      }

      if (!res.ok) {
        const error = await res.json();
        throw new Error(error.message);
      }

      return await res.json();
    } catch (err) {
      if (attempt === retries) throw err;
      // Exponential backoff
      await new Promise((r) => setTimeout(r, Math.pow(2, attempt) * 100));
    }
  }
}

Build a Reusable Helper

Wrap the API in a simple module you can import anywhere:

// lib/email.js
const SMTPFAST_URL = "https://smtpfa.st/api/v1/emails";

async function send({ from, to, subject, html, text, replyTo, tags }) {
  const res = await fetch(SMTPFAST_URL, {
    method: "POST",
    headers: {
      Authorization: `Bearer ${process.env.SMTPFAST_API_KEY}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      from,
      to,
      subject,
      html,
      text,
      reply_to: replyTo,
      tags,
    }),
  });

  if (!res.ok) {
    const error = await res.json();
    throw new Error(`SMTPfast error: ${error.message}`);
  }

  return res.json();
}

module.exports = { send };

Use it in your app:

const email = require("./lib/email");

// Welcome email
await email.send({
  from: "App <[email protected]>",
  to: user.email,
  subject: "Welcome to our app!",
  html: `<h1>Welcome, ${user.name}!</h1>`,
});

// Password reset
await email.send({
  from: "Security <[email protected]>",
  to: user.email,
  subject: "Reset your password",
  html: `<p>Click <a href="${resetLink}">here</a> to reset your password.</p>`,
  tags: [{ name: "type", value: "password-reset" }],
});

Use with Express

Here is a common pattern for sending emails from an Express route:

const express = require("express");
const email = require("./lib/email");
const app = express();

app.use(express.json());

app.post("/api/invite", async (req, res) => {
  const { inviteeEmail, teamName } = req.body;

  try {
    const { id } = await email.send({
      from: `${teamName} <[email protected]>`,
      to: inviteeEmail,
      subject: `You're invited to join ${teamName}`,
      html: `<p>Click <a href="https://yourapp.com/invite/${inviteToken}">here</a> to join.</p>`,
    });

    res.json({ success: true, emailId: id });
  } catch (err) {
    console.error("Failed to send invite email:", err);
    res.status(500).json({ error: "Failed to send invitation" });
  }
});

Check Delivery Status

After sending, you can check whether the email was delivered:

async function checkEmailStatus(emailId) {
  const res = await fetch(`https://smtpfa.st/api/v1/emails/${emailId}`, {
    headers: {
      Authorization: `Bearer ${process.env.SMTPFAST_API_KEY}`,
    },
  });

  const data = await res.json();
  console.log("Status:", data.last_event); // "delivered", "bounced", etc.
  return data;
}

TypeScript Version

If you are using TypeScript, here is a typed version of the helper:

interface SendEmailOptions {
  from: string;
  to: string | string[];
  subject: string;
  html?: string;
  text?: string;
  replyTo?: string;
  tags?: Array<{ name: string; value: string }>;
}

interface SendEmailResponse {
  id: string;
}

async function sendEmail(options: SendEmailOptions): Promise<SendEmailResponse> {
  const res = await fetch("https://smtpfa.st/api/v1/emails", {
    method: "POST",
    headers: {
      Authorization: `Bearer ${process.env.SMTPFAST_API_KEY}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      from: options.from,
      to: options.to,
      subject: options.subject,
      html: options.html,
      text: options.text,
      reply_to: options.replyTo,
      tags: options.tags,
    }),
  });

  if (!res.ok) {
    const error = await res.json();
    throw new Error(`SMTPfast error: ${error.message}`);
  }

  return res.json();
}

Key Takeaways

  1. No SDK needed - use fetch() built into Node.js 18+
  2. Handle rate limits (429) with retry-after headers
  3. Wrap the API in a reusable module
  4. Add exponential backoff for production reliability
  5. Check delivery status via the GET endpoint

Ready to get started?

Start sending transactional email today. Free to start, no credit card required.

Get Started for Free