Autohospedado de Correo Corporativo
Volver a proyectos

Autohospedado de Correo Corporativo

python fastapi bootstrap docker postfix dovecot rspamd nginx smtp imap pop3 dns dkim jwt

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

SnappyMail — webmail por defecto del sistema (interfaz gráfica)

¿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

Logo de 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

  1. Recepción: correo entrante → Postfix (SMTP 25) → Rspamd (anti-spam) → ClamAV (antivirus) → Dovecot (entrega al buzón)
  2. Envío: cliente de correo → Postfix (465/587) → firma DKIM → entrega al servidor destino
  3. 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

Volver a proyectos