| Recommend this page to a friend! |
| PHP MIME Email Message Parser | > | All threads | > | solution to cid:inline/embedded images | > | (Un) Subscribe thread alerts |
| |||||||||||||||
Hello,
Here's my little contribution to this excellent script, hope it helps some other's stranded by the same problem. First.. tweak your mime_parser to save the body parts with their original name (which will in turn save the inline images with their corresponding filename of image001..002 etc... (inline images are not saved with their original name from the beginning just check your var_dump($results)).... So.. the tweak for mime_parser.php: under the >Function DecodeStream($parameters, &$end_of_message, &$decoded) under the >case MIME_MESSAGE_GET_BODY: find the line starting with: $path= goto the end of the line and replace: .strval($this->body_part_number); with: .$this->$name; .... that's the end of the tweak for mime_parser so it saves the body parts with their corresponding original file name. Once this is done, and with decode_bodies=1; and 'SaveBody'=>'/path' enabled... Here it comes... Before you echo $results['Data'].. add the following.. /////////////////// embedded inline images with CID by Nstiac $str=$results['Data']; if (count($results['Related'])>0) { for ($temp=0; $temp<count($results['Related']); $temp++) { $str=ereg_replace($results['Related'][$temp]['ContentID'],$results['Related'][$temp]['FileName'],$str); } } $str=ereg_replace('cid:',"path-to-your-saved-images-folder",$str); $results['Data']=$str; /////////////////// and just echo the results... images should show up.. if they dont, check the html source of your parsed email to find out what's wrong with the path =) Hope this helps in making mime_parser and the rest of the mail classes from Manuel more useful. p.s.- Kudos to Manuel for this excellent set of mail classes!
Just be careful when you use the original message file names.
The reason why the class does not use the original file names is because the message may contain a malicious file name that may overwrite important files in other directories in your system. Imagine if the file name is /etc/passwd or /etc/shadow . At least you should use the PHP basename() function to make sure the file name does not include directory path names.
Excellent suggestion!
I'm not that into security, so it's a great thing you tell me this. Thank you,
i tried your solution but there is some problem with replacing
strval($this->body_part_number); with .$this->$name even .$this->name produces errors if i use strval($this->body_part_number); it creates files with name as body_part_number's value and no file extention. I want to display inline images or save them as attachments can u please help me!!!
You are using the class private variables. Do not use them.
If you want to find the message parts of HTML images or other embedded parts, you should look at the message-id: header of each part.
Hi there,
I'm also trying to get this solution to work, but I'm getting an error when trying to access $this->name too. Manuel, thanks so much for your class, but I'm also running into the need to parse inline/embedded images and then saving them as a file. I've already got this done for real attachments, but I can't figure out how to get the inline ones. I'm not quite sure this solution posted is the right one. If you have some time can you help point me in the right direction? I'm very new to working with emails and I understand it gets pretty complicated. Anything would help. Thanks, Calvin
Bare in mind this tweak was done for :
/* * mime_parser.php * * @(#) $Id: mime_parser.php,v 1.60 2008/07/17 00:54:24 mlemos Exp $ * */ Ah.. and forgot something before line $path= must add: if ($decoded['FileName']!="") { $name=$decoded['FileName']; } else { $name="part".strval($this->body_part_number); } // so to give $name an actual value =) And do not forget to add Manuel security precaution by changing .$this->$name to .$this->tempvar.basename($name) so it looks like: case MIME_MESSAGE_GET_BODY: switch($type) { case 'BodyData': if(IsSet($parameters['SaveBody'])) { if(!IsSet($decoded['BodyFile'])) { if ($decoded['FileName']!="") { $name=$decoded['FileName']; } else { $name="part".strval($this->body_part_number); } /* do not forget that some filenames come encoded on ISO-8859-1 or other encodings so you need to add something to decode this.. echo $name to have a look at what it looks like to be able to figure how to decode it.. and finally .. */ $name=urldecode($name); //echo "#########".$name; //just to check final name... $directory_separator=(defined('DIRECTORY_SEPARATOR') ? DIRECTORY_SEPARATOR : '/'); $path = (strlen($parameters['SaveBody']) ? ($parameters['SaveBody'].(strcmp($parameters['SaveBody'][strlen($parameters['SaveBody'])-1], $directory_separator) ? $directory_separator : '')) : '').$this->tempvar.basename($name); .... Best of luck .. it sure does works for me ;-)
You should not need to change the class. All you need to do is to change the cid: URLs in the message HTML part to URLs that point to the same parser script and passing the id in front of cid to that script.
Here is the simplified version of the replacement code. $html = str_replace('cid:', '?cid=', $html); But do not use this or else you will be subject to security exploits. The right way is to use an HTML parser to find links or whatever uses embeded messages. Then replace the link URLs like the above, but use HtmlSpecialChars to encode URLs properly and avoid cross-site scripting attacks. For the actual parsing you can use a class like this secure HTML parser and filter. phpclasses.org/secure-html-filterThen in your parser script, look for $_GET['cid'] parameter. If present, parse the message again with the MIME parser but search for the message part with the content-id header that is the same as the cid parameter and serve its contents. |
info at phpclasses dot org.
