# Warmbox Self-hosted email warmup and deliverability engine for custom domains. Uses SMTP to send realistic B2B conversations and IMAP to rescue messages from spam folders, flag them as important, and reply — improving sender reputation over time. ## Tech Stack - **Runtime:** Node.js + TypeScript + Express - **Database:** SQLite via Prisma ORM - **Email:** nodemailer (SMTP), imapflow (IMAP) - **AI:** OpenRouter (free models) for conversation generation - **Scheduler:** node-cron ## Quick Start ### 1. Install dependencies ```bash npm install ``` ### 2. Configure environment ```bash cp .env.example .env ``` Generate an encryption key: ```bash openssl rand -hex 32 ``` Set these in `.env`: | Variable | Description | | ---------------- | --------------------------------------------------------------------------- | | `DATABASE_URL` | SQLite path, e.g. `file:./prisma/dev.db` (configured in `prisma.config.ts`) | | `ENCRYPTION_KEY` | 64-char hex string (32 bytes) for AES-256-GCM password encryption | | `AI_API_KEY` | API key from [OpenRouter](https://openrouter.ai/keys) (free tier works) | | `AI_BASE_URL` | Default `https://openrouter.ai/api/v1` | | `AI_MODEL` | Default `openrouter/free` (auto-picks a free model) | | `API_KEY` | Optional API key for REST auth (`x-api-key` header) | | `PORT` | HTTP port (default `3000`) | ### Get a free AI API key (OpenRouter) Email generation only needs a small, fast language model — not GPT-4 class reasoning. 1. Sign up at [openrouter.ai](https://openrouter.ai/) 2. Go to [openrouter.ai/keys](https://openrouter.ai/keys) and create an API key 3. Paste it into `.env` as `AI_API_KEY` **Recommended free models** (set `AI_MODEL` in `.env`): | Model | Notes | | --------------------------------------- | ---------------------------------------------- | | `openrouter/free` | Auto-selects an available free model (default) | | `google/gemma-2-9b-it:free` | Good quality, reliable JSON | | `meta-llama/llama-3.2-3b-instruct:free` | Fast, lightweight | You do **not** need an OpenAI account. ### 3. Run database migrations ```bash npm run db:migrate ``` ### 4. Start the server ```bash npm run dev ``` The API and cron jobs start together. Default schedules: - **Dispatcher:** every 15 minutes — sends warmup emails - **Rescuer:** every 10 minutes — rescues spam, replies to inbox - **Ramp:** midnight daily — increases `currentRamp` per inbox ### 5. Add mailboxes You need **at least 2 active inboxes** for warmup to work. Warmbox randomly pairs senders and receivers from your pool. #### SMTP/IMAP settings by provider Every inbox needs **4 connection fields** plus credentials: | Field | What it is | | ----------------------- | ---------------------------------------------- | | `smtpHost` / `smtpPort` | Where to **send** mail | | `imapHost` / `imapPort` | Where to **read** mail (spam rescue + replies) | | `username` | Usually the full email address | | `password` | **App password** (not your login password) | ##### Gmail (including Google Workspace custom domains) If `hello@fillcareapp.com` is hosted on **Google Workspace**, use Gmail servers: | Field | Value | | ---------- | ---------------- | | `smtpHost` | `smtp.gmail.com` | | `smtpPort` | `587` | | `imapHost` | `imap.gmail.com` | | `imapPort` | `993` | **App password setup:** 1. Enable 2-Step Verification on the Google account 2. Go to [myaccount.google.com/apppasswords](https://myaccount.google.com/apppasswords) 3. Create an app password for "Mail" → copy the 16-character code 4. Use that code as `password` in Warmbox ##### Yahoo Mail | Field | Value | | ---------- | --------------------- | | `smtpHost` | `smtp.mail.yahoo.com` | | `smtpPort` | `587` | | `imapHost` | `imap.mail.yahoo.com` | | `imapPort` | `993` | App password: [Yahoo Account Security](https://login.yahoo.com/account/security) → Generate app password. ##### Outlook / Hotmail / Live.com (@live.com, @outlook.com, @hotmail.com) | Field | Value | | ---------- | ----------------------- | | `smtpHost` | `smtp-mail.outlook.com` | | `smtpPort` | `587` | | `imapHost` | `outlook.office365.com` | | `imapPort` | `993` | App password: [Microsoft Account Security](https://account.microsoft.com/security) → Advanced security → App passwords. IMAP must be enabled in Outlook settings. ##### Custom domain (cPanel / generic hosting) If `hello@fillcareapp.com` is on cPanel or similar (not Google/Microsoft), check your host's email docs. Common pattern: | Field | Value | | ---------- | ------------------------------------------------ | | `smtpHost` | `mail.fillcareapp.com` or `smtp.fillcareapp.com` | | `smtpPort` | `587` (or `465` for SSL) | | `imapHost` | `mail.fillcareapp.com` or `imap.fillcareapp.com` | | `imapPort` | `993` | Ask your DNS/hosting provider if unsure — look for "IMAP/SMTP settings" in cPanel → Email Accounts. #### Example: FillCare + personal accounts Add `hello@fillcareapp.com` as your primary warmup domain (industry: `Childcare`), then add 4–5 Gmail/Yahoo/Live accounts as the reply pool. **1. Primary domain (FillCare)** ```bash curl -X POST http://localhost:3000/api/inboxes \ -H "Content-Type: application/json" \ -d '{ "email": "hello@fillcareapp.com", "smtpHost": "smtp.gmail.com", "smtpPort": 587, "imapHost": "imap.gmail.com", "imapPort": 993, "username": "hello@fillcareapp.com", "password": "hkem mfmi bkmg bqyw", "industry": "Childcare", "dailyLimit": 40, "currentRamp": 5 }' ``` > If FillCare email is **not** on Google Workspace, swap `smtpHost`/`imapHost` to your host's values (see table above). **2. Gmail account** ```bash curl -X POST http://localhost:3000/api/inboxes \ -H "Content-Type: application/json" \ -d '{ "email": "you@gmail.com", "smtpHost": "smtp.gmail.com", "smtpPort": 587, "imapHost": "imap.gmail.com", "imapPort": 993, "username": "you@gmail.com", "password": "your-gmail-app-password", "industry": "SaaS" }' ``` **3. Yahoo account** ```bash curl -X POST http://localhost:3000/api/inboxes \ -H "Content-Type: application/json" \ -d '{ "email": "you@yahoo.com", "smtpHost": "smtp.mail.yahoo.com", "smtpPort": 587, "imapHost": "imap.mail.yahoo.com", "imapPort": 993, "username": "you@yahoo.com", "password": "your-yahoo-app-password", "industry": "Marketing" }' ``` **4. Live.com / Outlook account** ```bash curl -X POST http://localhost:3000/api/inboxes \ -H "Content-Type: application/json" \ -d '{ "email": "you@live.com", "smtpHost": "smtp-mail.outlook.com", "smtpPort": 587, "imapHost": "outlook.office365.com", "imapPort": 993, "username": "you@live.com", "password": "your-microsoft-app-password", "industry": "Finance" }' ``` Repeat for each additional Gmail/Yahoo/Live account. Mixing providers is fine — Warmbox only needs them all in the same pool. ### 6. Test connections After adding each inbox, verify SMTP + IMAP: ```bash curl -X POST http://localhost:3000/api/inboxes/{id}/test ``` A successful response looks like: ```json { "ok": true, "smtp": { "ok": true }, "imap": { "ok": true } } ``` If either fails, double-check the app password and that IMAP is enabled on the account. ### 7. Monitor logs ```bash curl http://localhost:3000/api/logs ``` Watch for status progression: `sent` → `rescued_from_spam` → `replied` → `complete`. ## API Reference All endpoints under `/api` accept optional `x-api-key` header when `API_KEY` is set. | Method | Path | Description | | -------- | ----------------------- | --------------------------------------------------- | | `POST` | `/api/inboxes` | Create inbox | | `GET` | `/api/inboxes` | List inboxes | | `GET` | `/api/inboxes/:id` | Get inbox | | `PATCH` | `/api/inboxes/:id` | Update inbox | | `DELETE` | `/api/inboxes/:id` | Delete inbox | | `POST` | `/api/inboxes/:id/test` | Test SMTP + IMAP | | `GET` | `/api/logs` | List warmup logs (`?status=&inboxId=&page=&limit=`) | | `GET` | `/api/settings` | Get settings | | `PATCH` | `/api/settings` | Update settings | | `GET` | `/health` | Health check | ## Project Structure ``` src/ ├── config.ts # Environment validation ├── index.ts # Express + scheduler bootstrap ├── jobs/ │ ├── dispatcher.job.ts # Sends warmup emails │ ├── rescuer.job.ts # Spam rescue + replies │ └── scheduler.ts # Cron wiring ├── lib/ # Prisma, logger, inbox guard ├── middleware/ # Auth, error handling ├── models/ # Enums, types ├── routes/ # REST endpoints └── services/ ├── ai.service.ts # OpenRouter conversation generator ├── crypto.service.ts # AES-256-GCM encryption ├── email.service.ts # SMTP via nodemailer ├── imap.service.ts # IMAP via imapflow └── settings.service.ts prisma/ └── schema.prisma # Database schema ``` ## How It Works 1. **Dispatcher** picks random sender/receiver pairs from active inboxes, generates a B2B email via AI, and sends via SMTP. 2. **Rescuer** scans spam folders (`[Gmail]/Spam`, `Junk`, `Spam`) for warmup emails, moves them to INBOX, flags them as read/starred/important. 3. **Rescuer** also processes unread warmup emails already in INBOX, generates contextual AI replies, and sends them back. 4. Failed IMAP/SMTP connections mark the inbox as `error` and skip it until credentials are fixed. ## Production ```bash npm run build npm start ``` Use a process manager (systemd, PM2) and back up the SQLite database file regularly. ## License MIT