Guides

Send email with Amazon SES from Node.js

Amazon SES is the cheapest way to send transactional email, and the Node.js SDK call itself is short. The friction is everything around it: a new SES account can only send to addresses you've personally verified until AWS approves a production-access request, and there's no REST API, webhook signing, or idempotency layer included — you build those yourself.

This guide shows the raw SES call, the sandbox limit you'll hit immediately, and the one-call alternative if you'd rather skip straight to a working API.

  1. 1.Install the SES v2 SDK

    Amazon SES's current SDK is the v2 client, `@aws-sdk/client-sesv2` — the same client Irisend's own SES provider is built on.

    npm install @aws-sdk/client-sesv2
  2. 2.Send a simple email

    `SendEmailCommand` takes a `FromEmailAddress`, a `Destination.ToAddresses` array, and a `Content.Simple` body with `Subject` and `Body.Html`/`Body.Text` — field names straight from AWS's own SES v2 API reference.

    import { SESv2Client, SendEmailCommand } from "@aws-sdk/client-sesv2";
    
    const ses = new SESv2Client({ region: "eu-west-1" });
    
    await ses.send(new SendEmailCommand({
      FromEmailAddress: "[email protected]",
      Destination: { ToAddresses: ["[email protected]"] },
      Content: {
        Simple: {
          Subject: { Data: "Your receipt" },
          Body: { Html: { Data: "<p>Thanks for your order.</p>" } },
        },
      },
    }));
  3. 3.Mind the SES sandbox

    Every new SES account starts in the sandbox: you can only send to addresses or domains you've personally verified in that AWS account, and you're capped at a low daily volume. Leaving the sandbox means filing a production-access request and waiting for AWS to approve it — a real, multi-day step most "send an email with SES" tutorials skip.

    Irisend's own SES provider has to handle exactly this: a sandboxed deployment rejects unverified recipients with a specific, actionable error instead of a raw AWS exception, because it's an operator problem the end customer needs to be told about plainly.

  4. 4.Or skip the SDK: one call, no sandbox wrangling

    Irisend's managed sending already runs on SES in production access, so there's no sandbox step on your side — verify your domain, then send with the same request shape Resend popularized.

    curl -X POST https://api.irisend.com/emails \
      -H "Authorization: Bearer $IRISEND_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{
        "from": "[email protected]",
        "to": "[email protected]",
        "subject": "Your receipt",
        "html": "<p>Thanks for your order.</p>"
      }'
  5. 5.Test sends without an inbox

    Local and CI runs default to `EMAIL_PROVIDER=log`, a sandbox provider that never leaves the server. Send to a magic local-part — `bounced@`, `complained@`, `delayed@`, `opened@`, `clicked@` — to simulate that event without any real mailbox.

    curl -X POST https://api.irisend.com/emails \
      -H "Authorization: Bearer ir_xxxx" -H "Content-Type: application/json" \
      -d '{"from":"[email protected]","to":"[email protected]","subject":"Test","html":"<p>Test</p>"}'

Related

Next

Read the full API reference, the Resend migration guide, or see pricing.