EmailComponent in a (cake) Shell

by Jippi
This little Shell Task will allow you to use the EmailComponent from your shell applications like you normally do from WWW.

The problem

How can I use the kickass EmailComponent from my Shell?

The solution

EmailTask

The description

This little Shell Task will allow you to use the EmailComponent from your shell applications like you normally do from WWW.

The code should pretty much explain itself. Below is a simple use example:

Demo

Put this code in APP/vendors/shells/my.php

MAKE SURE TO CHANGE THE EMAIL ADDRESSES TO VALID ONES

PHP Snippet:

<?php 
class MyShell extends Shell {
/**
 * List of tasks for this shell
 *
 * @var array
 */
    
var $tasks = array('Email');

/**
 * Email task
 *
 * @var EmailTask
 */
    
var $Email;

/**
 * Startup method for the shell
 *
 * Lets set some default params for the EmailTask
 *
 */
    
function startup() {
        
$this->Email->settings(array(
            
'from' => 'Me <my@mail.com>',
            
'template' => 'test'
        
));
    }

/**
 * Send just one email
 *
 */
    
function sendMeAnEmail() {
        return 
$this->Email->send(array(
            
'to' => 'some@mail.com',
            
'subject' => 'Talking to myself'
        
));
    }

/**
 * Send multiple emails, change a few variables on the fly
 * and test that we can 'set' variables to the view
 *
 */
    
function sendMyFriendsAnEmail() {
        
$myFriends = array('fake@mail.com''fake@mail.box''fake@user.com');
        
$this->Email->settings(array('subject' => 'Hello friends'));
        foreach (
$myFriends AS $friend) {
            
$this->Email->set('someVar'$friend);
            
$this->Email->send(array(
                
'to' => $friend
                
'subject' => 'Hello ' $friend
            
));
        }
    }
}
?>

Code

Put this code in APP/vendors/shells/tasks/email.php

PHP Snippet:

<?php 
App
::import('Core''Controller');
App::import('Component''Email');

class 
EmailTask extends Shell {
/**
* Controller class
*
* @var Controller
*/
    
var $Controller;

/**
* EmailComponent
*
* @var EmailComponent
*/
    
var $Email;

/**
* List of default variables for EmailComponent
*
* @var array
*/
    
var $defaults = array(
        
'to'        => null,
        
'subject'   => null,
        
'charset'   => 'UTF-8',
        
'from'      => null,
        
'sendAs'    => 'html',
        
'template'  => null,
        
'debug'     => false,
        
'additionalParams'    => '',
        
'layout'    => 'default'
    
);

/**
* Startup for the EmailTask
*
*/
    
function initialize() {
        
$this->Controller =& new Controller();
        
$this->Email =& new EmailComponent(null);
        
$this->Email->startup($this->Controller);
    }

/**
* Send an email useing the EmailComponent
*
* @param array $settings
* @return boolean
*/
    
function send($settings = array()) {
        
$this->settings($settings);
        return 
$this->Email->send();
    }

/**
* Used to set view vars to the Controller so
* that they will be available when the view render
* the template
*
* @param string $name
* @param mixed $data
*/
    
function set($name$data) {
        
$this->Controller->set($name$data);
    }

/**
* Change default variables
* Fancy if you want to send many emails and only want
* to change 'from' or few keys
*
* @param array $settings
*/
    
function settings($settings = array()) {
        
$this->Email->_set($this->defaults array_filter(am($this->defaults$settings)));
    }
}
?>

Watch the magic

Make sure you have created a .ctp file in APP/views/elements/email/html/test.ctp

Make sure you have created a .ctp file in
APP/views/layouts/email/html/default.ctp

Go into the CAKE/console directory and execute:
(Windows) cake.bat my sendMyFriendsAnEmail
(Linux) ./cake my sendMyFriendsAnEmail

Thanks to gwoo for feedback and on this little snippet and mariano_iglesias for proofing :)

Report

More on Tutorials

Advertising

Comments

  • carcus88 posted on 02/10/10 06:37:05 PM

    It seems your host is running PHP in "safe mode" so you cannot use the set_time_limit() function. See http://us2.php.net/manual/en/features.safe-mode.php
    Please use IRC for support and general questions.
  • leafchild posted on 02/10/10 06:04:16 PM
    I'm seeing this message every time run the script


    Warning: set_time_limit(): Cannot set time limit in safe mode in /var/www/vhosts/mydomain.com/httpdocs/cake_1.2.5/cake/console/cake.php on line 129

    how can I fix it??
  • leafchild posted on 02/10/10 02:37:58 PM
    I don't want to all email is same contents.

    How can I change message part??


  • carcus88 posted on 01/27/10 03:08:01 PM
    This "task" is ok but has drawbacks. After using it I found out its better to use App::Import to just import the Email component and use it directly.

    Its as simple as this....


    App::import('Component', 'Email');

    class MyShell extends Shell {
       

        public function __construct(&$dispatch) {
            $this->Email = new EmailComponent();
            parent::__construct($dispatch);
        }

    }
  • ceeram posted on 11/12/09 05:35:10 PM
    If you are using routes for your app, and want to use Helper::url() for instance $html->url(array('controller'=>'users','action'=>'login', 'prefix'=>'manager') the ususal way, you need to include the Router class and routes.
    in you shell:

    App::import('Core', array('Router','Controller'));
    include CONFIGS . 'routes.php';
    //and if you want to use $full parameter:
    define('FULL_BASE_URL', 'http://www.domain.com')
  • ceeram posted on 07/17/09 04:09:32 PM
    I use the following code(some copy/paste from your code) in my shell to use the EmailComponent like in a normal controller:

    App::import('Core', 'Controller');
    App::import('Component', 'Email');
    $this->Controller =& new Controller();
    $this->Email =& new EmailComponent(null);
    $this->Email->initialize($this->Controller);

    then set the variable with $this->Controller->set('name', $variable)
    • ceeram posted on 02/01/11 07:52:00 AM
      if your email elements are located in a plugin add this line:
      $this->Controller->plugin = 'pluginname';

      [quote] I use the following code(some copy/paste from your code) in my shell to use the EmailComponent like in a normal controller:

      App::import('Core', 'Controller');
      App::import('Component', 'Email');
      $this->Controller =& new Controller();
      $this->Controller->plugin = 'pluginname';// put it here
      $this->Email =& new EmailComponent(null);
      $this->Email->initialize($this->Controller);

      then set the variable with $this->Controller->set('name', $variable) [end quote]
  • jaydipdave posted on 05/07/09 05:10:59 AM
    Correction:

    Replace the Send Function with this code.


    /**
    * Send an email useing the EmailComponent
    *
    * @param array $settings
    * @return boolean
    */
        function send($settings = array()) {
            $this->settings($settings);
            $this->Email->Controller = $this->Controller;
            return $this->Email->send();
        }


    Just a suggestion,

    Thanks,

    Jaydeep Dave
  • mattalexx posted on 03/22/09 06:36:35 PM
    This works for me in version 1.2.1.8004:

    <?php
    class CronShell extends Shell {
        function 
    daily() {
            
    App::import('Component''Email');
            
    $this->Email =& new EmailComponent(null);
            
    $this->Email->from 'foo';
            
    $this->Email->to 'foo';
            
    $this->Email->subject 'foo';
            
    $this->Email->send('foo');
        }
    }
  • Romiz posted on 03/02/09 01:47:00 PM
    Hi,

    I have made all as here is written, but got error:
    Notice: Undefined property: View::$webroot in ..../cake/libs/view/view.php on line 751

    Anybody know how fix it?

    Thanks.
    • eberfreitas posted on 04/30/09 10:01:30 AM
      Hi,

      I have made all as here is written, but got error:
      Notice: Undefined property: View::$webroot in ..../cake/libs/view/view.php on line 751

      Anybody know how fix it?

      Thanks.

      Just follow Andras' post... you have to change:

      LN 44: $this->Email->startup($this->Controller);

      To:

      LN 44: $this->Email->initialize($this->Controller);

      And you are good to go :)
    • eberfreitas posted on 04/30/09 08:54:05 AM
      Hi,

      I have made all as here is written, but got error:
      Notice: Undefined property: View::$webroot in ..../cake/libs/view/view.php on line 751

      Anybody know how fix it?

      Thanks.

      I'm having the very same problem... I'll try to find it out... Anything I post something in here!
  • andras posted on 01/20/09 04:15:48 PM
    Had to change in EmailTask from startup() to initialize for cake 1.2 final as:

    function initialize() {
    $this->Controller =& new Controller();
    $this->Email =& new EmailComponent(null);
    $this->Email->initialize($this->Controller);
    }

  • oh4real posted on 11/22/08 06:13:37 PM
    Thanks HEAPS! for this task. My crontab jobs can now send emails when discovering stuff.

    But, can't send text emails.

    Trying Email->sendAs ='both', but keep getting 451 error. The same text/html emails send via non-console controllers just fine.

    Also, when I throw a 'debug()' into the html email to see what's going on, I get 451s, as well.

    Obviously most people use an html-compatible mail client, but still is there some reason this Task can't send text emails or html emails with debug() calls in it?

    oh4real

  • lalinux posted on 02/29/08 05:47:37 PM
    Hi, i have the same problem and what i did was:

    remove the lines:

    // App::import('Core', 'Controller');
    // App::import('Component', 'Email');

    and change the function initialize to:


        function initialize() {
            loadComponent('Email');
    //         $this->Controller =& new Controller();
            $this->Email =& new EmailComponent(null);
            $this->Email->startup($this->Controller);
        }

    im using the version "1.2.0.5875 pre-beta"
    i hope this help you

  • charlie posted on 02/21/08 06:00:40 PM
    Hi,

    I'm using an old version of Cake 1.2 and can't update to a new version otherwise my app will break in two ;)

    Is there a replacement for the two App:import()?
    App::import('Core', 'Controller');
    App::import('Component', 'Email');

    thnx
  • kabturek posted on 01/08/08 12:43:19 PM
    Thanks for a very usefull tutorial Jippi.

    A nice addition is the Router so that urls in emails will use our custom routes.
    To use the router change the second line in the task to:

    App::import('Core', array('Router','Controller'));
    and add

    include CONFIGS . 'routes.php';
    to the task initialize() method
    • PierreLechelle posted on 12/16/10 09:48:35 AM
      Great Tasks & Tutorial, thank's !

      [quote]
      App::import('Core', array('Router','Controller'));
      and add

      include CONFIGS . 'routes.php';
      [end quote]
      This code will not work. Router is a Core lib, instead you should use :


      App::import('Core', array('Controller', 'Router'));

      We also don't need to include the configuration file ;).
login to post a comment.