Brief Overview of the new EmailComponent

By GreyCells aka "GreyCells"
It's often more practical (read: maintainable) to use the built in components and much as I like SwiftMailer, I thought it best that I investigated Cake's core EmailComponent.
Big Note: The examples below are not intented for production servers, but just to give an idea of the files/code snippets needed to send email.

First create your email layouts. Create a default.ctp in the following directories:
Download code
views/layouts/email/text/

views/layouts/email/html/


The text layout (not a template):

View Template:

Download code
<?php echo $content_for_layout?>

and the html layout:

View Template:

Download code
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<body>
<?php echo $content_for_layout?>
</body>
</html>


This is a dummy controller for demonstration purposes only:

Controller Class:

Download code <?php 
class MailerController extends AppController {

    var 
$name 'Mailer';
    
//Not using a model
    
var $uses '';
    
//The built in Cake Mailer
    
var $components = array('Email');
    

}
?>


Simple text Message


To send a simple text message (useful for alerts etc), you do not need templates. Example function for the dummy Mailer controller:

Controller Class:

Download code <?php 
    
/**
     * Send a text string as email body
     */
    
function sendSimpleMail() {
        
$this->Email->to 'yourlogin@localhost';
        
$this->Email->subject 'Cake test simple email';
        
$this->Email->replyTo 'noreply@example.com';
        
$this->Email->from 'Cake Test Account <noreply@example.com>';
        
//Set the body of the mail as we send it.
        //Note: the text can be an array, each element will appear as a
        //seperate line in the message body.
        
if ( $this->Email->send('Here is the body of the email') ) {
            
$this->Session->setFlash('Simple email sent');
        } else {
            
$this->Session->setFlash('Simple email not sent');
        }
        
$this->redirect('/');
    }
?>

This can be called from http://localhost/mailer/sendSimpleMail - if all is OK, you should receive an email just by visiting the URL.

Pretty easy so far. Note: by default Cake EmailComponent uses the built in php mail() function, so if you are having problems, please ensure you can use that function successfully directly from a php script.

The mail function used by $this->Email->send() can be set via $this->Email->delivery to 'mail' or 'smtp', but I have only tested 'mail' (the default).

Text Message from a Template


Templates for emails are stored by default in views/element/email/text or views/elements/email/html

Create the following template in views/elements/email/text/test.ctp:

View Template:

Download code
Here is the template body text.

<?php echo $someValue?>



And the function for the dummy controller:

Controller Class:

Download code <?php 
    
/**
     * Use a layout for the message body
     * Create the following files:
     * views/elements/email/text/test.ctp
     * 
     * containing: the layout you want for your email
     *
     */
    
function sendTemplateMail() {
        
$this->Email->to 'yourlogin@localhost';
        
$this->Email->subject 'Cake test template email';
        
$this->Email->replyTo 'noreply@example.com';
        
$this->Email->from 'Cake Test Account <noreply@example.com>';
        
$this->Email->template 'test';
        
//Set view variables as normal
        
$this->set('someValue''Cake tastes good today');
        
//Do not pass any args to send()
        
if ( $this->Email->send() ) {
            
$this->Session->setFlash('Template email sent');
        } else {
            
$this->Session->setFlash('Template email not sent');
        }
        
$this->redirect('/');
        
    }
?>


Nothing very new here, just set view variables as you would normally (they are shared across all views). If you expect to have lots of email templates (elements), then you can organize them within sub-directories of view/elements/email/text and view/elements/email/html then prefix 'mydir/' to the $this->Email->template value. e.g.: $this->Email->template = 'mydir/test'.

Html Message from a template


Cake's Mail component supports 'text', 'html' or 'both' styles of email. The default is (quite rightly) 'text' and can be changed via $this->Email->sendAs().


Create the following template in views/elements/email/text/test2.ctp:

View Template:

Download code
Here is the template body text for test2.

<?php echo $someValue?>


and views/elements/email/html/test2.ctp:

View Template:

Download code
<h2>
Here is the template body text.
</h2>
<p><em><?php echo $someValue?></em></p>



Example function for our dummy Mailer controller:

Controller Class:

Download code <?php 
    
/**
     * Use a layout for the message body
     * Create the following files:
     * views/elements/email/html/test2.ctp
     * views/element/email/text/test2.ctp
     * 
     * containing: the layouts you want for your email
     *
     */
    
function sendTemplateHtmlMail() {
        
$this->Email->to 'yourlogin@localhost';
        
$this->Email->subject 'Cake test template email';
        
$this->Email->replyTo 'noreply@example.com';
        
$this->Email->from 'Cake Test Account <noreply@example.com>';
        
$this->Email->template 'test2';
        
//Send as 'html', 'text' or 'both' (default is 'text')
        
$this->Email->sendAs 'both';
        
//Set view variables as normal
        
$this->set('someValue''Cake and cream is good for you');
        
//Do not pass any args to send()
        
if ( $this->Email->send() ) {
            
$this->Session->setFlash('Template html email sent');
        } else {
            
$this->Session->setFlash('Template html email not sent');
        }
//        $this->redirect('/');
        
    
}

?>


That's all there is to it. Cake's EmailComponent is also able to handle attachments, but that is for a later date.

The last function did not work until I had 'fixed' a few things in email.php. See https://trac.cakephp.org/ticket/1851 if you want to play now.




Comments 203

CakePHP team comments Author comments

Question

1 Spam Deterrent

So does this solution have built in spam deterrent so I can use an email form on my website and not worry about it getting hijacked? Or do I need to filter the users input and would that be something I would handle with the sanitizer in cake?

Huey
posted Wed, Dec 31st 1969, 18:00 by Jeff Huelsbeck

Question

2 Why is this code NOT for production servers

Thanks for the great tutorial, GreyCells! It came at the perfect time for me.

In the tutorial you warn that:
"The examples below are not intented for production servers"
and: "This is a dummy controller for demonstration purposes only."

What's wrong with using this code for a production server? Besides continuing to tailor the code to our own application, is there something wrong with using the example code as is? Could you list the things you would recommend shoring up before releasing this code into the wild?

Many thanks!
Robin
posted Wed, Dec 31st 1969, 18:00 by Robin

Question

3 Why ever use SwiftMailer

Also, the EmailComponent looks like a great alternative to SwiftMailer. Can anyone offer some suggestions on why a CakePHP app would use SwiftMailer instead?

Many thanks!
Robin
posted Wed, Dec 31st 1969, 18:00 by Robin

Comment

4 This code is for demonstration purposes only

Robin - The sample code has not been written with a production environment in mind, so has not been fully tested, parameters are not sanitized etc. I would not recommend having a controller method that allows the world to generate email without (at least) some form of logging/authentication/throttling. I would also recommend using Cake's Security component (http://manual.cakephp.org/chapter/security) and to read 'How to break Web Software' by Andres and Whittaker.

Which sort of answers Huey/Jeff's question. I'm not a big fan of captcha's etc because of accessability issues, although they do have their place. There is a lot you can do to mitigate the risk if you implement a simple IP address based throttling system and use Cake's security component.

Robin - Why use SwiftMailer? Well, it's a mature, feature complete library that allows you to very easily do things such as attachments etc. I'm sure Cake's mail component will match the features and stability soon, but don't forget 1.2 is still in heavy development.

~GreyCells
posted Wed, Dec 31st 1969, 18:00 by GreyCells

Comment

5 Update to Sending Simple Text

In newer versions of the EmailComponent, the class attribute $template is defaulted to 'default'. This means that in order to use Email::send('Some simple text content') you must first explicitly set Email->template = null;

See: https://trac.cakephp.org/ticket/2105

~GreyCells
posted Wed, Dec 31st 1969, 18:00 by GreyCells

Comment

6 Templates and set() in PHP4

In php4 using $this->set will not make your variable available to the email template. You will get an error in your sent email similar to:

<br />
<b>Notice</b>: Undefined variable: aVariable in <b>/blah/blah/user/htdocs/create/app/views/elements/email/text/invite.ctp</b> on line <b>3</b><br />

To get over this you can use $this->Email->Controller->set() instead.
posted Tue, Apr 3rd 2007, 08:37 by Carey Baird

Question

7 Change in location of templates

The article states that templates are in views/layouts/email/* however the current version seems to want them in views/elements/email. Is this a recent change and will it stay that way?
posted Tue, Apr 17th 2007, 11:02 by Andrew

Comment

8 Change in location of templates

The article states that templates are in views/layouts/email/* however the current version seems to want them in views/elements/email. Is this a recent change and will it stay that way?

As far as I'm aware (i.e. my apps still work), nothing has changed wrt layouts and templates. The text and html layouts (for all mails) are still located in views/layouts/email/* and the individual templates (for each mail) are in views/elements/email/*

~GreyCells
posted Tue, Apr 17th 2007, 17:22 by GreyCells

Question

9 Help simple email

I've tried to send a simple email following thedirections in this article, also set template = null, but no mail gets send, Email->send returns false. I can however on the same server send an email using PHP's mail() function.

I've downloaded cake_1.2.0.5146alpha.zip yesterday, replaced the cake folder of the cake_1.1.14.4797 installation. All's well except that the email component doesn't send mail.

What I've done:

1. There's a default.ctp in app/views/layouts/email/html and app/views/layouts/email/text.
2. Created the mailcontroller:

class MailerController extends AppController {

var $name = 'Mailer';
var $uses = '';
var $components = array( 'Email' );


function sendSimpleMail() {

$this->Email->to = 'romano@iblis.demon.nl';
$this->Email->subject = 'Cake test simple email';
$this->Email->replyTo = 'noreply@adomain.com';
$this->Email->from = 'Cake Test Account <noreply@adomain.com>';
$this->Email->template = null;

if ( $this->Email->send('Here is the body of the email') ) {
// $this->Session->setFlash('Simple email sent');
// exit( 'ja' );
}
else {
// $this->Session->setFlash('Simple email not sent');
// exit( 'nee' );
}
$this->redirect('/');
}
}


Called the action via the url.

Any ideas where I might find the solution to this problem?

Best regards,
Romano
posted Tue, Jun 5th 2007, 06:13 by Romano

Comment

10 Safe mode issue

To reply to my own message above, the problem seems to be that the fifth parameter in PHP's mail() function cannot be used in safe mode. If I remove it from the Email components __mail function, all works fine.

Ciao,
Romano
posted Wed, Jun 6th 2007, 05:00 by Romano

Question

11 Validation

Thanks for the guide. What's the best way to validate some fields before sending the email? For example, if my form requires a name and a valid email, would I make a model for it? And I want the form to redisplay with the entered values if it fails validation.
posted Wed, Sep 26th 2007, 15:29 by Danny Ferguson

Comment

12 line breaks

with text formatted email.. does anyone know why one line break in my template turns into two line breaks when it gets recieved by the user.

it's like i have a choice.. two line breaks or none.. :(
posted Mon, Nov 5th 2007, 17:40 by Rob Conner

Comment

13 thanks for the pointers

Hey,

i just wanna say thank you for the tut, i've tried it and everything worked as you have described!!

if anyone has questions, please ask and i will try to help out.

Joren
posted Tue, Dec 25th 2007, 15:51 by joren

Question

14 Everything worked except...

Everything works as advertised except the emails don't get received by aol, hotmail, and various other mail servers that require a reverse dns lookup since it's sending from my local server. I can't seem to get the smtp to work sending out through gmail. Any ideas?

** EDIT: Nevermind, this was actually a reverse DNS issue with my server. If you find that you are having issues sending to certain email addresses you can check your reverse dns for your server here: http://postmaster.info.aol.com/tools/rdns.html **

@Rob: what are you using for line breaks? I've been using \n in my mail content and it seems to translate correctly.
posted Thu, Feb 14th 2008, 15:19 by Jeff Huelsbeck

Login to Submit a Comment