tags:

views:

773

answers:

2

Hello,

I am new to CakePHP and trying desperately to learn!

My most recent struggle is with the Email Component.

I have a contract. When I create the contract, I add a user. When I save the new contract...for the first time, I want to send an email to the user in that contract that allows them to click on a link back to the contract, and then accept or reject the contract.

How do I send this email?

The more details I can get, answer-wise, the better. Everything I have read out there is surprisingly confusing. Do I need to configure smtp settings? How do I grab the user in the contract after it has been saved and pass it and the link to the contract on to the email? How do I know if the email has been sent, without going and checking my email every single time?

Here is the code I have in my contracts_controller.php for the email sending function: (A Contract belongsTo a User, and a User hasMany Contracts.)

function _sendContractEmail($id) {
        $this->Email->smtpOptions = array(
        'port'=>'465',
        'timeout'=>'30',
        'host'=>'ssl://smtp.gmail.com',
        'username'=>'username',
        'password'=>'password'
        );
        $this->Email->delivery = 'smtp';
        $User = $this->Contract->User->read(null,$id);
        $this->Email->to = '[email protected]';
        $this->Email->subject = '';
        $this->Email->replyTo = '[email protected]';
        $this->Email->from = 'Jeremiah Oits <[email protected]>';
        $this->Email->template = 'simple_message';
        $this->Email->sendAs = 'html';
        $this->set('User', $User);
        $this->Email->_debug = true;
        $this->Email->send('Test Email');
        $this->redirect(array('controller'=>'contracts', 'action'=>'index'));
    }

Here is the code I have in my contracts_controller.php add() function:

function add() {
        if (!empty($this->data)) {
            $this->Contract->create();
            if ($this->Contract->save($this->data)) {
                $this->Session->setFlash(__('The Contract has been saved', true));
                $this->_sendContractEmail($this->Contract->User->id);
            } else {
                $this->Session->setFlash(__('The Contract could not be saved. Please, try again.', true));
            }

And, this is at the top of my contracts_controller.php file after the $name and $helpers:

var $components = array('Email');

I guess I should point out that I was having trouble with the template, so to test it, I included the body of the email directly in the send(), and I specified the to email address rather than using a variable. Still...nothing! No error, no email.

Any help would be greatly appreciated! I really have no idea what I am doing wrong!

Thanks,

Jeremiah

A: 

I would put this in a comment, but it got a bit long.

Have you tried using just a local email server, rather than connecting to gmail? It might be that the gmail server is rejecting your email because it is being generated from a local source. I would recommend trying something like MDaemon locally to see if you can generate an email to yourself first. Be sure to allow open relay, or your mail will bounce locally.

Where have you saved your email templates? They should be in here, app/views/elements/email/html and app/views/elements/email/text also be sure to set your content and in the template use echo $content_for_layout as per the docs, http://book.cakephp.org/view/269/Sending-a-basic-message the api is also worth a look to ensure you have the correct parameters, http://api.cakephp.org/class/email-component

To pass the details into the email message, you can simply use $this->set in your controller action, and then in your email template, you can do an echo $var to output it. The email works just like a regular view, except it is dispatched via email rather than to a browser.

If you want to check if the mail has been sent, then you can wrap the $email->Send() in an if statement.

if($email->Send()){ echo "Your contract has been dispatched!"; }

Which makes me think have you instantiated the email component? I tend to use,

$email = new Email();

Then set the class variables on that. I've not seen it used as $this->Email before, although that may well work :)

DavidYell
I second David's suggestion to try sending mail locally before you send it through gmail. In addition, I believe gmail has a hard limit to the number of emails / day you can send out through SMTP -- 500 or 1k, I think. So if your app will need to send more than that, you need a different solution. Personally, I use gmail for incoming mail, and send outgoing through my local server (also allows you to finagle mail server settings so you can dump the "from travis on behalf of..." line.
Travis Leleu
Also, David, if you put Email in the $components array in the controller, the controller will instantiate it for you, creating a member attribute that you can access from Controller::Email (like you mention above).
Travis Leleu
You could also try using a 3rd party email library like PHPMailer to make sure your smtp settings are correct.
HyperCas
Email templates should be under /app/views/layouts/email and under the folders 'html' and 'text'
HyperCas
A: 

http://book.cakephp.org/view/481/Sending-A-Message-Using-SMTP

Use the code sample from the page, specifically the last section to get error notices

/* Check for SMTP errors. */
    $this->set('smtp-errors', $this->Email->smtpError);

You can print the smtp errors using pr(smtp-errors) your view.

The layouts for emails should be located under

/app/view/layout/email/html
/app/view/layout/email/text

If you want copy and modify default templates they can be found under

/libs/view/layouts/email/html
/libs/view/layouts/email/text

Your code looks correct. The problem is probably with the SMTP server rejecting the email.

Oh and you should also check you debug.log and error.log under /app/tmp/logs

HyperCas