SwiftMailer Component

By Othman ouahbi aka "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 Sun, Dec 31st 2006, 06:08 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 Tue, Jan 9th 2007, 07:57 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 Wed, Dec 31st 1969, 18:00 by choi hyungnam

Comment

4 cake version

cake version is 1.1.13.4450
posted Wed, Dec 31st 1969, 18:00 by choi hyungnam

Bug

5 error

All i get is..

Fatal error: Call to undefined method Swift::isConnected() in E:xampphtdocsportfolioappcontrollerscomponentsswift_mailer.php on line 46
posted Wed, Dec 31st 1969, 18:00 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 Sat, Apr 21st 2007, 12:23 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 Sat, Apr 21st 2007, 15:17 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 Tue, Jun 5th 2007, 08:10 by Sajid

Comment

9 3.x update

Hey Scott, could you post that 3.x update?
posted Fri, Jun 15th 2007, 11:39 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 Sun, Jun 17th 2007, 16:53 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 = '<address>';
$this->SwiftMailer->password = '<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 Sun, Jul 29th 2007, 06:11 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 Wed, May 7th 2008, 10:45 by Wouter Verweirder

Login to Submit a Comment