How to Do Email Sending with Nodemailer on Claude Code

In this article

To send emails with Nodemailer in Claude Code, install the package, describe your SMTP configuration in plain English, and let Claude scaffold the transporter, message options, and send logic for you. This workflow is ideal for Node.js and TypeScript developers wiring up transactional email — contact forms, password resets, notification systems — without switching tabs to read docs. Claude handles the boilerplate; you stay in flow.

  • Nodemailer is the most-used Node.js email library, with over 14 million weekly npm downloads.
  • Claude Code can generate a working transporter and sendMail call from a single natural-language prompt.
  • Credentials should always live in .env — Claude Code can create and manage that file for you too.

What is Nodemailer and why use it with Claude Code?

Nodemailer is a zero-dependency Node.js module for sending email via SMTP, SES, or other transports. It supports attachments, HTML bodies, embedded images, and OAuth2 authentication. It is the de-facto standard for transactional email in the Node ecosystem.

Claude Code is Anthropic's agentic coding CLI that runs in your terminal. Instead of writing boilerplate from scratch, you describe what you need and Claude generates, edits, and runs the code inside your project. For an integration like Nodemailer — where the setup is repetitive but the details matter (ports, TLS flags, auth methods) — delegating to Claude saves meaningful time and avoids subtle misconfiguration bugs.

How to set up Nodemailer in your project with Claude Code

Step 1: install Nodemailer

Open your project in the terminal and launch Claude Code with claude. Then prompt it directly:

"Install nodemailer and its TypeScript types as dependencies in this project."

Claude will run npm install nodemailer (and @types/nodemailer for TypeScript projects) using its Bash tool, confirming the output before proceeding.

Step 2: create your .env file with SMTP credentials

Never hard-code credentials. Ask Claude to set up your environment variables:

"Create a .env file with placeholders for SMTP_HOST, SMTP_PORT, SMTP_USER, SMTP_PASS, and EMAIL_FROM. Add .env to .gitignore if it isn't already."

Claude will create both files correctly. For more detail on this pattern, see the guide on env file management on Claude Code.

Step 3: scaffold the transporter and send function

Prompt Claude to generate the core email module:

"Create a src/lib/mailer.ts file that exports a sendEmail function. Use nodemailer with an SMTP transporter configured from environment variables. The function should accept to, subject, and html parameters."

Claude will produce a typed, production-ready module. A typical result looks like this:

import nodemailer from 'nodemailer';

const transporter = nodemailer.createTransport({
  host: process.env.SMTP_HOST,
  port: Number(process.env.SMTP_PORT),
  secure: Number(process.env.SMTP_PORT) === 465,
  auth: {
    user: process.env.SMTP_USER,
    pass: process.env.SMTP_PASS,
  },
});

export async function sendEmail(to: string, subject: string, html: string) {
  return transporter.sendMail({
    from: process.env.EMAIL_FROM,
    to,
    subject,
    html,
  });
}

Step 4: test with a real send

Ask Claude to write a quick test script:

"Write a scripts/test-email.ts script that calls sendEmail with a test recipient and subject, then run it."

Claude will write the script and execute it via its Bash tool, capturing the Nodemailer response object so you can verify message IDs and acceptance. For Gmail, make sure you use an App Password rather than your main account password when 2FA is enabled.

Provider-specific configurations Claude Code handles well

ProviderSMTP HostPortNotes
Gmailsmtp.gmail.com587 (STARTTLS)Requires App Password with 2FA
SendGridsmtp.sendgrid.net587Use "apikey" as username, API key as password
Mailgunsmtp.mailgun.org587Domain must be verified in dashboard
AWS SESemail-smtp.us-east-1.amazonaws.com587SMTP credentials differ from IAM keys
Resendsmtp.resend.com465Modern provider, great deliverability

For any of these, tell Claude which provider you're using and it will fill in the correct host, port, and TLS settings automatically. If you're building Stripe-triggered emails (order confirmations, receipts), the Stripe payment integration guide pairs naturally with this workflow.

Useful prompts for common Nodemailer tasks

  • HTML templates: "Add a templates/welcome.html file and update sendEmail to accept an optional templateName that loads and injects variables into the HTML."
  • Attachments: "Update the sendEmail function to accept an optional attachments array compatible with Nodemailer's attachment format."
  • OAuth2 (Gmail): "Refactor the transporter to use OAuth2 authentication instead of username/password. Add the required env vars."
  • Queue with retry: "Wrap sendEmail in a retry function that attempts 3 times with exponential backoff on transient SMTP errors."
  • Integration test: "Set up Ethereal Email as a test account for CI so sendEmail works without real credentials in tests." (Ethereal is Nodemailer's official fake SMTP service.)

For building complete automated notification pipelines, see also the automated email reports guide and the guide on env variable management on Claude Code.

How Claude Code handles the back-and-forth

Nodemailer issues are often environmental: wrong port, TLS mismatch, credential format errors. Claude Code's agentic loop means it can read the error output from a failed send attempt and immediately suggest the fix — changing secure: true to false, switching ports from 465 to 587, or pointing you at the correct App Password setup page — without you having to paste errors back in manually.

This tight feedback loop is where Claude Code earns its place. The best Claude Code commands for developers guide covers the broader toolkit that makes this debugging flow possible.

Staying within your Claude Code usage limits

An integration like this typically takes 10-20 prompts across install, scaffold, debug, and test phases. That's a reasonable token budget, but if you hit it mid-session while a failing test is still open, you're locked out for up to 5 hours. Knowing exactly where you stand before you start a focused coding block is the difference between shipping and waiting.

You can check your current usage with the /usage command inside Claude Code, or visit claude.ai/settings/usage. For a passive, always-visible signal, Usagebar sits in your macOS menu bar and shows your live usage percentage with smart alerts at 50%, 75%, and 90%. Credentials are stored in macOS Keychain, and the tool is free for students. No context switching, no surprises.

Get Usagebar — instant download, pay what you want.

Key takeaways

  1. Install Nodemailer via Claude Code's Bash tool with a single natural-language prompt.
  2. Always store SMTP credentials in .env — ask Claude to scaffold the file and update .gitignore.
  3. Scaffold a typed sendEmail function in one prompt; Claude handles port and TLS configuration automatically.
  4. Use Ethereal Email for testing in CI without real credentials.
  5. For provider-specific quirks (App Passwords, OAuth2, SES SMTP vs IAM), describe the provider and let Claude generate the correct config.
  6. Monitor your Claude Code usage with /usage or Usagebar to avoid mid-session lockouts during integration work.

Sources

Never Get Locked Out Mid-Task Again

Never hit your usage limits unexpectedly. Usagebar lives in your menu bar and shows your 5-hour and weekly limits at a glance.

Get Usagebar

$9 — one-time, lifetime updates