Una de las ventajas de utilizar un Framework como CakePHP es que enviar emails es muy sencillo.
Sin embargo hay dos cosas que la clase CakeEmail no hace:
- Detectar automáticamente los tipos MIME
- Embeber automáticamente las imágenes
Para solucionar ambos puntos he creado una clase que extiende a CakeEmail dotándola de estas funcionalidades: FawnoEmail.
Para añadir la detección de los tipos MIME he clonado la función attachments de la clase original y le he añadido el siguiente código:
if (!isset($fileInfo['mimetype'])) {
if (function_exists('mime_content_type')) {
$fileInfo['mimetype'] = mime_content_type($fileInfo['file']);
} else {
$fileInfo['mimetype'] = 'application/octet-stream';
}
}
Básicamente CakeEmail establece el MimeType como ‘application/octet-stream’ para todos los adjuntos que no especifiquen explícitamente un MimeType. Lo que he hecho es detectar si existe la función “mime_content_type” y usarla en caso afirmativo.
En teoría la función “mime_content_type” existe desde la versión 4.3 de PHP y por tanto no sería necesario comprobar la existencia de la función…
Para embeber las imágenes de manera automática he extendido la función _renderTemplates. En términos sencillos el truco consiste en obtener el renderizado del mail antes de ser enviado, de esta forma buscamos las imágenes a embeber y procedemos a ello.
La primera dificultad es determinar las imágenes que hay que embeber, lo he solucionado buscando todos las rutas que comiencen por “file:”, “file://”, “cid:” y “cid://”.
Para cada imagen genero un contentId que utilizo para adjuntar la imagen y luego como ruta en el cuerpo del mail:
$rendered = parent::_renderTemplates($content);
if (!empty($rendered['html'])) {
$rendered['html'] = str_replace(array('file:', 'file://', 'cid://'), 'cid:', $rendered['html']);
if (preg_match_all('~(["\'])cid:([^\1]+)\1~iU', $rendered['html'], $img)) {
$img = array_unique($img[2]);
foreach ($img as $file) if (is_file($file)) {
$cid = sha1($file);
$images['cid:' . $cid] = array('file' => $file, 'contentId' => $cid);
$files['cid:' . $cid] = $file;
$cids['cid:' . $cid] = $cid;
}
$this->addAttachments($images);
$rendered['html'] = str_replace($files, $cids, $rendered['html']);
}
}
En el GitHub de Fawno tenéis disponible la clase.