public function testEmbeddedFilesWithMultipartDataCreateMultipartRelatedContentAsAnAlternative() { $message = Swift_Message::newInstance(); $message->setCharset('utf-8'); $message->setSubject('test subject'); $message->addPart('plain part', 'text/plain'); $image = Swift_Image::newInstance('<image data>', 'image.gif', 'image/gif'); $cid = $message->embed($image); $message->setBody('<img src="' . $cid . '" />', 'text/html'); $message->setTo(array('*****@*****.**' => 'User')); $message->setFrom(array('*****@*****.**' => 'Other')); $message->setSender(array('*****@*****.**' => 'Other')); $id = $message->getId(); $date = preg_quote(date('r', $message->getDate()), '~'); $boundary = $message->getBoundary(); $cidVal = $image->getId(); $this->assertRegExp('~^' . 'Sender: Other <*****@*****.**>' . "\r\n" . 'Message-ID: <' . $id . '>' . "\r\n" . 'Date: ' . $date . "\r\n" . 'Subject: test subject' . "\r\n" . 'From: Other <*****@*****.**>' . "\r\n" . 'To: User <*****@*****.**>' . "\r\n" . 'MIME-Version: 1.0' . "\r\n" . 'Content-Type: multipart/alternative;' . "\r\n" . ' boundary="' . $boundary . '"' . "\r\n" . "\r\n\r\n" . '--' . $boundary . "\r\n" . 'Content-Type: text/plain; charset=utf-8' . "\r\n" . 'Content-Transfer-Encoding: quoted-printable' . "\r\n" . "\r\n" . 'plain part' . "\r\n\r\n" . '--' . $boundary . "\r\n" . 'Content-Type: multipart/related;' . "\r\n" . ' boundary="(.*?)"' . "\r\n" . "\r\n\r\n" . '--\\1' . "\r\n" . 'Content-Type: text/html; charset=utf-8' . "\r\n" . 'Content-Transfer-Encoding: quoted-printable' . "\r\n" . "\r\n" . '<img.*?/>' . "\r\n\r\n" . '--\\1' . "\r\n" . 'Content-Type: image/gif; name=image.gif' . "\r\n" . 'Content-Transfer-Encoding: base64' . "\r\n" . 'Content-Disposition: inline; filename=image.gif' . "\r\n" . 'Content-ID: <' . $cidVal . '>' . "\r\n" . "\r\n" . preg_quote(base64_encode('<image data>'), '~') . "\r\n\r\n" . '--\\1--' . "\r\n" . "\r\n\r\n" . '--' . $boundary . '--' . "\r\n" . '$~D', $message->toString()); }
/** * Embed files into message * Note: Is better to use the Message object directly * * @param string Path or dynamic * @param string|mixed Path to file or file content when type is dynamic * @param string File name * @param string Mime type of image * @return int */ public function embed($type, $file = '', $name = null, $content_type = null) { switch ($type) { case 'path': if ($file == '') { return; } return $this->swMessage->embed(Swift_Image::fromPath($file)); break; case 'dynamic': if ($file == null || $file == '') { return; } return $this->swMessage->embed(Swift_Image::newInstance($file, $name, $content_type)); } }
/** * Process inline images. Convert it to embedded attachments and update message body. * * @param \Swift_Message $message * @param EmailModel $model */ protected function processEmbeddedImages(\Swift_Message $message, EmailModel $model) { if ($model->getType() === 'html') { $guesser = ExtensionGuesser::getInstance(); $body = $message->getBody(); $body = preg_replace_callback('/<img(.*)src(\\s*)=(\\s*)["\'](.*)["\']/U', function ($matches) use($message, $guesser, $model) { if (count($matches) === 5) { // 1st match contains any data between '<img' and 'src' parts (e.g. 'width=100') $imgConfig = $matches[1]; // 4th match contains src attribute value $srcData = $matches[4]; if (strpos($srcData, 'data:image') === 0) { list($mime, $content) = explode(';', $srcData); list($encoding, $file) = explode(',', $content); $mime = str_replace('data:', '', $mime); $fileName = sprintf('%s.%s', uniqid(), $guesser->guess($mime)); $swiftAttachment = \Swift_Image::newInstance(ContentDecoder::decode($file, $encoding), $fileName, $mime); /** @var $message \Swift_Message */ $id = $message->embed($swiftAttachment); $attachmentContent = new EmailAttachmentContent(); $attachmentContent->setContent($file); $attachmentContent->setContentTransferEncoding($encoding); $emailAttachment = new EmailAttachment(); $emailAttachment->setEmbeddedContentId($swiftAttachment->getId()); $emailAttachment->setFileName($fileName); $emailAttachment->setContentType($mime); $attachmentContent->setEmailAttachment($emailAttachment); $emailAttachment->setContent($attachmentContent); $emailAttachmentModel = new EmailAttachmentModel(); $emailAttachmentModel->setEmailAttachment($emailAttachment); $model->addAttachment($emailAttachmentModel); return sprintf('<img%ssrc="%s"', $imgConfig, $id); } } }, $body); $message->setBody($body, 'text/html'); } }
/** * Recursively embed all images in the array into the message * @param \Swift_Message $message * @param array $params * @return array $params */ private function embedImages(&$message, &$params) { // loop through the array foreach ($params as $key => $value) { // if the current value is an array if (is_array($value)) { // search for more images deeper in the arrays $value = $this->embedImages($message, $value); $params[$key] = $value; // if the current value is an existing file from the image-folder, embed it } elseif (is_string($value)) { if (is_file($value)) { // check if the file is from an allowed folder if ($this->templateProvider->isFileAllowed($value) !== false) { $encodedImage = $this->cachedEmbedImage($value); if ($encodedImage != null) { $id = $message->embed($encodedImage); $params[$key] = $id; } } // the $filePath isn't a regular file } else { // add a null-value to the cache for this path, so we don't try again. $this->imageCache[$value] = null; } //if the current value is a generated image } elseif (is_resource($value) && stripos(get_resource_type($value), "gd") == 0) { // get the image-data as string ob_start(); imagepng($value); $imageData = ob_get_clean(); // encode the image $encodedImage = \Swift_Image::newInstance($imageData, "generatedImage" . md5($imageData)); $id = $message->embed($encodedImage); $params[$key] = $id; } else { // don't do anything } } // remove duplicate-attachments $message->setChildren(array_unique($message->getChildren())); return $params; }
/** * Embed a file from a string. Returns the CID id. * * @param $fileContent * @param $filename * @param string $mimeType * @return string */ public function embedFromStream($fileContent, $filename, $mimeType = 'image/jpeg') { return $this->messageInstance->embed(\Swift_Image::newInstance($fileContent, $filename, $mimeType)); }
/** * Process inline images.. * * @param Swift_Message $m * The message which inline images are to be added to. * @param array $images * The images which are to be added as inline images to the provided * message. */ private function embed(Swift_Message $m, array $images) { // Iterate through each array element. foreach ($images as $image) { if ($image instanceof \stdClass) { // Validate required fields. if (empty($image->uri) || empty($image->filename) || empty($image->filemime) || empty($image->cid)) { continue; } // Keep track of the 'cid' assigned to the embedded image. $cid = NULL; // Get image data. if (UrlHelper::isValid($image->uri, TRUE)) { $content = file_get_contents($image->uri); } else { $content = file_get_contents(\Drupal::service('file_system')->realpath($image->uri)); } $filename = $image->filename; $filemime = $image->filemime; // Embed image. $cid = $m->embed(Swift_Image::newInstance($content, $filename, $filemime)); // The provided 'cid' needs to be replaced with the 'cid' returned // by the Swift Mailer library. $body = $m->getBody(); $body = preg_replace('/cid.*' . $image->cid . '/', $cid, $body); $m->setBody($body); } } }
/** * Process inline images.. * * @param \Swift_Message $m * The message which inline images are to be added to. * @param array $images * The images which are to be added as inline images to the provided * message. */ protected function embed(\Swift_Message $m, array $images) { // Iterate through each array element. foreach ($images as $image) { if ($image instanceof \stdClass) { // Validate required fields. if (empty($image->uri) || empty($image->filename) || empty($image->filemime) || empty($image->cid)) { continue; } // Get image data. if (valid_url($image->uri, true)) { $content = file_get_contents($image->uri); } else { $content = file_get_contents(drupal_realpath($image->uri)); } $filename = $image->filename; $filemime = $image->filemime; // Embed image. $cid = $m->embed(\Swift_Image::newInstance($content, $filename, $filemime)); // The provided 'cid' needs to be replaced with the 'cid' returned // by the Swift Mailer library. $body = $m->getBody(); $body = preg_replace('/cid.*' . $image->cid . '/', $cid, $body); $m->setBody($body); } } }
/** * Add embedded HTML images (image dir) * * @access protected * @param Swift_Message $message */ protected function add_html_images(&$message) { $path = Config::$email_directory . '/media/'; if (!file_exists($path)) { return; } $html_body = $message->getBody(); if ($handle = opendir($path)) { while (false !== ($file = readdir($handle))) { if (substr($file, 0, 1) != '.' && strpos($html_body, $file) !== false) { $swift_image = \Swift_Image::newInstance(file_get_contents($path . $file), $file, Util::mime_type($path . $file)); $html_body = str_replace($file, $message->embed($swift_image), $html_body); } } } $message->setBody($html_body); closedir($handle); }