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.
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 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.
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. See the DNS a sending domain needs.
Through the API
Get a key from Connected apps 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.
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 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:
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 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:
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.
Testing without emailing anyone
Send to the test addresses. They work over SMTP and the API alike, and never reach a real inbox.