Mailing Service Setup
Learn how to set up, configure, and run the Reloop mailing service locally.
The Mailing Service is an ElysiaJS microservice that handles bulk outbound campaign dispatching, job queuing, and campaign delivery logic. It authenticates sending requests, compiles custom templates with recipient metadata, injects tracking links, and feeds the outbound queues.
Before starting the Mailing Service, make sure you've completed the base Local Development Setup (installed Bun, configured the hosts file, and started the Docker container stack).
Quick Start
Dependencies are handled globally at the root directory. You can start the Mailing Service development server instantly:
# Start the dev server with hot reloading
bun be:mailing:dev
cd apps/backend/mailing
bun dev
Once running, the Mailing Service will listen locally on port 8015. You can query it via Caddy at https://local.reloop.sh/api/mail 🎉
Service Information
- Directory Location:
apps/backend/mailing/ - Local Listening Port:
8015(ElysiaJS gateway) - Unified Access Route: https://local.reloop.sh/api/mail
- Primary Tech Stack: ElysiaJS, PostgreSQL, Redis, NATS, BullMQ
- Dependencies: Relies on PostgreSQL (to fetch campaigns), Redis (for job queues & rate limiting), NATS (for event streams), and Kumomta (MTA engine at http://localhost:8020).
Environment Configuration
The Mailing Service environment variables are defined in apps/backend/mailing/.env. If you ran bun env:setup at the root, your .env is already configured:
# Database & Cache Configurations
PG_URL=postgresql://reloop:reloop123@localhost:5432/reloop
REDIS_URL=redis://:reloop123@localhost:6379
# Server Gateway Configuration
PORT=8015
BASE_URL="https://local.reloop.sh"
NODE_ENV=development
# Event Bus Broker
NATS_URL=nats://localhost:4222
# MTA Engine Connection
KUMOMTA_HTTP_URL=http://localhost:8020
Reference Table
| Variable | Required | Default Value | Description |
|---|---|---|---|
PG_URL | YES | postgresql://... | PostgreSQL database connection string. |
REDIS_URL | YES | redis://... | Redis cache and queue manager connection URL. |
PORT | YES | 8015 | Local port number the Elysia app listens to on the host. |
BASE_URL | YES | https://local.reloop.sh | Main application domain (used for cookie validations). |
NATS_URL | YES | nats://localhost:4222 | Connection URL for NATS event bus messaging. |
KUMOMTA_HTTP_URL | YES | http://localhost:8020 | HTTP URL of the local Kumomta SMTP engine. |
NODE_ENV | YES | development | Active environment scope (development or production). |
Development Commands
All workspace operations should be executed from the monorepo root directory using Turborepo filters:
| Command | Action | Scope |
|---|---|---|
bun be:mailing:dev | Start the Mailing dev server with hot reloading | Development |
bun run --filter=mailing build | Compile the Mailing service for production | Production |
bun run --filter=mailing start | Run the compiled production build locally | Production |
bun run --filter=mailing check-types | Verify TypeScript type-safety | Code Quality |
Database & Queue Schemas
Mailing Service acts as the transactional sending pipeline, orchestrating relational tables from packages/db/src/schema/email.ts alongside high-throughput Redis job queues.
Relational Tables Utilized
email_log: Records outbound mail logs, status checks, recipients, cc/bcc fields, priority constraints, and physical sizes (see Email Service Schema).template: Reads visual HTML layout blueprints compiled by developers or customers (see Template Service Schema).
Redis BullMQ Job Queues
Background queue scheduling handles async dispatches, rate limiting, and retries.
| Queue Name | Job Payload | Processing Behavior |
|---|---|---|
mail-queue | { logId: string, recipient: string } | Fetches email_log, compiles HTML templates, verifies domains, and delivers via MTA servers. |
mail-retry-queue | { logId: string, retryAttempt: number } | Holds soft-bounced logs under exponential backoff waiting for retry periods. |
analytics-queue | { event: string, metadata: object } | Buffers real-time delivery and click tracking events to ClickHouse. |
Interactive API Docs (Swagger)
The Mailing Service publishes dynamic Swagger documentation directly from ElysiaJS. To test endpoints and query API structures:
- Open your browser and navigate to the interactive Swagger playground at https://local.reloop.sh/api/mail/openapi (or http://localhost:8015/api/mail/openapi directly).
- Use the interactive Swagger UI playground to run queries and inspect request schemas.
Core Operational Flow
- Authentication: Incoming requests to send campaign emails are validated using developer API keys or active dashboard user sessions.
- Template Compilation: Merges recipient custom tags (e.g.
{{ first_name }}) with templates using the@reloop/uilayouts. - Link & Click Injection: Outbound HTML is modified to inject tracking pixels and secure redirect links wrapping active hyperlinks (redirecting clicks back to
https://local.reloop.sh/api/mail/click). - BullMQ Queue Management: Outbound campaigns are segmented into individual jobs and pushed to BullMQ queues inside Redis to balance system load.
- MTA Dispatch: The job queue worker pops active mail targets and dispatches compiled tracked payloads to Kumomta (
http://localhost:8020) for SMTP delivery.