Adjuntar archivos en emails de CakePhp

Adjuntar archivos en emails de CakePhp

 

Una cosa que se echa mucho de menos la desarrollar con CakePhp es la falta de poder adjuntar archivos en Emails enviados con el componente de serie incoroporado en CakePHP, pero no os preocupeis, hemos descubierto que hacerlo es mucho más facil de lo que os pueda parecer a simple vista:

Necesitaremos editar el componente email original de Cake, por lo que o lo editais directamente en libs de Cake o lo copiais a vuestra carpeta de componentes.
Si no lo copiais debeis tener en cuenta que si algún día actualizais la versión de Cakephp perderéis los cambios que hagais ahora.

El componente original lo encontrareis en: /cake/libs/controller/components/email.php
Os recomiendo que lo copieis a: /app/controllers/components/email.php

Al copiarlo estareis editando una copia del componente original, por lo que podeis actualizar Cakphp y todo seguirá enviado correos igualmente con adjuntos, mantendreis el control, y si Cake actualiza el componente no os afectará y siempre tendreis la posibilidad de actualizarlo manualmente sin sorpresas.

Los cambios

Alrededor de la línea 481:
Cambiar:

$this->__header[] = 'Content-Type: multipart/mixed; boundary="' . $this->__boundary . '"';

Por:

$this->__header[] = 'Content-Type: multipart/related; boundary="' . $this->__boundary . '"';

Alrededor de la línea 521, cambiar:

			$file = $this->__findFiles($attachment);
 			if (!empty($file)) {
 				$files[] = $file;
			}
 		}
		foreach ($files as $file) {
 			$handle = fopen($file, 'rb');
 			$data = fread($handle, filesize($file));
 			$data = chunk_split(base64_encode($data)) ;
 			fclose($handle);

 			$this->__message[] = '--' . $this->__boundary;
			$this->__message[] = 'Content-Type: application/octet-stream';
 			$this->__message[] = 'Content-Transfer-Encoding: base64';
			$this->__message[] = 'Content-Disposition: attachment; filename="' . basename($file) . '"';

Por esto otro:

			if (is_array($attachment)) {
				$file = $this->__findFiles($attachment['filename']);
				$mimetype = $attachment['mimetype'];
				$cid = $attachment['cid'];
			}
			else {
				$file = $this->__findFiles($attachment);
				$mimetype = 'application/octet-stream';
				$cid = '';
			}
 			if (!empty($file)) {
 				$files[] = $file;
				$mimetypes[] = $mimetype;
				$cids[] = $cid;
			}
 		}

		foreach ($files as $index=>$file) {
 			$handle = fopen($file, 'rb');
 			$data = fread($handle, filesize($file));
 			$data = chunk_split(base64_encode($data)) ;
 			fclose($handle);

 			$this->__message[] = '--' . $this->__boundary;
			$this->__message[] = 'Content-Type: '.$mimetypes[$index];
 			$this->__message[] = 'Content-Transfer-Encoding: base64';
			if ($cids[$index] != '') {
				$this->__message[] = 'Content-ID: ';
				$this->__message[] = 'Content-Disposition: inline; filename="' . basename($file) . '"';
			}
			else
				$this->__message[] = 'Content-Disposition: attachment; filename="' . basename($file) . '"';

 

El uso cotidiano

Ya habeis terminado con los cambios en el componente, podéis cerrarlo, y directamente abrir un controlador donde envieis correo y donde esteis enviado el correo, antes de la funcion $this->Email->send(); incluis lo siguiete.

$this->Email->attachments = array (
     array('filename'=>ROOT.'/app/webroot/img/logo.png',
     'mimetype'=>'image/png',
     'cid'=>'part1.1.1@domain.com'),
  );

De esta sencilla manera, en el email ya disponeis adjunto del logo.png alojado en la carpeta IMG, sólo te queda mostrarlo directamente en el layout o el la vista con el siguiente tag:

<img src="cid:part1.1.1@domain.com" ...>

Comparte este artículo