Mailchimp / Mandrill Module
Overview
The Mailchimp module provides transactional email capabilities via Mandrill (Mailchimp's transactional email API). It supports two sending modes:
- Template emails — Uses pre-built Mandrill templates with dynamic merge variables
- Plain text emails — Sends raw text content
Architecture
The module follows hexagonal architecture with clear layer separation:
mailchimp/
├── domain/
│ ├── mandrill-email.port.ts # Port interface (MandrillEmailPort)
│ └── mandrill.types.ts # Framework-agnostic types
├── application/
│ └── mandrill.service.ts # Use case orchestration
├── infrastructure/
│ ├── mailchimp.providers.ts # SDK client factory + port binding
│ └── mandrill-email.adapter.ts # SDK implementation of MandrillEmailPort
├── interfaces/
│ └── mandrill-event.handler.ts # Event listener (driving adapter)
└── mailchimp.module.ts # NestJS module definition
Dependency Flow
interfaces/ → application/ → domain/ ← infrastructure/
(events) (service) (port) (SDK adapter)
- Domain defines the
MandrillEmailPortcontract and framework-agnostic types - Application (
MandrillService) orchestrates via the port — no SDK dependency - Infrastructure (
MandrillEmailAdapter) implements the port using the Mandrill SDK - Interfaces (
MandrillEventHandler) listens for events and delegates to the service
Integration
Event-Driven (Internal)
Other modules can trigger emails by emitting events:
import { MandrillEvents } from "@flowpos-workspace/global/enums/mailchimp.enums";
// Template email
this.eventEmitter.emit(MandrillEvents.SendTransactionEmailTemplate, {
templateId: "welcome-email",
to: [{ email: "user@example.com", name: "John" }],
subject: "Welcome!",
data: { firstName: "John", businessName: "Acme" },
});
// Plain text email
this.eventEmitter.emit(MandrillEvents.SendTransactionEmailPlain, {
to: [{ email: "user@example.com" }],
subject: "Reset code",
content: "Your code is 123456",
});
Direct Injection
Import MailchimpModule and inject MandrillService:
@Module({ imports: [MailchimpModule] })
export class MyModule {}
@Injectable()
export class MyService {
constructor(private readonly mandrillService: MandrillService) {}
async notify() {
await this.mandrillService.sendTemplateEmail({
templateId: "order-confirmation",
to: [{ email: "customer@example.com" }],
subject: "Order Confirmed",
data: { orderId: "12345" },
});
}
}
Configuration
| Environment Variable | Required | Description |
|---|---|---|
MANDRILL_API_KEY | Yes | Mandrill API key for transactional emails |
Relationship to Communications Module
The communications module uses SendGrid as the primary email provider via EmailAdapterService. The Mandrill module exists as a separate transactional email channel — it is not part of the multi-channel communications pipeline.
Use Mandrill for:
- System-level transactional emails (invites, password resets, alerts)
- Template-driven emails managed in the Mandrill dashboard
Use Communications/SendGrid for:
- Business-initiated customer communications
- Multi-channel (email + SMS + WhatsApp) workflows
- Communications with tracking, queuing, and retry logic