|
En este tutorial crearemos un script CGI que envíe
un correo y devuelva una página que indique que
el correo ha sido enviado. Sin embargo, los conceptos
serán bastante geniales para permitir que el script
pueda ser adaptado a cualquier proyecto donde sea necesario
enviar un correo desde un script. También veremos
brevemente como examinar las áreas de texto línea
por línea.
Como siempre, cuando empezamos, necesitaremos un formulario.
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
<html>
<!--Javier Pérez Delgado (jperez@ctv.es) All
Rights Reserved -->
<head>
<link rev=made href="mailto:jperez@ctv.es">
<title>Enviar correo desde un script CGI</title>
</head>
<body>
<P>Este formulario encía correo a la dirección
de la persona mostrada.</P>
<form method="POST" action="http://www.ctv.es/USERS/cgi-bin/mail.pl">
<P>Tu dirección: <INPUT NAME="De"
SIZE=36></P>
<P>Tu URL: <INPUT NAME="xurl" SIZE=36></P>
<P>Subject: <INPUT NAME="subject"
SIZE=40></P>
<P>Mensaje:</P>
<P><TEXTAREA name="body" rows=10
cols=60></TEXTAREA></P>
<P><input type="submit" value="Enviar
mansaje">
<input type="reset" value="Borrar
todo"></P>
</FORM>
</P>
</body>
</html>
Ahora pasaremos al script. Como siempre deberá
empezar con una llamada al perl, algunos comentarios
y una llamada a la rutina ReadParse, en la librería
cgi-lib.pl. También haremos verificaciones de
que el cuerpo del mensaje no está vacío,
y de que la dirección contiene una arroba (@).
Otra validación será para comprobar que
de pasan argumentos, lo pondremos porque la gente tiene
tendencia a llamar a los scripts de correo sin argumentos
(eg: no desde un formulario), no entiendo por qué.
Para comprobar que no hay argumentos, simplemente examinaremos
si el vector %in que la librería cgi-lib.pl nos
devuelve tiene alguna tecla. Recuerda, que ningún
argumento, significa que no nos han pasado nada, sin
embargo, alguien puede pasar los argumentos en blanco,
de aquí las dos comprobaciones. La manera de
comprobar los valores de las teclas del vector es usar
la función keys(). Esta función espera
un array asociativo como argumento. Simplemente comprobaremos
que devuelve algo, imprimiendo un mensaje de error si
no hay teclas. El código pude ser este:
if (!keys(%in)) {
# niguna tecla ha sido pasada, imprimir mensaje de error,
y si es apropiado salir.
}
Date cuenta de que el signo '!' al principio de la
llamada a keys(), significa 'no' o negación.
Quiere decir que si keys() no devuelve nada (falso),
será negado para que sea cierto y el if se ejecute.
Ahora que hemos validado las entradas, y se pueden realizar
más comprobaciones, necesitaremos enviar la carta.
Para ello necesitaremos un programa que acepte una carta
del stdin. Luego usaremos sendmail en el ejemplo. Si
no estás en un entorno Unix, necesitarás
otro programa apropiado para hacerlo. Como no conozco
otro tipo de sistemas, no puedo hacer ninguna recomendación.
Usar este programa será similar a escribir en
un fichero. Necesitamos abrir el programa para aceptar
la entrada, escribir al FILEHANDLE. Abrir un programa
que espera entradas por el stdin es bastante fácil
em Perl. Además, es muy fácil pasar el
argumento de la línea de comandos. En este ejemplo,
abriremos sendmail, y diremos que busque en la carta
la dirección de destino.
open(MAIL,"|/usr/lib/sendmail -t");
Como se puede observar, es igual que una llamada a
fichero, pero los símbolos '>' o '<' han
sido sustituidos por un '|' (tubería). Esto indica
que lo que hay detrás de la tubería es
un ejecutable, y que lo que imprimamos en este FILEHANDLE
se deberá pasar como entrada a el programa ejecutable.
Nota: No he comprobado si la operación anterior
terminó con éxito, pero deberíamos
hacerlo. La manera más sencilla de hacerlo, es
apoyarnos en que el comando open devuelve true cuando
ha tenido éxito. Solo debemos hacer un OR entre
el comando open y otro comando conociendo que ese comando
será ejecutado si el open falla. El ejemplo de
abajo realiza un OR con el comando die. Este comando
imprime un mensaje de error y sale del programa.
open(MAIL,"|/usr/lib/sendmail -t") || die
"La llamada a sendmail ha fallado";
El imprimir la carta funciona como esperamos. Recuerda,
sin embargo, que estamos imprimiendo un trozo de e-mail,
por lo que deberemos poner las cabeceras adecuadas,
un línea en blanco y el cuerpo del mensaje. Puedes
echar un vistazo a un e-Mail que hayas recibido y comprobar
las cabeceras. Describiré abajo lo más
importante. Los comentarios serán de ayuda.
# Esta es la línea 'para'. Si tenemos el nombre
y la dirección, escribiremos
# primero el nombre y luego la dirección entre
<>
print MAIL "To: $in{'De'}\n";
# Esta es la línea 'De'. Pondremos el mismo
nombre en la línea 'De' y en la 'para'
# Recuerda que no hay seguridad comprobando el email,
por ello estas líneas
# pueden ser falsificadas. NO FALSIFIQUES EL EMAIL,
no es divertido y en algunos lugares
# es un delito.
print MAIL "From: $in{De}\n";
# Esta es la línea 'contestar a'. Esta línea
se incluye debido a que algunos programas
# son bastante tontos y no siempre responden a la línea
'De'.
# Al menos respetarán esta línea.
print MAIL "Reply-To: $in{De}\n";
# Lo siguiente son cabeceras X. Son creadas por el usuario
y pueden contener
# todo lo que desees. Incluyo una línea de descripción
# también he escrito las líneas REMOTE_HOST,
REMOTE_ADDR, y REMOTE_USER para
# ayudar al seguimiento (traking) de la carta.
# Solo escribo la línea X-URL si el usuario ha
dado una url. Este tipo
# de comprobación probablemente hecha también
en el X-Remote-Host y X-Remote-User
print MAIL "X-mailer: Mail.pl, a cgi-bin script
at http://www.ctv.es/users/jperez/www/tutor/ /index.html\n";
print MAIL "X-Remote-Host: $ENV{'REMOTE_HOST'}
($ENV{'REMOTE_ADDR'})\n";
print MAIL "X-Remote-User: $ENV{'REMOTE_USER'}\n";
print MAIL "X-disclaimer: La línea De: puede
estar falsificada ";
print MAIL "No confiar en un 100% sobre la integridad
de este mail. ";
print MAIL "No somos responsables de este correo
de ninguna manera\n";
if ($in{xurl} ne "") {
print MAIL "X-URL: $in{xurl}\n";
}
# Finalmente escribimos la famosa línea del
asunto.
# Presatr atención en la segunda nueva línea.
Esta es la línea
# que va a separar el encabezado del cuerpo del mensaje.
print MAIL "Subject: $in{subject} (WWW generated
email)\n\n";
# Ahora vamos a escribir elcuerpo del mensaje.
print MAIL $in{'body'};
Solo quedan dos cosas. Primero debemos cerrar la conexión
con sendmail. Segundo debemos imprimir una página
enseñando al usuario la carta que envía.
Para cerrar la conexión, usaremos el comando
close, justo como en cualquier otro manejador:
close(MAIL);
Imprimir la respuesta no es diferente a las otras páginas
generadas dinámicamente que ya hemos creado anteriormente.
Deberemos dividir el campo TEXTAREA en líneas
colocando un <BR> al final de cada una. Esto se
hace principalmente para demostrar como se divide un
campo de texto. Recuerda sin embargo que html no respeta
las nuevas líneas. Con ello se consigue el poder
hacer los párrafos de manera más clara,
pero el beneficio de hacerlo es cuestionable.
El valor del campo body (cuerpo del mensaje), no es
más que un conjunto de frases separadas con un
retorno de carro. Podemos usar la función split()
para separarlas. Esta función necesita dos parámetros:
la cadena o carácter para separar y la variable
a separar, y retorna un array con los elementos separados.
Usaremos split en un bucle foreach:
foreach $l (split('\n',$in{'body'})) {
print "$l<BR>\n";
}
Como se puede ver separa la variable $in{'body'} en
partes cada nueva línea, y la imprime seguida
de un <BR>. |