Internet: programando CGIs

 Volver al Indice – Internet y Tutoriales de Diseño Web

Por Alejandro Franco – contáctenos

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>
<head>
<link rev=made href=”mailto:jperez@dominio.com”>
<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.dominio.com/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)) {
# ninguna tecla ha sido pulsada, 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.htmln”;
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 maneran”;
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)nn”;

# 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>.