@sendgrid/mail vs mailgun-js vs nodemailer vs resend vs sendgrid
Sending Transactional Emails in Node.js
@sendgrid/mailmailgun-jsnodemailerresendsendgridSimilar Packages:

Sending Transactional Emails in Node.js

These five libraries enable Node.js applications to send emails, but they use different underlying methods. nodemailer is a standalone SMTP client that works with any email server. @sendgrid/mail, mailgun-js, resend, and sendgrid are SDKs for specific Email API services. The API-based tools handle delivery infrastructure for you, while nodemailer requires you to manage an SMTP server or relay. Choosing the right one depends on whether you need a specific provider's features or a generic SMTP solution.

Npm Package Weekly Downloads Trend

3 Years

Github Stars Ranking

Stat Detail

Package
Downloads
Stars
Size
Issues
Publish
License
@sendgrid/mail03,05217.4 kB938 months agoMIT
mailgun-js0892-528 years agoMIT
nodemailer017,568549 kB1a day agoMIT-0
resend0912231 kB162 days agoMIT
sendgrid03,052-939 years agoMIT

Sending Transactional Emails in Node.js: API SDKs vs SMTP

These five libraries solve the same problem β€” sending emails from a Node.js backend β€” but they take different paths. nodemailer uses the SMTP protocol to talk to any mail server. The others (@sendgrid/mail, mailgun-js, resend, sendgrid) are HTTP API clients for specific email delivery services. Let's compare how they handle setup, sending, and attachments.

πŸ”‘ Authentication & Setup

@sendgrid/mail uses an API Key set globally or per request.

const sgMail = require('@sendgrid/mail');
sgMail.setApiKey(process.env.SENDGRID_API_KEY);

mailgun-js requires your domain and API Key during initialization.

const mailgun = require('mailgun-js');
const mg = mailgun({ apiKey: process.env.MAILGUN_KEY, domain: 'yourdomain.com' });

nodemailer needs SMTP credentials (host, port, user, pass).

const nodemailer = require('nodemailer');
const transporter = nodemailer.createTransport({
  host: 'smtp.example.com',
  port: 587,
  auth: { user: 'user', pass: 'pass' }
});

resend initializes with an API Key to create a client instance.

const { Resend } = require('resend');
const resend = new Resend(process.env.RESEND_API_KEY);

sendgrid (Legacy) uses a constructor with the API Key.

const sendgrid = require('sendgrid');
const sg = new sendgrid.SendGrid(process.env.SENDGRID_API_KEY);

πŸ“€ Sending a Basic Email

@sendgrid/mail sends a message object with to, from, subject, and content.

await sgMail.send({
  to: 'user@example.com',
  from: 'me@example.com',
  subject: 'Hello',
  text: 'World',
  html: '<strong>World</strong>'
});

mailgun-js uses a messages().send() method with form-style data.

const data = {
  from: 'Me <me@example.com>',
  to: 'user@example.com',
  subject: 'Hello',
  text: 'World',
  html: '<strong>World</strong>'
};
await mg.messages().send(data);

nodemailer uses sendMail with a similar object structure.

await transporter.sendMail({
  from: 'me@example.com',
  to: 'user@example.com',
  subject: 'Hello',
  text: 'World',
  html: '<strong>World</strong>'
});

resend uses a clean emails.send method with arrays for recipients.

await resend.emails.send({
  from: 'me@example.com',
  to: ['user@example.com'],
  subject: 'Hello',
  text: 'World',
  html: '<strong>World</strong>'
});

sendgrid (Legacy) uses a SendGrid instance and a Email object.

const email = new sendgrid.Email({
  to: 'user@example.com',
  from: 'me@example.com',
  subject: 'Hello',
  text: 'World',
  html: '<strong>World</strong>'
});
sg.send(email);

πŸ“Ž Handling Attachments

@sendgrid/mail expects attachments as an array of objects with content (base64).

const attachment = {
  content: Buffer.from('file content').toString('base64'),
  filename: 'doc.pdf',
  type: 'application/pdf'
};
await sgMail.send({ to: '...', from: '...', subject: '...', attachments: [attachment] });

mailgun-js accepts file paths or streams in the attachment array.

const data = {
  to: 'user@example.com',
  from: 'me@example.com',
  subject: 'File',
  text: 'See attached',
  attachment: ['/path/to/file.pdf']
};
await mg.messages().send(data);

nodemailer handles attachments flexibly with paths or buffers.

await transporter.sendMail({
  to: 'user@example.com',
  from: 'me@example.com',
  subject: 'File',
  text: 'See attached',
  attachments: [{ path: '/path/to/file.pdf' }]
});

resend uses an array of objects with content (buffer or string) and filename.

await resend.emails.send({
  to: ['user@example.com'],
  from: 'me@example.com',
  subject: 'File',
  text: 'See attached',
  attachments: [{ filename: 'doc.pdf', content: Buffer.from('file') }]
});

sendgrid (Legacy) uses the addFile method on the Email object.

const email = new sendgrid.Email({ /*...*/ });
email.addFile('/path/to/file.pdf');
sg.send(email);

⚠️ Maintenance & Architecture

sendgrid is deprecated. It was the v2 SDK and is no longer updated. Using it in new projects is risky because it lacks security patches and new features. You should treat it as legacy code that needs migration to @sendgrid/mail.

mailgun-js is a community-maintained wrapper. The official Mailgun SDK is now mailgun.js. While mailgun-js still works, it may not support the latest API endpoints. For long-term stability, verify if mailgun.js fits your needs better.

nodemailer is protocol-based. It does not depend on a specific company's API uptime. This makes it very stable for local testing or self-hosted servers. However, you must manage your own SMTP relay for production delivery to avoid spam folders.

@sendgrid/mail and resend are modern API clients. They abstract away SMTP entirely. This reduces setup time but locks you into their delivery infrastructure. resend is newer and focuses heavily on developer experience, while @sendgrid/mail is an enterprise standard.

🀝 Similarities: Shared Ground

While the implementation differs, all five libraries share core concepts for defining email messages.

1. πŸ“¨ Standard Message Fields

  • All use from, to, subject, and text/html fields.
  • The data structure is nearly identical across packages.
// Common structure across all 5
const msg = {
  from: 'me@example.com',
  to: 'user@example.com',
  subject: 'Test',
  text: 'Hello'
};

2. ⚑ Async/Await Support

  • All support modern JavaScript Promises.
  • You can use await to handle sending logic cleanly.
// All support this pattern
try {
  await client.send(msg);
} catch (error) {
  console.error(error);
}

3. πŸ” Environment Variables

  • All require secrets (API Keys or Passwords).
  • Best practice is to load these from .env files.
// All rely on this
const key = process.env.API_KEY;

πŸ“Š Summary: Key Similarities

FeatureShared by All 5 Packages
Core FieldsπŸ“¨ From, To, Subject, Body
Async Model⚑ Promises / Async-Await
SecurityπŸ” API Keys or SMTP Auth
AttachmentsπŸ“Ž Supported (varying formats)
Node Version🟒 Compatible with modern Node.js

πŸ†š Summary: Key Differences

FeatureAPI SDKs (@sendgrid/mail, resend, mailgun-js, sendgrid)SMTP (nodemailer)
Protocol🌐 HTTP REST APIπŸ“  SMTP Protocol
Infrastructure☁️ Managed by ProviderπŸ–₯️ You Manage Relay
Setup Time⚑ Fast (API Key only)🐒 Slower (SMTP Config)
Vendor Lock-inπŸ”’ High (Specific Provider)πŸ”“ Low (Any SMTP Server)
Status⚠️ sendgrid is Deprecatedβœ… Stable

πŸ’‘ The Big Picture

nodemailer is the universal adapter πŸ”Œ. Use it when you need flexibility, local testing without external dependencies, or when you already have an SMTP server. It keeps your code portable between providers.

@sendgrid/mail and resend are the modern specialists πŸš€. Use them when you want a managed service that handles deliverability, tracking, and templates for you. resend is great for new apps wanting a fresh DX; @sendgrid/mail is best for enterprise needs.

mailgun-js and sendgrid are the legacy options πŸ•°οΈ. Avoid sendgrid entirely in new work. Use mailgun-js only if you are stuck with it; otherwise, look at mailgun.js or switch providers.

Final Thought: For most modern web apps, an API-based service like resend or @sendgrid/mail saves the most time. If you need total control or offline capability, nodemailer remains the gold standard for SMTP.

How to Choose: @sendgrid/mail vs mailgun-js vs nodemailer vs resend vs sendgrid

  • @sendgrid/mail:

    Choose @sendgrid/mail if you are using SendGrid as your email provider and want the official, maintained SDK. It offers full access to SendGrid features like templates, tracking, and batch sending. This is the standard choice for teams already invested in the SendGrid ecosystem who need reliable API integration.

  • mailgun-js:

    Choose mailgun-js only if you are maintaining a legacy project that already depends on it. For new projects, prefer the newer mailgun.js SDK or another provider, as this package has seen less active maintenance recently. It is suitable for Mailgun users who need a quick integration but should be evaluated against modern alternatives.

  • nodemailer:

    Choose nodemailer if you need to send emails via SMTP without locking into a specific API provider. It is ideal for local development, self-hosted mail servers, or when you want to switch email providers without changing code. It is the most flexible option for generic email sending needs.

  • resend:

    Choose resend if you want a modern, developer-first email API with a clean SDK and React email template support. It is excellent for new projects that prioritize ease of use, strong TypeScript types, and a simplified setup process. This is a top pick for startups and teams wanting a fresh alternative to legacy providers.

  • sendgrid:

    Do NOT choose sendgrid for new projects as it is the deprecated legacy v2 SDK. It lacks support for newer SendGrid features and is no longer maintained. You should migrate any existing usage to @sendgrid/mail to ensure security and compatibility with current API standards.

README for @sendgrid/mail

BuildStatus npm version

This package is part of a monorepo, please see this README for details.

Mail Service for the SendGrid v3 Web API

This is a dedicated service for interaction with the mail endpoint of the SendGrid v3 API.

Installation

Prerequisites

  • Node.js version 6, 8 or >=10
  • A Twilio SendGrid account, sign up for free to send up to 40,000 emails for the first 30 days or check out our pricing.

Obtain an API Key

Grab your API Key from the Twilio SendGrid UI.

Setup Environment Variables

Do not hardcode your Twilio SendGrid API Key into your code. Instead, use an environment variable or some other secure means of protecting your Twilio SendGrid API Key. Following is an example of using an environment variable.

Update the development environment with your SENDGRID_API_KEY, for example:

echo "export SENDGRID_API_KEY='YOUR_API_KEY'" > sendgrid.env
echo "sendgrid.env" >> .gitignore
source ./sendgrid.env

Install Package

The following recommended installation requires npm. If you are unfamiliar with npm, see the npm docs. Npm comes installed with Node.js since node version 0.8.x, therefore, you likely already have it.

npm install --save @sendgrid/mail

You may also use yarn to install.

yarn add @sendgrid/mail

Verify Sender Identity

Verify an email address or domain in the Sender Authentication tab. Without this you will receive a 403 Forbidden response when trying to send mail.

Quick Start, Hello Email

The following is the minimum needed code to send a simple email. Use this example, and modify the to and from variables:

For more complex use cases, please see USE_CASES.md.

const sgMail = require('@sendgrid/mail');
sgMail.setApiKey(process.env.SENDGRID_API_KEY);
const msg = {
  to: 'test@example.com',
  from: 'test@example.com', // Use the email address or domain you verified above
  subject: 'Sending with Twilio SendGrid is Fun',
  text: 'and easy to do anywhere, even with Node.js',
  html: '<strong>and easy to do anywhere, even with Node.js</strong>',
};
//ES6
sgMail
  .send(msg)
  .then(() => {}, error => {
    console.error(error);

    if (error.response) {
      console.error(error.response.body)
    }
  });
//ES8
(async () => {
  try {
    await sgMail.send(msg);
  } catch (error) {
    console.error(error);

    if (error.response) {
      console.error(error.response.body)
    }
  }
})();

After executing the above code, you should have an email in the inbox of the recipient. You can check the status of your email in the UI. Alternatively, we can post events to a URL of your choice using our Event Webhook. This gives you data about the events that occur as Twilio SendGrid processes your email.

Troubleshooting

Please see our troubleshooting guide for common library issues.

Announcements

All updates to this library are documented in our CHANGELOG and releases.

How to Contribute

We encourage contribution to our libraries (you might even score some nifty swag), please see our CONTRIBUTING guide for details.

About

@sendgrid/mail is maintained and funded by Twilio SendGrid, Inc. The names and logos for @sendgrid/mail are trademarks of Twilio SendGrid, Inc.

If you need help installing or using the library, please check the Twilio SendGrid Support Help Center.

If you've instead found a bug in the library or would like new features added, go ahead and open issues or pull requests against this repo!

Twilio SendGrid Logo