Send email with NestJS
A provider you inject, so the key stays in configuration and out of the controllers.
You need a verified sending domain and an API key from Settings › API Keys. If neither exists yet, the quickstart covers both in a couple of minutes.
Install
npm i sending-sdkSend
import { Injectable } from "@nestjs/common";
import { ConfigService } from "@nestjs/config";
import { Sending } from "sending-sdk";
@Injectable()
export class EmailService {
private readonly client: Sending;
constructor(config: ConfigService) {
this.client = new Sending({ apiKey: config.getOrThrow<string>("SENDING_API_KEY") });
}
welcome(to: string, userId: string) {
return this.client.emails.send({
from: "Acme <[email protected]>",
to,
subject: "Welcome",
html: "<p>You're in.</p>",
idempotencyKey: `welcome-${userId}`,
});
}
}A successful call answers 202 with the message id: accepted and queued, not yet delivered. Delivery, opens, bounces and complaints arrive later, on webhooks or in the dashboard.
What changes in NestJS
One provider, injected where it is needed. getOrThrow fails at boot when the key is missing, which is far better than discovering it on the first signup.
The thing that catches people
For webhooks, register the raw body in main.ts (bodyParser: false plus express.raw on that path) or the signature check will never pass.
Next
- All the fields: cc and bcc, reply-to, attachments, templates, scheduling.
- Webhooks: delivery, bounce and complaint events, signed with HMAC.
- Domains: SPF, DKIM and MAIL FROM, and why sending is refused until they are in place.
- MCP: the same operations as tools, when the one writing the code is an agent.