Sign inGet Started

Node.js SDK

Send email with AdonisJS

Use Parcel Wing from AdonisJS services and controllers while keeping secrets in server environment variables.

Install the SDK

The official SDK is published as @parcelwing/node.

Terminal

npm install @parcelwing/node

Environment

Add the Parcel Wing API key and default sender to your AdonisJS environment variables.

.env

PARCEL_WING_API_KEY=pw_live_...
PARCEL_WING_FROM_EMAIL="Acme <[email protected]>"

Mail service

Wrap the SDK in an application service so controllers do not duplicate sending logic.

app/services/mail_service.ts

import env from "#start/env";
import { ParcelWing, ParcelWingError } from "@parcelwing/node";
 
export default class MailService {
private parcelWing = new ParcelWing({
apiKey: env.get("PARCEL_WING_API_KEY"),
});
 
async sendWelcomeEmail(email: string, firstName = "friend") {
try {
const [message] = await this.parcelWing.emails.send({
from: env.get("PARCEL_WING_FROM_EMAIL"),
to: email,
template_alias: "welcome_email",
template_params: {
first_name: firstName,
},
});
 
return message;
} catch (error) {
if (error instanceof ParcelWingError) {
error.message =
"Parcel Wing request " +
(error.requestId ?? "unknown") +
" failed";
}
 
throw error;
}
}
}

Controller

Call your mail service from a controller after request validation and authorization.

app/controllers/emails_controller.ts

import type { HttpContext } from "@adonisjs/core/http";
import MailService from "#services/mail_service";
 
export default class EmailsController {
async sendWelcome({ request, response }: HttpContext) {
const payload = request.only(["email", "firstName"]);
const mail = new MailService();
 
const message = await mail.sendWelcomeEmail(
payload.email,
payload.firstName,
);
 
return response.ok({ id: message?.id });
}
}

Routes

Expose the controller through an AdonisJS route when the browser or another service needs to trigger the email.

start/routes.ts

import router from "@adonisjs/core/services/router";
 
const EmailsController = () => import("#controllers/emails_controller");
 
router.post("/emails/welcome", [EmailsController, "sendWelcome"]);

Production notes

  • Store PARCEL_WING_API_KEY only in trusted server environments.
  • Validate request payloads before sending with the SDK.
  • Use templates for repeatable lifecycle emails such as invites, onboarding, and receipts.