Sending Emails with Node.js and PostaSend. A Complete Guide
This guide covers four email flows you will need in any production Node.js application: welcome emails on signup, OTP delivery for authentication, invoice emails with PDF attachments, and a webhook listener that keeps your database in sync with email delivery events. By the end, you will have a complete email layer that handles the common cases cleanly and gives you the observability to debug the edge cases.
Start with npm install postasend and initialize a single shared client in a lib/email.ts module using your POSTASEND_API_KEY environment variable. Sharing one client instance across your application avoids repeated initialization overhead and makes the client easy to mock in tests. For welcome emails and OTPs, the send call is straightforward, from your verified domain, to the user's address, with an html body. Store the returned messageId against the user record so you have an audit trail for support tickets.
Invoice attachments require one additional field: an attachments array where each item has a filename, a contentType, and a content field containing the base64-encoded file. Read the PDF buffer with fs.readFileSync and call .toString('base64') on it before passing it in. PostaSend accepts up to 25 MB of attachments per message. For larger files, include a download link in the email body instead.
The webhook listener is where your integration goes from good to production-grade. Create an endpoint in your Express or Next.js app that receives POST requests from PostaSend, verifies the HMAC-SHA256 signature using your webhook secret, and updates your database based on the event type. The events you care most about are email.delivered (mark the record as sent), email.bounced (flag the address, stop sending to it), and email.complained (immediately suppress and investigate). With these four flows in place, your email layer handles the full lifecycle of every message your application sends.