Skip to main content

Built-in HTTP Mailer

node-auth ships a built-in HTTP mailer transport (MailerService) that sends transactional emails by posting JSON payloads to any HTTP email relay โ€” Mailgun, SendGrid, Brevo, Postmark, or a custom gateway.

No SMTP setup needed. Point it at your relay's endpoint, set an API key, and every auth email (password reset, magic link, welcome, email verification, email-changed notification) is sent automatically using built-in bilingual (๐Ÿ‡ฌ๐Ÿ‡ง English / ๐Ÿ‡ฎ๐Ÿ‡น Italian) templates.


How it worksโ€‹


Configurationโ€‹

import { AuthConfigurator } from '@nik2208/node-auth';

const auth = new AuthConfigurator({
accessTokenSecret: process.env.ACCESS_TOKEN_SECRET!,
refreshTokenSecret: process.env.REFRESH_TOKEN_SECRET!,

email: {
// Single URL (classic, works as before)
siteUrl: 'https://yourapp.com',

// โ€” OR โ€” array of allowed front-end origins (dynamic mode).
// For email links the FIRST entry is used as the base URL.
// For OAuth redirects the URL is resolved dynamically from the request
// Origin/Referer header (see CORS & Dynamic siteUrl guide).
// siteUrl: ['https://app.example.com', 'https://admin.example.com'],

mailer: {
endpoint: process.env.MAILER_ENDPOINT!, // e.g. https://api.brevo.com/v3/smtp/email
apiKey: process.env.MAILER_API_KEY!,
from: 'no-reply@yourapp.com',
fromName: 'Your App', // optional sender display name
provider: 'brevo', // optional โ€” forwarded to the relay as-is
defaultLang: 'en', // 'en' (default) | 'it'
},
},
}, userStore);

MailerConfig referenceโ€‹

FieldTypeRequiredDescription
endpointstringโœ…Full URL of the HTTP relay (POST target)
apiKeystringโœ…Sent as X-API-Key header
fromstringโœ…Sender email address
fromNamestringโŒSender display name
providerstringโŒForwarded to relay as provider field
defaultLang'en' | 'it'โŒDefault template language (default: 'en')

Request body sent to the relayโ€‹

{
"to": "user@example.com",
"subject": "Reset your password",
"html": "<p>Click <a href=\"โ€ฆ\">here</a> to resetโ€ฆ</p>",
"text": "Click here to reset: https://โ€ฆ",
"from": "no-reply@yourapp.com",
"fromName": "Your App",
"provider": "brevo"
}

The relay receives a standard POST with Content-Type: application/json and X-API-Key header. Adapt to your provider's format in the relay if needed.


Per-request language overrideโ€‹

Users can request a specific email language by including emailLang in the request body:

curl -X POST /auth/forgot-password \
-H 'Content-Type: application/json' \
-d '{"email":"user@example.com","emailLang":"it"}'

Supported values: 'en', 'it'.


Built-in email templatesโ€‹

TriggerMethodTemplate (en)Template (it)
POST /auth/forgot-passwordsendPasswordReset"Reset your password""Reimposta la tua password"
POST /auth/magic-link/sendsendMagicLink"Your magic sign-in link""Il tuo link di accesso"
POST /auth/registersendWelcome"Welcome! Your account has been created""Benvenuto! Il tuo account รจ stato creato"
POST /auth/send-verification-emailsendVerificationEmail"Verify your email address""Verifica il tuo indirizzo email"
POST /auth/change-email/confirmsendEmailChanged"Your email address has been updated""Il tuo indirizzo email รจ stato aggiornato"

Custom callback overridesโ€‹

If you prefer to send emails yourself (e.g. with a custom template engine), use the callback overrides in AuthConfig.email. Callbacks always take priority over the mailer transport:

const auth = new AuthConfigurator({
email: {
siteUrl: 'https://yourapp.com',

// Override: custom password-reset email
sendPasswordReset: async (to, token, link, lang) => {
await myMailer.send({
to,
subject: 'Reset your password',
html: myTemplateEngine.render('password-reset', { link, lang }),
});
},

// Override: custom magic-link email
sendMagicLink: async (to, token, link, lang) => {
await myMailer.send({ to, subject: 'Your login link', html: `<a href="${link}">Sign in</a>` });
},

// Override: welcome email (e.g. after admin creates user via admin panel)
sendWelcome: async (to, data, lang) => {
await myMailer.send({ to, subject: 'Welcome', html: myTemplateEngine.render('welcome', data) });
},

// Override: email verification
sendVerificationEmail: async (to, token, link, lang) => {
await myMailer.send({ to, subject: 'Verify your email', html: `<a href="${link}">Verify</a>` });
},

// Override: email-changed notification
sendEmailChanged: async (to, newEmail, lang) => {
await myMailer.send({ to, subject: 'Email updated', html: `Your email is now ${newEmail}` });
},
},
}, userStore);

Using MailerService standaloneโ€‹

The MailerService class is exported and can be used directly in your own services:

import { MailerService } from '@nik2208/node-auth';

const mailer = new MailerService({
endpoint: 'https://api.brevo.com/v3/smtp/email',
apiKey: process.env.MAILER_API_KEY!,
from: 'no-reply@yourapp.com',
defaultLang: 'it',
});

// Send individual emails
await mailer.sendPasswordReset('user@example.com', token, 'https://app.com/reset?token=โ€ฆ');
await mailer.sendMagicLink('user@example.com', token, 'https://app.com/verify?token=โ€ฆ');
await mailer.sendWelcome('user@example.com', { loginUrl: 'https://app.com/login' });
await mailer.sendVerificationEmail('user@example.com', token, 'https://app.com/verify-email?token=โ€ฆ');
await mailer.sendEmailChanged('old@example.com', 'new@example.com');

The siteUrl field accepts either a single string or an array of strings. When you have multiple front-end origins (e.g. a public app and an admin panel) pass an array โ€” the first entry is used as the base URL for all email links.

email: {
// First entry is used for all email links (magic link, password reset, etc.)
siteUrl: ["https://app.example.com", "https://admin.example.com"],
mailer: { /* โ€ฆ */ },
}

For OAuth post-login redirects the URL is resolved dynamically from the Origin / Referer request header and validated against the same array. See CORS & Dynamic siteUrl for the complete guide.