FawnoEmail: enviar emails desde CakePHP con imágenes embebidas

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:

  1. Detectar automáticamente los tipos MIME
  2. 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.

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *