Starter
For your first email program.
$192 billed yearly.
20,000 emails / month
Choose Starter- 5 brands · 3 seats
- 5 custom sending domains
- 500 email verifications/month
- $1.50 / 1,000 extra emails
Nodemailer installs from npm and has no runtime dependencies of its own, which is part of why it became the default choice.
It supports both SMTP and a pluggable transport interface, so the same calling code can target a provider's HTTP API through a transport plugin instead of SMTP.
The working sequence is two steps. Create a transporter with the host, port, security flag and authentication object. Call sendMail with an options object holding from, to, subject, and either text or html.
The secure flag is the setting people get wrong. Set to true it opens an implicit TLS connection, which pairs with port 465. The false value instead starts in the clear and upgrades through STARTTLS, which is the port 587 path. Pairing secure: true with port 587 produces a connection that hangs rather than returning a usable error.
Set both text and html when sending HTML. Nodemailer assembles the multipart message, and the plain-text part is what some clients render and what filters treat more favorably.
sendMail returns a promise resolving to an info object containing the message ID and the server's accepted and rejected recipient arrays. A send can resolve successfully while individual recipients were rejected, so checking info.rejected matters when sending to more than one address.
Reuse a transporter across sends rather than creating one per message. Each new transporter opens a fresh connection, and providers limit concurrent connections per account.
Running the file executes the send. Because sendMail is asynchronous, an unhandled rejection exits silently in older Node versions, so wrap the call in try/catch or attach a catch handler.
Credentials belong in environment variables rather than the source file. A committed application password is a live sending credential for the mailbox that issued it.
Gmail uses smtp.gmail.com on port 587 with STARTTLS or 465 with implicit TLS. Google blocks ordinary account passwords for third-party clients, so an app password generated against an account with two-step verification is required.
Microsoft 365 uses smtp.office365.com on port 587 with STARTTLS, documented in Microsoft's settings reference. Basic authentication on this path is scheduled for deprecation in favor of OAuth, which Nodemailer supports through an OAuth2 auth object.
Both are mailbox providers, and both apply per-mailbox sending limits sized for a person rather than an application. Microsoft documents 10,000 recipients per day and 30 messages per minute on client submission.
For application volume the alternative is a submission service authenticating as your own verified domain, reached either over SMTP with issued credentials or through an HTTP API. Nitrosend's integration surface is a REST API, an MCP server, a CLI and a typed Node SDK, @nitrosend/sdk, so integration there is a package install or an ordinary HTTP request.
There is one official package for Node and TypeScript, and it is the exception to the REST-only rule that applies to every other language. It is fully typed, ships with zero runtime dependencies, and requires Node 18 or later.
Zero dependencies is a deliberate property rather than a boast. An email SDK sitting in a dependency tree with a dozen transitive packages is a supply-chain surface attached to a credential that can send as your domain, so the smaller that surface the better.
Most consequential is the split between server and browser entry points. The main export is a server SDK for Node, edge functions or any backend, and it takes a secret key with full account access. The package also publishes a separate browser entry, and the distinction is not cosmetic: a secret key must never reach a browser bundle, and having two entry points is what makes that boundary explicit rather than a matter of discipline.
Worth knowing that raw HTTP is still a first-class option. Our own REST guide's JavaScript examples use plain fetch, and there is nothing second-class about that: the package calls the same API, and the same key authenticates both, so the choice is about typing convenience rather than capability.
None of that split, the typed errors, the zero dependencies, is really the point. The point is you don't have to write any of it. Tell Claude, Cursor, or Codex to send the email, and our MCP server composes it, picks the transport, and sends, with you approving before anything leaves. Email marketing is moving from developers wiring up SDKs to agents doing the wiring, and Nitrosend is the option built for that shift, which is why we're a listed plugin in ChatGPT's plugin directory rather than just another package on npm.
Every plan includes full stack emailing: Flows, Newsletter Campaigns and Transactional Email, plus our NitroWheel LLM and all agent integrations (Claude, ChatGPT, Codex, Cursor and others). Pay for what you send, not who you store.
Every paid plan includes 3 agent inboxes and no Nitrosend footer.
For your first email program.
$192 billed yearly.
20,000 emails / month
Choose StarterFor a growing audience.
$480 billed yearly.
60,000 emails / month
Choose ProFor teams and agencies.
$1,440 billed yearly.
200,000 emails / month
Choose GrowthFor high-volume sending.
$2,880 billed yearly.
500,000 emails / month
Choose ScaleSending 500,000+ emails a month? Get a custom plan designed for you, with volume email pricing and capacity that fits your business.
5,000 emails to start, then 500 emails every month. No expiry on your starter emails.
Daily allowances depend on your plan and sender standing. Strong list, domain and delivery evidence can raise standing, including on day one. Trusted receives the full plan allowance; available email credits, safety checks and delivery pacing still apply.
Free forever. No credit card required. See full comparison →