CakePHP
  • Documentation
    • Book
    • API
    • Videos
    • Reporting Security Issues
    • Privacy Policy
    • Logos & Trademarks
  • Business Solutions
  • Swag
  • Road Trip
  • Team
  • Community
    • Community
    • Get Involved
    • Issues (GitHub)
    • Bakery
    • Featured Resources
    • Training
    • Meetups
    • My CakePHP
    • CakeFest
    • Newsletter
    • Linkedin
    • YouTube
    • Facebook
    • Twitter
    • Mastodon
    • Help & Support
    • Forum
    • Stack Overflow
    • Slack
    • Paid Support
CakePHP

C CakePHP 1.3 API

  • Overview
  • Tree
  • Deprecated
  • Version:
    • 1.3
      • 4.2
      • 4.1
      • 4.0
      • 3.9
      • 3.8
      • 3.7
      • 3.6
      • 3.5
      • 3.4
      • 3.3
      • 3.2
      • 3.1
      • 3.0
      • 2.10
      • 2.9
      • 2.8
      • 2.7
      • 2.6
      • 2.5
      • 2.4
      • 2.3
      • 2.2
      • 2.1
      • 2.0
      • 1.3
      • 1.2

Classes

  • AclBase
  • AclBehavior
  • AclComponent
  • AclNode
  • AclShell
  • Aco
  • AcoAction
  • AjaxHelper
  • ApcEngine
  • ApiShell
  • App
  • AppController
  • AppHelper
  • AppModel
  • Aro
  • AuthComponent
  • BakeShell
  • BakeTask
  • BehaviorCollection
  • Cache
  • CacheEngine
  • CacheHelper
  • CakeErrorController
  • CakeLog
  • CakeRoute
  • CakeSchema
  • CakeSession
  • CakeSocket
  • ClassRegistry
  • Component
  • Configure
  • ConnectionManager
  • ConsoleShell
  • ContainableBehavior
  • Controller
  • ControllerTask
  • CookieComponent
  • DataSource
  • DbAcl
  • DbConfigTask
  • DboMssql
  • DboMysql
  • DboMysqlBase
  • DboMysqli
  • DboOracle
  • DboPostgres
  • DboSource
  • DboSqlite
  • Debugger
  • EmailComponent
  • ErrorHandler
  • ExtractTask
  • File
  • FileEngine
  • FileLog
  • FixtureTask
  • Folder
  • FormHelper
  • Helper
  • HtmlHelper
  • HttpSocket
  • I18n
  • I18nModel
  • I18nShell
  • Inflector
  • IniAcl
  • JavascriptHelper
  • JqueryEngineHelper
  • JsBaseEngineHelper
  • JsHelper
  • L10n
  • MagicDb
  • MagicFileResource
  • MediaView
  • MemcacheEngine
  • Model
  • ModelBehavior
  • ModelTask
  • MootoolsEngineHelper
  • Multibyte
  • NumberHelper
  • Object
  • Overloadable
  • Overloadable2
  • PagesController
  • PaginatorHelper
  • Permission
  • PluginShortRoute
  • PluginTask
  • ProjectTask
  • PrototypeEngineHelper
  • RequestHandlerComponent
  • Router
  • RssHelper
  • Sanitize
  • Scaffold
  • ScaffoldView
  • SchemaShell
  • Security
  • SecurityComponent
  • SessionComponent
  • SessionHelper
  • Set
  • Shell
  • String
  • TemplateTask
  • TestSuiteShell
  • TestTask
  • TextHelper
  • ThemeView
  • TimeHelper
  • TranslateBehavior
  • TreeBehavior
  • Validation
  • View
  • ViewTask
  • XcacheEngine
  • Xml
  • XmlElement
  • XmlHelper
  • XmlManager
  • XmlNode
  • XmlTextNode

Functions

  • mb_encode_mimeheader
  • mb_stripos
  • mb_stristr
  • mb_strlen
  • mb_strpos
  • mb_strrchr
  • mb_strrichr
  • mb_strripos
  • mb_strrpos
  • mb_strstr
  • mb_strtolower
  • mb_strtoupper
  • mb_substr
  • mb_substr_count
   1: <?php
   2: /**
   3:  * Email Component
   4:  *
   5:  * PHP versions 4 and 5
   6:  *
   7:  * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
   8:  * Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org)
   9:  *
  10:  * Licensed under The MIT License
  11:  * Redistributions of files must retain the above copyright notice.
  12:  *
  13:  * @copyright     Copyright 2005-2012, Cake Software Foundation, Inc. (http://cakefoundation.org)
  14:  * @link          http://cakephp.org CakePHP(tm) Project
  15:  * @package       cake
  16:  * @subpackage    cake.cake.libs.controller.components
  17:  * @since         CakePHP(tm) v 1.2.0.3467
  18:  * @license       MIT License (http://www.opensource.org/licenses/mit-license.php)
  19:  */
  20: App::import('Core', 'Multibyte');
  21: App::import('Core', 'String');
  22: 
  23: /**
  24:  * EmailComponent
  25:  *
  26:  * This component is used for handling Internet Message Format based
  27:  * based on the standard outlined in http://www.rfc-editor.org/rfc/rfc2822.txt
  28:  *
  29:  * @package       cake
  30:  * @subpackage    cake.cake.libs.controller.components
  31:  * @link http://book.cakephp.org/1.3/en/The-Manual/Core-Components/Email.html
  32:  *
  33:  */
  34: class EmailComponent extends Object{
  35: 
  36: /**
  37:  * Recipient of the email
  38:  *
  39:  * @var string
  40:  * @access public
  41:  */
  42:     var $to = null;
  43: 
  44: /**
  45:  * The mail which the email is sent from
  46:  *
  47:  * @var string
  48:  * @access public
  49:  */
  50:     var $from = null;
  51: 
  52: /**
  53:  * The email the recipient will reply to
  54:  *
  55:  * @var string
  56:  * @access public
  57:  */
  58:     var $replyTo = null;
  59: 
  60: /**
  61:  * The read receipt email
  62:  *
  63:  * @var string
  64:  * @access public
  65:  */
  66:     var $readReceipt = null;
  67: 
  68: /**
  69:  * The mail that will be used in case of any errors like
  70:  * - Remote mailserver down
  71:  * - Remote user has exceeded his quota
  72:  * - Unknown user
  73:  *
  74:  * @var string
  75:  * @access public
  76:  */
  77:     var $return = null;
  78: 
  79: /**
  80:  * Carbon Copy
  81:  *
  82:  * List of email's that should receive a copy of the email.
  83:  * The Recipient WILL be able to see this list
  84:  *
  85:  * @var array
  86:  * @access public
  87:  */
  88:     var $cc = array();
  89: 
  90: /**
  91:  * Blind Carbon Copy
  92:  *
  93:  * List of email's that should receive a copy of the email.
  94:  * The Recipient WILL NOT be able to see this list
  95:  *
  96:  * @var array
  97:  * @access public
  98:  */
  99:     var $bcc = array();
 100: 
 101: /**
 102:  * The date to put in the Date: header.  This should be a date
 103:  * conformant with the RFC2822 standard.  Leave null, to have
 104:  * today's date generated.
 105:  *
 106:  * @var string
 107:  */
 108:     var $date = null;
 109: 
 110: /**
 111:  * The subject of the email
 112:  *
 113:  * @var string
 114:  * @access public
 115:  */
 116:     var $subject = null;
 117: 
 118: /**
 119:  * Associative array of a user defined headers
 120:  * Keys will be prefixed 'X-' as per RFC2822 Section 4.7.5
 121:  *
 122:  * @var array
 123:  * @access public
 124:  */
 125:     var $headers = array();
 126: 
 127: /**
 128:  * List of additional headers
 129:  *
 130:  * These will NOT be used if you are using safemode and mail()
 131:  *
 132:  * @var string
 133:  * @access public
 134:  */
 135:     var $additionalParams = null;
 136: 
 137: /**
 138:  * Layout for the View
 139:  *
 140:  * @var string
 141:  * @access public
 142:  */
 143:     var $layout = 'default';
 144: 
 145: /**
 146:  * Template for the view
 147:  *
 148:  * @var string
 149:  * @access public
 150:  */
 151:     var $template = null;
 152: 
 153: /**
 154:  * as per RFC2822 Section 2.1.1
 155:  *
 156:  * @var integer
 157:  * @access public
 158:  */
 159:     var $lineLength = 70;
 160: 
 161: /**
 162:  * Line feed character(s) to be used when sending using mail() function
 163:  * By default PHP_EOL is used.
 164:  * RFC2822 requires it to be CRLF but some Unix
 165:  * mail transfer agents replace LF by CRLF automatically
 166:  * (which leads to doubling CR if CRLF is used).
 167:  *
 168:  * @var string
 169:  * @access public
 170:  */
 171:     var $lineFeed = PHP_EOL;
 172: 
 173: /**
 174:  * @deprecated see lineLength
 175:  */
 176:     var $_lineLength = null;
 177: 
 178: /**
 179:  * What format should the email be sent in
 180:  *
 181:  * Supported formats:
 182:  * - text
 183:  * - html
 184:  * - both
 185:  *
 186:  * @var string
 187:  * @access public
 188:  */
 189:     var $sendAs = 'text';
 190: 
 191: /**
 192:  * What method should the email be sent by
 193:  *
 194:  * Supported methods:
 195:  * - mail
 196:  * - smtp
 197:  * - debug
 198:  *
 199:  * @var string
 200:  * @access public
 201:  */
 202:     var $delivery = 'mail';
 203: 
 204: /**
 205:  * charset the email is sent in
 206:  *
 207:  * @var string
 208:  * @access public
 209:  */
 210:     var $charset = 'utf-8';
 211: 
 212: /**
 213:  * List of files that should be attached to the email.
 214:  *
 215:  * Can be both absolute and relative paths
 216:  *
 217:  * @var array
 218:  * @access public
 219:  */
 220:     var $attachments = array();
 221: 
 222: /**
 223:  * What mailer should EmailComponent identify itself as
 224:  *
 225:  * @var string
 226:  * @access public
 227:  */
 228:     var $xMailer = 'CakePHP Email Component';
 229: 
 230: /**
 231:  * The list of paths to search if an attachment isnt absolute
 232:  *
 233:  * @var array
 234:  * @access public
 235:  */
 236:     var $filePaths = array();
 237: 
 238: /**
 239:  * List of options to use for smtp mail method
 240:  *
 241:  * Options is:
 242:  * - port
 243:  * - host
 244:  * - timeout
 245:  * - username
 246:  * - password
 247:  * - client
 248:  *
 249:  * @var array
 250:  * @access public
 251:  * @link http://book.cakephp.org/1.3/en/The-Manual/Core-Components/Email.html#sending-a-message-using-smtp
 252:  */
 253:     var $smtpOptions = array();
 254: 
 255: /**
 256:  * Placeholder for any errors that might happen with the
 257:  * smtp mail methods
 258:  *
 259:  * @var string
 260:  * @access public
 261:  */
 262:     var $smtpError = null;
 263: 
 264: /**
 265:  * Contains the rendered plain text message if one was sent.
 266:  *
 267:  * @var string
 268:  * @access public
 269:  */
 270:     var $textMessage = null;
 271: 
 272: /**
 273:  * Contains the rendered HTML message if one was sent.
 274:  *
 275:  * @var string
 276:  * @access public
 277:  */
 278:     var $htmlMessage = null;
 279: 
 280: /**
 281:  * Whether to generate a Message-ID header for the
 282:  * e-mail. True to generate a Message-ID, False to let
 283:  * it be handled by sendmail (or similar) or a string
 284:  * to completely override the Message-ID.
 285:  *
 286:  * If you are sending Email from a shell, be sure to set this value.  As you
 287:  * could encounter delivery issues if you do not.
 288:  *
 289:  * @var mixed
 290:  * @access public
 291:  */
 292:     var $messageId = true;
 293: 
 294: /**
 295:  * Temporary store of message header lines
 296:  *
 297:  * @var array
 298:  * @access private
 299:  */
 300:     var $__header = array();
 301: 
 302: /**
 303:  * If set, boundary to use for multipart mime messages
 304:  *
 305:  * @var string
 306:  * @access private
 307:  */
 308:     var $__boundary = null;
 309: 
 310: /**
 311:  * Temporary store of message lines
 312:  *
 313:  * @var array
 314:  * @access private
 315:  */
 316:     var $__message = array();
 317: 
 318: /**
 319:  * Variable that holds SMTP connection
 320:  *
 321:  * @var resource
 322:  * @access private
 323:  */
 324:     var $__smtpConnection = null;
 325: 
 326: /**
 327:  * Initialize component
 328:  *
 329:  * @param object $controller Instantiating controller
 330:  * @access public
 331:  */
 332:     function initialize(&$controller, $settings = array()) {
 333:         $this->Controller =& $controller;
 334:         if (Configure::read('App.encoding') !== null) {
 335:             $this->charset = Configure::read('App.encoding');
 336:         }
 337:         $this->_set($settings);
 338:     }
 339: 
 340: /**
 341:  * Startup component
 342:  *
 343:  * @param object $controller Instantiating controller
 344:  * @access public
 345:  */
 346:     function startup(&$controller) {}
 347: 
 348: /**
 349:  * Send an email using the specified content, template and layout
 350:  *
 351:  * @param mixed $content Either an array of text lines, or a string with contents
 352:  *  If you are rendering a template this variable will be sent to the templates as `$content`
 353:  * @param string $template Template to use when sending email
 354:  * @param string $layout Layout to use to enclose email body
 355:  * @return boolean Success
 356:  * @access public
 357:  */
 358:     function send($content = null, $template = null, $layout = null) {
 359:         $this->_createHeader();
 360: 
 361:         if ($template) {
 362:             $this->template = $template;
 363:         }
 364: 
 365:         if ($layout) {
 366:             $this->layout = $layout;
 367:         }
 368: 
 369:         if (is_array($content)) {
 370:             $content = implode("\n", $content) . "\n";
 371:         }
 372: 
 373:         $this->htmlMessage = $this->textMessage = null;
 374:         if ($content) {
 375:             if ($this->sendAs === 'html') {
 376:                 $this->htmlMessage = $content;
 377:             } elseif ($this->sendAs === 'text') {
 378:                 $this->textMessage = $content;
 379:             } else {
 380:                 $this->htmlMessage = $this->textMessage = $content;
 381:             }
 382:         }
 383: 
 384:         if ($this->sendAs === 'text') {
 385:             $message = $this->_wrap($content);
 386:         } else {
 387:             $message = $this->_wrap($content, 998);
 388:         }
 389: 
 390:         if ($this->template === null) {
 391:             $message = $this->_formatMessage($message);
 392:         } else {
 393:             $message = $this->_render($message);
 394:         }
 395: 
 396:         $message[] = '';
 397:         $this->__message = $message;
 398: 
 399:         if (!empty($this->attachments)) {
 400:             $this->_attachFiles();
 401:         }
 402: 
 403:         if (!empty($this->attachments)) {
 404:             $this->__message[] = '';
 405:             $this->__message[] = '--' . $this->__boundary . '--';
 406:             $this->__message[] = '';
 407:         }
 408: 
 409:         $_method = '_' . $this->delivery;
 410:         $sent = $this->$_method();
 411: 
 412:         $this->__header = array();
 413:         $this->__message = array();
 414: 
 415:         return $sent;
 416:     }
 417: 
 418: /**
 419:  * Reset all EmailComponent internal variables to be able to send out a new email.
 420:  *
 421:  * @access public
 422:  * @link http://book.cakephp.org/1.3/en/The-Manual/Core-Components/Email.html#sending-multiple-emails-in-a-loop
 423:  */
 424:     function reset() {
 425:         $this->template = null;
 426:         $this->to = array();
 427:         $this->from = null;
 428:         $this->replyTo = null;
 429:         $this->return = null;
 430:         $this->cc = array();
 431:         $this->bcc = array();
 432:         $this->headers = array();
 433:         $this->subject = null;
 434:         $this->additionalParams = null;
 435:         $this->date = null;
 436:         $this->smtpError = null;
 437:         $this->attachments = array();
 438:         $this->htmlMessage = null;
 439:         $this->textMessage = null;
 440:         $this->messageId = true;
 441:         $this->delivery = 'mail';
 442:         $this->__header = array();
 443:         $this->__boundary = null;
 444:         $this->__message = array();
 445:     }
 446: 
 447: /**
 448:  * Render the contents using the current layout and template.
 449:  *
 450:  * @param string $content Content to render
 451:  * @return array Email ready to be sent
 452:  * @access private
 453:  */
 454:     function _render($content) {
 455:         $viewClass = $this->Controller->view;
 456: 
 457:         if ($viewClass != 'View') {
 458:             list($plugin, $viewClass) = pluginSplit($viewClass);
 459:             $viewClass = $viewClass . 'View';
 460:             App::import('View', $this->Controller->view);
 461:         }
 462: 
 463:         $View = new $viewClass($this->Controller);
 464:         $View->layout = $this->layout;
 465:         $msg = array();
 466: 
 467:         $content = implode("\n", $content);
 468: 
 469:         if ($this->sendAs === 'both') {
 470:             $htmlContent = $content;
 471:             if (!empty($this->attachments)) {
 472:                 $msg[] = '--' . $this->__boundary;
 473:                 $msg[] = 'Content-Type: multipart/alternative; boundary="alt-' . $this->__boundary . '"';
 474:                 $msg[] = '';
 475:             }
 476:             $msg[] = '--alt-' . $this->__boundary;
 477:             $msg[] = 'Content-Type: text/plain; charset=' . $this->charset;
 478:             $msg[] = 'Content-Transfer-Encoding: 7bit';
 479:             $msg[] = '';
 480: 
 481:             $content = $View->element('email' . DS . 'text' . DS . $this->template, array('content' => $content), true);
 482:             $View->layoutPath = 'email' . DS . 'text';
 483:             $content = explode("\n", $this->textMessage = str_replace(array("\r\n", "\r"), "\n", $View->renderLayout($content)));
 484: 
 485:             $msg = array_merge($msg, $content);
 486: 
 487:             $msg[] = '';
 488:             $msg[] = '--alt-' . $this->__boundary;
 489:             $msg[] = 'Content-Type: text/html; charset=' . $this->charset;
 490:             $msg[] = 'Content-Transfer-Encoding: 7bit';
 491:             $msg[] = '';
 492: 
 493:             $htmlContent = $View->element('email' . DS . 'html' . DS . $this->template, array('content' => $htmlContent), true);
 494:             $View->layoutPath = 'email' . DS . 'html';
 495:             $htmlContent = explode("\n", $this->htmlMessage = str_replace(array("\r\n", "\r"), "\n", $View->renderLayout($htmlContent)));
 496: 
 497:             $msg = array_merge($msg, $htmlContent);
 498: 
 499:             $msg[] = '';
 500:             $msg[] = '--alt-' . $this->__boundary . '--';
 501:             $msg[] = '';
 502: 
 503:             ClassRegistry::removeObject('view');
 504:             return $msg;
 505:         }
 506: 
 507:         if (!empty($this->attachments)) {
 508:             if ($this->sendAs === 'html') {
 509:                 $msg[] = '';
 510:                 $msg[] = '--' . $this->__boundary;
 511:                 $msg[] = 'Content-Type: text/html; charset=' . $this->charset;
 512:                 $msg[] = 'Content-Transfer-Encoding: 7bit';
 513:                 $msg[] = '';
 514:             } else {
 515:                 $msg[] = '--' . $this->__boundary;
 516:                 $msg[] = 'Content-Type: text/plain; charset=' . $this->charset;
 517:                 $msg[] = 'Content-Transfer-Encoding: 7bit';
 518:                 $msg[] = '';
 519:             }
 520:         }
 521: 
 522:         $content = $View->element('email' . DS . $this->sendAs . DS . $this->template, array('content' => $content), true);
 523:         $View->layoutPath = 'email' . DS . $this->sendAs;
 524:         $content = explode("\n", $rendered = str_replace(array("\r\n", "\r"), "\n", $View->renderLayout($content)));
 525: 
 526:         if ($this->sendAs === 'html') {
 527:             $this->htmlMessage = $rendered;
 528:         } else {
 529:             $this->textMessage = $rendered;
 530:         }
 531: 
 532:         $msg = array_merge($msg, $content);
 533:         ClassRegistry::removeObject('view');
 534: 
 535:         return $msg;
 536:     }
 537: 
 538: /**
 539:  * Create unique boundary identifier
 540:  *
 541:  * @access private
 542:  */
 543:     function _createboundary() {
 544:         $this->__boundary = md5(uniqid(time()));
 545:     }
 546: 
 547: /**
 548:  * Sets headers for the message
 549:  *
 550:  * @access public
 551:  * @param array Associative array containing headers to be set.
 552:  */
 553:     function header($headers) {
 554:         foreach ($headers as $header => $value) {
 555:             $this->__header[] = sprintf('%s: %s', trim($header), trim($value));
 556:         }
 557:     }
 558: /**
 559:  * Create emails headers including (but not limited to) from email address, reply to,
 560:  * bcc and cc.
 561:  *
 562:  * @access private
 563:  */
 564:     function _createHeader() {
 565:         $headers = array();
 566: 
 567:         if ($this->delivery == 'smtp') {
 568:             $headers['To'] = implode(', ', array_map(array($this, '_formatAddress'), (array)$this->to));
 569:         }
 570:         $headers['From'] = $this->_formatAddress($this->from);
 571: 
 572:         if (!empty($this->replyTo)) {
 573:             $headers['Reply-To'] = $this->_formatAddress($this->replyTo);
 574:         }
 575:         if (!empty($this->return)) {
 576:             $headers['Return-Path'] = $this->_formatAddress($this->return);
 577:         }
 578:         if (!empty($this->readReceipt)) {
 579:             $headers['Disposition-Notification-To'] = $this->_formatAddress($this->readReceipt);
 580:         }
 581: 
 582:         if (!empty($this->cc)) {
 583:             $headers['Cc'] = implode(', ', array_map(array($this, '_formatAddress'), (array)$this->cc));
 584:         }
 585: 
 586:         if (!empty($this->bcc) && $this->delivery != 'smtp') {
 587:             $headers['Bcc'] = implode(', ', array_map(array($this, '_formatAddress'), (array)$this->bcc));
 588:         }
 589:         if ($this->delivery == 'smtp') {
 590:             $headers['Subject'] = $this->_encode($this->subject);
 591:         }
 592: 
 593:         if ($this->messageId !== false) {
 594:             if ($this->messageId === true) {
 595:                 $headers['Message-ID'] = '<' . str_replace('-', '', String::uuid()) . '@' . env('HTTP_HOST') . '>';
 596:             } else {
 597:                 $headers['Message-ID'] = $this->messageId;
 598:             }
 599:         }
 600: 
 601:         $date = $this->date;
 602:         if ($date == false) {
 603:             $date = date(DATE_RFC2822);
 604:         }
 605:         $headers['Date'] = $date;
 606: 
 607:         $headers['X-Mailer'] = $this->xMailer;
 608: 
 609:         if (!empty($this->headers)) {
 610:             foreach ($this->headers as $key => $val) {
 611:                 $headers['X-' . $key] = $val;
 612:             }
 613:         }
 614: 
 615:         if (!empty($this->attachments) || $this->sendAs === 'both') {
 616:             $this->_createBoundary();
 617:         }
 618: 
 619:         if (!empty($this->attachments)) {
 620:             $headers['Content-Type'] = 'multipart/mixed; boundary="' . $this->__boundary . '"';
 621:         } elseif ($this->sendAs === 'text') {
 622:             $headers['Content-Type'] = 'text/plain; charset=' . $this->charset;
 623:         } elseif ($this->sendAs === 'html') {
 624:             $headers['Content-Type'] = 'text/html; charset=' . $this->charset;
 625:         } elseif ($this->sendAs === 'both') {
 626:             $headers['Content-Type'] = 'multipart/alternative; boundary="alt-' . $this->__boundary . '"';
 627:         }
 628:         
 629:         $headers['MIME-Version'] = '1.0';
 630:         $headers['Content-Transfer-Encoding'] = '7bit';
 631: 
 632:         $this->header($headers);
 633:     }
 634: 
 635: /**
 636:  * Format the message by seeing if it has attachments.
 637:  *
 638:  * @param string $message Message to format
 639:  * @access private
 640:  */
 641:     function _formatMessage($message) {
 642:         if (!empty($this->attachments)) {
 643:             $prefix = array('--' . $this->__boundary);
 644:             if ($this->sendAs === 'text') {
 645:                 $prefix[] = 'Content-Type: text/plain; charset=' . $this->charset;
 646:             } elseif ($this->sendAs === 'html') {
 647:                 $prefix[] = 'Content-Type: text/html; charset=' . $this->charset;
 648:             } elseif ($this->sendAs === 'both') {
 649:                 $prefix[] = 'Content-Type: multipart/alternative; boundary="alt-' . $this->__boundary . '"';
 650:             }
 651:             $prefix[] = 'Content-Transfer-Encoding: 7bit';
 652:             $prefix[] = '';
 653:             $message = array_merge($prefix, $message);
 654:         }
 655:         return $message;
 656:     }
 657: 
 658: /**
 659:  * Attach files by adding file contents inside boundaries.
 660:  *
 661:  * @access private
 662:  * @TODO: modify to use the core File class?
 663:  */
 664:     function _attachFiles() {
 665:         $files = array();
 666:         foreach ($this->attachments as $filename => $attachment) {
 667:             $file = $this->_findFiles($attachment);
 668:             if (!empty($file)) {
 669:                 if (is_int($filename)) {
 670:                     $filename = basename($file);
 671:                 }
 672:                 $files[$filename] = $file;
 673:             }
 674:         }
 675: 
 676:         foreach ($files as $filename => $file) {
 677:             $handle = fopen($file, 'rb');
 678:             $data = fread($handle, filesize($file));
 679:             $data = chunk_split(base64_encode($data)) ;
 680:             fclose($handle);
 681: 
 682:             $this->__message[] = '--' . $this->__boundary;
 683:             $this->__message[] = 'Content-Type: application/octet-stream';
 684:             $this->__message[] = 'Content-Transfer-Encoding: base64';
 685:             $this->__message[] = 'Content-Disposition: attachment; filename="' . basename($filename) . '"';
 686:             $this->__message[] = '';
 687:             $this->__message[] = $data;
 688:             $this->__message[] = '';
 689:         }
 690:     }
 691: 
 692: /**
 693:  * Find the specified attachment in the list of file paths
 694:  *
 695:  * @param string $attachment Attachment file name to find
 696:  * @return string Path to located file
 697:  * @access private
 698:  */
 699:     function _findFiles($attachment) {
 700:         if (file_exists($attachment)) {
 701:             return $attachment;
 702:         }
 703:         foreach ($this->filePaths as $path) {
 704:             if (file_exists($path . DS . $attachment)) {
 705:                 $file = $path . DS . $attachment;
 706:                 return $file;
 707:             }
 708:         }
 709:         return null;
 710:     }
 711: 
 712: /**
 713:  * Wrap the message using EmailComponent::$lineLength
 714:  *
 715:  * @param string $message Message to wrap
 716:  * @param integer $lineLength Max length of line
 717:  * @return array Wrapped message
 718:  * @access protected
 719:  */
 720:     function _wrap($message, $lineLength = null) {
 721:         $message = $this->_strip($message, true);
 722:         $message = str_replace(array("\r\n","\r"), "\n", $message);
 723:         $lines = explode("\n", $message);
 724:         $formatted = array();
 725: 
 726:         if ($this->_lineLength !== null) {
 727:             trigger_error(__('_lineLength cannot be accessed please use lineLength', true), E_USER_WARNING);
 728:             $this->lineLength = $this->_lineLength;
 729:         }
 730: 
 731:         if (!$lineLength) {
 732:             $lineLength = $this->lineLength;
 733:         }
 734: 
 735:         foreach ($lines as $line) {
 736:             if (substr($line, 0, 1) == '.') {
 737:                 $line = '.' . $line;
 738:             }
 739:             $formatted = array_merge($formatted, explode("\n", wordwrap($line, $lineLength, "\n", true)));
 740:         }
 741:         $formatted[] = '';
 742:         return $formatted;
 743:     }
 744: 
 745: /**
 746:  * Encode the specified string using the current charset
 747:  *
 748:  * @param string $subject String to encode
 749:  * @return string Encoded string
 750:  * @access private
 751:  */
 752:     function _encode($subject) {
 753:         $subject = $this->_strip($subject);
 754: 
 755:         $nl = "\r\n";
 756:         if ($this->delivery == 'mail') {
 757:             $nl = '';
 758:         }
 759:         $internalEncoding = function_exists('mb_internal_encoding');
 760:         if ($internalEncoding) {
 761:             $restore = mb_internal_encoding();
 762:             mb_internal_encoding($this->charset);
 763:         }
 764:         $return = mb_encode_mimeheader($subject, $this->charset, 'B', $nl);
 765:         if ($internalEncoding) {
 766:             mb_internal_encoding($restore);
 767:         }
 768:         return $return;
 769:     }
 770: 
 771: /**
 772:  * Format a string as an email address
 773:  *
 774:  * @param string $string String representing an email address
 775:  * @return string Email address suitable for email headers or smtp pipe
 776:  * @access private
 777:  */
 778:     function _formatAddress($string, $smtp = false) {
 779:         $hasAlias = preg_match('/((.*))?\s?<(.+)>/', $string, $matches);
 780:         if ($smtp && $hasAlias) {
 781:             return $this->_strip('<' .  $matches[3] . '>');
 782:         } elseif ($smtp) {
 783:             return $this->_strip('<' . $string . '>');
 784:         }
 785: 
 786:         if ($hasAlias && !empty($matches[2])) {
 787:             return $this->_encode(trim($matches[2])) . $this->_strip(' <' . $matches[3] . '>');
 788:         }
 789:         return $this->_strip($string);
 790:     }
 791: 
 792: /**
 793:  * Remove certain elements (such as bcc:, to:, %0a) from given value.
 794:  * Helps prevent header injection / mainipulation on user content.
 795:  *
 796:  * @param string $value Value to strip
 797:  * @param boolean $message Set to true to indicate main message content
 798:  * @return string Stripped value
 799:  * @access private
 800:  */
 801:     function _strip($value, $message = false) {
 802:         $search  = '%0a|%0d|Content-(?:Type|Transfer-Encoding)\:';
 803:         $search .= '|charset\=|mime-version\:|multipart/mixed|(?:[\n\r]+to|b?cc)\:.*';
 804: 
 805:         if ($message !== true) {
 806:             $search .= '|\r|\n';
 807:         }
 808:         $search = '#(?:' . $search . ')#i';
 809:         while (preg_match($search, $value)) {
 810:             $value = preg_replace($search, '', $value);
 811:         }
 812:         return $value;
 813:     }
 814: 
 815: /**
 816:  * Wrapper for PHP mail function used for sending out emails
 817:  *
 818:  * @return bool Success
 819:  * @access private
 820:  */
 821:     function _mail() {
 822:         $header = implode($this->lineFeed, $this->__header);
 823:         $message = implode($this->lineFeed, $this->__message);
 824:         if (is_array($this->to)) {
 825:             $to = implode(', ', array_map(array($this, '_formatAddress'), $this->to));
 826:         } else {
 827:             $to = $this->to;
 828:         }
 829:         if (ini_get('safe_mode')) {
 830:             return @mail($to, $this->_encode($this->subject), $message, $header);
 831:         }
 832:         return @mail($to, $this->_encode($this->subject), $message, $header, $this->additionalParams);
 833:     }
 834: 
 835: 
 836: /**
 837:  * Helper method to get socket, overridden in tests
 838:  *
 839:  * @param array $config Config data for the socket.
 840:  * @return void
 841:  * @access protected
 842:  */
 843:     function _getSocket($config) {
 844:         $this->__smtpConnection =& new CakeSocket($config);
 845:     }
 846: 
 847: /**
 848:  * Sends out email via SMTP
 849:  *
 850:  * @return bool Success
 851:  * @access private
 852:  */
 853:     function _smtp() {
 854:         App::import('Core', array('CakeSocket'));
 855: 
 856:         $defaults = array(
 857:             'host' => 'localhost',
 858:             'port' => 25,
 859:             'protocol' => 'smtp',
 860:             'timeout' => 30
 861:         );
 862:         $this->smtpOptions = array_merge($defaults, $this->smtpOptions);
 863:         $this->_getSocket($this->smtpOptions);
 864: 
 865:         if (!$this->__smtpConnection->connect()) {
 866:             $this->smtpError = $this->__smtpConnection->lastError();
 867:             return false;
 868:         } elseif (!$this->_smtpSend(null, '220')) {
 869:             return false;
 870:         }
 871: 
 872:         $httpHost = env('HTTP_HOST');
 873: 
 874:         if (isset($this->smtpOptions['client'])) {
 875:             $host = $this->smtpOptions['client'];
 876:         } elseif (!empty($httpHost)) {
 877:             list($host) = explode(':', $httpHost);
 878:         } else {
 879:             $host = 'localhost';
 880:         }
 881: 
 882:         if (!$this->_smtpSend("EHLO {$host}", '250') && !$this->_smtpSend("HELO {$host}", '250')) {
 883:             return false;
 884:         }
 885: 
 886:         if (isset($this->smtpOptions['username']) && isset($this->smtpOptions['password'])) {
 887:             $authRequired = $this->_smtpSend('AUTH LOGIN', '334|503');
 888:             if ($authRequired == '334') {
 889:                 if (!$this->_smtpSend(base64_encode($this->smtpOptions['username']), '334')) {
 890:                     return false;
 891:                 }
 892:                 if (!$this->_smtpSend(base64_encode($this->smtpOptions['password']), '235')) {
 893:                     return false;
 894:                 }
 895:             } elseif ($authRequired != '503') {
 896:                 return false;
 897:             }
 898:         }
 899: 
 900:         if (!$this->_smtpSend('MAIL FROM: ' . $this->_formatAddress($this->from, true))) {
 901:             return false;
 902:         }
 903: 
 904:         if (!is_array($this->to)) {
 905:             $tos = array_map('trim', explode(',', $this->to));
 906:         } else {
 907:             $tos = $this->to;
 908:         }
 909:         foreach ($tos as $to) {
 910:             if (!$this->_smtpSend('RCPT TO: ' . $this->_formatAddress($to, true))) {
 911:                 return false;
 912:             }
 913:         }
 914: 
 915:         foreach ($this->cc as $cc) {
 916:             if (!$this->_smtpSend('RCPT TO: ' . $this->_formatAddress($cc, true))) {
 917:                 return false;
 918:             }
 919:         }
 920:         foreach ($this->bcc as $bcc) {
 921:             if (!$this->_smtpSend('RCPT TO: ' . $this->_formatAddress($bcc, true))) {
 922:                 return false;
 923:             }
 924:         }
 925: 
 926:         if (!$this->_smtpSend('DATA', '354')) {
 927:             return false;
 928:         }
 929: 
 930:         $header = implode("\r\n", $this->__header);
 931:         $message = implode("\r\n", $this->__message);
 932:         if (!$this->_smtpSend($header . "\r\n\r\n" . $message . "\r\n\r\n\r\n.")) {
 933:             return false;
 934:         }
 935:         $this->_smtpSend('QUIT', false);
 936: 
 937:         $this->__smtpConnection->disconnect();
 938:         return true;
 939:     }
 940: 
 941: /**
 942:  * Protected method for sending data to SMTP connection
 943:  *
 944:  * @param string $data data to be sent to SMTP server
 945:  * @param mixed $checkCode code to check for in server response, false to skip
 946:  * @return bool Success
 947:  * @access protected
 948:  */
 949:     function _smtpSend($data, $checkCode = '250') {
 950:         if (!is_null($data)) {
 951:             $this->__smtpConnection->write($data . "\r\n");
 952:         }
 953:         while ($checkCode !== false) {
 954:             $response = '';
 955:             $startTime = time();
 956:             while (substr($response, -2) !== "\r\n" && ((time() - $startTime) < $this->smtpOptions['timeout'])) {
 957:                 $response .= $this->__smtpConnection->read();
 958:             }
 959:             if (substr($response, -2) !== "\r\n") {
 960:                 $this->smtpError = 'timeout';
 961:                 return false;
 962:             }
 963:             $response = end(explode("\r\n", rtrim($response, "\r\n")));
 964: 
 965:             if (preg_match('/^(' . $checkCode . ')(.)/', $response, $code)) {
 966:                 if ($code[2] === '-') {
 967:                     continue;
 968:                 }
 969:                 return $code[1];
 970:             }
 971:             $this->smtpError = $response;
 972:             return false;
 973:         }
 974:         return true;
 975:     }
 976: 
 977: /**
 978:  * Set as controller flash message a debug message showing current settings in component
 979:  *
 980:  * @return boolean Success
 981:  * @access private
 982:  */
 983:     function _debug() {
 984:         $nl = "\n";
 985:         $header = implode($nl, $this->__header);
 986:         $message = implode($nl, $this->__message);
 987:         $fm = '<pre>';
 988: 
 989:         if (is_array($this->to)) {
 990:             $to = implode(', ', array_map(array($this, '_formatAddress'), $this->to));
 991:         } else {
 992:             $to = $this->to;
 993:         }
 994:         $fm .= sprintf('%s %s%s', 'To:', $to, $nl);
 995:         $fm .= sprintf('%s %s%s', 'From:', $this->from, $nl);
 996:         $fm .= sprintf('%s %s%s', 'Subject:', $this->_encode($this->subject), $nl);
 997:         $fm .= sprintf('%s%3$s%3$s%s', 'Header:', $header, $nl);
 998:         $fm .= sprintf('%s%3$s%3$s%s', 'Parameters:', $this->additionalParams, $nl);
 999:         $fm .= sprintf('%s%3$s%3$s%s', 'Message:', $message, $nl);
1000:         $fm .= '</pre>';
1001: 
1002:         if (isset($this->Controller->Session)) {
1003:             $this->Controller->Session->setFlash($fm, 'default', null, 'email');
1004:             return true;
1005:         }
1006:         return $fm;
1007:     }
1008: }
1009: 
OpenHub
Rackspace
Rackspace
  • Business Solutions
  • Showcase
  • Documentation
  • Book
  • API
  • Videos
  • Reporting Security Issues
  • Privacy Policy
  • Logos & Trademarks
  • Community
  • Get Involved
  • Issues (GitHub)
  • Bakery
  • Featured Resources
  • Training
  • Meetups
  • My CakePHP
  • CakeFest
  • Newsletter
  • Linkedin
  • YouTube
  • Facebook
  • Twitter
  • Mastodon
  • Help & Support
  • Forum
  • Stack Overflow
  • Slack
  • Paid Support

Generated using CakePHP API Docs