PHPMailer with native API for PHP 5.x
This tutorial on using PHPMailer with Cake (http://bakery.cakephp.org/articles/view/94) has a comment requesting a component that lets you use the native PHPMailer API. This is possible with PHP5's built-in overloading capabilities.
The Mailer component acts as a delegator and looks like this:
In your controller, do the following:
That's all! You can now call any PHPMailer method through $this->Mailer->MethodName() and set any class variable through $this->Mailer->varName = 'value'.
Component Class:
<?php
class MailerComponent extends Object
{
/**
* PHPMailer object.
*
* @access private
* @var object
*/
var $m;
/**
* Creates the PHPMailer object and sets default values.
* Must be called before working with the component!
*
* @access public
* @return void
*/
function init()
{
// Include the class file and create PHPMailer instance
vendor('phpmailer/class.phpmailer');
$this->m = new PHPMailer;
// Set default PHPMailer variables (see PHPMailer API for more info)
$this->From = 'me@example.com';
$this->FromName ='MyName';
// set more PHPMailer vars, for smtp etc.
}
function __set($name, $value)
{
$this->m->{$name} = $value;
}
function __get($name)
{
if (isset($this->m->{$name})) {
return $this->m->{$name};
}
}
function __call($method, $args)
{
if (method_exists($this->m, $method)) {
return call_user_func_array(array($this->m, $method), $args);
}
}
}
?>
In your controller, do the following:
Controller Class:
<?php
var $components = array('Mailer');
// Inside your method:
// Set up mail
$this->Mailer->init();
$this->Mailer->AddAddress('recipient@example.com');
$this->Mailer->Subject = 'My Subject';
// Set PHPMailer vars and call PHPMailer methods (see PHPMailer API for more info)
// Set mail body
ob_start();
$this->render('nameOfEmailTemplate', 'nameOfEmailLayout');
$this->Mailer->Body = ob_get_clean();
// Send mail
if ($this->Mailer->send()) {
echo 'Mail was sent successfully.';
} else {
echo 'There was a problem sending mail: '.$this->Mailer->ErrorInfo;
}
?>
That's all! You can now call any PHPMailer method through $this->Mailer->MethodName() and set any class variable through $this->Mailer->varName = 'value'.








but no matter what i do, it does not work
either i get a plain text result like this:
(sent by mail):
From: MyName
X-Mailer: PHPMailer (phpmailer.codeworxtech.com) [version 2.3] MIME-Version: 1.0
Content-Transfer-Encoding: 8bit
Content-Type: text/plain; charset="utf-8"
or some error error trying to get some template to work:
Indirect modification of overloaded property MailerComponent::$controller has no effect
etc..
has anybody a full working phpmailer component running?
maybe even with some example calls
would be very helpful
thx
I replaced $this->data with $this->controller->viewVars to effectively gain access to any view variables in my email layout.
Works great, thanks for all the good posts!
For those of you whom have been having the rendering issue with the blank emails going through due to a glitch somewhere with the output buffering, please have a look at my code below.
function getBody() {
$temp_layout = $this -> controller -> layout;
$this -> controller -> layout = '';
ob_start();
$this -> controller -> autoRender = false;
App::import('Core', array('View'));
$viewClass = new View($this -> controller);
$this -> template = $viewClass -> _getViewFileName($this -> template);
$content = $viewClass -> _render($this -> template, $this -> data);
echo $viewClass -> renderLayout($content, 'email');
$this -> controller -> autoRender = 'auto';
$body = ob_get_clean();
$this -> controller -> layout = $temp_layout;
return $body;
}
It might not be the right way to solve the issue but at least it works fine. I'm in a hurry to get my site fixed right now, but might digg in a bit more later on in order to pinpoint the actual issue.
All the best,
Antonie
I've gotten pretty much everything working, except one major part.
When it sends out emails, the subject and body are completely blank?
Here's my component:
Component Class:
<?php
<?php
class MailerComponent extends Object
{
/**
* PHPMailer object.
*
* @access private
* @var object
*/
var $m;
var $controller;
/**
* Creates the PHPMailer object and sets default values.
* Must be called before working with the component!
*
* @access public
* @return void
*/
function init()
{
// Include the class file and create PHPMailer instance
App::import('Vendor', 'PHPMailer', array('file' => 'phpmailer'.DS.'class
$this->m = new PHPMailer;
// Set default PHPMailer variables (see PHPMailer API for more info)
$this->From = 'verification@aevumdecessus.com';
$this->FromName ='Aevum Decessus Administration';
// set more PHPMailer vars, for smtp etc.
$this->IsSMPT();
$this->SMTPAuth = true;
$this->Host = 'aevumdecessus.com';
$this->Username = 'verification';
$this->Password = 'aS$h0l3';
}
function setBody($template, $layout)
{
$this->Body = $this->_render($template.'_html', $layout.'_html');
$this->AltBody = $this->_render($template.'_text', $layout.'_text');
}
function _render($template, $layout)
{
ob_start();
$this->controller->autoRender = false;
$this->controller->render($template, $layout);
$this->controller->autoRender = 'auto';
return ob_get_clean();
}
function __set($name, $value)
{
$this->m->{$name} = $value;
}
function __get($name)
{
if (isset($this->m->{$name})) {
return $this->m->{$name};
}
}
function __call($method, $args)
{
if (method_exists($this->m, $method)) {
return call_user_func_array(array($this->m, $method), $args);
}
}
}
?>
?>
and my controller:
Controller Class:
<?php$this->User->set($this->data);
$this->Mailer->controller = &$this;
$this->Mailer->init();
$this->set('token', $this->data['User']['email_token']);
$emails = $this->data['User']['email'];
$this->Mailer->AddAddress($emails);
$this->Mailer->Suject = 'Please Validate your account';
$this->Mailer->setBody('/email/validation', 'email');
if ($this->Mailer->send())
{
$errors = $this->Mailer->ErrorInfo;
//$this->User->save();
}
else
$errors = 'Error Sending: '.$this->Mailer->ErrorInfo;
$this->set('errors', $errors);
?>
<?php
function _render($template,$layout) {
ob_start();
$this->controller->autoRender = false;
$this->controller->render($template,$layout);
$this->controller->autoRender = 'auto';
$mail = ob_get_clean();
return $mail;
}
?>
Do you know how I can prevent this from happening?
$this->Mailer->IsHtml(true);
I am using your guide but ran into a problem.
The email that i receive is the raw html code.
How do I ensure that the actual html file is being sent and no t the raw code ?
Thanks.
For example, I added the following snippet to my version of the MailerComponent:
Component Class:
<?php
var $controller;
function startup(&$controller) {
$this->controller = $controller;
$this->init();
}
/**
* Set the body of the email
*/
function setBody($template, $layout = 'email') {
$this->Body = $this->_render($template, $layout);
}
/**
* Set the AltBody, like for the text in HTML+TXT emails
*/
function setAltBody($template, $layout = 'email') {
$this->AltBody = $this->_render($template, $layout);
}
function _render($template, $layout) {
ob_start();
$this->controller->render($template, $layout);
return ob_get_clean();
}
?>
Is your $layout shown properly with a plain text template/layout using render as above? I've tried and the template content is correct, but no layout is shown (perhaps it would have something to do with ob_get_clean() ending the output rendering prematurely?)
Thanks a lot!
Controller Class:
<?php
Now its possible to use component exactly like PHPmailer object.vendor('phpmailer/class.phpmailer');
class MailerComponent extends PHPMailer
{}
?>
$this->Mailer->errorInfo;should be:$this->Mailer->ErrorInfo;Thanks :)
{
$this->m->{$name) = $value;
}
should be
function __set($name, $value)
{
$this->m->{$name} = $value;
}
thanks for the example !
For the methods
function send()
{
return $this->m->send();
}
And for properties:
function setBody($value)
{
return $this->m->Body = $value;
}
$this->Mailer = 'smtp';
it worked like a charm. thanks man.
I fixed it, thank you for reporting.
Comments are closed for articles over a year old