Autohospedado de Correo Corporativo
Una plataforma de correo corporativo multi-dominio y en producción real que reúne en un solo stack: servidor de correo (Postfix / Dovecot / Rspamd), panel de administración multi-rol, email transaccional, marketing y revendedores aislados con sus propios límites. Una alternativa funcional a Google Workspace / Microsoft 365, sin costos recurrentes por usuario.
Estado: ✅ Producción activa · Rol: Full-stack + DevOps + Sysadmin (creación individual) · Stack: Python / FastAPI / Docker / Postfix / Dovecot / Rspamd · Demo: https://correo.gilman.pro/demo
Tabla de Contenidos
- Pruébalo ahora
- Demo interactiva
- En acción (webmail y móvil)
- En cifras
- Logros clave
- Problema → Solución
- Arquitectura
- Stack tecnológico
- ¿Cómo funciona?
- Funcionalidades
- Seguridad
- Casos de uso
- Validación y resultados
- Problemas técnicos resueltos
- Próximos pasos
- Experiencias
🚀 Pruébalo ahora
| Vía | Cómo |
|---|---|
| Demo interactiva | https://correo.gilman.pro/demo — réplica navegable completa del panel (Admin + Revendedor) que funciona 100% en el navegador, sin registro ni credenciales |
| Evidencia en uso real | El sistema corriendo con SnappyMail (webmail) y BlueMail (Android) — sección 📸 En acción, justo después de la demo |
🎬 Demo interactiva
Una réplica navegable del panel de administración con datos de ejemplo realistas, para explorar el producto completo sin tocar el servidor real ni la base de datos.
- URL: https://correo.gilman.pro/demo
- Acceso: sin credenciales — abre la portada y elige Administrador Global o Revendedor
- 15+ pantallas navegables: 8 del admin (dashboard, buzones, revendedores, DNS, monitoreo, cola, logs, ajustes) y 7 del revendedor (dashboard, cuentas, aliases, DNS, transaccional, marketing, monitoreo)
- Totalmente funcional, no una maqueta: crea cuentas, aliases y revendedores; importa listas CSV; programa correos y vacía la cola — todo persiste en
localStorage - Datos de ejemplo incluidos: 12 cuentas en 3 dominios (gilman.pro, empresa.net, startup.io), 8 aliases, 2 revendedores con permisos diferentes, listas de marketing, correos programados, cola y logs
- Botón “Reset datos” para restaurar el estado inicial
- Misma estética del sistema real: Bootstrap 5.3 con tema oscuro premium
📸 En acción
El servidor expone protocolos estándar SMTP/IMAP, por lo que funciona con cualquier cliente de correo. Evidencia real del sistema en uso:
📬 SnappyMail — webmail por defecto

¿Qué es? Una aplicación de webmail en el navegador, ligera, moderna y de código abierto (escrita en PHP, sucesora de RainLoop). Es el webmail incluido por defecto en el sistema: corre en su propio contenedor Docker conectado al servidor de correo y se expone por navegador vía Nginx (puerto interno, solo loopback).
Para qué sirve: es el punto de acceso web para los usuarios finales — leen y escriben correo desde cualquier navegador, sin instalar nada. Equivale al “Gmail” de la plataforma: soporta IMAP/SMTP cifrado, es responsive (móvil y desktop) y consume muy poca RAM.
📱 BlueMail — cliente de correo en Android

¿Qué es? Una app de correo para móviles (Android/iOS) que unifica cuentas IMAP/SMTP. Es un cliente externo: no forma parte del servidor, simplemente habla los protocolos estándar del correo.
Para qué sirve: demuestra que el sistema no es cerrado. Con la configuración del servidor (host, puertos 465/993, usuario y contraseña), la app se conecta con total normalidad y permite leer y enviar correos desde el teléfono. Funciona igual con Outlook, Gmail, Thunderbird o cualquier cliente del mercado.
📊 En cifras
| Métrica | Valor |
|---|---|
| Contenedores Docker | 3 (mailserver · mail-admin · snappymail) |
| Puertos de correo gestionados | 8 (SMTP 25/465/587 · IMAP 143/993 · POP3 110/995 · Sieve 4190) |
| Puertos web | 2 internos (panel + webmail) — solo loopback |
| Dominios | Ilimitados (multi-dominio) |
| Revendedores | Ilimitados, con aislamiento total |
| Endpoints API | 35+ |
| Líneas de código | ~2,000 (backend + templates) |
| Bugs documentados y resueltos | 63+ con bitácora de aprendizaje |
| RAM total de contenedores | ~1.5 GB |
| Uptime en producción | 99.9% |
| Tiempo de desarrollo | 1 mes |
| Roles de usuario | 2 (admin global + revendedor con permisos granulares) |
🏆 Logros clave
⚙️ Funcionalidad
- Sistema de correo corporativo completo, en producción real, con múltiples dominios operando
- Multi-tenant con revendedores aislados: cada uno gestiona su propio panel, dominio y límites configurables
- Reemplazo funcional de Google Workspace / M365 sin costos recurrentes por usuario
- 35+ endpoints API con panel web completo (Jinja2 + Bootstrap 5.3)
🛡️ Seguridad
- Auditoría de seguridad completa con remediación de hallazgos críticos
- Aislamiento estricto de revendedores: toda validación se realiza en backend, nunca en el frontend
- 63+ bugs documentados y resueltos, incluidos vectores de ataque reales (inyección de comandos, abuso de roles, fuerza bruta)
🎨 UX y producto
- Demo navegable del panel para presentar el producto sin exponer datos reales
- Permisos granulares: transaccional, marketing y monitoreo se activan individualmente por revendedor
- Impersonate en 1 clic: el admin entra a cualquier panel de revendedor para dar soporte
🎯 Problema → Solución
| Problema | Solución |
|---|---|
| El correo corporativo tiene un costo por usuario (Google Workspace / M365) | Plataforma autoalojada multi-dominio sin costo recurrente por buzón |
| Un hosting quiere dar correo a sus clientes sin exponer el sistema | Revendedores aislados: cada uno administra solo su dominio y sus límites |
| Enviar correos transaccionales exige integrarse con APIs de pago | SMTP nativo con snippets listos para PHP, Python y Node.js |
| Hacer newsletters requiere herramientas externas costosas | Marketing integrado: listas CSV, variables {{nombre}}, envío inmediato o programado |
| Configurar el DNS del correo (SPF, DKIM, DMARC) es propenso a errores | Generador de registros por dominio + verificación de propagación en tiempo real |
| Sin visibilidad del servidor de correo | Monitoreo: CPU/RAM/disco, estadísticas de Rspamd, puertos, cola en vivo y visor de logs |
| Reconstruir el stack hacía perder datos | Volúmenes Docker + persistencia JSON con escritura atómica |
🏗️ Arquitectura
Diagrama general del sistema
graph TB
subgraph Internet["🌐 Internet"]
U["👤 Clientes / Webmail"]
A["👤 Admin / Revendedores"]
EXT["📨 Servidores externos SMTP"]
end
subgraph CloudPanel["☁️ Proxy"]
NGINX["Nginx Reverse Proxy<br/>HTTPS / Let's Encrypt"]
end
subgraph Docker["🐳 Docker Compose"]
direction TB
subgraph MS["📧 mailserver"]
POSTFIX["Postfix<br/>SMTP"]
DOVECOT["Dovecot<br/>IMAP / POP3"]
RSPAMD["Rspamd<br/>Anti-spam"]
CLAMAV["ClamAV<br/>Antivirus"]
FAIL2BAN["Fail2Ban"]
end
subgraph ADMIN["⚙️ mail-admin"]
API["FastAPI / Python 3.12"]
JINJA["Jinja2 Templates / Bootstrap 5"]
JSON["Archivos JSON"]
end
subgraph WEBMAIL["📬 snappymail"]
SNAPPY["SnappyMail — webmail PHP"]
end
end
U --> NGINX
A --> NGINX
EXT --> POSTFIX
NGINX --> SNAPPY
NGINX --> API
API -.->|Docker SDK| POSTFIX
API -.->|Docker SDK| DOVECOT
POSTFIX --> RSPAMD
RSPAMD --> CLAMAV
POSTFIX --> DOVECOT
Flujo de un correo entrante
sequenceDiagram
participant E as 📨 Servidor externo
participant P as Postfix (SMTP)
participant R as Rspamd (Anti-spam)
participant C as ClamAV (Antivirus)
participant D as Dovecot (LMTP)
participant B as 📬 Buzón
E->>P: SMTP 25 - Correo entrante
P->>R: Filtro anti-spam
R->>R: Greylisting + ML
R->>C: Escaneo de virus
C->>D: Correo limpio
D->>B: Entrega al buzón
Infraestructura Docker y persistencia
graph TB
subgraph HOST["🖥️ Servidor"]
subgraph VOLUMES["💾 Volúmenes"]
V1["mail-data/ — Buzones"]
V2["config/ — Cuentas + aliases"]
V3["admin-data/ — JSON persistentes"]
end
subgraph CONT["📦 Contenedores"]
MS["🐳 mailserver<br/>Postfix + Dovecot + Rspamd"]
MA["🐳 mail-admin<br/>FastAPI Python 3.12"]
SM["🐳 snappymail<br/>Webmail PHP"]
end
end
MS --- V1
MS --- V2
MA --- V3
MA -.->|Docker SDK| MS
subgraph PORTS["🔌 Puertos"]
P1["25 / 465 / 587<br/>SMTP"]
P2["143 / 993 / 110 / 995 / 4190<br/>IMAP / POP3 / Sieve"]
P3["Webmail (interno)"]
P4["Panel Admin (interno)"]
end
MS --- P1
MS --- P2
SM --- P3
MA --- P4
🧰 Stack tecnológico
| Capa | Tecnología | Propósito |
|---|---|---|
| Backend | Python 3.12 + FastAPI + Uvicorn | API async, validación por roles en cada endpoint |
| Frontend | Jinja2 + Bootstrap 5.3 + Bootstrap Icons | Panel admin responsive multi-rol |
| Servidor de correo | Postfix + Dovecot (Docker Mailserver) | SMTP/IMAP/POP3/Sieve en producción |
| Anti-spam / AV | Rspamd (greylisting + ML) + ClamAV + Fail2Ban | Filtrado de spam, antivirus, anti fuerza bruta |
| Webmail | SnappyMail (PHP) | Webmail por defecto del sistema — contenedor propio conectado al correo |
| Proxy / SSL | Nginx + Let’s Encrypt | Terminación TLS, puertos web solo loopback |
| Auth | JWT (HS256) + bcrypt + rate limiting | Sesiones y protección de accesos |
| Persistencia | Archivos JSON (escritura atómica) | Sin base de datos externa |
| Orquestación | Docker SDK for Python | Gestión del mailserver desde el panel |
| Infraestructura | 3 contenedores · 8 puertos de correo · red bridge aislada | Stack completo autoalojado |
⚙️ ¿Cómo funciona?
Flujo de correo
- Recepción: correo entrante → Postfix (SMTP 25) → Rspamd (anti-spam) → ClamAV (antivirus) → Dovecot (entrega al buzón)
- Envío: cliente de correo → Postfix (465/587) → firma DKIM → entrega al servidor destino
- Catch-All: si el destinatario no existe, Postfix redirige al buzón atrapa-todo configurado
Sistema de roles
- Admin global: solo supervisión; asigna recursos a revendedores, sin dominio propio
- Revendedor: gestión completa de su dominio con límites configurables (buzones, aliases, almacenamiento)
- Permisos granulares: transaccional, marketing y monitoreo se activan individualmente por revendedor
- Aislamiento estricto: toda validación se hace en backend — el revendedor nunca puede operar fuera de su dominio
⚙️ Funcionalidades
🔐 Panel de administración multi-rol
| Funcionalidad | Admin | Revendedor |
|---|---|---|
| Dashboard con métricas | ✅ Global | ✅ Su dominio |
| CRUD cuentas de correo | ❌ Solo lectura | ✅ Completo |
| CRUD aliases | ❌ Bloqueado | ✅ Completo |
| Catch-All (atrapa todo) | ❌ Bloqueado | ✅ Configurable |
| Gestión de revendedores | ✅ Completo | ❌ |
| Impersonate (1 clic) | ✅ A cualquier revendedor | ❌ |
| Marketing / Transaccional | ❌ Sin acceso | ✅ Según permisos |
| DNS multi-dominio | ✅ Global | ✅ Su dominio |
📤 Email transaccional
- Envío desde cualquier cuenta vía SMTP con snippets listos para PHP, Python y Node.js
- Integración rápida con apps externas — sin APIs de pago por correo
📣 Email marketing
- Listas de contacto con importación CSV y variables de personalización (
{{nombre}},{{email}}) - Envío inmediato o programado con scheduler background (revisa cada 30s)
🌐 DNS multi-dominio
- Registros sugeridos por dominio: A, MX, SPF, DKIM, DMARC, MTA-STS, SRV, autoconfig, autodiscover
- Generador de DKIM integrado y verificación de propagación DNS en tiempo real
📊 Monitoreo
- Métricas del servidor: CPU, RAM, disco, uptime
- Estadísticas de Rspamd: escaneados, aprendidos, conexiones
- Estado de puertos SMTP/IMAP/POP3/Sieve, cola de correo en vivo y visor de logs con filtro
📱 Compatible con cualquier cliente de correo
- Protocolos estándar SMTP / IMAP / POP3 / Sieve: el servidor no impone un cliente propietario
- Probado en producción con SnappyMail — el webmail por defecto, que corre en su propio contenedor conectado al correo — y con BlueMail en Android
- Funciona igual con Outlook, Gmail, Thunderbird o cualquier app del mercado
🛡️ Seguridad
El sistema fue diseñado con defensa en profundidad:
- ✅ JWT (HS256) + bcrypt + rate limiting: autenticación robusta en todos los accesos
- ✅ Anti-inyección de comandos:
shlex.quote()+ heredoc + sanitización de headers en el envío - ✅ Aislamiento de revendedores por diseño: el dominio se fuerza desde el JWT; los datos del cliente se ignoran; validación de rol en cada endpoint
- ✅ Verificación de estado en cada request: un revendedor desactivado pierde acceso al instante, no al próximo login
- ✅ Rspamd (ML) + ClamAV + Fail2Ban contra spam, virus y fuerza bruta
- ✅ Puertos web solo en loopback: panel y webmail no expuestos públicamente
- ✅ Auditoría de seguridad completa con remediación de hallazgos críticos implementada
💼 Casos de uso
| Sector | Uso |
|---|---|
| Hosting multi-tenant | Ofrecer correo a clientes con paneles aislados |
| Empresa / corporativo | Email de marca con N dominios gestionados centralizadamente |
| Revendedores de hosting | Cada uno con su dominio, límites y permisos propios |
| Marketing digital | Newsletters y campañas con listas segmentadas |
| Apps / SaaS | Transaccional: notificaciones, confirmaciones, facturación |
✅ Validación y resultados
| Área | Resultado |
|---|---|
| Producción | ✅ Activa con múltiples dominios reales operando |
| Correo de punta a punta | ✅ Envío → firma DKIM → entrega verificado en producción |
| Entregabilidad (spam test) | ✅ 10/10 en mail-tester.com — SPF, DKIM y DMARC verificados en vivo |
| Clientes de correo reales | ✅ Probado desde SnappyMail (webmail) y BlueMail (Android) |
| Bugs resueltos | ✅ 63+ documentados en bitácora de aprendizaje |
| Seguridad | ✅ Auditoría completa con hallazgos críticos remediados |
| Disponibilidad | ✅ 99.9% uptime |
| Persistencia | ✅ Rebuilds sin pérdida de datos (volúmenes + JSON atómico) |
| Integridad de datos | ✅ doveadm reload explícito tras cada operación — las cuentas nuevas se ven al instante |
📬 Entregabilidad verificada: 10/10 en mail-tester.com
Prueba en vivo con mail-tester.com — puntuación 10/10 (“Perfect, you can send”). El correo no solo “funciona”: está autenticado y tiene buena reputación, para llegar a la bandeja de entrada y no al spam.
| Autenticación | Resultado en vivo |
|---|---|
| SPF | ✅ v=spf1 mx -all — el servidor 167.114.169.134 está autorizado para enviar por gilman.pro |
| DKIM | ✅ Firma rsa-sha256 válida con clave pública de 2048 bits (selector mail) |
| DMARC | ✅ v=DMARC1; p=reject — política estricta; verificación dmarc=pass |
| Reverse DNS | ✅ 167.114.169.134 → correo.gilman.pro, coincide con el HELO |
| MX / A | ✅ gilman.pro MX → correo.gilman.pro → 167.114.169.134 |
| Reputación IP | ✅ Sin presencia en 23 listas negras (Spamhaus, Barracuda, SORBS, SpamCop…) |
SpamAssassin: score 0.2 (el umbral de spam es -5). La suma de estos seis puntos hace que el envío pase con nota perfecta.
🧠 Problemas técnicos resueltos
Los desafíos más significativos del desarrollo y cómo los resolví:
| Problema | Solución |
|---|---|
| Inyección de comandos en envío de correos | shlex.quote() + heredoc + sanitización de headers |
| Revendedor desactivado seguía accediendo | Verificación de estado en cada request (no solo al login) |
| Admin creaba cuentas sin autorización | Separación estricta de roles: el admin solo supervisa |
| ZeroDivisionError en barras de progreso | Validación de límites antes de calcular porcentajes |
| Alias multi-recipiente no se eliminaban | Parser corregido para dividir por coma |
| Datos no persistían al rebuild | Volumen Docker agregado al compose |
| Revendedor creaba cuentas en otros dominios | El dominio se fuerza desde el JWT; se ignoran los datos del cliente |
| Dovecot no veía cuentas nuevas | doveadm reload explícito tras cada operación |
| Scheduler saturaba conexiones Docker | Singleton del cliente Docker SDK reutilizado en todo el ciclo de vida |
🎯 Próximos pasos
Ya tengo definido el siguiente ciclo de mejoras:
- CSRF tokens en formularios POST
- Security headers (CSP, HSTS, X-Frame-Options)
- Mover secretos a Docker secrets / vault
- Rate limiting general en todos los endpoints POST
- API REST pública con documentación OpenAPI (v4.0)
- Migrar a un frontend SPA moderno (Vue.js / React)
🧑💻 Experiencias
Construí este proyecto con ayuda de asistentes de IA, pero el entendimiento vino de leer, probar, romper y arreglar. La IA aceleró la ejecución; las decisiones de arquitectura, la depuración y el criterio fueron completamente míos.
Conceptos que realmente entendí en el proceso
- Cómo funciona el correo electrónico por dentro: SMTP, IMAP, el rol de Postfix y Dovecot, la ruta completa de un correo desde que se envía hasta que llega al buzón
- Infraestructura de seguridad: DKIM (firmas), SPF (autorización de servidores), DMARC (política de entrega) — cómo se complementan
- Pensamiento ofensivo-defensivo: identificar vectores de ataque (inyección, JWT, fuerza bruta) y proteger el sistema contra ellos
- Docker en producción: redes, volúmenes, healthchecks, Docker SDK, reconstrucción sin pérdida de datos
- Debugging real: los bugs no vienen con stack trace bonito — a veces el error es “no funciona” y hay que descubrir por qué
Lo que más valoro
- Un sistema en producción real construido desde cero
- Una bitácora con 63+ bugs resueltos — cada uno fue una lección concreta
- Saber que si algo se rompe, puedo arreglarlo porque conozco el sistema por dentro
- Que la IA es una herramienta, no un reemplazo — el criterio sigue siendo humano
Proyecto desarrollado por Gilberto Castillo — Julio 2026 · Demo actualizada Agosto 2026