SwiftMailer Component

By Othman ouahbi (CraZyLeGs)
This is a component that does encapsulate but not hide swift mailer.
In addition, it adds some nifty features.
In short, this is just a delicious cake-ish swift Mailer.

Component Class:

Download code <?php 
/*
 * SwiftMailer Component By othman ouahbi.
 * comments, bug reports are welcome crazylegs AT gmail DOT com
 * @author othman ouahbi aka CraZyLeGs
 * @version 0.1 
 * @license MIT
 */

class SwiftMailerComponent extends Object {
    var 
$controller false;
    var 
$mailer null;
    var 
$connection 'smtp'// sendmail, native

    
var $smtp_host null// null auto detect
    
var $smtp_port false// false to let the mailer choose. default 25, 465 for ssl.
    
var $smtp_type 'open'// open, ssl, tls

    
var $username null;
    var 
$password null;

    var 
$layout 'swift_email';

    var 
$email_views_dir 'swift_emails';

    var 
$sendmail_cmd false// false: SWIFT_AUTO_DETECT, 'default': '/usr/sbin/sendmail -bs' etc..

    
function startup(& $controller) {
        
$this->controller = & $controller;
    }

    function 
connect() {
        switch (
$this->connection) {
            case 
'smtp' :
                
$this->connect_smtp();
                break;
            case 
'sendmail' :
                
$this->connect_sendmail();
                break;
            case 
'native' :
            default :
                
$this->connect_native();
                break;
        }

        return 
$this->mailer->isConnected();
    }

    function 
connect_native() {
        
vendor('Swift');
        
vendor('Swift/Connection/NativeMail');

        
$this->mailer = new Swift(new Swift_Connection_NativeMail());
    }

    function 
connect_sendmail() {
        
vendor('Swift');
        
vendor('Swift/Connection/SendMail');

        if (
$this->sendmail_cmd == false) {
            
$this->sendmail_cmd SWIFT_AUTO_DETECT;
        }
        elseif (
$this->sendmail_cmd == 'default') {
            
$this->sendmail_cmd '/usr/sbin/sendmail -bs';
        }

        
$this->mailer = new Swift(new Swift_Connection_SendMail($this->sendmail_cmd));
    }

    function 
connect_smtp() {
        
vendor('Swift');
        
vendor('Swift/Connection/SMTP');

        
// SWIFT_AUTO_DETECT
        
if (is_null($this->smtp_host)) {
            
$this->smtp_host SWIFT_AUTO_DETECT;
        }
        
        if (
is_null($this->smtp_port)) {
            
$this->smtp_port SWIFT_AUTO_DETECT;
        }
        
        
$ssl_types = array('open'=>SWIFT_OPEN,'ssl'=>SWIFT_SSL,'tls'=>SWIFT_TLS);
        
        if(
in_array($this->smtp_type, array ('open','ssl','tls')))
        {
            
$ssl_type $ssl_types[$this->smtp_type];
        }else
        {
            
$ssl_type $ssl_types['open'];
        }

        
$this->mailer = new Swift(new Swift_Connection_SMTP($this->smtp_host$this->smtp_port$ssl_type));

    }

    function 
auth() {
        return (
$this->mailer->authenticate($this->username$this->password));
    }

    function 
errors() {
        return 
$this->mailer->errors;
    }

    function 
transactions() {
        return 
$this->mailer->transactions;
    }

    function 
close() {
        
$this->mailer->close();
    }

    
/*
     * description: 
     * Renders a body view located in the emails dir.
     * if html, wraps it with a layout and embeds images that have the embed="swift" attribute
     * strip tags if plain.
     */
    
function viewBody($name$type 'both'$return false) {
        switch (
$type) {
            case 
'both' :
                
$plain true;
                
$html true;
                break;
            case 
'html' :
                
$html true;
                break;
            case 
'plain' :
                
$plain true;
                break;
            default :
                return;
                break;
        }

        if (isset (
$html)) {
            
$name .= "_html";
            
$view VIEWS $this->email_views_dir DS $name '.thtml';
            
$old_layout $this->controller->layout;
            
ob_start();
            
$this->controller->render(null$this->layout$view);
            
$html_msg ob_get_clean();
            
$html_msg $this->replaceIMG($html_msg);
            
$this->controller->layout $old_layout;
        }

        if (isset (
$plain)) {
            
$view VIEWS $this->email_views_dir DS $name '.thtml';
            
$old_layout $this->controller->layout;
            
$this->controller->layout '';
            
ob_start();
            
$this->controller->render(nullnull$view);
            
$plain_msg strip_tags(ob_get_clean());
            
$this->controller->layout $old_layout;
        }

        switch (
$type) {
            case 
'both' :
                if (
$return) {
                    return array (
                        
$plain_msg,
                        
$html_msg
                    
);
                }
                
$this->mailer->addPart($html_msg'text/html');
                
$this->mailer->addPart($plain_msg'text/plain');
                break;
            case 
'html' :
                if (
$return) {
                    return 
$html_msg;
                }
                
$this->mailer->addPart($html_msg'text/html');
                break;
            case 
'plain' :
                if (
$return) {
                    return 
$plain_msg;
                }
                
$this->mailer->addPart($plain_msg'text/plain');
                break;
        }

    }

    function 
replaceIMG($msg) {
        
$matches = array ();
        
$files = array ();
        if (
preg_match_all('#<img.*src=\"(.*?)\".*?\/>#'$msg$matches)) {
            for (
$i 0$i count($matches[0]); $i++) {
                
$pos strpos($matches[0][$i], 'embed="swift"');
                if (
$pos !== false) {
                    
$file substr($matches[1][$i], strrpos($matches[1][$i], '/') + 1);
                    if (
array_key_exists($file$files)) {
                        
$replace $files[$file];
                    } else {
                        
$replace $this->mailer->addImage(WWW_ROOT 'img' DS $file);
                        
$files[$file] = $replace;
                    }

                    
$msg str_replace($matches[1][$i], $replace$msg);
                }
            }
        }
        return 
$msg;

    }

    
/*
     * description: 
     * Wraps the body with a layout, strips tags if not html
     */
    
function wrapBody($msg$type 'plain'$return false) {
        
$view VIEWS $this->email_views_dir DS 'default.thtml';

        
$this->controller->set('swiftMailer_data'$msg);

        
ob_start();
        
$this->controller->render(null$this->layout$view);
        
$msg ob_get_clean();

        if (
$type != 'html') {
            
$msg strip_tags($msg);
        }

        if (
$return) {
            return 
$msg;
        }

        
$this->mailer->addPart($msg, ($type == 'html') ? 'text/html' 'text/plain');
    }

    
// original idea Tommy0    
    
function addTo($type$address$name false) {
        if (
in_array($type, array (
                
'to',
                
'from',
                
'cc',
                
'bcc'
            
))) {
            if (!
$name) {
                
$val $address;
            } else {
                
$val = array (
                    
$name,
                    
$address
                
);
            }

            if (
$type == 'from') {
                
$this-> $type $val;
            } else {
                if (!isset (
$this-> $type)) {
                    
$this-> $type = array ();
                }
                
array_push($this-> $type$val);
            }
        }
    }

    
// original idea Tommy0
    
function send($subject) {
        if (!empty (
$this->cc)) {
            
$this->mailer->addCc($this->cc);
        }
        if (!empty (
$this->bcc)) {
            
$this->mailer->addBcc($this->bcc);
        }
        if (
is_array($this->from)) {
            
$from '"' $this->from[0] . '" <' $this->from[1] . '>';
        } else {
            
$from $this->from;
        }
        if (!empty (
$this->username) && !$this->auth()) {
            return 
false;
        }
        if (
$this->mailer->send($this->to$from$subject)) {
            
$this->mailer->close();
            return 
true;
        }
        return 
false;
    }

    function 
sendWrap($subject$body$type 'plain') {
        
$this->wrapBody($body$type);

        return 
$this->send($subject);
    }

    function 
sendView($subject$view$type 'plain') {
        
$this->viewBody($view$type);

        return 
$this->send($subject);
    }

}
?>

 

Comments 192

CakePHP Team Comments Author Comments
 

Bug

1 Destination error when sending several mails

Hi !

Thanks for the great component

Ive noticed that when in the same controller action, several mails have to be sent, it is needed to reset the 'to' (also cc, bcc or from) list, otherwise all recipients from previous mails will receive other mails.

I've inserted this code snippet to be able to reset the different lists from the controller action :

8<------------

function resetTo($type) {
if (in_array($type, array (
'to',
'from',
'cc',
'bcc',
'all'
))) {
if ($type == 'all') {
$this->resetTo('from');
$this->resetTo('to');
$this->resetTo('cc');
$this->resetTo('bcc');
} else {
if (isset ($this-> $type)) {
unset($this-> $type);
}
}
}
}

---------------------

For me it worked like a charm and until now, I've seen no side effect.
Best regards

Flow
Posted Dec 31, 2006 by Florent Peyraud
 

Bug

2 typo

as far as i can tel there is a typo in the connect_sendmail function.

function connect_sendmail() {
vendor('Swift');
vendor('Swift/Connection/SendMail');

should be:

function connect_sendmail() {
vendor('Swift');
vendor('Swift/Connection/Sendmail');
Posted Jan 9, 2007 by Thomas Pedersen
 

Bug

3 view output


...
$view = VIEWS . $this->email_views_dir . DS . 'default.thtml';
...
$this->controller->render(null, $this->layout, $view);

It is not applied.
Posted Dec 31, 1969 by choi hyungnam
 

Comment

4 cake version

cake version is 1.1.13.4450
Posted Dec 31, 1969 by choi hyungnam
 

Bug

5 error

All i get is..

Fatal error: Call to undefined method Swift::isConnected() in E:\xampp\htdocs\portfolio\app\controllers\components\swift_mailer.php on line 46
Posted Dec 31, 1969 by chris
 

Question

6 Update for Swift 3.x

Great component - very handy. Any plans for an update that will work with Swift 3.x.x? Thanks.

Posted Apr 21, 2007 by TM
 

Comment

7 Update for Swift 3.x

Funny you should mention it, I wrote an update for it last night. A simple method of update would be to use EasySwift instead of the Swift library. The update I wrote doesn't use that since they stated they have no idea how long it will stay around. I'll post the component and such after I review my code and make sure it isn't crap. I'll also add support for attaching files.
Posted Apr 21, 2007 by Scott Zwerner
 

Question

8 Any Update for Swift 3.x

Any update for Swift 3.x.x .i waiting for it

as i am getting this error

Fatal error: Call to undefined method Swift::isConnected() in E:xampphtdocsportfolioappcontrollerscomponentsswift_mailer.php on line 46

thanks in Advance
Posted Jun 5, 2007 by Sajid
 

Comment

9 3.x update

Hey Scott, could you post that 3.x update?
Posted Jun 15, 2007 by Eric Winchell
 

Comment

10 Use EasySwift with 3.x

This component works with 3.x with some minor changes. Follow the install instructions from the tutorial and additionally copy EasySwift.php in to app/vendors.

Next, edit the component and change all occurrences of vendor('Swift') to vendor('EasySwift'). Also change all occurrences of new Swift() to new EasySwift().
Posted Jun 17, 2007 by Billy Gunn
 

Question

11 EasySwift with 3.x does not work

I made all changes. But with Swift 3.2.6 PHP5 it works not!

/ SwiftMailer
$this->SwiftMailer->connection = 'smtp';
$this->SwiftMailer->smtp_host = 'mail.gmx.net';
$this->SwiftMailer->smtp_port = 25;
$this->SwiftMailer->smtp_type = 'open';

$this->SwiftMailer->username = '
';
$this->SwiftMailer->password = '';

if($this->SwiftMailer->connect())
{
$this->SwiftMailer->addTo('to',"xyz@web.de","Mr. XYZ");
$this->SwiftMailer->addTo('from',"abc@gmx.de","Mr. ABC");

//$this->SwiftMailer->sendView("Golfstartzeiten-Planer Password vergessen",'default');

//if(!$this->SwiftMailer->sendWrap("Golfstartzeiten-Planer Password vergessen",'default'))
if(!$this->SwiftMailer->send("Golfstartzeiten-Planer Password vergessen"))
{
echo "The mailer failed to Send. Errors:";
pr($this->SwiftMailer->errors());
}

echo "Log:";
pr($this->SwiftMailer->transactions());
}
else
{
echo "The mailer failed to connect. Errors:";
pr($this->SwiftMailer->errors());
}

This error is always shown:

The mailer failed to Send. Errors:

Array
(
)
//-------------------------------------------

Any Ideas here!
Posted Jul 29, 2007 by Sascha Deus
 

Comment

12 CakePHP SwiftMailer 3 Component

I adjusted the component, so it works with SwiftMailer 3. You can find it at http://blog.aboutme.be/2008/05/07/cakephp-swiftmailer-3-component/
Posted May 7, 2008 by Wouter Verweirder