Lenguajes - Enviar un email con un archivo adjunto

Junio 2017

Tanto los emails como las páginas web contienen cabeceras (headers en inglés).
Estas cabeceras sirven para dar información necesaria como la dirección del destinatario, la del remitente, la fecha de envío, el asunto del email, etc.
Estas son organizadas de la siguiente manera:
Nombre_cabecera: valor\n\r
Nombre_cabecera: valor\n\r
[...]
Nombre_cabecera: valor\n\n\r
Cuerpo del mensaje…

Donde “\n” significa retorno a la línea, y “\r” para situarse al inicio de la línea.

En parte trabajando con estas cabeceras es que podemos enviar un email con un archivo adjunto por medio de un programa.
Las cabeceras indican también el tipo de mensaje: email en html, email con solo texto, etc.
Para enviar un email con un archivo adjunto, debemos darle el tipo multipart/mixed para señalar que se encontrarán varias partes en ese email (aquí, el mensaje principal y el archivo adjunto).

Para separar estas partes se utiliza lo que se llama una “frontera” (boundary en inglés).
Esta frontera debe ser una cadena de caracteres única para que no sea encontrada en nuestro mensaje principal.

Por ejemplo "didondinaditondelosdudosdodudundodudindon" (utiliza de preferencia caracteres acsii, yo no sé como un cliente de correo electrónico reaccionara con caracteres avanzados).
Para nuestras cabeceras nos contentaremos con declarar la dirección del remitente, la versión de MIME y el tipo de mensaje, y como es un mensaje con archivo adjunto, debemos precisar la frontera:
From: remitente@dominio.es\r\n
MIME-Version: 1.0\r\n
Content-Type: multipart/mixed; boundary="didondinaditondelosdudosdodudundodudindon"\r\n\n

(Observa que el final de las cabeceras se caracteriza por dos saltos de línea).
Para comenzar una parte del cuerpo del email, comenzaremos mostrando la frontera. Cuando una frontera abre una parte, es precedida de dos guiones: “—“. La terminaremos con un salto de línea:
--didondinaditondelosdudosdodudundodudindon\n


Vamos a indicar que el mensaje legible del email será un simple texto. Entonces ponemos le tipo de esta parte (con el conjunto de caracteres que conviene, aquí el conjunto de caracteres que utiliza el alfabeto español):
Content-Type: text/plain; charset=ISO-8859-1\r\n\n

Mensaje principal del mail.\n\n
En lo que sigue, nos interesaremos al archivo adjunto. Para poner datos binarios en un email, por lo general se utiliza un estándar llamado base64 que permite transformar estos datos en caracteres.
Entonces vamos a mover nuestra frontera para delimitar esta parte y precisar en nuestras cabeceras:
-El tipo de archivo (vamos a utilizar un doc como Word)
-El tipo de codificación del archivo (aquí base64)
-la disposición del archivo en el email (archivo adjunto) y su nombre.
--didondinaditondelosdudosdodudundodudindon\n
Content-Type: application/msword; name="nombre_archivo"\r\n
Content-Transfer-Encoding: base64\r\n
Content-Disposition: attachment; filename="nombre_archivo"\r\n\n


A continuación, mostraremos el contenido de nuestro archivo codificado en base64.

Y finalmente, cerraremos nuestra frontera.
Para cerrar una frontera, hay que hacerla seguir y preceder de dos guiones "--", o sea:
--didondinaditondelosdudosdodudundodudindon--\n

Y listo el email no tiene más que ser enviado.
Cuestión de concretizar todo esto, vamos a implementar el envío de este email en Php (práctico con sus funciones email() y base64_encode() todas listas):
<?php
$boundary='didondinaditondelosdudosdodudundodudindon';
//Cabeceras del email
$headers="From: remitente@dominio.es\r\n
MIME-Version: 1.0\r\n
Content-Type: multipart/mixed; boundary=\"$boundary\"\r\n\n";

//Cuerpo del email comenzando por el mensaje principal
$body="--". $boundary ."\n
Content-Type: text/plain; charset=ISO-8859-1\r\n\n
Mensaje principal del email.\n\n";

/* Archivo adjunto, vamos a indicar que nuestro archivo se llama bidule.doc y que se encuentra
 en el directorio actual */

$archivo=file_get_contents('./bidule.doc');
/* Utilizaremos chunk_split() que organizará come se debe la codificación hecha en base 64 para
 estar conforme a los estándares */
$archivo=chunk_split( base64_encode($archivo) );

//Escritura del archivo adjunto
$body = $body . "--" .$boundary. "\n
Content-Type: application/msword; name=\"nombre_archivo\"\r\n
Content-Transfer-Encoding: base64\r\n
Content-Disposition: attachment; filename=\"nombre_archivo\"\r\n\n
$archivo";

//Cierre de la frontera
$body = $body . "--" . $boundary ."--";

//Envío del email
email("destinatario@bidule.es", "objeto", $body, $headers);
?>

Y listo :-)

Fuente:
-http://www.hochfeiler.it/alvise/smtp.htm
-http://fr2.php.net/manual/es/function.mail.php (ver ejemplos en la discusión)

Consulta también

Publicado por Carlos-vialfa. Última actualización: 15 de agosto de 2008 a las 01:37 por Carlos-vialfa.
El documento «Lenguajes - Enviar un email con un archivo adjunto» se encuentra disponible bajo una licencia Creative Commons. Puedes copiarlo o modificarlo libremente. No olvides citar a CCM (es.ccm.net) como tu fuente de información.