Custom domain email hosting for $2/month. IMAP/SMTP, works with any email client.
Status: In development — following the execution plan in
TASKS.md.
docs/PLAN.md— Full project plan (Sections 1–22)TASKS.md— Sequential execution task list
plainmail/
├── src/ # Node.js/Express backend
│ ├── lib/ # Utilities (jwt, password, dkim, dns, audit)
│ ├── middleware/ # Express middleware (auth, admin, error-handler)
│ ├── services/ # MailcowService, StripeService, EmailService
│ ├── workers/ # BullMQ workers (dns-verification, dunning, cleanup)
│ ├── routes/ # Express route handlers
│ └── __mocks__/ # Mailcow stub server for local dev
├── client/ # React/Vite frontend
│ ├── src/
│ │ ├── pages/ # Route-level page components
│ │ ├── components/ # Reusable UI components
│ │ ├── context/ # React context (AuthContext)
│ │ ├── hooks/ # Custom hooks (useAuth, etc.)
│ │ └── lib/ # Utilities (analytics, plausible, api client)
├── prisma/ # Prisma schema and migrations
│ ├── schema.prisma
│ ├── migrations/
│ └── seed.ts
├── scripts/ # Deployment and maintenance scripts
├── keys/ # JWT RSA keys (gitignored — see keys/.gitkeep)
├── .github/workflows/ # CI/CD GitHub Actions
├── docs/ # Project documentation
│ └── PLAN.md
├── TASKS.md # Execution task list
├── .env.example # Environment variable template
└── docker-compose.dev.yml
# 1. Clone the repo
git clone git@github.com:<username>/plainmail.git
cd plainmail
# 2. Set up environment
cp .env.example .env.local
cp client/.env.example client/.env.local
# Edit .env.local with your values
# 3. Generate JWT keys
mkdir -p keys
openssl genrsa -out keys/jwt-private.pem 2048
openssl rsa -in keys/jwt-private.pem -pubout -out keys/jwt-public.pem
# 4. Start dev infrastructure (Postgres, Redis, Mailcow stub)
npm run dev:infra
# 5. Run database migrations and seed
npm run db:migrate
npm run db:seed
# 6. Start the backend
npm run dev
# 7. In a new terminal, start the workers
npm run dev:workers
# 8. In a new terminal, start the frontend
cd client && npm run dev- Backend: Node.js, Express, TypeScript, Prisma, BullMQ
- Frontend: React, Vite, TypeScript, React Router
- Mail Infrastructure: Mailcow (Postfix + Dovecot + Rspamd)
- Database: PostgreSQL 16, Redis 7
- Billing: Stripe
- Transactional Email: Resend
- Analytics: Plausible (marketing site), PostHog (in-app)
- Hosting: Hetzner Cloud