I'm trying to send an email from AppController in my CakePHP 2.0 app. It works fine if I send it from the PagesController, but I need to be able to send from AppController as well.
I have:
function sendSystemEmail($to = EMAIL_CONTACT, $from = EMAIL_FROM, $subject = null, $body = null, $view = null, $vars = null) {
App::uses('CakeEmail', 'Network/Email');
$email = new CakeEmail();
$email->viewVars(array(
'body' => $body,
'vars' => $vars
));
$email->template($view)
->emailFormat('html')
->from($from)
->to($to)
->subject($subject)
->send();
return;
}
When I use this, I don't get any errors, but the email doesn't arrive. I can't see that there's any different between this and the code I have in PagesController, so I'm assuming that there's something that AppController doesn't have access to maybe? I can't figure out what though!
Sharon, you're not putting the configuration method.. this parameter can put in the constructor of classEmail too, this way..
$email = new CakeEmail('pop3'); //can be smtp or the protocole you are using..
or
$email->config('pop3')
and you need to define the connection here..
./app/Config/email.php
class EmailConfig {
public $pop3 = array(
'transport' => 'Mail',
'from' => 'you#localhost',
//'charset' => 'utf-8',
//'headerCharset' => 'utf-8',
);
Related
I can't send an attachment with the email. I don't get an error and I do send the message so the email works but no attachment.
Is my filepath not correct as the file exists in this file? Is it because I am using windows with file paths?
This is just a test email below to see if this function actually works for an attachment but it isn't working for me. I checked other answers and this seems to be the way to construct this.
http://book.cakephp.org/2.0/en/core-utility-libraries/email.html
public function sendEmailattach($to,$message,$subject,$attach) {
$Email = new CakeEmail();
$Email->config('gmail3');
$Email->filePaths = array('D:\crm5\app\Attachments');
$Email->attachments =array('Ch9-anna tax.docx');
$to='jXXXXX#gmail.com';//testing real email account
// $Email->from( array('admin#a.com.au' => 'A'));
$Email->from( array('jxxxxx#gmail.com' => 'test'));
$Email->to($to);
$Email->subject($subject);
$Email->send();
// $Email->send($message);
}//public
UPDATE
Tried all 3 methods and no error and no attachment?
// $Email->attachments('D:\AA-website design\crm5\app\Attachments\Ch9-anna tax.docx') ;
$Email->attachments(array('Ch9-anna tax.docx' => array(
'file' => 'D:\AA-website design\crm5\app\Attachments\Ch9-anna tax.docx',
) ));
// $Email->attachments(array('D:\AA-website design\crm5\app\Attachments\Ch9-anna tax.docx'));
$email = new CakeEmail('default');
$attachment = [
'file.pdf' => [
'file' => '/my/absolute/path/on/server/file.pdf',
'mimetype' => 'application/pdf',
'contentId' => uniqid()
]
];
$variables = ['emailHeader' => 'Hello'];
$email->attachments($attachment);
$email->from(['info#example.com' => 'Example'])
->to('recipient#example.com')
->subject('Subject')
->template('template')
->emailFormat('both')
->viewVars($variables)
->send();
Just read the manual instead just looking at the links, honestly I have doubt's you read it at all:
http://book.cakephp.org/2.0/en/core-utility-libraries/email.html#sending-attachments
It clearly shows that attachments is a method and not a property. It even has examples of what the method accepts.
i am working on a cakephp 2.3. i want to load Email component into my class which is in Lib folder. same case for Vendor files too at the moment what i am doing is this..
App::uses('EmailComponent', 'Controller/Component');
class Email {
public static function sendemail($toEmail,$template,$subject) {
$this->Email->smtpOptions = array(
'port'=>'25',
'timeout'=>'30',
'host' => 'host',
'username'=>'username',
'password'=>'password'
);
$this->Email->template = $template;
$this->Email->from = 'no-reply#hello.com';
$this->Email->to = $toEmail;
$this->Email->subject = $subject;
$this->Email->sendAs = 'both';
$this->Email->delivery = 'smtp';
$this->Email->send();
}
i am not able to use $this.. i am getting this error
$this when not in object context
You don't do that, components are controller "extensions", they are not ment to be used without them.
For emailing purposes use the CakeEmail class (the E-Mail component is deprecated anyways).
App::uses('CakeEmail', 'Network/Email');
// ...
$Email = new CakeEmail(array(
'port' => 25,
'timeout' => 30,
'host' => 'host',
'username' => 'username',
'password' => 'password',
'transport' => 'Smtp'
));
$Email->template($template)
->emailFormat('both')
->from('no-reply#hello.com')
->to($toEmail)
->subject($subject)
->send();
$this can be use in class for their on variables and method define within class
In cakephp $this is used in controller when the $components array is defined within controller.
Try this
$email = EmailComponent();
$email->$smtpOptions= array();
I was able to overcome this in one of my Lib classes with Cake 3 using the following...
$oRegistry = new ComponentRegistry();
$oComponent = $oRegistry->load('PluginName.ComponentName');
I'm unsure if this creates any kinda discord with the state with the app's component registry; but, for my purposes, it seems to work.
Hope this helps someone :)
I was using the following code snippet to send mails, but moving to another host messed everything up:
public function forgetpwd(){
//code omitted
if($this->User->saveField('token_hash',$fu['User']['token_hash'] )){
//============Email================//
/* SMTP Options */
$this->Email->smtpOptions = array(
'host' => 'smtp.gmail.com',
'port'=>'465',
'transport' => 'Smtp',
'username'=>'email#gmail.com',
'password'=>'secret',
'tls' => true
);
$this->Email->template = 'resetpw';
$this->Email->from = 'noreply#email.com';
$this->Email->to = $fu['User']['name'].'<'.$fu['User']['email'].'>';
$this->Email->subject = __('Recover your password');
$this->Email->sendAs = 'both';
$this->Email->delivery = 'smtp';
$this->set('ms', $ms);
$this->Email->send();
$this->set('smtp_errors', $this->Email->smtpError);
$this->Session->setFlash(__('Check your email to recover your password'));
}
//============EndEmail=============//
So there is this view forgetpwd.ctp where user is asked to enter his/her email address, and when trying to send the email, I am given the two following errors:
Error: The view for UsersController::forgetpwd() was not found.
Error: Confirm you have created the file: /home/public_html/development/app/View/Emails/text/resetpw.ctp
I am sure that the resetpw.ctp exists in the right place.
I have edited the email config and tried to adopt the 2.3 cakePHP way, and this is what I have ended up with:
if($this->User->saveField('token_hash',$fu['User']['token_hash'] )){
App::uses('CakeEmail', 'Network/Email');
$Email = new CakeEmail('default');
$Email->to($fu['User']['email'])
->subject('Reset your password')
->message($key)
->send();
$this->Session->setFlash(__('Check your mail to reset your password'));
$this->redirect(array('controller'=>'users','action'=>'reset'));
But now, when I try to send an email, I get the following error:
Call to a member function send() on a non-object
change
'host' => 'smtp.gmail.com',
to
'host' => 'ssl://smtp.gmail.com',
also put your config info in email.php inside App/Config/ as referenced here:
http://book.cakephp.org/2.0/en/core-utility-libraries/email.html#configuration
I am trying to write a phpunit test for a Laravel controller which expects post requests with a body in JSON format.
A simplified version of the controller:
class Account_Controller extends Base_Controller
{
public $restful = true;
public function post_login()
{
$credentials = Input::json();
return json_encode(array(
'email' => $credentials->email,
'session' => 'random_session_key'
));
}
}
Currently I have a test method which is correctly sending the data as urlencoded form data, but I cannot work out how to send the data as JSON.
My test method (I used the github gist here when writing the test)
class AccountControllerTest extends PHPUnit_Framework_TestCase {
public function testLogin()
{
$post_data = array(
'email' => 'user#example.com',
'password' => 'example_password'
);
Request::foundation()->server->set('REQUEST_METHOD', 'POST');
Request::foundation()->request->add($post_data);
$response = Controller::call('account#login', $post_data);
//check the $response
}
}
I am using angularjs on the frontend and by default, requests sent to the server are in JSON format. I would prefer not to change this to send a urlencoded form.
Does anyone know how I could write a test method which provides the controller with a JSON encoded body?
In Laravel 5, the call() method has changed:
$this->call(
'PUT',
$url,
[],
[],
[],
['CONTENT_TYPE' => 'application/json'],
json_encode($data_array)
);
I think that Symphony's request() method is being called:
http://symfony.com/doc/current/book/testing.html
This is how I go about doing this in Laravel4
// Now Up-vote something with id 53
$this->client->request('POST', '/api/1.0/something/53/rating', array('rating' => 1) );
// I hope we always get a 200 OK
$this->assertTrue($this->client->getResponse()->isOk());
// Get the response and decode it
$jsonResponse = $this->client->getResponse()->getContent();
$responseData = json_decode($jsonResponse);
$responseData will be a PHP object equal to the json response and will allow you to then test the response :)
Here's what worked for me.
$postData = array('foo' => 'bar');
$postRequest = $this->action('POST', 'MyController#myaction', array(), array(), array(), array(), json_encode($postData));
$this->assertTrue($this->client->getResponse()->isOk());
That seventh argument to $this->action is content. See docs at http://laravel.com/api/source-class-Illuminate.Foundation.Testing.TestCase.html#_action
There is a lot easier way of doing this. You can simply set Input::$json property to the object you want to send as post parameter. See Sample code below
$data = array(
'name' => 'sample name',
'email' => 'abc#yahoo.com',
);
Input::$json = (object)$data;
Request::setMethod('POST');
$response = Controller::call('client#create');
$this->assertNotNull($response);
$this->assertEquals(200, $response->status());
I hope this helps you with your test cases
Update : The original article is available here http://forums.laravel.io/viewtopic.php?id=2521
A simple solution would be to use CURL - which will then also allow you to capture the 'response' from the server.
class AccountControllerTest extends PHPUnit_Framework_TestCase
{
public function testLogin()
{
$url = "account/login";
$post_data = array(
'email' => 'user#example.com',
'password' => 'example_password'
);
$content = json_encode($post_data);
$curl = curl_init($url);
curl_setopt($curl, CURLOPT_HEADER, false);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_HTTPHEADER, array("Content-type: application/json"));
curl_setopt($curl, CURLOPT_POST, true);
curl_setopt($curl, CURLOPT_POSTFIELDS, $content);
$json_response = curl_exec($curl);
$status = curl_getinfo($curl, CURLINFO_HTTP_CODE);
curl_close($curl);
$response = json_decode($json_response, true);
// Do some $this->Assert() stuff here on the $status
}
}
CURL will actually simulate the raw HTTP post with JSON - so you know you are truly testing your functionality;
As of Laravel 5.1 there is a much easier way to test JSON controllers via PHPunit. Simply pass an array with the data and it'll get encoded automatically.
public function testBasicExample()
{
$this->post('/user', ['name' => 'Sally'])
->seeJson([
'created' => true,
]);
}
From the docs: http://laravel.com/docs/5.1/testing#testing-json-apis
Since at least Laravel 5.2 there is a json() method in Illuminate\Foundation\Testing\Concerns\MakesHttpRequests therefore you can do the following:
$data = [
"name" => "Foobar"
];
$response = $this->json('POST', '/endpoint', $data);
Also since Laravel 5.3 there are also convenient methods like putJson(), postJson(), etc. Therefore it can be even shortened further to:
$data = [
"name" => "Foobar"
];
$response = $this->postJson('/endpooint', $data);
And then you can do $response->assertJson(...) like:
$response->assertJson(fn (AssertableJson $json) => $json->hasAll(['id', 'name']));
In Cake 1.3, the EmailComponent did what it should do. The new Cake Email class in 2.0 turned out to be a frustration....No emails sent, No errors....vague documentation...
I have tried all possible variants, tried it with my SMTP, Mail() and Gmail, nothing happens. Hereby my latest attempt:
Controller snippet:
//on top of page
App::uses('CakeEmail', 'Network/Email');
//in method
$email = new CakeEmail();
$email->template('contact_email')
->emailFormat('text')
->to('my#gmail.com')
->from('other#gmail.com')
->send();
Email.php Config file:
class EmailConfig {
//It also does not work with a constructor
public $gmail = array(
'host' => 'ssl://smtp.gmail.com',
'port' => 465,
'username' => 'my#gmail.com',
'password' => '***',
'transport' => 'Smtp'
);
Can someone please post WORKING code for the Email Class. Many thanks
I think you have to load your config from Config/email.php explicitly, it is not loaded automatically, not even the default config:
$email = new CakeEmail();
$email->config('default');
//or in constructor::
$email = new CakeEmail('default');
In my opinion you should use this:
$email = new CakeEmail('gmail');
This is my email config file . I didnt do any change here
class EmailConfig {
public $default = array(
'transport' => 'Mail',
'from' => 'Admin <no-reply#example.com>',
'charset' => 'utf-8',
'headerCharset' => 'utf-8',
);
}
This is how i send the mail
$email = new CakeEmail();
$result = $email->template('welcome')
->emailFormat('text')
->to($NewUser['email'])
->from('admin#example.com')
->send();
var_dump($result);