Fixing content type ordering when content_type is not defined.
[akelos.git] / lib / AkActionMailer.php
blob290a5b6e344e80b2b2d2a68e17b161bf4c394d41
1 <?php
2 /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
4 // +----------------------------------------------------------------------+
5 // | Akelos Framework - http://www.akelos.org |
6 // +----------------------------------------------------------------------+
7 // | Copyright (c) 2002-2006, Akelos Media, S.L. & Bermi Ferrer Martinez |
8 // | Released under the GNU Lesser General Public License, see LICENSE.txt|
9 // +----------------------------------------------------------------------+
11 /**
12 * @package AkelosFramework
13 * @subpackage AkActionMailer
14 * @author Bermi Ferrer <bermi a.t akelos c.om>
15 * @copyright Copyright (c) 2002-2006, Akelos Media, S.L. http://www.akelos.org
16 * @license GNU Lesser General Public License <http://www.gnu.org/copyleft/lesser.html>
19 require_once(AK_LIB_DIR.DS.'AkBaseModel.php');
20 require_once(AK_LIB_DIR.DS.'AkActionMailer'.DS.'AkMailMessage.php');
21 require_once(AK_LIB_DIR.DS.'AkActionMailer'.DS.'AkMailParser.php');
22 require_once(AK_LIB_DIR.DS.'AkActionMailer'.DS.'AkActionMailerQuoting.php');
23 require_once(AK_LIB_DIR.DS.'AkActionMailer'.DS.'AkMailComposer.php');
25 ak_define('MAIL_EMBED_IMAGES_AUTOMATICALLY_ON_EMAILS', false);
26 ak_define('ACTION_MAILER_DEFAULT_CHARSET', AK_CHARSET);
27 ak_define('ACTION_MAILER_EOL', "\r\n");
28 ak_define('ACTION_MAILER_EMAIL_REGULAR_EXPRESSION', "([a-z0-9_\-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([a-z0-9\-]+\.)+))([a-z]{2,4}|[0-9]{1,3})(\]?)");
29 ak_define('ACTION_MAILER_RFC_2822_DATE_REGULAR_EXPRESSION', "(?:(Mon|Tue|Wed|Thu|Fri|Sat|Sun), *)?(\d\d?) (Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) (\d\d\d\d) (\d{2}:\d{2}(?::\d\d)) (UT|GMT|EST|EDT|CST|CDT|MST|MDT|PST|PDT|[A-Z]|(?:\+|\-)\d{4})");
31 /**
32 * AkActionMailer allows you to send email from your application using a mailer model and views.
34 * = Mailer Models
36 * To use AkActionMailer, you need to create a mailer model.
38 * $ ./script/generate mailer Notifier
40 * The generated model inherits from AkActionMailer. Emails are defined by
41 * creating methods within the model which are then used to set variables to be
42 * used in the mail template, to change options on the mail, or to add attachments.
44 * Examples:
46 * class Notifier extends AkActionMailer
47 * {
48 * function signupNotification($Recipient)
49 * {
50 * $this->setRecipients($Recipient->getEmailAddressWithName());
51 * $this->setFrom("system@example.com");
52 * $this->setSubject("New account information");
53 * $this->setBody(array('account' => $Recipient ));
54 * }
55 * }
57 * Mailer methods have the following configuration methods available.
59 * * <tt>setRecipients</tt> - Takes one or more email addresses. These addresses are where your email will be delivered to. Sets the <tt>To:</tt> header.
60 * * <tt>setSubject</tt> - The subject of your email. Sets the <tt>Subject:</tt> header.
61 * * <tt>setFrom</tt> - Who the email you are sending is from. Sets the <tt>From:</tt> header.
62 * * <tt>setCc</tt> - Takes one or more email addresses. These addresses will receive a carbon copy of your email. Sets the <tt>Cc:</tt> header.
63 * * <tt>setBcc</tt> - Takes one or more email address. These addresses will receive a blind carbon copy of your email. Sets the <tt>Bcc</tt> header.
64 * * <tt>setSentOn</tt> - The date on which the message was sent. If not set, the header wil be set by the delivery agent.
65 * * <tt>setContentType</tt> - Specify the content type of the message. Defaults to <tt>text/plain</tt>.
66 * * <tt>setHeaders</tt> - Specify additional headers to be set for the message, e.g. <tt>$this->setHeaders(array('X-Mail-Count' => 107370));</tt>.
68 * The <tt>setBody</tt> method has special behavior. It takes an array which generates an instance variable
69 * named after each key in the array containing the value that that key points to.
71 * So, for example, <tt>setBody(array("account" => $Recipient));</tt> would result
72 * in an instance variable <tt>$account</tt> with the value of <tt>$Recipient</tt> being accessible in the
73 * view.
76 * = Mailer views
78 * Like AkAkActionController, each mailer class has a corresponding view directory
79 * in which each method of the class looks for a template with its name.
80 * To define a template to be used with a mailing, create an <tt>.tpl</tt> file with the same name as the method
81 * in your mailer model. For example, in the mailer defined above, the template at
82 * <tt>app/views/notifier/signup_notification.tpl</tt> would be used to generate the email.
84 * Variables defined in the model are accessible as instance variables in the view.
86 * Emails by default are sent in plain text, so a sample view for our model example might look like this:
88 * Hi {account.name},
89 * Thanks for joining our service! Please check back often.
91 * You can even use Action View helpers in these views. For example:
93 * You got a new note!
94 * <?=$text_helper->truncate($note->body, 25);?>
97 * = Generating URLs for mailer views
99 * If your view includes URLs from the application, you need to use Ak::urlFor in
100 * the mailing method instead of the view.
101 * Unlike controllers from Action View, the mailer instance doesn't have any
102 * context about the incoming request. That's why you need to jump this little
103 * hoop and supply all the details needed for the URL.
105 * Example:
107 * function signupNotification($Recipient)
109 * // This is the same as calling each individual setter
110 * $this->setAttributes(array(
111 * 'recipients' => $Recipient->getEmailAddressWithName(),
112 * 'from' => "system@example.com",
113 * 'subject' => "New account information",
114 * 'body' => array(
115 * 'account' => $Recipient,
116 * 'home_page' => Ak::urlFor(array('host' => "example.com", 'controller' => "welcome", 'action' => "greeting"))
118 * ));
121 * You can now access @home_page in the template and get http://example.com/welcome/greeting.
123 * = Sending mail
125 * Once a mailer action and template are defined, you can deliver your message or
126 * create it and save it for delivery later:
128 * Notifier::deliver('signup_notification', $David); // sends the email
129 * $Message = Notifier::create('signup_notification', $David); // => A PEAR::Mail object
130 * Notifier::deliver($Message);
132 * You never instantiate your mailer class. Rather, your delivery instance
133 * methods are automatically wrapped in class methods that are called statically
134 * The <tt>signup_notification</tt> method defined above is delivered by invoking
135 * <tt>$Notifier =& new Notifier(); $Notifier->signupNotification(); $Notifier->deliver();</tt>.
138 * = HTML email
140 * To send mail as HTML, make sure your view (the <tt>.tpl</tt> file) generates HTML and
141 * set the content type to html.
143 * class ApplicationMailer extends AkActionMailer
145 * function signupNotification($Recipient)
147 * $this->setAttributes(array(
148 * 'recipients' => $Recipient->getEmailAddressWithName(),
149 * 'from' => "system@example.com",
150 * 'subject' => "New account information",
151 * 'body' => array('account' => $Recipient),
152 * 'content_type' => text/html" // Here's where the magic happens
153 * ));
158 * = Multipart email
160 * You can explicitly specify multipart messages:
162 * class ApplicationMailer extends AkActionMailer
164 * function signupNotification($Recipient)
166 * $this->setAttributes(array(
167 * 'recipients' => $Recipient->getEmailAddressWithName(),
168 * 'from' => "system@example.com",
169 * 'subject' => "New account information"
170 * ));
172 * $this->addPart(array(
173 * 'content_type' => "text/html",
174 * 'body' => $this->renderMessage('signup-as-html', 'account' => $recipient)));
176 * $this->addPart("text/plain", array(
177 * 'transfer_encoding' = "base64",
178 * 'body' => $this->renderMessage('signup-as-plain', 'account' => $recipient)));
182 * Multipart messages can also be used implicitly because AkActionMailer will automatically
183 * detect and use multipart templates, where each template is named after the name of the action, followed
184 * by the content type. Each such detected template will be added as separate part to the message.
186 * For example, if the following templates existed:
187 * * signup_notification.text.plain.tpl
188 * * signup_notification.text.html.tpl
190 * Each would be rendered and added as a separate part to the message,
191 * with the corresponding content type. The same body array is passed to
192 * each template.
195 * = Attachments
197 * Attachments can be added by using the +addAttachment+ method.
199 * Example:
201 * class ApplicationMailer extends AkActionMailer
203 * // attachments
204 * function signupNotification($Recipient)
206 * $this->setAttributes(array(
207 * 'recipients' => $Recipient->getEmailAddressWithName(),
208 * 'from' => "system@example.com",
209 * 'subject' => "New account information"
210 * ));
212 * $this->addAttachment(array(
213 * 'content_type' => 'image/jpeg',
214 * 'body' => Ak::file_get_contents("an-image.jpg")));
216 * $this->addAttachment('application/pdf', generate_your_pdf_here());
221 * = Configuration options
223 * These options are specified on the class level, as class attriibutes
224 * <tt>$AkActionMailerInstance->templateRoot = "/my/templates";</tt>
226 * * <tt>templateRoot</tt> - template root determines the base from which template references will be made.
228 * * <tt>server_settings</tt> - Allows detailed configuration of the server:
229 * * <tt>address</tt> Allows you to use a remote mail server. Just change it
230 * from its default "localhost" setting.
231 * * <tt>port</tt> On the off chance that your mail server doesn't run on port 25, you can change it.
232 * * <tt>domain</tt> If you need to specify a HELO domain, you can do it here.
233 * * <tt>user_name</tt> If your mail server requires authentication, set the username in this setting.
234 * * <tt>password</tt> If your mail server requires authentication, set the password in this setting.
235 * * <tt>authentication</tt> If your mail server requires authentication, you need to specify the authentication type here.
236 * Options are: plain, login, cram_md5
238 * * <tt>delivery_method</tt> - Defines a delivery method. Possible values are 'php' (default), 'smtp', and 'test'.
240 * * <tt>perform_deliveries</tt> - Determines whether AkActionMailer::deliver(*) methods are actually carried out. By default they are,
241 * but this can be turned off to help functional testing.
243 * * <tt>deliveries</tt> - Keeps an array of all the emails sent out through the Action Mailer with delivery_method 'test'. Most useful
244 * for unit and functional testing.
246 * * <tt>default_charset</tt> - The default charset used for the body and to encode the subject. Defaults to UTF-8. You can also
247 * pick a different charset from inside a method with <tt>$this->charset</tt>.
248 * * <tt>default_content_type</tt> - The default content type used for the main part of the message. Defaults to "text/plain". You
249 * can also pick a different content type from inside a method with <tt>$this->content_type</tt>.
250 * * <tt>default_mime_version</tt> - The default mime version used for the message. Defaults to "1.0". You
251 * can also pick a different value from inside a method with <tt>$this->mime_version</tt>.
252 * * <tt>default_implicit_parts_order</tt> - When a message is built implicitly (i.e. multiple parts are assembled from templates
253 * which specify the content type in their filenames) this variable controls how the parts are ordered. Defaults to
254 * array("multipart/alternative", "text/html", "text/enriched", "text/plain"). Items that appear first in the array have higher priority in the mail client
255 * and appear last in the mime encoded message. You can also pick a different order from inside a method with
256 * <tt>$this->implicit_parts_order</tt>.
258 class AkActionMailer extends AkBaseModel
260 var $templateRoot;
261 var $server_settings = array(
262 'address' => 'localhost',
263 'port' => 25,
264 'domain' => 'localhost.localdomain',
265 'user_name' => null,
266 'password' => null,
267 'authentication' => null
270 var $delivery_method = 'php';
271 var $perform_deliveries = true;
272 var $deliveries = array();
273 var $default_charset = AK_ACTION_MAILER_DEFAULT_CHARSET;
274 var $default_content_type = 'text/plain';
275 var $default_mime_version = '1.0';
276 var $default_implicit_parts_order = array('multipart/alternative', 'text/html', 'text/enriched', 'text/plain');
277 var $helpers = array('mail');
278 var $Message;
279 var $Composer;
280 var $_defaultMailDriverName = 'AkMailMessage';
282 function __construct($Driver = null)
284 $this->loadSettings();
285 if(empty($Driver)){
286 $this->Message =& new $this->_defaultMailDriverName();
287 }else{
288 $this->Message =& $Driver;
292 function loadSettings()
294 if($settings = Ak::getSettings('mailer', false)){
295 foreach ($settings as $k=>$v){
296 $this->$k = $v;
302 * Specify the template name to use for current message. This is the "base"
303 * template name, without the extension or directory, and may be used to
304 * have multiple mailer methods share the same template.
306 function setTemplate($template_name)
308 $this->template = $template_name;
312 * Override the mailer name, which defaults to an inflected version of the
313 * mailer's class name. If you want to use a template in a non-standard
314 * location, you can use this to specify that location.
316 function setMailerName($mailerName)
318 $this->mailerName = $mailerName;
321 // Mail object specific setters
325 * Define the body of the message. This is either an array (in which case it
326 * specifies the variables to pass to the template when it is rendered),
327 * or a string, in which case it specifies the actual text of the message.
329 function setBody($body)
331 if(is_array($body) && count($body) == 1 && array_key_exists(0,$body)){
332 $body = $body[0];
334 $this->Message->setBody($body);
338 * Specify the CC addresses for the message.
340 function setCc($cc)
342 $this->Message->setCc($cc);
346 * Specify the BCC addresses for the message.
348 function setBcc($bcc)
350 $this->Message->setBcc($bcc);
353 * Specify the charset to use for the message. This defaults to the
354 * +default_charset+ specified for AkActionMailer.
356 function setCharset($charset)
358 $this->Message->setCharset($charset);
362 * Specify the content type for the message. This defaults to <tt>text/plain</tt>
363 * in most cases, but can be automatically set in some situations.
365 function setContentType($content_type)
367 $this->Message->setContentType($content_type);
371 * Specify the from address for the message.
373 function setFrom($from)
375 $this->Message->setFrom($from);
379 * Specify additional headers to be added to the message.
381 function setHeaders($headers)
383 $this->Message->setHeaders($headers);
387 * Specify the order in which parts should be sorted, based on content-type.
388 * This defaults to the value for the +default_implicit_parts_order+.
390 function setImplicitPartsOrder($implicit_parts_order)
392 $this->Message->setImplicitPartsOrder($implicit_parts_order);
397 * Defaults to "1.0", but may be explicitly given if needed.
399 function setMimeVersion($mime_version)
401 $this->Message->setMimeVersion($mime_version);
405 * The recipient addresses for the message, either as a string (for a single
406 * address) or an array (for multiple addresses).
408 function setRecipients($recipients)
410 $this->Message->setRecipients($recipients);
414 * The date on which the message was sent. If not set (the default), the
415 * header will be set by the delivery agent.
417 function setSentOn($date)
419 $this->Message->setSentOn($date);
424 * Specify the subject of the message.
426 function setSubject($subject)
428 $this->Message->setSubject($subject);
432 * Add an attachment to the message.
434 * Example:
436 * class ApplicationMailer extends AkActionMailer
438 * // attachments
439 * function signupNotification($Recipient)
441 * $this->setAttributes(array(
442 * 'recipients' => $Recipient->getEmailAddressWithName(),
443 * 'from' => "system@example.com",
444 * 'subject' => "New account information"
445 * ));
447 * $this->addAttachment(array(
448 * 'content_type' => 'image/jpeg',
449 * 'body' => Ak::file_get_contents("an-image.jpg")));
451 * $this->addAttachment('application/pdf', generate_your_pdf_here());
457 function addAttachment()
459 $args = func_get_args();
460 return call_user_func_array(array(&$this->Message, 'setAttachment'), $args);
464 * Generic setter
466 * Calling $this->set(array('body'=>'Hello World', 'subject' => 'First subject'));
467 * is the same as calling $this->setBody('Hello World'); and $this->setSubject('First Subject');
469 * This simplifies creating mail objects from datasources.
471 * If the method does not exists the parameter will be added to the body.
473 function set($attributes = array())
475 if(!empty($attributes['template'])){
476 $this->setTemplate($attributes['template']);
477 unset($attributes['template']);
480 if((!empty($attributes['attachment']) || !empty($attributes['attachments'])) &&
481 (empty($attributes['parts']) && empty($attributes['part']) && empty($attributes['body']))){
482 // we can render here the body if there are attachments
485 $this->Message->set($attributes);
490 * Gets a well formed mail in plain text
492 function getEncoded()
494 $this->Message->getEncoded();
498 * The mail object instance referenced by this mailer.
500 function &getMail()
502 return $this->Message;
507 * Receives a raw email, parses it into an email object, decodes it,
508 * instantiates a new mailer, and passes the email object to the mailer
509 * object's #receive method. If you want your mailer to be able to
510 * process incoming messages, you'll need to implement a #receive
511 * method that accepts the email object as a parameter and then call
512 * the AkActionMailer::recieve method using "parent::recieve($Message);"
515 * class MyMailer extends AkActionMailer{
516 * function receive($Message){
517 * parent::recieve($Message);
518 * ...
522 function &receive($raw_mail)
524 $this->Message =& AkMailBase::parse($raw_mail);
525 return $this->Message;
530 * Deliver the given mail object directly. This can be used to deliver
531 * a preconstructed mail object, like:
533 * $email =& $MyMailer->createSomeMail($parameters);
534 * $email->setHeader("frobnicate");
535 * MyMailer::deliver($email);
537 function deliverDirectly(&$Message)
539 $Message =& new $this->_defaultMailDriverName ($Message);
540 $Message->send();
543 function getRawMessage()
545 if(empty($this->Message->_has_been_created_by_mailer)){
546 trigger_error(Ak::t('You need to create() a message before getting it as raw text.'),E_USER_ERROR);
547 return false;
549 $Composer =& $this->getComposer();
550 return $Composer->getRawMessage();
555 * Initialize the mailer via the given +method_name+. The body will be
556 * rendered and a new AkMailMessage object created.
558 function &create($method_name, $parameters, $content_type = '')
560 $Composer =& $this->getComposer();
561 $args = func_get_args();
562 call_user_func_array(array(&$Composer, 'build'), $args);
563 $this->Message->_has_been_created_by_mailer = true;
564 return $this->Message;
569 * Delivers an AkMailMessage object. By default, it delivers the cached mail
570 * object (from the AkActionMailer::create method). If no cached mail object exists, and
571 * no alternate has been given as the parameter, this will fail.
573 function deliver($method_name, $parameters = null, $Message = null)
575 if(empty($Message) && empty($this->Message)){
576 $this->create($method_name, $parameters);
577 }elseif(!empty($Message)){
578 $this->Message =& $Message;
581 !empty($this->Message) or trigger_error(Ak::t('No mail object available for delivery!'), E_USER_ERROR);
582 if(!empty($this->perform_deliveries)){
583 $this->{"perform".ucfirst(strtolower($this->delivery_method))."Delivery"}($this->Message);
585 $this->Message->_has_been_delivered_by_mailer = true;
586 return $this->Message;
589 function performSmtpDelivery(&$Message, $settings = array())
591 $default_settings = array(
592 'host' => @$this->server_settings['address'],
593 'localhost' => @$this->server_settings['domain'],
594 'port' => @$this->server_settings['port'],
595 'username' => @$this->server_settings['user_name'],
596 'password' => @$this->server_settings['password'],
597 'auth' => (!empty($this->server_settings['user_name']) || @$this->server_settings['authentication']),
598 'debug' => true
600 $settings = array_merge($default_settings, $settings);
602 return $this->_deliverUsingMailDeliveryMethod('Smtp', $Message, $settings);
606 function performPhpDelivery(&$Message, $settings = array())
608 return $this->_deliverUsingMailDeliveryMethod('PhpMail', $Message, $settings);
611 function performTestDelivery(&$Message)
613 return $this->_deliverUsingMailDeliveryMethod('Test', $Message, array('ActionMailer'=>&$this));
618 function renderMessage($method_name, $body, $options = array())
620 return $this->render(array_merge($options, array('file' => $method_name, 'body' => $body)));
623 function render($options = array())
625 $body = $options['body'];
626 unset($options['body']);
627 $Template =& $this->_initializeTemplateClass($body);
628 $options['locals'] = array_merge((array)@$options['locals'], $this->getHelpers());
629 $options['locals'] = array_merge($options['locals'], array('mailer'=>&$this));
630 return $Template->render($options);
633 function getTemplatePath()
635 return $this->templateRoot.DS.$this->mailerName;
641 * Set up the default values for the various instance variables of this
642 * mailer. Subclasses may override this method to provide different
643 * defaults.
645 function initializeDefaults($method_name)
647 foreach (array('charset','content_type','implicit_parts_order', 'mime_version') as $attribute) {
648 $method = 'set'.AkInflector::camelize($attribute);
649 $this->Message->$method(empty($this->$attribute) ? $this->{'default_'.$attribute} : $this->$attribute);
651 foreach (array('parts','headers','body') as $attribute) {
652 $method = 'set'.AkInflector::camelize($attribute);
653 $this->Message->$method(empty($this->$attribute) ? array() : $this->$attribute);
656 $this->templateRoot = empty($this->templateRoot) ? AK_APP_DIR.DS.'views' : $this->templateRoot;
657 $this->template = empty($this->template) ? $method_name : $this->template;
658 $this->mailerName = empty($this->mailerName) ? AkInflector::underscore($this->getModelName()) : $this->mailerName;
662 function &_initializeTemplateClass($assigns)
664 require_once(AK_LIB_DIR.DS.'AkActionView.php');
665 $TemplateInstance =& new AkActionView($this->getTemplatePath(), $assigns, $this);
666 require_once (AK_LIB_DIR.DS.'AkActionView'.DS.'AkPhpTemplateHandler.php');
667 $TemplateInstance->_registerTemplateHandler('tpl','AkPhpTemplateHandler');
668 return $TemplateInstance;
671 function &getComposer()
673 if(empty($this->Composer)){
674 $this->setComposer();
676 return $this->Composer;
679 function setComposer($Composer = null)
681 if(!empty($Composer)){
682 $this->Composer = $Composer;
683 }else{
684 $this->Composer =& new AkMailComposer();
685 $this->Composer->init($this);
691 * Alias for getModelName
693 function getMailerName()
695 return $this->getModelName();
700 * Creates an instance of each available helper and links it into into current mailer.
702 * Mailer helpers work as Controller helpers but without the Request context
704 function &getHelpers()
706 static $helpers = array();
707 require_once(AK_LIB_DIR.DS.'AkActionView'.DS.'AkActionViewHelper.php');
709 $mailer_helpers = array_merge(Ak::toArray($this->helpers), array(substr($this->getModelName(),-6)));
710 $mailer_helpers = array_unique(array_map(array('AkInflector','underscore'), $mailer_helpers));
712 foreach ($mailer_helpers as $file => $mailer_helper){
713 $full_path = preg_match('/[\\\\\/]+/',$file);
714 $helper_class_name = AkInflector::camelize($mailer_helper).'Helper';
715 $attribute_name = (!$full_path ? AkInflector::underscore($helper_class_name) : substr($file,0,-4));
716 if(empty($helpers[$attribute_name])){
717 if($full_path){
718 include_once($file);
719 }else{
720 $helper_file_name = $mailer_helper.'_helper.php';
721 if(file_exists(AK_LIB_DIR.DS.'AkActionView'.DS.'helpers'.DS.$helper_file_name)){
722 include_once(AK_LIB_DIR.DS.'AkActionView'.DS.'helpers'.DS.$helper_file_name);
723 }elseif (file_exists(AK_HELPERS_DIR.DS.$helper_file_name)){
724 include_once(AK_HELPERS_DIR.DS.$helper_file_name);
728 if(class_exists($helper_class_name)){
729 if(empty($helpers[$attribute_name])){
730 $helpers[$attribute_name] =& new $helper_class_name(&$this);
731 if(method_exists($helpers[$attribute_name],'setController')){
732 $helpers[$attribute_name]->setController(&$this);
734 if(method_exists($helpers[$attribute_name],'setMailer')){
735 $helpers[$attribute_name]->setMailer(&$this);
737 if(method_exists($helpers[$attribute_name],'init')){
738 $helpers[$attribute_name]->init();
745 return $helpers;
748 function _deliverUsingMailDeliveryMethod($method, &$Message, $options)
750 $handler_name = 'Ak'.AkInflector::camelize(Ak::sanitize_include($method, 'paranoid')).'Delivery';
751 $handler_path = AK_LIB_DIR.DS.'AkActionMailer'.DS.'AkMailDelivery'.DS.$handler_name.'.php';
752 if(file_exists($handler_path)){
753 require_once($handler_path);
756 if(!class_exists($handler_name)){
757 trigger_error(Ak::t('Could not find message handler %handler_name', array('%handler_name'=>$handler_name)), E_USER_ERROR);
758 return false;
760 $DeliveryHandler = new $handler_name();
761 $this->Message =& $Message;
762 return $DeliveryHandler->deliver($this, $options);