Jump to content
  • Checkout
  • Login
  • Get in touch

osCommerce

The e-commerce.

Embed images in html emails?


Carbon

Recommended Posts

Hi,

 

I'm trying to send html emails from OSC that have the images embedded (not attached) so that the html formatted email message and relevant images are displayed in the customer's email client (e.g. Outlook) without them having to click the "Some images have been blocked...." message header bar.

 

I start off by defining the html and the text version of the message as well as defining the dir that contains the used images...

 

<?php
$html = 'THE HTML MESSAGE WITH ABSOLUTE URLs FOR IMAGES e.g. <img src="http://www.somewhere.com/images/image.gif">';
$text = 'THE TEXT MESSAGE';
$imagedir = 'http://www.somewhere.com/images/";
?>

 

Then using "email.php" which is included I construct and send the email...

 

<?php
$email_message = new email(array('X-Mailer: osCommerce Mailer'));
$email_message->add_html($html, $text, $imagedir);
$email_message->build_message();
$email_message->send($order->customer['name'], $order->customer['email_address'], STORE_OWNER, STORE_OWNER_EMAIL_ADDRESS, EMAIL_TEXT_SUBJECT);
?>

 

As originally stated, this all works fine but the code is NOT embedding the images, so I have followed the code trail but can't figure out why it's not working...

 

So, using the above snippet, the first thing that happens is a new email is set up...

 

$email_message = new email(array('X-Mailer: osCommerce Mailer'));

 

Next we make a call to the function "add_html" (included in email.php class) and supply three parameters (the html message, the text message and the image dir)...

 

$email_message->add_html($html, $text, $imagedir);

 

Here is the function copied from email.php...

 

	function add_html($html, $text = NULL, $images_dir = NULL) {
  $this->html = tep_convert_linefeeds(array("\r\n", "\n", "\r"), '<br>', $html);
  $this->html_text = tep_convert_linefeeds(array("\r\n", "\n", "\r"), $this->lf, $text);

  if (isset($images_dir)) $this->find_html_images($images_dir);
}

 

So, we know that the $html and the $text gets added ok so the bit we're interested in is the "if (isset($images_dir)) $this->find_html_images($images_dir);" line which essentially says... if $images_dir is passed as a parameter (which it is, and I've also tried just declaring the string) then pass "http://www.somewhere.com/images/" as the string $images_dir to the find_html_images function.

 

OK so let's follow the code trail...

 

	function find_html_images($images_dir) {
// Build the list of image extensions
  while (list($key, ) = each($this->image_types)) {
	$extensions[] = $key;
  }

  preg_match_all('/"([^"]+\.(' . implode('|', $extensions).'))"/Ui', $this->html, $images);

  for ($i=0; $i<count($images[1]); $i++) {
	if (file_exists($images_dir . $images[1][$i])) {
	  $html_images[] = $images[1][$i];
	  $this->html = str_replace($images[1][$i], basename($images[1][$i]), $this->html);
	}
  }

  if (tep_not_null($html_images)) {
// If duplicate images are embedded, they may show up as attachments, so remove them.
	$html_images = array_unique($html_images);
	sort($html_images);

	for ($i=0; $i<count($html_images); $i++) {
	  if ($image = $this->get_file($images_dir . $html_images[$i])) {
		$content_type = $this->image_types[substr($html_images[$i], strrpos($html_images[$i], '.') + 1)];
		$this->add_html_image($image, basename($html_images[$i]), $content_type);
	  }
	}
  }
}

 

Not entirely sure what happens here but it looks like it takes a look into the images dir (passed as $images_dir) and builds a list (array) of the images it finds and then modifies the names in the list from "image1.gif" to "image1" (or something similar... not that important right now).

 

The function then removes any duplicate entries from the list and goes through the html part of the message ($html) that was "added" replacing image references with modified versions, probably changing "<img scr="http://www.somewhere.com/images/image1.gif" to something like "<img src="image1">. Again the finer details here aren't that important.

 

The last part of the function "$this->add_html_image($image, basename($html_images[$i]), $content_type);" seems to take the list of unique images used in the html part and pass it to another function called "add_html_image".

 

OK so let's follow the code trail...

 

	function add_html_image($file, $name = '', $c_type='application/octet-stream') {
  $this->html_images[] = array('body' => $file,
							   'name' => $name,
							   'c_type' => $c_type,
							   'cid' => md5(uniqid(time())));
}

 

This function seems to take the image list and modify further to add name, type and a unique identifier. The code trail ends here so we go back to our original code which calls the "build_message()" function.

 

This function is supposed to read in all of the images from the above list, encode them and add it to the html email message (this doesn't happen as the images don't appear in the recieved email source), also it should (I think) change all of the image references in the html part to point to the encoded image using cid: and name to match the html image to the encoded image.

 

Any help greatly appreciated.

 

Cheers

 

Carbon

Link to comment
Share on other sites

  • 2 years later...

Since my newsletter images (and store logos) are located in different folders, I changed the function below to replace the relative paths by absolute paths correctly.

 

   function find_html_images($images_dir) {
// Build the list of image extensions
     while (list($key, ) = each($this->image_types)) {
       $extensions[] = $key;
     }

     preg_match_all('/"([^"]+\.(' . implode('|', $extensions).'))"/Ui', $this->html, $images);


  for ($i=0; $i<count($images[1]); $i++) {
       if (file_exists(str_replace(HTTP_SERVER.DIR_WS_CATALOG, DIR_FS_DOCUMENT_ROOT,$images[1][$i]))) {
         $html_images[] = str_replace(HTTP_SERVER.DIR_WS_CATALOG, DIR_FS_DOCUMENT_ROOT,$images[1][$i]);
         $this->html = str_replace(HTTP_SERVER.DIR_WS_CATALOG, DIR_FS_DOCUMENT_ROOT, $this->html);
       }
     }


  if (tep_not_null($html_images)) {
// If duplicate images are embedded, they may show up as attachments, so remove them.
       $html_images = array_unique($html_images);
       sort($html_images);

       for ($i=0; $i<count($html_images); $i++) {
         if ($image = $this->get_file($html_images[$i])) {
           $content_type = $this->image_types[substr($html_images[$i], strrpos($html_images[$i], '.') + 1)];
           $this->add_html_image($image, $html_images[$i], $content_type);
         }
       }
     }
   }

Link to comment
Share on other sites

  • 5 months later...

The email-Class has a bug. You'll have to replace the original code with the following to get OSC to embed images in HTML-mails:

classes/email.php:

function find_html_images($images_dir) {

// Build the list of image extensions
     while (list($key, ) = each($this->image_types)) {
       $extensions[] = $key;
     }

     preg_match_all('/"([^"]+\.(' . implode('|', $extensions).'))"/Ui', $this->html, $images);
     for ($i=0; $i<count($images[1]); $i++) {
       if (file_exists($images_dir . [b]basename([/b]$images[1][$i][b])[/b])) {
         $html_images[] = $images[1][$i];
         $this->html = str_replace($images[1][$i], basename($images[1][$i]), $this->html);
       }
     }

     if (tep_not_null($html_images)) {
// If duplicate images are embedded, they may show up as attachments, so remove them.
       $html_images = array_unique($html_images);
       sort($html_images);

       for ($i=0; $i<count($html_images); $i++) {
         if ($image = $this->get_file($images_dir . [b]basename([/b]$html_images[$i][b])[/b])) {
           $content_type = $this->image_types[substr($html_images[$i], strrpos($html_images[$i], '.') + 1)];
           $this->add_html_image($image, basename($html_images[$i]), $content_type);
         }
       }
     }
   }

 

and

 

functions/general.php:

  function tep_mail($to_name, $to_email_address, $email_subject, $email_text, $from_email_name, $from_email_address) {
   if (SEND_EMAILS != 'true') return false;

   // Instantiate a new mail object
   $message = new email(array('X-Mailer: osCommerce'));

   // Build the text version
   $text = strip_tags($email_text);
   if (EMAIL_USE_HTML == 'true') {
     $message->add_html($email_text, $text[b], DIR_FS_CATALOG . DIR_WS_IMAGES[/b]);
   } else {
     $message->add_text($text);
   }

   // Send message
   $message->build_message();
   $message->send($to_name, $to_email_address, $from_email_name, $from_email_address, $email_subject);
 }

Link to comment
Share on other sites

Shit - forum doesn't display the '' correct in the code-snippets. Use this corrected version.

The email-Class has a bug. You'll have to replace the original code with the following to get OSC to embed images in HTML-mails:

classes/email.php:

function find_html_images($images_dir) {

// Build the list of image extensions
     while (list($key, ) = each($this->image_types)) {
       $extensions[] = $key;
     }

     preg_match_all('/"([^"]+\.(' . implode('|', $extensions).'))"/Ui', $this->html, $images);
     for ($i=0; $i<count($images[1]); $i++) {
       if (file_exists($images_dir . basename($images[1][$i]))) {
         $html_images[] = $images[1][$i];
         $this->html = str_replace($images[1][$i], basename($images[1][$i]), $this->html);
       }
     }

     if (tep_not_null($html_images)) {
// If duplicate images are embedded, they may show up as attachments, so remove them.
       $html_images = array_unique($html_images);
       sort($html_images);

       for ($i=0; $i<count($html_images); $i++) {
         if ($image = $this->get_file($images_dir . basename($html_images[$i]))) {
           $content_type = $this->image_types[substr($html_images[$i], strrpos($html_images[$i], '.') + 1)];
           $this->add_html_image($image, basename($html_images[$i]), $content_type);
         }
       }
     }
   }

 

and

 

functions/general.php:

  function tep_mail($to_name, $to_email_address, $email_subject, $email_text, $from_email_name, $from_email_address) {
   if (SEND_EMAILS != 'true') return false;

   // Instantiate a new mail object
   $message = new email(array('X-Mailer: osCommerce'));

   // Build the text version
   $text = strip_tags($email_text);
   if (EMAIL_USE_HTML == 'true') {
     $message->add_html($email_text, $text, DIR_FS_CATALOG . DIR_WS_IMAGES);
   } else {
     $message->add_text($text);
   }

   // Send message
   $message->build_message();
   $message->send($to_name, $to_email_address, $from_email_name, $from_email_address, $email_subject);
 }

Link to comment
Share on other sites

  • 5 months later...

Hi, there verry intresting... I tried this a little Time ago, with no Result.

 

So how can I embed a Picture now?

 

I tried <img src="cid:imagename"> in the Text

 

an tried to embed it with $message->add_html_image('jpg','imagename');

 

what did I get wrong?

 

best regards

life long and knusper

Link to comment
Share on other sites

My current find_html_images()-function looks like:

    function find_html_images($images_dir) {

// Build the list of image extensions
     while (list($key, ) = each($this->image_types)) {
       $extensions[] = $key;
     }

     preg_match_all('/"([^"]+\.(' . implode('|', $extensions).'))"/Ui', $this->html, $images);
     for ($i=0; $i<count($images[1]); $i++) {
	$new_img = str_replace(HTTP_SERVER . DIR_WS_HTTP_CATALOG, '', $images[1][$i]);
	if (strlen(DIR_WS_HTTP_CATALOG) > 1) $new_img = str_replace(DIR_WS_HTTP_CATALOG,'',$new_img);	
       if (file_exists( DIR_FS_CATALOG .  $new_img)) {
         $html_images[] = $new_img;
         $this->html = str_replace($images[1][$i], basename($images[1][$i]), $this->html);
       }
     }

     if (tep_not_null($html_images)) {
// If duplicate images are embedded, they may show up as attachments, so remove them.
       $html_images = array_unique($html_images);
       sort($html_images);

       for ($i=0; $i<count($html_images); $i++) {
         if ($image = $this->get_file(DIR_FS_CATALOG . $html_images[$i])) {
           $content_type = $this->image_types[substr($html_images[$i], strrpos($html_images[$i], '.') + 1)];
           $this->add_html_image($image, basename($html_images[$i]), $content_type);
         }
       }
     }
   }

 

Just use images with relative path in your HTML:

<img src="images/test.gif">

or absolute path:

<img src="http://your_server.com/catalog/images/test.gif">

Absolute path has to begin with "HTTP_SERVER . DIR_WS_HTTP_CATALOG" (e.g. http://your_server.com/catalog/).

Both examples will be converted to embedded images in HTML-emails.

 

Don't use "$message->add_html_image" as it only attaches a image to the email (e.g. $message->add_html_image("images/test.gif","Testimage")), but afterwards you'll don't have a reference (the "cid") to this image, so you can't use it in HTML.

Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.

×
×
  • Create New...