SwiftMailer Component Tutorial

By Othman ouahbi (CraZyLeGs)
Based on Chris Corbyn's excellent Swift Mailer. This is a component that does encapsulate it but not hide it, while it adds some nifty features. Read on how to bake with it.

Prerequisites


I would still advise you read the Swift Mailer documentation here: http://www.swiftmailer.org/docs/ SwiftMailer Component isn't an attempt to hide the already excellent class written by Chris Corbyn. Rather, the component tries to integrate and extend it (read, Cake-ish!).
The Swift object is still accessible through the member variable $this->SwiftMailer->mailer.

But first things first, Swift Mailer can be found here: http://www.swiftmailer.org/download/ The version this Component is based on is Swift-2.1.17-php4.
Download the package and extract it. put Swift.php and the Swift folder into your vendors directory.
you should have something like:
Download code
vendors/
        Swift/
        Swift.php
You are ready to go.

Installation

Grab the component located here: http://bakery.cakephp.org/articles/view/192 Put it in your components folder and save it as swift_mailer.php, not swiftmailer.php!
If you don't understand why, you should probably read the conventions appendix in the manual here:
http://manual.cakephp.org/appendix/conventions
Add the component to your controller:
Download code
var $components = array('SwiftMailer'); // along with the other components you use.
Woot, you serious?! Yep. Well you know, it's Cake! ;)

Making the connection

Swift Mailer has three connection types: native, sendmail and smtp. We're going to see how to establish a connection using each type.

Native Mail

In this type, Swift uses the PHP's mail function.
This is what you should do:
Download code
$this->SwiftMailer->connection = 'native';

if($this->SwiftMailer->connect())
{
    // ..
}
That's all? Absolutely.

Sendmail

Quoting the Swift Mailer documentation:
Establishes a I/O hook to a sendmail process running in -bs mode. The binary does not strictly need to be sendmail, it will work with exim, qmail and postfix too providing the version in question supports running in -bs mode.
Here is how to do it using the component:
Download code
$this->SwiftMailer->connection = 'sendmail';
$this->SwiftMailer->sendmail_cmd = '/usr/sbin/sendmail -bs';

if($this->SwiftMailer->connect())
{
    // ..
}
$sendmail_cmd defaults to false, Swift will then try to find sendmail itself by using the linux command `which`. Setting it to 'default' is equivalent to '/usr/sbin/sendmail -bs'.

SMTP

This is the default connection type. Here is how to use it:
Download code
$this->SwiftMailer->connection  = 'smtp'; // default and thus you don't have to specify it
$this->SwiftMailer->smtp_host   = 'smtp.gmail.com';
$this->SwiftMailer->smtp_type   = 'tls'; 

if($this->SwiftMailer->connect())
{
    // ..
}
$smtp_host is the fully qualified domain name of the server you wish to connect to. Defaults to null in the Component, which means Swift will read the value from php.ini
$smtp_port: The default SMTP port is 25, 465 for SSL. It is set to false in the Component, to let Swift choose the value depending on $smtp_type. Set it to null to tell Swift to read the value from php.ini
$smtp_type Can be one of the following values: 'open', 'ssl', 'tls'.
Depending on your SMTP server, you should set this value accordingly.
By the way Gmail uses TLS.

Auth

If your server requires authetication, you can set up your username and password by doing the following:
Download code
$this->SwiftMailer->username  = 'user@gmail.com';
$this->SwiftMailer->password  = 'secret';
Depending on your server, your username might be 'user' or 'user@domain.tld'.

Sending Mail

To avoid redundancy, I'm not going to focus on how to send mail using the Swift Mailer, rather, I will show how to do it using the component. If you need to access the Swift object directly, use $this->SwiftMailer->mailer.

This component isn't attempting to hide Swift, but rather extend it's functionality and make it Cake-ish. Swift's syntax is really clear/clean, and re-inventing it is really pointless. That being said, I'm going to show you what this component adds:

addTo($type, $address, $name = false)

Originally, this function was written by TommyO in his component. I liked the idea, so I added it. I had to modify it though.
$type Can be one of these values: 'from', 'to', 'cc', 'bcc'.
You can have many 'to','cc', 'bcc' entries, but only one 'from'.
Here are examples of usage:
Download code

    $this->SwiftMailer->addTo('from',"user@gmail.com","firstname lastname");
    
    $this->SwiftMailer->addTo('to',"user@domain.tld");
    $this->SwiftMailer->addTo('to',"foobar@domain.tld","Foo Bar");
    $this->SwiftMailer->addTo('to',"crazylegs@gmail.com","CraZyLeGs");
    
    $this->SwiftMailer->addTo('cc',"cc1@domain.tld","C C 1");
    $this->SwiftMailer->addTo('cc',"cc2@domain.tld","C C 2");
    
    $this->SwiftMailer->addTo('bcc',"bcc1@domain.tld","B C C 1");
    $this->SwiftMailer->addTo('bcc',"bcc2@domain.tld","B C C 2");
    

Adding a body

To add body to your message you can use the $mailer object within the component. Refer to the Swift Mailer documentation for more info.
Example:
Download code
$this->SwiftMailer->mailer->addPart("Plain Body");
$this->SwiftMailer->mailer->addPart("Html Body", 'text/html');

I want to send it, damn it!

Fine.
Download code
$this->SwiftMailer->send("Subject");
Happy? You could just do it with internal Swift object though: $this->SwiftMailer->send(...);

What's the difference, then? Well, the component's send method takes into consideration the parts you added using addPart, and if you have specified a username and password, it will try to authenticate.
Oh really?! Really. Nice!!!. I know.
Until now, it's been pretty basic, but bear with me and continue reading.

wrapBody($msg, $type = 'plain', $return = false)

Actually, the exciting part starts here. The Swift Mailer Component has the capability to wrap your body message with a layout. Yeah, a Cake layout.
In the controller there is a variable called $layout, which defaults to 'swift_email', and it is the layout you want your message to get wrapped with. You need to create swift_email.thtml in your layouts folder.

An example of a layout:

View Template:

Download code
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<base href="<?=FULL_BASE_URL?>" />
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>CakePHP SwiftMailer Component</title>
</head>

<body style="background: #dedede; padding-top: 100px;" >

<?=$html->image('w3c_xhtml10.png')?> <br/>
<?=$html->image('w3c_css.png')?><br/>
<?=$html->image('cake.power.png',array('embed'=>'swift'))?><br/>
<?=$content_for_layout; ?>
</body>
</html>

Please notice " />, You need to have this in order for internal elements ( img, anchors, etc.) to link properly from within the mail client reading the Email you're going to send.

There is also $email_views_dir which is the folder within the views directory where emails to be sent will be stored. More on that in the next section, but for now you need to have a view called default.thtml in there for wrapBody to function.

Content of default.thtml :

View Template:

Download code
<?php echo $swiftMailer_data;?>

$msg is the message you want to get wrapped by the layout.
$type Either 'plain' or 'html', if plain, the HTML tags are stripped.
$return defaults to false, if true the wrapped msg is returned instead of added in the mail. You can call $this->SwiftMailer->mailer->addPart to add it then.
Usage:
Download code
$this->SwiftMailer->wrapBody("My Plain Body");
$this->SwiftMailer->wrapBody("My HTML Body",'html');

$body = $this->SwiftMailer->wrapBody("I want my body",'html',true);

This function can be useful for example to send a newsLetter, the body content is coming from the database where you archive the newsletters sent, you wrap the newsletter with a layout and you're all set!

function viewBody($name, $type = 'both', $return = false)

With SwiftMailer Component, you have the possibility to send views you prepared in advance. A common example would be a confirmation email, etc. The views should be located in the directory specified by $email_views_dir.

$msg is the name of the view you want to send without .thtml
$type can be one of the following values 'plain', 'html' or 'both', 'both' is the default
$return defaults to false, if true the rendered view is returned instead of added in the mail. you can call $this->SwiftMailer->mailer->addPart to add it then.
if $type is plain, the html tags are striped. if 'both', both an html and plain versions are added.
The 'html' view must have the suffix '_html', so if you plan to send an html confirmation email, you should name your view confirm_html.thtml.
So if type is 'both' and you want to send the confirm view, you need to actually have two views, one named confirm.thtml for the plain version and one named confirm_html.thtml for the HTML version. Clear? Thought so.
Usage:
Download code

$this->SwiftMailer->viewBody('confirm'); // defaults to 'both'
$this->SwiftMailer->viewBody('confirm','plain');
$this->SwiftMailer->viewBody('confirm','html');

$html_plain = $this->SwiftMailer->viewBody('confirm','plain',true);
$html_body  = $this->SwiftMailer->viewBody('confirm','html',true);
// $both_body will contain an array of both the 'plain' and 'html' versions, in this order.
$both_body = $this->SwiftMailer->viewBody('confirm','both',true);


Shortcut functions

sendWrap($subject, $body, $type = 'plain')

This function is equivalent to calling wrapBody and send.

sendWrap($subject, $body, $type = 'plain')

This function is equivalent to calling viewBody and send.

Complete example

Download code
$this->SwiftMailer->connection  = 'smtp';
$this->SwiftMailer->smtp_host   = 'smtp.gmail.com';
$this->SwiftMailer->smtp_type   = 'tls'; 

$this->SwiftMailer->username  = 'user@gmail.com';
$this->SwiftMailer->password  = 'secret';
 
if($this->SwiftMailer->connect())
{
    $this->SwiftMailer->addTo('to',"crazylegs@gmail.com","CraZyLeGs");
    $this->SwiftMailer->addTo('from',"user@gmail.com","some user");
    
    if(!$this->SwiftMailer->sendView("SwiftComponent::sendView Exemple","confirm",'both'))
    {
        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());
}

Bonus

One thing that is nice with Swift Mailer, is a function called addImage, it embeds an image into the body of the email to display inline.
Something like:

View Template:

Download code
<img src="'.$swift->addImage($path_to_image).'" alt="Holiday" />
The problem with that though, is that Cake is an MVC framework and thus the view doesn't have business logic so it can not access the Mailer, well actually it can($this->controller->SwiftMailer->mailer->addImage(WWW_ROOT.'img'.'ewww_ugly.jpg');), but it should not, read it, must not.
And so there is no obvious way of calling addImage from the view, if we want to embed images. I hear you saying, use a helper, will this won't solve the issue, because, you would want to create an instance of Swift, that instance will not be the one the component is using.
Oh Ma'..so what's the solution? Heh, don't beat me if I say that it's already solved. actually the component's viewBody function solves it. Shut up!! yeah, it actually looks for images that have the param embed="swift" in them and converts them automagically into embeded images! You're kidding? Hell, no.
[view] image('cake.power.png',array('embed'=>'swift'))?> That was my bonus.

Conclusion

That's it guys, I hope you'll find the component useful, Thanks to Chris Corbyn for making such a great class. As always, comments enhancements, typo corrections, bug reports are welcome.

 

Comments 193

CakePHP Team Comments Author Comments
 

Comment

1 Merge view with variables

Hello

I would like to be able to setup a view for an email and have placeholder for data e.g.

Hello [Firstname]
Is this possible?
Posted Jul 20, 2007 by Jono
 

Bug

2 Swift Mail could not Connect

As I trying to connect the Swift Mail it is showing the following error

Call to undefined method stdClass::connect() in /data/projects/cake_test/controllers/admins_controller.php on line 80

Here is my controller code

function news()
{
$res = $this->Member->query("SELECT members.email FROM members");
foreach($res as $val)
{
$this->SwiftMailer->connection = 'native';

if($this->SwiftMailer->connect())
{
$this->SwiftMailer->addTo('to',"$val","CraZyLeGs");
$this->SwiftMailer->addTo('from',"santosh@apexdivision.com","Santosh");

if(!$this->SwiftMailer->sendView("SwiftComponent::sendView Exemple","confirm",'both'))
{
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());
}

}


}
Posted Aug 1, 2007 by Mithun Das
 

Comment

3 Thank You

At LAst I a have successfully connected to Swift Mail.
I changed the component
vendor('Swift');
vendor('Swift/Connection/SMTP');

To

vendor('Swift'.DS.'Swift');
vendor('Swift'.DS.'Connection'.DS.'SMTP');

And I am successfull in sending mails also newsletters
Posted Aug 1, 2007 by Mithun Das
 

Comment

4 Sending Attachment With Swift Mailer

Well I have Finally solved this problem

Just a little modification in The sendWrap function() [Which I am using to send my mails] of the component.

This is how it looks now

function sendWrap($subject, $body, $type = plain',$data,$filename,$type) {

$this->wrapBody($body, $type);
$this->mailer->addAttachment($data, $filename, $type);

return $this->send($subject);
}
Posted Aug 6, 2007 by Mithun Das
 

Comment

5 The Post is not at all abug

As I trying to connect the Swift Mail it is showing the following error

Call to undefined method stdClass::connect() in /data/projects/cake_test/controllers/admins_controller.php on line 80

Here is my controller code

function news()
{
$res = $this->Member->query("SELECT members.email FROM members");
foreach($res as $val)
{
$this->SwiftMailer->connection = 'native';

if($this->SwiftMailer->connect())
{
$this->SwiftMailer->addTo('to',"$val","CraZyLeGs");
$this->SwiftMailer->addTo('from',"santosh@apexdivision.com","Santosh");

if(!$this->SwiftMailer->sendView("SwiftComponent::sendView Exemple","confirm",'both'))
{
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 is not at all a bug it is just a simple error. From my part.
Posted Aug 6, 2007 by Mithun Das
 

Comment

6 Awsome Component

Undoubtedly this is an awsum component I have gone through many components in the Bakery but is one of the most good one for using. The logics are so well defined that u can easily modify it as per your requirement. As I have to add the attachment logic (Look at my previous post: Sending Attachment With Swift Mailer) it was very simple and error free.
Previously I had had some errors but those are all due to my coding not for the component. I have fixed all of them and my newsletter is working great. Thanks again.

Mithun
Posted Aug 6, 2007 by Mithun Das
 

Comment

7 loading Swift vs. EasySwift

Just grabbed latest PHP5 version of SwiftMailer, which at present is 3.3.2.

My first issue was that the tutorial says to copy in Swift.php so you have the following directory structure: /app/vendors/Swift/Swift.php. I found that Swift was not being loaded, as the vendors line in the component is lookinf for Swift.php in the vendors root dir. The solution is to copy the Swift.php file, the EasySwift.php file (more on this later) and Swift folder from the downloaded package to the vendors folder. So now you have

/app/vendors/EasySwift.php
/app/vendors/Swift.php
/app/vendors/Swift/{lots of stuff}

Had issues with notices of undefined constants on things like 'SWIFT_TLS'. So did a search of all the files in the package and found that only EasySwift.php defines these at all. So, I had to change all lines reading

vendors('Swift');
to

vendors('EasySwift');
That cleared up the notices, and actually started looking like it was trying to connect via tls:// protocol.

Finally, Swift's inbuilt debugging statements told me to go enable tls for php, which I'm working on now. Will write again if that didn't solve everything.
Posted Nov 17, 2007 by James Revillini
 

Comment

8 EasySwift continued

this comment at the top of EasySwift explains things:
/**
* EasySwift: Facade for Swift Mailer Version 3.
* Provides (most of) the API from older versions of Swift, wrapped around the new version 3 API.
* Due to the popularity of the new API, EasySwift will not be around indefinitely.
* @package EasySwift
* @author Chris Corbyn * @deprecated
*/

SO, this means that all calls to 'new Swift' in swift_mailer.php must become 'new EasySwift'

I'm still having issues, but it may be how I'm trying to authenticate, rather than with the component.
Posted Nov 17, 2007 by James Revillini
 

Comment

9 Use this component in 1.2.x.x with a minor fix

Hi. Here's a dumb "gotcha" that took me a while to understand. I needed to migrate this component to 1.2.x.x and I was getting all kind of annoying Notices. Just in case you are having this problem:

Make this change from line 40 to line 72. It's just substituting the deprecated vendor() function for the new App::import()

    function connect_native() {
        App::import( 'vendor', 'Swift', array('file' => 'Swift.php'));
        App::import ( 'vendor', 'SwiftConnectionNativeMail', array('file' => 'Swift'.DS.'Connection'.DS.'NativeMail.php') );

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

    function connect_sendmail() {
        App::import( 'vendor', 'Swift', array('file' => 'Swift.php'));
        App::import( 'vendor', 'SwiftConnectionSendMail' , array('file' => 'Swift'.DS.'Connection'.DS.'SendMail.php'));

        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() {
        App::import( 'vendor', 'Swift', array('file' => 'Swift.php') );
        App::import( 'vendor', 'SwiftConnectionSMTP', array('file' => 'Swift'.DS.'Connection'.DS.'SMTP.php'));

Posted Aug 5, 2008 by Ana Daz
 

Comment

10 Blank emails

Just want to start by saying what a great component you've created. I've been working it into an app of mine, and I'm having a problem with blank emails. In my controller, I'm using the separate wrapBody() and send() methods, and with the following:

$this->SwiftMailer->wrapBody($msg, 'html', false);

the app breaks with:

Fatal error: Call to a member function on a non-object in /path/to/app/controllers/components/swift_mailer.php on line 232

If I set the $return parameter to true, it will return $msg and send the email, but the email is empty and doesn't respect the $type parameter, sending text/plain.

Any assistance anyone can offer would be appreciated. Thanks in advance.
Posted Feb 25, 2009 by Ken Bergquist
 

Comment

11 Blank emails

Replying to my own comment here...

As it turns out, I had the wrapBody() before the connect() statement. DOH!

But the email is still sent empty. It IS now respecting the $type.

Just want to start by saying what a great component you've created. I've been working it into an app of mine, and I'm having a problem with blank emails. In my controller, I'm using the separate wrapBody() and send() methods, and with the following:

$this->SwiftMailer->wrapBody($msg, 'html', false);

the app breaks with:

Fatal error: Call to a member function on a non-object in /path/to/app/controllers/components/swift_mailer.php on line 232

If I set the $return parameter to true, it will return $msg and send the email, but the email is empty and doesn't respect the $type parameter, sending text/plain.

Any assistance anyone can offer would be appreciated. Thanks in advance.
Posted Feb 25, 2009 by Ken Bergquist
 

Comment

12 Blank emails No More

Got it working - here's my modified component code. Please also note I have made it .ctp friendly, no longer requiring the deprecated .thtml extension on views.

Component Class:

<?php 
<?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 'email';

    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 isConnected() {
//        return true;
//    }

    
function connect_native() {
        
App::import'vendor''SwiftMailer/EasySwift', array('file' => 'EasySwift.php'));
//        App::import ( 'vendor', 'SwiftConnectionNativeMail', array('file' => 'Swift'.DS.'Connection'.DS.'NativeMail.php') );

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

    function 
connect_sendmail() {
        
App::import'vendor''SwiftMailer/EasySwift', array('file' => 'EasySwift.php'));
//        App::import( 'vendor', 'SwiftConnectionSendMail' , array('file' => 'Swift'.DS.'Connection'.DS.'SendMail.php'));

        
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 EasySwift(new Swift_Connection_SendMail($this->sendmail_cmd));
    }

    function 
connect_smtp() {
        
App::import'vendor''SwiftMailer/EasySwift', array('file' => 'EasySwift.php') ); 
//        App::import( 'vendor', 'SwiftConnectionSMTP', array('file' => 'Swift'.DS.'Connection'.DS.'SMTP.php')); 

        // 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 EasySwift(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 $this->email_views_dir DS $name;
            
$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 $this->email_views_dir DS $name;
            
$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 $this->email_views_dir DS 'default';

        
$this->controller->set('swiftMailer_data'$msg);
// commented out buffer code... that's what was blanking the email output for some reason.
//        ob_start();
        
$this->controller->render(null$this->layout$view);
//        $msg = ob_get_clean();

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

        if (
$return) {
            return 
$msg;
        }

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

    
// 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);
    }

}
?>
?>
Posted Feb 26, 2009 by Ken Bergquist