Skip to content

Send email from Express

  1. Install the SDK

    Terminal window
    npm install vaartix

    Keep your key in an environment variable, for example in .env loaded with node --env-file=.env server.js:

    .env
    VAARTIX_API_KEY=vx_live_...
  2. Send an email from a route

    server.js
    import express from 'express';
    import { Vaartix } from 'vaartix';
    const app = express();
    const vaartix = new Vaartix(); // reads VAARTIX_API_KEY
    app.post('/orders/:id/confirm', express.json(), async (req, res) => {
    const { data, error } = await vaartix.emails.send(
    {
    from: 'Acme <[email protected]>',
    to: req.body.email,
    subject: `Order ${req.params.id} is confirmed`,
    html: `<p>Thanks! We'll ship order <strong>${req.params.id}</strong> soon.</p>`,
    },
    // Retrying the request won't send the email twice.
    { idempotencyKey: `order-confirmed-${req.params.id}` },
    );
    if (error) return res.status(error.statusCode ?? 500).json({ error: error.message });
    res.json({ emailId: data.id });
    });
    app.listen(3000);

    The SDK never throws for API or network errors: check error. Its type tells you what went wrong (see Errors).

Until your domain is verified, send from @test.vaartix.com to [email protected]: see Test mode.

Signatures are checked against the exact bytes Vaartix sent, so use express.raw() on the webhook route instead of express.json():

server.js
import { verifyWebhook, WebhookVerificationError } from 'vaartix';
app.post('/webhooks/vaartix', express.raw({ type: 'application/json' }), (req, res) => {
let event;
try {
event = verifyWebhook({
payload: req.body, // a Buffer
headers: req.headers,
secret: process.env.VAARTIX_WEBHOOK_SECRET,
});
} catch (err) {
if (err instanceof WebhookVerificationError) return res.sendStatus(400);
throw err;
}
switch (event.type) {
case 'email.bounced':
case 'email.complained':
// Stop emailing event.data.recipient
break;
case 'email.delivered':
// Mark it delivered in your database
break;
}
res.sendStatus(200);
});

If app.use(express.json()) is registered for the whole app, register the webhook route before it, or the body arrives already parsed and the signature check fails.