59 Php. Formatos Mime

1,730 views

Published on

Published in: Technology
0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total views
1,730
On SlideShare
0
From Embeds
0
Number of Embeds
2
Actions
Shares
0
Downloads
31
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

59 Php. Formatos Mime

  1. 1. Formatos MIME Formato de los mensajes de correo electrónico Las cabeceras MIME de un mensaje En la página anterior hemos Aquí tienes un ejemplo con los diferentes elementos del encabezado de un mensaje. hablado acerca de la manera de Como ves, he incluido todos los elementos dentro de la función mail. enviar un e-mail y veíamos la forma de insertar el cuarto <? parámetro de la función mail para mail("juan@mispruebas.com", "Cabeceras", "Prueba de cabeceras", incluir algunos elementos de los "Date: 24 de Junio de 2001 encabezados MIME. MIME-Version: 1.0 El formato de los mensajes está From: Estudiante Perico<perico@mispruebas.com> especificado en una serie de Cc:perico@mispruebas.com normas conocidas como el MIME Bcc:andres@mispruebas.com (Multipurpose Internet Mail Reply-To: perico@mispruebas.com Extensions) en las que se X-Mailer: PHP/".phpversion()); establecen los contenidos y la ?> sintaxis de las diferentes partes de un mensaje. ejemplo98.php Recordemos que la función mail(dest, asunt, men, cab) Una forma un poco más depurada del script anterior podría ser esta que incluimos aquí debajo. tiene cuatro parámetros y que las especificaciones del MIME aluden a Sus particularidades son las siguientes: los dos últimos, es decir a men (el cuerpo del mensaje) y cab que es el encabezado del mismo. s Recogemos los datos en variables e insertamos en la función mail esas variables s La variable $cabecera tiene algunas singularidades: Respecto a dest (destinatario) y s La vamos construyendo añadiendo subcadenas: date, from, etc. etc. asunt no se requieren más s En cada subcadena dejamos pegado el contenido a las comillas iniciales comentarios que reiterar la s Al final de cada subcadena (cada una contiene un elemento del encabezado) necesidad de incluir esos valores insertamos n para el carácter especial que indica a PHP un salto de línea (e-mail del destinatario y asunto) imprescindible bien directamente, como parámetro en la función, o a través de una variable tal como hemos comentado en la página anterior. <? # datos del mensaje Cabeceras de los mensajes $destinatario="juan@mispruebas.com"; $titulo="Cabeceras en variables"; Los diferentes elementos de la $mensaje="Nueva prueba de cabeceras"; cabecera de un mensaje deben $responder="andres@mispruebas.com"; insertarse siempre separados por $remite="andres@mispruebas.com"; saltos de línea bien pulsando $remitente="Otra vez Andrés"; Enter o incluyendo la secuencia n # cabeceras dentro de la misma de línea. $cabecera ="Date: ".date("l j F Y, G:i")."n"; No pueden incluirse espacios, ni al $cabecera .="MIME-Version: 1.0n"; comiezo de las nuevas líneas ni $cabecera .="From: ".$remitente."<".$remite.">n"; después de n, y las comillas –que $cabecera .="Return-path: ". $remite."n"; han de contener todo el $cabecera .="X-Mailer: PHP/". phpversion()."n"; encabezado– se abren delante del primero de ellos y no se cierran if( mail($destinatario, $titulo, $mensaje,$cabecera)){ hasta después de haber escrito el echo "mensaje enviado"; último. } Pueden contener lo siguiente: ?> Date: xxxxx ejemplo99.php Date: debe escribirse con esta sintaxis exactamente. El parámetro xxxxx es una cadena Algunas funciones PHP que incorporamos en estos ejemplos que contendrá la fecha de envío del mensaje y que puede obtenerse a través de una de las Podrás ver en estos ejemplos algunas funciones raras que vamos a comentar funciones de fecha de PHP tal seguidamente: como puedes ver en el ejemplo. uniqid(pre,bol) MIME-Version: 1.0 Genera un identificador único basado en la hora actual del sistema expresada en Este elemento de la cabecera microsegundos y con una longitud de 13 caracteres. especificará la versión MIME que ha de utilizar el cliente de correo El parámetro pre permite establecer una cadena o número (puede ser una cadena vacía) para poder interpretar adecuadamente el contenido de los que se antepone al identificador generado por la función. mensajes. Opcionalmente permite el segundo parámetro bol que debe ser un valor booleano (TRUE From: remitente<e-mail> ó FALSE) o también 0 ó 1. Este elemento de la cabecera Cuando este parámetro es TRUE añade al final de la cadena generada anteriormente otra permite indicar el nombre del subcadena numérica -generada aleatoriamente- de nueve dígitos, que refuerza la unicidad remitente (remitente) y su del identificador. dirección e-mail siguiendo la sintaxis que se especifica. El eregi_replace(busca, reemplaza, cadena) nombre, como un elemento independiente y la dirección e-mail Busca en la cadena especificada en el parámetro cadena (que puede ser una cadena o dentro de < >. una variable que contenga una cadena) las subcadenas especificadas en busca (pueden ser ¡Cuidado! expresiones regulares) y sustituye esas subcadenas por el contenido del parámetro reemplaza.
  2. 2. No debemos poner comillas ni en el nombre del remitente, ni en la Esta función devuelve la cadena modificada. dirección e-mail, ni en la fecha, etcétera. strip_tags(cadena, excepciones) Respecto a Cc: y Bcc: ; Reply-To: Suprime todas las etiquetas HTML contenidas en cadena salvo las que se indiquen en y X-Mailer: son válidos los excepciones. comentarios que hemos hecho en la página anterior. Por ejemplo: strip_tags($cadena, '<i><u><b>') eliminaría todas las etiquetas HTML, Si no se especifica lo contrario, los salvo las indicadas aquí y sus correspondientes cierres. mensajes se envían como texto sin formato, pero existen Si no se especifican excepciones elimina todas las etiquetas. opciones que permiten especificar el formato que ha de tener un base64_encode(cadena) mensaje. Devuelve una cadena codificada en base64. Esta codificación se hace para permitir que La especificación de un formato las informaciones binarias puedan ser correctamente manipuladas por sistemas que no obliga a incluir otro elemento en generan correctamente los 8 bits, tal como ocurre frecuentemente en los cuerpos de los cabecera del mensaje: mensajes de correo electrónico. Content-Type: base64_decode(cadena) Este elemento debe ir seguido de Realiza el proceso inverso a la anterior. Decodifica una cadena previamente codificada la especificación en la que se indique el tipo de contenido. Tiene en base64. la sintaxis: tipo/subtipo chunk_split(cadena, longitud, separador) El MIME establece un gran variedad de opciones para este Devuelve una cadena obtenida al insertar en la cadena especificada -a intervalos del propósito. Hablaremos de dos de número de caracteres especificados en el parámetro numérico longitud- el contenido de ellas: una subcadena indicada en el parámetro separador. text/plain Por defecto -cuando no se especifican los parámetros- longitud es igual a 76 caracteres y el separador es la cadena rn (retorno y salto de línea). El text/plain es la opción por defecto y señala que el contenido Esta función se utiliza para convertir al formato especificado en la RFC 2045 del mensaje es de tipo texto (especificación para MIME) las cadenas obtenidas por base64_encode. (text) y del subtipo sin formato (plain) Es el formato habitual de los ficheros adjuntos de los e-mail. text/html Como la opción anterior, es tipo Mensaje con contenido alternativo texto, pero en este caso, el subtipo es html con lo cual el mensaje se visualizará en formato html siempre que el cliente de <? correo permite esa posibilidad. # creamos la variables "salto" para "mayor comodidad # un salto es la secuencia retorno de carro-nueva línea Mensajes multiparte # dos saltos es algo similar pero duplicado $UN_SALTO="rn"; Los tipos anteriores permiten enviar mensajes simples (sin $DOS_SALTOS="rnrn"; ficheros adjuntos) en uno u otro formato, pero el MIME nos da # creamos el remitente, etc. y también la que parte que opciones para insertar dentro de # contiene el código HTML del mensaje un mismo mensaje elementos de diferentes tipos y subtipos. $destinatario="juan@mispruebas.com"; $titulo="Mensaje alternativo Texto Plano - HTML "; Las opciones de mayor interés son $mensaje="<html><head></head><body bgcolor='#ff0000'>"; las siguientes: $mensaje .="<font face='Arial' size=6>Prueba HTML</font>"; multipart/alternative $mensaje .="</body></html>"; $responder="andres@mispruebas.com"; Es la forma de especificar que el $remite="andres@mispruebas.com"; mensaje tiene varias partes $remitente="Andrés Pérez y Pérez"; (multipart) de las que el destinatario ha de ver una sola # creamos el separador de bloques del mensaje (alternative). # anteponiento "_separador" aunque podríamos haber puesto "tiburcio" Se podría utilizar en casos en los # generamos un identificador unico utilizando un numero aleatorio que sea necesario prever la # como "semilla" y luego lo codificamos con la función md5 posibilidad de que un mensaje con formato HTML pueda ser $separador ="_separador".md5 (uniqid (rand())); visualizado como texto plano cuando el cliente de correo no # creamos la variable cabecera con los elementos soporte HTML. # ya utilizados en los ejemplos anteriores y ponemos al final # de cada elemento UN SALTO DE LINEA Podemos hacer un mensaje a medida que se presentará de una forma u otra según el cliente $cabecera = "Date: ".date("l j F Y, G:i").$UN_SALTO; utilizado para leerlo. $cabecera .="MIME-Version: 1.0n"; $cabecera .="From: ".$remitente."<".$remite.">".$UN_SALTO; multipart/mixed $cabecera .= "Return-path: ". $remite.$UN_SALTO; $cabecera .="Cc:perico@mispruebas.com".$UN_SALTO; Cuando en el Content-Type se $cabecera .="Reply-To: ".$remite.$UN_SALTO; establece el tipo multiparte y el $cabecera .="X-Mailer: PHP/". phpversion().$UN_SALTO; subtipo mezclado (mixed) será cuando tengamos la posibilidad de adjuntar ficheros al mensaje. # AQUÍ DEFINIMOS EL CONTENIDO MULTIPART, fíjate que lo acabamos con ";" Las diferentes partes de un $cabecera .="Content-Type: multipart/alternative;".$UN_SALTO; mensaje deben ir separadas – tanto en modo alternativo como # insertamos BOUNDARY (fíjate que dejo un espacio mezclado– y para ello hay que # en BLANCO DELANTE y ponemos al FINAL los DOS SALTOS DE LINEA incluir un nuevo elemento en el encabezado. Se trata de un $cabecera .=" boundary=$separador".$DOS_SALTOS; separador al que se llama boundary. # colocamos el primer separador(con los dos guiones delante) boundary=cadena # antes de insertar la primera parte del mensaje
  3. 3. # que es el texto plano para el caso de que el cliente de correo Dentro del encabezado y siempre # no soporte HTML en línea aparte (fíjate que en los ejemplos o está en línea aparte o $texto_plano ="--$separador".$UN_SALTO; aparece el n) debemos incluir el elemento boundary= (sin símbolo de $ delante) y detrás del signo # especificamos el tipo de contenido y la codificación igual una cadena (en este caso # e inserto DOS SALTOS AL FINAL ya que ahi acaba la cabecera de esta parte entre comillas) que en principio $texto_plano .="Content-Type:text/plain; charset="ISO-8859-1"". puede ser una cadena cualquiera $UN_SALTO; que no contenga espacios, aunque $texto_plano .="Content-Transfer-Encoding: 7bit".$DOS_SALTOS; lo habitual es incluirla con el formato que podemos ver en los # cambiamos las etiquetas "<br>" por saltos de línea ejemplos. # y luego quitamos todas las etiquetas HTML del cuerpo del mensaje # ya que el texto plano no debe llevar ese tipo de etiquetas El cuerpo del mensaje $extractor= strip_tags(eregi_replace("<br>", $UN_SALTO, $mensaje)); En su formato más simple el cuerpo del mensaje contiene $texto_plano .=$extractor; únicamente texto, pero cuando se trata de multipartes deberá # insertamos un nuevo separador para señalar el final contener necesariamente: los # de la primera parte del mensaje y el comienzo de la segunda separadores de las diferentes # en este caso ponemos UN SALTO delante del separador ya que de lo partes, los encabezados de cada contrario una de las partes y sus respectivos # al componer el mensaje se uniría con la cadena texto_plano anterior contenidos. # que no tiene SALTO DE LINEA AL FINAL La secuencia habría de ser de este tipo: $texto_html =$UN_SALTO."--$separador".$UN_SALTO; # especificamos el encabezado HTML para el siguiente bloque s Separador s Content-type # y ponemos en la ultima línea los DOS SALTOS DE LINEA s Content-Transfer-Encoding s **Content-Disposition $texto_html .="Content-Type:text/html; charset="ISO-8859-1"".$UN_SALTO; s **Lectura del fichero $texto_html .="Content-Transfer-Encoding: 7bit".$DOS_SALTOS; s **Codificación #añado la cadena que contiene el mensaje s Inserción en cuerpo $texto_html .= $mensaje; s Separador s ..... # insertamos SOLAMENTE un SALTO DE LINEA s otra parte # estamos al funal del mensaje s ... s Separador final $texto_html .=$UN_SALTO; Los apartados señalados con ** # unimos ambas cadenas para crear el cuerpo del mensaje sólo se incluirían en el caso de que junto con el mensaje se adjunten $mensaje=$texto_plano.$texto_html; ficheros. Content-type # enviamos el mensaje utilizando Los tipos y subtipos más habituales son los siguientes: if( mail($destinatario, $titulo, $mensaje,$cabecera)){ echo "mensaje enviado "; Para incluir textos: } los ya mencionados text/plain text/html ?> Para imágenes: según el tipo de imagen ejemplo100.php image/jpeg image/gif Para sonidos: Mensaje con ficheros adjuntos audio/basic Para vídeo: video/mpeg <? Para ejecutables, comprimidos y # definimos estas variables igual que en el ejemplo anterior otros ficheros adjuntos: application/octet-stream $UN_SALTO="rn"; En cualquier caso, si quieres $DOS_SALTOS="rnrn"; utilizar algún otro tipo de archivo puedes consultar en la web las #incluimos en varias, asunto, un texto en HTML especificaciones del MIME. # remitente, etc. etc. Aparte de tipo/subtipo puede $destinatario="perico@mispruebas.com"; añadirse a Content-type -en el $titulo="Mensaje con dos fichero adjuntos"; caso de texto- separado por punto $mensaje="<html><head></head><body bgcolor="#ff0000">"; y coma, la especificación del tipo $mensaje .="<font face="Arial" size=6>Prueba HTML </font>"; de alfabeto (charset=) seguida $mensaje .="</body></html>"; del tipo de codificación (te sugerimos el "ISO-8859-1" que $responder="andres@mispruebas.com"; hace alusión al alfabeto latino). $remite="andres@mispruebas.com"; $remitente="Andrés otra vez"; Cuando se trata de ficheros adjuntos deberemos poner, # definimos el separador de parte después del punto y coma, # con el mismo procedimiento del ejemplo anterior name= seguido del nombre y extensión del fichero que se $separador = "_separador_de_trozos_".md5 (uniqid (rand())); adjunta. Content-Transfer-Encoding # insertamos los datos de la cabecera del mensaje Este apartado del encabezado $cabecera = "Date: ".date("l j F Y, G:i").$UN_SALTO; puede especificar una de los $cabecera .= "MIME-Version: 1.0".$UN_SALTO; siguientes codificaciones: $cabecera .= "From: ".$remitente."<".$remite.">".$UN_SALTO;
  4. 4. 7BIT $cabecera .= "Return-path: ". $remite.$UN_SALTO; 8BIT $cabecera .= "Reply-To: ".$remite.$UN_SALTO; BASE64 $cabecera .="X-Mailer: PHP/". phpversion().$UN_SALTO; BINARY QUOTED-PRINTABLE # especificamos el tipo de contenido mutipart/mixed La transferencia codificada en 7bit # ya que ahora insertaremos ficheros de distinto tipo representa la codificación habitual en el formato ASCII de 7 bits. $cabecera .= "Content-Type: multipart/mixed;".$UN_SALTO; No permite caracteres ASCII con un código mayor que 127. # insertamos el valor de boundary haciéndola igual a $separador # y acabamos con DOS SALTOS porque es el FINAL DE LA CABECERA Quoted-printable constituye una de las alternativas al formato ASCII de 7 bits. $cabecera .= " boundary=$separador".$DOS_SALTOS; Esta codificación suele usarse /* Parte primera del envio -Mensaje en formato HTML cuando la mayoría de los ================================================ caracteres del mensaje puede escribirse con formato US ASCII de Separador inicial 7 bits. ------------------------------- */ Prevé que los caracteres con $texto ="--$separador".$UN_SALTO; códigos ASCII superiores 127 se expresen mediante un mecanismo /* Encabezado parcial especial. ------------------ */ /* especificamos que este primer elemento Evita, entre otras cosas, que las será texto y que irá codificado en formato 7 bits */ letras con tilde y algunos otros caracteres especiales se visualicen $texto .="Content-Type: text/html; charset="ISO-8859-1"".$UN_SALTO; incorrectamente. Es la forma de $texto .="Content-Transfer-Encoding: 7bit".$DOS_SALTOS; codificación más recomendable para textos. /* Contenido de esta parte del mensaje La codificación en base64 -----------------------------------*/ convierte cadenas binarias en # ya teniamos escrito el texto del mensaje más arriba cadenas de texto, con lo cual # simplemente lo añadimos a la cadena de texto pueden ser enviadas de forma más segura. Es la forma de codificación $texto .= $mensaje; habitual de las imágenes y los ficheros exe, zip, etcétera. #la variable $texto recoge esta parte del documento Content-Disposition # la uniremos al final con las siguientes Se utiliza únicamente cuando se /* Separador de partes insertan ficheros adjuntos. -------------------- */ Permite dos opciones: inline o attachment. $adj1 = $UN_SALTO."--$separador".$UN_SALTO; Inline permite que los contenidos /* Parte segunda de mensaje -Fichero adjunto nº 1 se visualicen junto con el cuerpo ==================================================== */ del mensaje mientras que con attachment sólo aparecerían /* Encabezado parcial como ficheros adjuntos. ------------------ */ # especificamos el tipo de contenido image/jpeg Por lo que hemos podido comprobar Outlook Express no # ya que ese será el documento que vamos a enviar suele respetar esa condición y # ponemos el nombre del fichero (debemos tenerlo en el servidor presenta siempre las imágenes en # con ese mismo nombre) el mensaje. Sin embargo, sí # establecemos in line como disposición para que pueda ser visualizado funciona en los correos web. # directamente en el cuerpo del mensajes # en filename le asignamos el nombre con el que queremos que sea Este elemento del encabezado # recibido por el destinatario lleva -separada por punto y coma- # por ultimo especificamos la codificacion como base64 una segunda parte. El filename=, donde se puede $adj1 .="Content-Type: image/jpeg;"; especificar entre comillas un $adj1 .=" name="casa08.jpg"".$UN_SALTO; nombre y una extensión (igual o $adj1 .="Content-Disposition: inline; "; distinta de la original) con la que $adj1 .="filename="leoncio.jpg"".$UN_SALTO; se denominará al fichero en el $adj1 .="Content-Transfer-Encoding: base64".$DOS_SALTOS; mensaje recibido. /* Lectura previa del fichero a adjuntar Lectura del fichero ------------------------------------------ */ Cuando se trata de insertar un # abrimos el fichero en modo lectura (r) fichero el proceso es el típico de # y leemos todo su contenido midiendo previamente lectura de ficheros, es decir: # su longitud con filesize # recogemos en $buff el contenido del fichero s Hay que crear el # y cerramos después identificador de recurso del fichero en modo lectura. $fp = fopen("casa08.jpg", "r"); s Recoger en una variable el $buff = fread($fp, filesize("casa08.jpg")); buffer de lectura. fclose($fp); s Cerrar el fichero. /* Codificación del fichero a adjuntar Codificación ------------------------------------------ */ # codificamos en base 64 y troceamos en lineas de 76 caracteres Una vez recogido en el fichero a # y añadimos el resultado a la variable adj1 transmitir en una variable, el paso siguiente es codificar esa variable. $adj1 .=chunk_split(base64_encode($buff)); Utilizaremos la codificación más habitual y flexible –base64– que /* Separador de partes requerirá el uso de dos nuevas -------------------- */ funciones PHP: $adj2 = $UN_SALTO."--$separador".$UN_SALTO; base64_encode chunk_split /* Tercera parte de mensaje -Fichero adjunto nº 2 Mediante la primera se realiza la ==================================================== */
  5. 5. codificación propiamente dicha mientras que la segunda organiza /* Encabezado parcial el fichero codificado en trozos, de ------------------ */ 76 caracteres cada uno, insertando # los contenidos del encabezado son similares al caso anterior detrás de cada uno un salto de línea. # con la salvedad de que el contenido es ahora # application/octet-stream ya que contiene un fichero ejecutable Si analizas un mensaje de correo # y la disposicion es attachment, no tiene sentido tratar que contenga un fichero adjunto – # de visualizar un fichero zip propiedades, ver codificación–, podrás ver esa fragmentación tan $adj2 .="Content-Type: application/octet-stream;"; cuidada -un montón de líneas de $adj2 .=" name="apachito.zip"".$UN_SALTO; texto muy raro- perfectamente $adj2 .="Content-Disposition: attachment; alineadas por los márgenes por filename="apachito.zip"".$UN_SALTO; efecto de chunk_split. $adj2 .="Content-Transfer-Encoding: base64".$DOS_SALTOS; Inserción en el cuerpo /* Lectura previa del fichero a adjuntar La fase final del proceso es la de ------------------------------------------ */ agrupar los diferentes trozos en # abrimos el fichero en modo lectura (r) una sola variable, que será la que # y leemos todo su contenido midiendo previamente se insertará como parámetro texto # su longitud con filesize en la función e-mail. # recogemos en $buff el contenido del fichero ¡Cuidado! # y cerramos después La inserción de ficheros adjuntos $fp = fopen("apachito.zip", "r"); requiere que éstos estén $buff = fread($fp, filesize("apachito.zip")); disponibles en el servidor por lo fclose($fp); que, antes de enviarlos, habrá que subirlos al servidor utilizando un /* Codificación del fichero a adjuntar proceso como el que hemos analizado cuando hablábamos de ------------------------------------------ */ Transferencia de ficheros. $adj2 .=chunk_split(base64_encode($buff)); Sobre los ejemplos /* Separador final YA NO HAY MAS PARTES ---------------------------------------- */ Hemos incluido dos ejemplos relativos al envío de ficheros en $adj2 .=$UN_SALTO."--$separador".$UN_SALTO; formato HTML y con ficheros adjuntos. /* Unión de todas las PARTES No entraremos en el estudio ---------------------------------------- */ detallado del MIME. # unimos en la variable mensaje todos los elementos # y lo hacemos por el orden en el que fueron creados Quedaremos únicamente en sus aspectos funcionales en cuanto a $mensaje=$texto.$adj1.$adj2; los requerimientos de formato, separadores, etc. /* Envio del mensaje Quizá te parezca obsesivo el ---------------------------------------- */ hincapié que hacemos en los ejemplos sobre los detalles de la if(mail($destinatario, $titulo, $mensaje,$cabecera)){ sintaxis. echo "mensaje enviado"; } Nuestra insistencia se debe al carácter sumamente estricto de la ?> especificación MIME, donde un simple salto de línea puede ser la causa de que script deje de ejemplo101.php funcionar. Ejercicio nº 32 Diseña un script de forma que al cargarse la página que lo contiene se envíe –de forma automática– un mensaje de correo, indicando la fecha y hora de acceso, al usuario juan@mispruebas.com Anterior Indice Siguiente

×