This IS useful: email datasource by Kevin van Zonnerveld

Looking for a shortcut to insert contents in a cake based cms, i found Kevin van Zonnerveld’s email datasource.

Originally taken from infinitas cms, although not 100% finished, it seems a great piece of code, and easy to use.

Just follow the instructions on github to grab – install – configure and implement it, create your model, and use the provided examples as a starter.

It will be easy to access your selected email account form within your cakephp app. Just using ->find (compelx conditions are not yet implemented, but the basic is here) and ->delete, as easy as in database backed models.
It was easy to add a “list relevant emails” section in my admin panel, adding controls on sender email address (discard the email message if not belonging to an authorized user) and so on.. and a “insert event/news/request form email” feature, that just expanded the normal add method, to feed it with properly parsed email content based on a simple parameter.

This method has many pros and cons. On the down side, issues with formatting and embedded images are the first concern. Based on the variety and diversity of email clients and webmails, we have no guarantees the message will be good enough to be the source of a properly formatted content. However, if you use it wisely it can be a good shortcut and timesaver: the best part is.. file upload by email.

Alas, the potential problems are relevant, but it’s something less tech savvy users usually love.

Email datasource can give us attached files as related models in our returned array. It is nice enough to list the properties of the files – most noticeably size and mime-type; both are useful for our purpose. The data can become really big, as files are included in the array as a binary / base64 stream. As long as you don’t hit the memory limit, it should work. (well, your users are not sending email messages with 50MB or more of attachements, aren’t they?)

So, in our (i.e) news add method, we can do something like:

[!code shown only as an example!]

  1. if(!is_null($email_id)) {
  2.  
  3. $this->set('email_id', $email_id);
  4.  
  5. //Here is my "TicketEmail" Model, that uses email datasource
  6. $Email = ClassRegistry::init('TicketEmail');
  7. $saved_email = $Email->find('first', array('recursive' => 1, 'conditions' => array('id' => $email_id)) );
  8.  
  9. // [..]
  10. // get subject, parse the body.. cake's Sanitize class will be useful
  11. // get author's data based on sender email, etc.
  12.  
  13. // Now check for attachements
  14. if(count($saved_email['Attachment'])) {
  15. foreach ($saved_email['Attachment'] as $aid => $attach) {
  16. if( $attach['size'] < 5000000 &&
  17. ($attach['datatype'] == 'image' || $attach['datatype'] == 'video'
  18. || in_array($attach['type'], array('pdf', [..]) ) ) //list of allowed mime-types
  19. ) {
  20. $binary_stream = base64_decode( $attach['attachment']);
  21. $filesize = file_put_contents(CAKE_CORE_INCLUDE_PATH . DS. 'app' .DS.'tmp'. DS .  $attach['filename'], $binary_stream);
  22. //tmp file saved
  23.  
  24. // we have the temporary file.. now we can save it as if it was uploaded form a posted form.
  25. //I'm using Media Plugin by Pavid Persson here
  26.  
  27. //now try to pass it to the asset model (->media plugin, save file, create versions..
  28. //like our usual file upload feature)
  29.  
  30. App::import('Model', 'Asset');
  31. $Asset = new Asset;
  32.  
  33. /*
  34.  * Save the attachments using media's plugin behaviours
  35.  */
  36.  
  37. if (!empty($this->data)) {
  38. $data['Asset']['name'] = $attach['filename'];
  39. $data['Asset']['file'] = CAKE_CORE_INCLUDE_PATH . DS. 'facile' .DS. 'tmp'. DS .  $attach['filename'];
  40. //[..] set other data..
  41. $Asset->create($data);
  42.  
  43. $this->set('asset_data', $data);
  44. //$this->set('Asset',$Asset);
  45.  
  46. //We have our textual content and attachments (pdfs.. images..)..
  47. //we can alter the textual content by including the first image (thumbnail) and append other downloadable attachements after the body
  48. if ($Asset->save($data, false)) {
  49. // processing.. not relevant
  50.  
  51. if(!$images_found && $attach['datatype'] == 'image') {
  52. $images_found = true;
  53.  
  54. //other not relevant stuff here..
  55.  
  56. $insert_left = '<p><div class="picture_left"><a href="/assets/show/'.$Asset->data['Asset']['id'].'"><img src="'.$path.'"  align="baseline" title="'.$attach['name'].'" alt="'.$attach['name'].'"/></a><p><em>'.$description.'</em></p></div>';
  57.  
  58. $this->data[$this->modelClass]['news_body'] = $insert_left . $this->data[$this->modelClass]['news_body'];
  59. } else {
  60.  
  61. $insert = '<a href="/assets/show/'.$Asset->data['Asset']['id'].'">'. $attach['name']. '</a>';
  62.  
  63. $this->data[$this->modelClass]['news_body'] .= $insert;
  64.  
  65. }

Here we are. Potentially a lot of copy and paste and file upload (and embed) spared: just send an email. Just two clicks to read the mailbox, view the message, and open the pre-compiled content add form, with saved attachments and “cover” image. Of course, this is only an alternative way to prepare content, it’s only meant to support your cms’ main functions.

CAVEATS

It’s still under development – in my case I had to make a copuple of changes. Pay attention and try this if you get the same issues.

To properly recognize attachments, I had to uncomment the line

#$Part->is_attachment = true;
in _awesomePart method.

Also, i had to use the ->deleteAll method (filtering by id) to delete a single message – the normal delete method deleted every message in the mailbox; i don’t know why -didn’t check further

  1. function admin_delete($id) {
  2. $this->TicketEmail->deleteAll(array(
  3. 'id' => $id,
  4. 'seen' => 1
  5. ));
  6. //$this->TicketEmail->delete($id); //Deleted everything..