Hace ya unos años publiqué una entrada muy útil en la que veíamos la forma de levantar un servidor web con Python ejecutando un comando muy simple:
$ python -m SimpleHTTPServer Serving HTTP on 0.0.0.0 port 8000 ...
Podemos hacer algo similar con un servidor SMTP. El módulo de Python SMTPServer permite lanzar con un único comando y ciertos argumentos un servidor SMTP que podemos utilizar a modo de SMTP falso para hacer pruebas o como SMTP relay completamente funcional. Lo que no he conseguido (que no se si se puede) es hacerlo funcionar como SMTP server independiente, sin necesidad de enviar los correos a través de un relay.
Para levantar un SMTP server que hace relay a otro servidor SMTP ejecutamos el siguiente comando:
$ python -m smtpd -n <HOST_SMTP>:<PUERTO_SMTP> <RELAY_SMTP>:<PUERTO_RELAY_SMTP>
Ejemplo:
$ python -m smtpd -n localhost:1125 smtp-relay:25
A partir de este momento podemos conectarnos a nuestro SMTP local y enviar mensajes haciendo relay contra smtprelay:
$ telnet localhost 1125 Trying 127.0.0.1... Connected to localhost. Escape character is '^]'. 220 lab01 Python SMTP proxy version 0.2 mail from: test@foo.com 250 Ok rcpt to: test@bar.com 250 Ok data Subject: Correo de prueba Esto es una prueba . 250 Ok quit
La otra opción que os comentaba es la de crear un servidor SMTP falso. Esto nos sirve entre otras cosas para poder probar que el envío de correos de una aplicación está funcionando sin tener que enviar realmente el correo.
Tenemos que pasar el parámetro «DebuggingServer«. Esto hace que los correos que enviemos a través de nuestro SMTP simplemente se muestren en la salida estándar (cuerpo y cabeceras simples del correo):
Levantamos el SMTP:
$ python -m smtpd -n -c DebuggingServer localhost:1125
Enviamos el correo:
$ telnet localhost 1125 Trying 127.0.0.1... Connected to localhost. Escape character is '^]'. 220 lab01 Python SMTP proxy version 0.2 mail from: test@foo.com 250 Ok rcpt to: test@bar.com 250 Ok data Subject: Correo de prueba Esto es una prueba . 250 Ok quit
Y vemos en STDOUT lo siguiente:
---------- MESSAGE FOLLOWS ---------- Subject: Correo de prueba Esto es una prueba X-Peer: 127.0.0.1 ------------ END MESSAGE ------------
Lo dicho, pensaba que ejecutando del siguiente modo el comando podríamos enviar sin necesidad de relay, pero haciendo un strace al proceso veo que lo intenta enviar por defecto al relay de localhost:25 así que no debe estar implementado:
$ python -m smtpd -n localhost:1125
read(5, "127.0.0.1\tlocalhost\n127.0.1.1\tno"..., 4096) = 4096 read(5, "", 4096) = 0 close(5) = 0 munmap(0x7f20a4311000, 4096) = 0 socket(PF_INET, SOCK_STREAM, IPPROTO_TCP) = 5 connect(5, {sa_family=AF_INET, sin_port=htons(25), sin_addr=inet_addr("127.0.0.1")}, 16) = -1 ECONNREFUSED (Connection refused)