# Sending from Node.js

> Send email through Reggio Digital from Node.js, with a plain fetch call to the API or with Nodemailer over SMTP.

Source: https://reggiodigital.com/developers/guides/node

From Node.js there are two ways to send through us.

- **Through the API** with `fetch`, which is built into Node 18 and later. No library to install, and you get a message id back, scheduling, batches, templates and a [lookup](https://reggiodigital.com/developers/email#checking-what-happened) for every message.
- **Over SMTP** with Nodemailer, if the application already uses it or a framework that sits on top of it. You change the transport and nothing else.

Both send from the business's own verified domain and show up on the account's [Sent page](https://reggiodigital.com/email/sent).

## Before you start

The from address has to be on a sending domain the account has verified. If the business has not added one yet, they do it under [Sending domains](https://reggiodigital.com/domains/sending). See [the DNS a sending domain needs](https://reggiodigital.com/developers/smtp#the-dns-a-sending-domain-needs).

## Through the API

Get a key from [Connected apps](https://reggiodigital.com/email/api/keys) with the `email:send` ability and give it to the process as `REGGIO_API_KEY`. Keep it on the server: never put it in code that runs in a browser, where anyone can read it.

```js
const response = await fetch("https://reggiodigital.com/api/v1/emails", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.REGGIO_API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
      "from": "hello@yourdomain.com",
      "to": [
          "success@simulator.amazonses.com"
      ],
      "subject": "Your receipt",
      "html": "<p>Thanks for your order.</p>",
      "text": "Thanks for your order.",
      "tags": {
          "kind": "receipt",
          "order": "1042"
      }
  }),
});

const body = await response.json();

if (!response.ok) {
  throw new Error(body.error.message);
}
```

A `202` with an `id` means we accepted it. Anything else carries an [error](https://reggiodigital.com/developers/conventions#errors) in the same shape every time, so one handler covers every call.

If the send happens inside something that retries, such as a queue worker, send an `Idempotency-Key` so a retry after a timeout never sends twice:

```js
const response = await fetch("https://reggiodigital.com/api/v1/emails", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.REGGIO_API_KEY}`,
    "Content-Type": "application/json",
    "Idempotency-Key": "receipt-1042",
  },
  body: JSON.stringify({
      "from": "hello@yourdomain.com",
      "to": [
          "success@simulator.amazonses.com"
      ],
      "subject": "Your receipt",
      "html": "<p>Thanks for your order.</p>",
      "text": "Thanks for your order.",
      "tags": {
          "kind": "receipt",
          "order": "1042"
      }
  }),
});

const body = await response.json();

if (!response.ok) {
  throw new Error(body.error.message);
}
```

## Over SMTP with Nodemailer

Open the domain under [Sending domains](https://reggiodigital.com/domains/sending) and choose to connect an app. Put the host, username and password it shows into the environment as `REGGIO_SMTP_HOST`, `REGGIO_SMTP_USERNAME` and `REGGIO_SMTP_PASSWORD`, then create one transporter and reuse it:

```js
import nodemailer from "nodemailer";

export const transporter = nodemailer.createTransport({
  host: process.env.REGGIO_SMTP_HOST,
  port: 587,
  secure: false,
  requireTLS: true,
  auth: {
    user: process.env.REGGIO_SMTP_USERNAME,
    pass: process.env.REGGIO_SMTP_PASSWORD,
  },
});

export async function sendReceipt(to) {
  return transporter.sendMail({
    from: "Your Shop <hello@yourdomain.com>",
    to,
    subject: "Your receipt",
    text: "Thanks for your order.",
    html: "<p>Thanks for your order.</p>",
  });
}
```

`secure: false` with `requireTLS: true` on port `587` is the combination our service expects: the connection starts in plain text and must upgrade to an encrypted one before anything is sent. `secure: true` expects encryption from the first byte and will time out on this port.

A display name in front of the address, as in `Your Shop <hello@yourdomain.com>`, is fine over SMTP. The address itself has to be on the domain the credentials were issued for.

`sendMail` resolving means we accepted the message, not that it arrived. To hear about deliveries and bounces, set up [webhooks](https://reggiodigital.com/developers/webhooks).

## Testing without emailing anyone

Send to the [test addresses](https://reggiodigital.com/developers/email#testing-without-emailing-anyone). They work over SMTP and the API alike, and never reach a real inbox.
