Configurar Postfix en Ubuntu para Enviar Correo desde tu Aplicación

Guía técnica para configurar Postfix en Ubuntu como relay SMTP, con SPF, DKIM y DMARC para entregar correos transaccionales desde tu aplicación.

Enviar correo desde tu aplicación parece simple hasta que el primer mensaje cae en el spam de Gmail o es rechazado por Outlook. Postfix es el servidor SMTP más usado en Ubuntu por ser estable, performante y bien documentado, pero la configuración por defecto no se acerca ni de lejos a lo que los proveedores modernos exigen para aceptar tus mensajes.

Esta guía es para desarrolladores que necesitan configurar Postfix en una VPS Ubuntu 24.04 LTS para enviar correos transaccionales — confirmación de registro, recuperación de contraseña, notificaciones de pedido. Vamos a configurar Postfix como relay autenticado, con SPF, DKIM y DMARC ajustados en el DNS, y a validar la entrega real. Tiempo estimado: 40 a 60 minutos, dependiendo del tiempo de propagación DNS.

El enfoque aquí es el de “null client” enviando vía relay autenticado externo. Es la configuración correcta para el 95% de los casos de aplicaciones web: más simple, más segura y con una tasa de entrega significativamente mejor que intentar enviar directo desde la VPS.

Prerrequisitos

Antes de empezar, asegúrate de tener el entorno preparado y las credenciales del relay a mano.

Prerrequisitos

Ubuntu 24.04 LTS con acceso sudo, dominio propio con control de DNS (Cloudflare, Registro.br, etc.), y credenciales de un relay SMTP externo (Amazon SES, Mailgun, SendGrid o similar). El relay necesita tener el dominio remitente validado.

Sistema Ubuntu 24.04 LTS
Paquetes postfix, libsasl2-modules, opendkim
Puertos salida 587 (submission) o 465 (smtps)
DNS Acceso para crear TXT y CNAME

Verifica también que el hostname de la VPS esté configurado correctamente — Postfix usa el hostname para identificarse en el HELO/EHLO, y si es genérico tipo ubuntu-vps los relays pueden rechazarlo.

hostnamectl set-hostname mail.tudominio.com
echo "127.0.1.1 mail.tudominio.com mail" | sudo tee -a /etc/hosts

Instalación de Postfix

La instalación estándar de Postfix en Ubuntu ya cubre casi todo lo que necesitamos, pero la configuración inicial vía debconf pide algunas elecciones importantes.

01

Actualiza el índice de paquetes e instala Postfix junto con los módulos SASL necesarios para autenticarse en el relay externo:

sudo apt update
sudo apt install -y postfix libsasl2-modules mailutils

Durante la instalación, debconf va a abrir una pantalla azul preguntando el tipo de configuración. Elige Internet Site with smarthost. A continuación, configura el “system mail name” como tudominio.com (sin subdominio).

02

Si pasaste de la pantalla de configuración sin prestar atención, vuelve a ejecutar el asistente:

sudo dpkg-reconfigure postfix

Selecciona Internet Site with smarthost, define el mail name como tudominio.com, y el SMTP relay host como [smtp.tuproveedor.com]:587 (con los corchetes, que desactivan el lookup MX).

Configuración del relay autenticado

Postfix necesita saber a dónde enviar y cómo autenticarse. Esto vive en dos archivos: main.cf (configuración principal) y sasl_passwd (credenciales).

03

Edita /etc/postfix/main.cf y añade o ajusta las siguientes directivas al final del archivo:

sudo nano /etc/postfix/main.cf
relayhost = [smtp.tuproveedor.com]:587
smtp_sasl_auth_enable = yes
smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd
smtp_sasl_security_options = noanonymous
smtp_tls_security_level = encrypt
smtp_tls_CAfile = /etc/ssl/certs/ca-certificates.crt
smtp_sasl_tls_security_options = noanonymous
header_size_limit = 4096000

La directiva smtp_tls_security_level = encrypt fuerza TLS en la salida — sin esto, tus credenciales SASL pueden ir en texto plano si el relay acepta plaintext.

04

Crea el archivo de credenciales con usuario y contraseña del relay:

sudo nano /etc/postfix/sasl_passwd

Añade una única línea en el formato:

[smtp.tuproveedor.com]:587 USUARIO_API:CLAVE_API

Guarda, compila para hash binario y protege el archivo — contiene credenciales en texto plano:

sudo postmap /etc/postfix/sasl_passwd
sudo chmod 600 /etc/postfix/sasl_passwd /etc/postfix/sasl_passwd.db
sudo systemctl restart postfix
Credenciales en backup

Recuerda excluir /etc/postfix/sasl_passwd (texto plano) de los backups públicos o del versionado. Mantén únicamente el archivo .db si necesitas restaurar — contiene el hash que usa Postfix.

Configurando SPF, DKIM y DMARC en el DNS

Sin autenticación DNS, ningún proveedor serio acepta tus correos de forma consistente. Vamos a configurar los tres registros esenciales.

SPF (Sender Policy Framework)

SPF declara qué servidores pueden enviar correo con tu dominio como remitente. Crea un registro TXT en el DNS de tu dominio:

Tipo: TXT
Nombre: @
Valor: v=spf1 include:_spf.tuproveedor.com -all

El -all al final es un hard fail — cualquier servidor fuera del include es rechazado. En producción, usa ~all (soft fail) durante los primeros días y migra a -all después de validar la entrega.

DKIM (DomainKeys Identified Mail)

DKIM firma criptográficamente cada correo enviado. La mayoría de los relays entregan la clave pública lista para pegar en el DNS — normalmente como CNAME o TXT. Toma los valores en el panel de tu proveedor de relay y crea los registros como se indica.

Si necesitas que el propio Postfix firme (raro en null client), instala opendkim:

05

Instala y configura OpenDKIM solo si tu relay no firma automáticamente:

sudo apt install -y opendkim opendkim-tools
sudo mkdir -p /etc/opendkim/keys/tudominio.com
cd /etc/opendkim/keys/tudominio.com
sudo opendkim-genkey -s default -d tudominio.com
sudo chown opendkim:opendkim default.private

El archivo default.txt generado contiene el registro TXT que necesitas publicar en el DNS en default._domainkey.tudominio.com.

DMARC

DMARC le indica al servidor receptor qué hacer con los correos que fallan SPF o DKIM. Empieza en modo monitoreo:

Tipo: TXT
Nombre: _dmarc
Valor: v=DMARC1; p=none; rua=mailto:[email protected]; pct=100

Después de una semana recolectando reportes y confirmando que SPF y DKIM pasan consistentemente, migra p=none a p=quarantine y luego a p=reject.

Verificación de la configuración

Antes de conectar esto a la aplicación, valida con pruebas manuales que todo funciona.

06

Envía un correo de prueba a una dirección Gmail (que ofrece reporte detallado de autenticación):

echo "Contenido del correo de prueba" | mail -s "Prueba Postfix Relay" \
  -a "From: [email protected]" [email protected]

Acompaña el log en tiempo real en otra sesión SSH para ver la conversación SMTP completa:

sudo tail -f /var/log/mail.log

Deberías ver líneas como status=sent (250 2.0.0 OK). Cualquier deferred o bounced indica un problema.

07

Abre el correo en Gmail, haz clic en los tres puntos y selecciona “Mostrar original”. Busca las líneas de cabecera:

SPF: PASS
DKIM: PASS
DMARC: PASS

Los tres necesitan estar en PASS. Si alguno aparece como FAIL o NEUTRAL, revisa el registro DNS correspondiente y espera la propagación (hasta 24 horas en algunos proveedores).

Herramienta de validación rápida

Para pruebas más detalladas, envía un correo a [email protected] o usa el sitio mail-tester.com. Ambos devuelven un reporte completo con SPF, DKIM, DMARC, reverse DNS y puntuación de spam.

Integrando con tu aplicación

Con Postfix funcionando como null client autenticado, tu aplicación envía correos vía SMTP localhost en el puerto 25 sin necesidad de conocer las credenciales del relay.

Ejemplo de configuración en variables de entorno

SMTP_HOST=127.0.0.1
SMTP_PORT=25
SMTP_USER=
SMTP_PASS=
MAIL_FROM=[email protected]

Frameworks como Laravel, Django, Rails y Node.js (nodemailer) consiguen enviar correos apuntando a 127.0.0.1:25 sin autenticación local — Postfix se encarga del relay autenticado con el proveedor externo.

Resolución de problemas

Mensajes atascados en deferred

Si postqueue -p muestra mensajes con estado deferred, normalmente es un problema de autenticación SASL o TLS:

sudo postqueue -p
sudo postcat -vq <ID_DEL_MENSAJE>

Revisa /var/log/mail.log para el mensaje de error específico. Los casos más comunes: contraseña del relay incorrecta (535 Authentication failed), TLS rechazado por el relay (STARTTLS failed), o IP de la VPS bloqueada por el relay (verifica en el panel del proveedor).

Error “Relay access denied”

Significa que estás intentando enviar con una dirección de remitente fuera del dominio autorizado en el relay. Confirma que el From: de la aplicación use exactamente el dominio configurado en el proveedor — y que el dominio esté validado en el panel.

Postfix no escucha en el puerto 25

Si tu aplicación no logra conectarse a 127.0.0.1:25, confirma que Postfix está escuchando:

sudo ss -tlnp | grep :25

Si no aparece nada, edita /etc/postfix/main.cf y confirma que inet_interfaces = loopback-only o inet_interfaces = all (para null client, loopback-only es lo correcto y más seguro). Reinicia con sudo systemctl restart postfix.

Próximos pasos

Con Postfix configurado, vale la pena explorar configuraciones de producción más robustas:

  • Configura postfix-pflogsumm para recibir reportes diarios por correo sobre volumen enviado, bounces e intentos sospechosos.
  • Implementa rate limiting vía smtpd_client_connection_rate_limit para protegerte de aplicaciones con bucle infinito de envío.
  • Usa una cola de jobs (Sidekiq, Celery, Laravel Queue) para encolar los envíos en vez de llamar sendmail de forma síncrona — así evitas bloquear las peticiones HTTP cuando el relay está lento.
  • Monitorea la reputación de tu dominio mensualmente con herramientas como Google Postmaster Tools y Microsoft SNDS.

Si estás llevando correo transaccional a producción, una VPS Hostini ya viene con IPv4 dedicada y reverse DNS configurable desde el panel — dos requisitos básicos para que cualquier proveedor de correo tome en serio tus envíos.

Preguntas frecuentes

¿Puedo enviar correos directamente desde la VPS sin usar un relay externo?

Técnicamente sí, pero la entrega va a sufrir. La mayoría de los proveedores de IPs cloud están en listas de reputación baja por defecto, y Gmail/Outlook suelen mandar directo a spam o rechazar. Para volúmenes bajos transaccionales (hasta algunos cientos al día), usa un relay autenticado como Amazon SES, Mailgun o SendGrid. El Postfix local queda únicamente como gateway.

¿Cuál es la diferencia entre Postfix como MTA completo y como null client?

MTA completo acepta correo desde fuera y entrega a usuarios locales u otros dominios — lo necesitas si alojas buzones. Null client (o send-only) solo envía correo generado localmente hacia un relay externo. Para aplicaciones web que disparan correos transaccionales, null client es el patrón correcto: menor superficie de ataque, configuración más simple.

¿Por qué mis correos van a spam aunque SPF, DKIM y DMARC sean válidos?

La autenticación resuelve identidad, no reputación. Si la IP de la VPS está en blacklists (Spamhaus, Barracuda) o tiene mal historial, incluso los correos autenticados van a spam. Verifica la reputación en mxtoolbox.com y considera usar un relay autenticado con IP dedicada, especialmente durante los primeros 30 días de envío.

Postfix está corriendo pero el correo no se envía. ¿Cómo depurar?

Empieza por journalctl -u postfix -n 100 y /var/log/mail.log para mensajes recientes. Usa postqueue -p para ver la cola atascada y postcat -vq ID para inspeccionar un mensaje específico. Si ves deferred con connection refused, el relay externo está bloqueando o tus credenciales SASL están mal — revisa /etc/postfix/sasl_passwd.

¿Necesito abrir el puerto 25 en el firewall?

Si usas relay externo (puerto 587 o 465 outbound), el puerto 25 no necesita estar abierto en el firewall — solo importa la salida autenticada. Si corres un MTA completo recibiendo correos, entonces 25 inbound es necesario. Para null client en VPS, mantén el 25 cerrado en la entrada y libera solamente 587/465 en la salida.

¿Cómo correr la prueba de envío sin necesitar un cliente SMTP completo?

Usa el comando sendmail directamente: echo 'Subject: prueba' | sendmail -v [email protected]. La flag -v muestra la conversación SMTP completa en tiempo real, útil para identificar handshake, autenticación y respuesta del servidor remoto. Alternativa: swaks --to [email protected] --from [email protected].

Temas:
Próximos pasos Cloud Ryzen con NVMe y protección DDoS siempre activa.Pon en producción en un VPS Hostini →
¿Te resultó útil este tutorial?
Hablar por WhatsApp