Muchos usuarios al registrarse en la web escriben direcciones de email inválidas (hotmeil.com, hotmaill.com, jotmail.com… y cosas peores, no es broma!) y esto hace que sendmail se vuelva loco. Constantemente trata de reenviarlos, resolver dominios que no existen o conectar a puertos que no responden… esto provoca que los logs de error crezcan de una forma espectacular y consume recursos de una forma que no había visto antes (sin duda por una configuración chapucera mía). Pero como la documentación de sendmail es para volverse loco y no me apetece probar otras cosas (como qmail o mail() de PEAR), haré un script en PHP que me haga la tarea de comprobar direcciones y mandar emails.
¿Cómo saber si una dirección es válida? Lo más simple sería mirar si responde a un ping.
sonic@XTC:~$ ping gmail.com
PING gmail.com (64.233.161.83) 56(84) bytes of data.
64 bytes from od-in-f83.google.com (64.233.161.83): icmp_seq=1 ttl=240 time=183 ms
64 bytes from od-in-f83.google.com (64.233.161.83): icmp_seq=2 ttl=240 time=224 ms
--- gmail.com ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 999ms
rtt min/avg/max/mdev = 183.999/204.274/224.550/20.280 ms
Pero claro, eso no significa nada. Podría ser un servidor de cualquier cosa. Habría que comprobar el puerto 25, pero…
sonic@XTC:~$ telnet gmail.com 25
Trying 64.233.161.83...
Trying 66.249.91.83...
Trying 209.85.171.83...
telnet: Unable to connect to remote host: Connection timed out
Lo más normal es que no responda ya que antes deberíamos mirar los registros MX. Se suelen utilizar distintos servidores para el correo. Es muy fácil de averiguar.
sonic@XTC:~$ dig -t MX gmail.com
; <<>> DiG 9.4.2-P2 <<>> -t MX gmail.com
;; global options: printcmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 25761
;; flags: qr rd ra; QUERY: 1, ANSWER: 5, AUTHORITY: 4, ADDITIONAL: 10
;; QUESTION SECTION:
;gmail.com. IN MX
;; ANSWER SECTION:
gmail.com. 244 IN MX 10 alt2.gmail-smtp-in.l.google.com.
gmail.com. 244 IN MX 50 gsmtp147.google.com.
gmail.com. 244 IN MX 50 gsmtp183.google.com.
gmail.com. 244 IN MX 5 gmail-smtp-in.l.google.com.
gmail.com. 244 IN MX 10 alt1.gmail-smtp-in.l.google.com.
;; AUTHORITY SECTION:
gmail.com. 241375 IN NS ns4.google.com.
gmail.com. 241375 IN NS ns1.google.com.
gmail.com. 241375 IN NS ns2.google.com.
gmail.com. 241375 IN NS ns3.google.com.
;; ADDITIONAL SECTION:
gmail-smtp-in.l.google.com. 238 IN A 209.85.129.114
gmail-smtp-in.l.google.com. 238 IN A 209.85.129.27
alt1.gmail-smtp-in.l.google.com. 44 IN A 209.85.147.27
alt2.gmail-smtp-in.l.google.com. 37 IN A 209.85.133.27
alt2.gmail-smtp-in.l.google.com. 37 IN A 209.85.133.114
gsmtp147.google.com. 4720 IN A 209.85.147.27
gsmtp183.google.com. 5711 IN A 64.233.183.27
ns1.google.com. 345591 IN A 216.239.32.10
ns2.google.com. 336560 IN A 216.239.34.10
ns4.google.com. 336560 IN A 216.239.38.10
;; Query time: 273 msec
;; SERVER: 192.168.0.1#53(192.168.0.1)
;; WHEN: Fri Oct 24 20:58:36 2008
;; MSG SIZE rcvd: 390
Ahora sí podemos hacer un telnet al servidor correcto:
sonic@XTC:~$ telnet gmail-smtp-in.l.google.com 25
Trying 72.14.221.114...
Connected to gmail-smtp-in.l.google.com.
Escape character is '^]'.
220 mx.google.com ESMTP
HELO hispashare.com
250 mx.google.com at your service
Ya estamos conectados al servidor de correo de google y podemos comunicarnos con él. Para comprobar si pepe@gmail.com es válido podemos hacer lo siguiente:
sonic@XTC:~$ telnet gmail-smtp-in.l.google.com 25
Trying 209.85.129.27...
Connected to gmail-smtp-in.l.google.com.
Escape character is '^]'.
220 mx.google.com ESMTP
HELO hispashare.com
250 mx.google.com at your service
MAIL FROM: <webmaster@hispashare.com>
250 2.1.0 OK
RCPT TO: <pepe@gmail.com>
550-5.1.1 The email account that you tried to reach does not exist. Please
550-5.1.1 try double-checking the recipient's email address for typos
550-5.1.1 or unnecessary spaces. Learn more at
550 5.1.1 http://mail.google.com/support/bin/answer.py?answer=6596
QUIT
221 2.0.0 closing connection
Connection closed by foreign host.
Y con estos pasos ya sabemos si un servidor existe, si es de correo y si la dirección es válida. Con una dirección correcta el resultado sería así:
RCPT TO: <hispashare@gmail.com>
250 2.1.5 OK
Eso es todo. No parece complicado de implementar en PHP así que este fin de semana haré mi propia función mail() para comprobar direcciones y mandar correo. Así podré quitar sendmail del servidor, que no me da más que dolores de cabeza (sí, lo más probable es que tenga algo mal configurado).