|
|
@@ -0,0 +1,450 @@
|
|
|
+<?php
|
|
|
+App::uses('CakeEmail', 'Network/Email');
|
|
|
+App::uses('CakeLog', 'Log');
|
|
|
+if (!defined('BR')) {
|
|
|
+ define('BR', '<br />');
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * Convenience class for internal mailer
|
|
|
+ * Adds some nice features
|
|
|
+ *
|
|
|
+ * @author Mark Scherer
|
|
|
+ * @license MIT
|
|
|
+ * 2011-10-31 ms
|
|
|
+ */
|
|
|
+class EmailLib extends CakeEmail {
|
|
|
+
|
|
|
+ public $error = '';
|
|
|
+
|
|
|
+ protected $_log = null;
|
|
|
+ protected $_debug = null;
|
|
|
+
|
|
|
+ # for multiple emails, just adjust these "default" values "on the fly"
|
|
|
+ public $deliveryMethod = 'mail';
|
|
|
+ public $layout = 'external'; # usually 'external' (internal for admins only)
|
|
|
+
|
|
|
+ # with presets, only TO/FROM (depends), subject and message has to be set
|
|
|
+ protected $presets = array(
|
|
|
+ 'user' => '',
|
|
|
+ 'admin' => '',
|
|
|
+ );
|
|
|
+
|
|
|
+ protected $options = array();
|
|
|
+
|
|
|
+ protected $complex = null; # if Controller is available, and layout/elements can be switched...
|
|
|
+
|
|
|
+ public function __construct($config = null) {
|
|
|
+ if ($config === null) {
|
|
|
+ $config = 'default';
|
|
|
+ }
|
|
|
+ parent::__construct($config);
|
|
|
+
|
|
|
+ $this->resetAndSet();
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * quick way to send emails to admin
|
|
|
+ * App::uses() + EmailLib::systemEmail()
|
|
|
+ *
|
|
|
+ * Note: always go out with default settings (e.g.: SMTP even if debug > 0)
|
|
|
+ * @return bool $success
|
|
|
+ * 2011-10-31 ms
|
|
|
+ */
|
|
|
+ public static function systemEmail($subject, $message = 'System Email', $transportConfig = null) {
|
|
|
+ $class = __CLASS__;
|
|
|
+ $instance = new $class($transportConfig);
|
|
|
+ $instance->to(Configure::read('Config.admin_email'));
|
|
|
+ $instance->from(Configure::read('Config.admin_email'));
|
|
|
+ if ($subject !== null) {
|
|
|
+ $instance->subject($subject);
|
|
|
+ }
|
|
|
+ if (is_array($message)) {
|
|
|
+ $instance->viewVars($message);
|
|
|
+ $message = null;
|
|
|
+ } elseif ($message === null && array_key_exists('message', $config = $instance->config())) {
|
|
|
+ $message = $config['message'];
|
|
|
+ }
|
|
|
+ if (true || $send === true) {
|
|
|
+ return $instance->send($message);
|
|
|
+ }
|
|
|
+ return $instance;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ public function layout($layout = false) {
|
|
|
+ if ($layout !== false) {
|
|
|
+ $this->_layout = $layout;
|
|
|
+ }
|
|
|
+ return $this;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * @param string $file: absolute path
|
|
|
+ * @param string $filename (optional)
|
|
|
+ * 2011-11-02 ms
|
|
|
+ */
|
|
|
+ public function addAttachment($file, $name = null) {
|
|
|
+ if (!empty($name)) {
|
|
|
+ return $this->addAttachments(array($name=>$file));
|
|
|
+ }
|
|
|
+ return $this->addAttachments($file);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * @param string $file: absolute path
|
|
|
+ * @param string $filename (optional)
|
|
|
+ * @return mixed ressource $EmailLib or string $contentId
|
|
|
+ * 2011-11-02 ms
|
|
|
+ */
|
|
|
+ public function addEmbeddedAttachment($file, $name = null, $contentId = null) {
|
|
|
+ $fileInfo = array();
|
|
|
+ $fileInfo['file'] = realpath($file);
|
|
|
+ $fileInfo['mimetype'] = $this->_getMime($file);
|
|
|
+ $fileInfo['contentId'] = $contentId ? $contentId : str_replace('-', '', String::uuid()) . '@' . env('HTTP_HOST');
|
|
|
+ if (empty($name)) {
|
|
|
+ $name = basename($file);
|
|
|
+ }
|
|
|
+ $file = array($name=>$fileInfo);
|
|
|
+ $res = $this->addAttachments($file);
|
|
|
+ if ($contentId === null) {
|
|
|
+ return $fileInfo['contentId'];
|
|
|
+ }
|
|
|
+ return $res;
|
|
|
+ }
|
|
|
+
|
|
|
+ protected function _getMime($filename) {
|
|
|
+ if (function_exists('finfo_open')) {
|
|
|
+ $finfo = finfo_open(FILEINFO_MIME);
|
|
|
+ $mimetype = finfo_file($finfo, $filename);
|
|
|
+ finfo_close($finfo);
|
|
|
+ } else {
|
|
|
+ //TODO: improve
|
|
|
+ $ext = pathinfo($filename, PATHINFO_EXTENSION);
|
|
|
+ switch ($ext) {
|
|
|
+ case "zip": $mime="application/zip"; break;
|
|
|
+ case "ez": $mime="application/andrew-inset"; break;
|
|
|
+ case "hqx": $mime="application/mac-binhex40"; break;
|
|
|
+ case "cpt": $mime="application/mac-compactpro"; break;
|
|
|
+ case "doc": $mime="application/msword"; break;
|
|
|
+ case "bin": $mime="application/octet-stream"; break;
|
|
|
+ case "dms": $mime="application/octet-stream"; break;
|
|
|
+ case "lha": $mime="application/octet-stream"; break;
|
|
|
+ case "lzh": $mime="application/octet-stream"; break;
|
|
|
+ case "exe": $mime="application/octet-stream"; break;
|
|
|
+ case "class": $mime="application/octet-stream"; break;
|
|
|
+ case "so": $mime="application/octet-stream"; break;
|
|
|
+ case "dll": $mime="application/octet-stream"; break;
|
|
|
+ case "oda": $mime="application/oda"; break;
|
|
|
+ case "pdf": $mime="application/pdf"; break;
|
|
|
+ case "ai": $mime="application/postscript"; break;
|
|
|
+ case "eps": $mime="application/postscript"; break;
|
|
|
+ case "ps": $mime="application/postscript"; break;
|
|
|
+ case "smi": $mime="application/smil"; break;
|
|
|
+ case "smil": $mime="application/smil"; break;
|
|
|
+ case "xls": $mime="application/vnd.ms-excel"; break;
|
|
|
+ case "ppt": $mime="application/vnd.ms-powerpoint"; break;
|
|
|
+ case "wbxml": $mime="application/vnd.wap.wbxml"; break;
|
|
|
+ case "wmlc": $mime="application/vnd.wap.wmlc"; break;
|
|
|
+ case "wmlsc": $mime="application/vnd.wap.wmlscriptc"; break;
|
|
|
+ case "bcpio": $mime="application/x-bcpio"; break;
|
|
|
+ case "vcd": $mime="application/x-cdlink"; break;
|
|
|
+ case "pgn": $mime="application/x-chess-pgn"; break;
|
|
|
+ case "cpio": $mime="application/x-cpio"; break;
|
|
|
+ case "csh": $mime="application/x-csh"; break;
|
|
|
+ case "dcr": $mime="application/x-director"; break;
|
|
|
+ case "dir": $mime="application/x-director"; break;
|
|
|
+ case "dxr": $mime="application/x-director"; break;
|
|
|
+ case "dvi": $mime="application/x-dvi"; break;
|
|
|
+ case "spl": $mime="application/x-futuresplash"; break;
|
|
|
+ case "gtar": $mime="application/x-gtar"; break;
|
|
|
+ case "hdf": $mime="application/x-hdf"; break;
|
|
|
+ case "js": $mime="application/x-javascript"; break;
|
|
|
+ case "skp": $mime="application/x-koan"; break;
|
|
|
+ case "skd": $mime="application/x-koan"; break;
|
|
|
+ case "skt": $mime="application/x-koan"; break;
|
|
|
+ case "skm": $mime="application/x-koan"; break;
|
|
|
+ case "latex": $mime="application/x-latex"; break;
|
|
|
+ case "nc": $mime="application/x-netcdf"; break;
|
|
|
+ case "cdf": $mime="application/x-netcdf"; break;
|
|
|
+ case "sh": $mime="application/x-sh"; break;
|
|
|
+ case "shar": $mime="application/x-shar"; break;
|
|
|
+ case "swf": $mime="application/x-shockwave-flash"; break;
|
|
|
+ case "sit": $mime="application/x-stuffit"; break;
|
|
|
+ case "sv4cpio": $mime="application/x-sv4cpio"; break;
|
|
|
+ case "sv4crc": $mime="application/x-sv4crc"; break;
|
|
|
+ case "tar": $mime="application/x-tar"; break;
|
|
|
+ case "tcl": $mime="application/x-tcl"; break;
|
|
|
+ case "tex": $mime="application/x-tex"; break;
|
|
|
+ case "texinfo": $mime="application/x-texinfo"; break;
|
|
|
+ case "texi": $mime="application/x-texinfo"; break;
|
|
|
+ case "t": $mime="application/x-troff"; break;
|
|
|
+ case "tr": $mime="application/x-troff"; break;
|
|
|
+ case "roff": $mime="application/x-troff"; break;
|
|
|
+ case "man": $mime="application/x-troff-man"; break;
|
|
|
+ case "me": $mime="application/x-troff-me"; break;
|
|
|
+ case "ms": $mime="application/x-troff-ms"; break;
|
|
|
+ case "ustar": $mime="application/x-ustar"; break;
|
|
|
+ case "src": $mime="application/x-wais-source"; break;
|
|
|
+ case "xhtml": $mime="application/xhtml+xml"; break;
|
|
|
+ case "xht": $mime="application/xhtml+xml"; break;
|
|
|
+ case "zip": $mime="application/zip"; break;
|
|
|
+ case "au": $mime="audio/basic"; break;
|
|
|
+ case "snd": $mime="audio/basic"; break;
|
|
|
+ case "mid": $mime="audio/midi"; break;
|
|
|
+ case "midi": $mime="audio/midi"; break;
|
|
|
+ case "kar": $mime="audio/midi"; break;
|
|
|
+ case "mpga": $mime="audio/mpeg"; break;
|
|
|
+ case "mp2": $mime="audio/mpeg"; break;
|
|
|
+ case "mp3": $mime="audio/mpeg"; break;
|
|
|
+ case "aif": $mime="audio/x-aiff"; break;
|
|
|
+ case "aiff": $mime="audio/x-aiff"; break;
|
|
|
+ case "aifc": $mime="audio/x-aiff"; break;
|
|
|
+ case "m3u": $mime="audio/x-mpegurl"; break;
|
|
|
+ case "ram": $mime="audio/x-pn-realaudio"; break;
|
|
|
+ case "rm": $mime="audio/x-pn-realaudio"; break;
|
|
|
+ case "rpm": $mime="audio/x-pn-realaudio-plugin"; break;
|
|
|
+ case "ra": $mime="audio/x-realaudio"; break;
|
|
|
+ case "wav": $mime="audio/x-wav"; break;
|
|
|
+ case "pdb": $mime="chemical/x-pdb"; break;
|
|
|
+ case "xyz": $mime="chemical/x-xyz"; break;
|
|
|
+ case "bmp": $mime="image/bmp"; break;
|
|
|
+ case "gif": $mime="image/gif"; break;
|
|
|
+ case "ief": $mime="image/ief"; break;
|
|
|
+ case "jpeg": $mime="image/jpeg"; break;
|
|
|
+ case "jpg": $mime="image/jpeg"; break;
|
|
|
+ case "jpe": $mime="image/jpeg"; break;
|
|
|
+ case "png": $mime="image/png"; break;
|
|
|
+ case "tiff": $mime="image/tiff"; break;
|
|
|
+ case "tif": $mime="image/tiff"; break;
|
|
|
+ case "djvu": $mime="image/vnd.djvu"; break;
|
|
|
+ case "djv": $mime="image/vnd.djvu"; break;
|
|
|
+ case "wbmp": $mime="image/vnd.wap.wbmp"; break;
|
|
|
+ case "ras": $mime="image/x-cmu-raster"; break;
|
|
|
+ case "pnm": $mime="image/x-portable-anymap"; break;
|
|
|
+ case "pbm": $mime="image/x-portable-bitmap"; break;
|
|
|
+ case "pgm": $mime="image/x-portable-graymap"; break;
|
|
|
+ case "ppm": $mime="image/x-portable-pixmap"; break;
|
|
|
+ case "rgb": $mime="image/x-rgb"; break;
|
|
|
+ case "xbm": $mime="image/x-xbitmap"; break;
|
|
|
+ case "xpm": $mime="image/x-xpixmap"; break;
|
|
|
+ case "xwd": $mime="image/x-xwindowdump"; break;
|
|
|
+ case "igs": $mime="model/iges"; break;
|
|
|
+ case "iges": $mime="model/iges"; break;
|
|
|
+ case "msh": $mime="model/mesh"; break;
|
|
|
+ case "mesh": $mime="model/mesh"; break;
|
|
|
+ case "silo": $mime="model/mesh"; break;
|
|
|
+ case "wrl": $mime="model/vrml"; break;
|
|
|
+ case "vrml": $mime="model/vrml"; break;
|
|
|
+ case "css": $mime="text/css"; break;
|
|
|
+ case "html": $mime="text/html"; break;
|
|
|
+ case "htm": $mime="text/html"; break;
|
|
|
+ case "asc": $mime="text/plain"; break;
|
|
|
+ case "txt": $mime="text/plain"; break;
|
|
|
+ case "rtx": $mime="text/richtext"; break;
|
|
|
+ case "rtf": $mime="text/rtf"; break;
|
|
|
+ case "sgml": $mime="text/sgml"; break;
|
|
|
+ case "sgm": $mime="text/sgml"; break;
|
|
|
+ case "tsv": $mime="text/tab-separated-values"; break;
|
|
|
+ case "wml": $mime="text/vnd.wap.wml"; break;
|
|
|
+ case "wmls": $mime="text/vnd.wap.wmlscript"; break;
|
|
|
+ case "etx": $mime="text/x-setext"; break;
|
|
|
+ case "xml": $mime="text/xml"; break;
|
|
|
+ case "xsl": $mime="text/xml"; break;
|
|
|
+ case "mpeg": $mime="video/mpeg"; break;
|
|
|
+ case "mpg": $mime="video/mpeg"; break;
|
|
|
+ case "mpe": $mime="video/mpeg"; break;
|
|
|
+ case "qt": $mime="video/quicktime"; break;
|
|
|
+ case "mov": $mime="video/quicktime"; break;
|
|
|
+ case "mxu": $mime="video/vnd.mpegurl"; break;
|
|
|
+ case "avi": $mime="video/x-msvideo"; break;
|
|
|
+ case "movie": $mime="video/x-sgi-movie"; break;
|
|
|
+ case "asf": $mime="video/x-ms-asf"; break;
|
|
|
+ case "asx": $mime="video/x-ms-asf"; break;
|
|
|
+ case "wm": $mime="video/x-ms-wm"; break;
|
|
|
+ case "wmv": $mime="video/x-ms-wmv"; break;
|
|
|
+ case "wvx": $mime="video/x-ms-wvx"; break;
|
|
|
+ case "ice": $mime="x-conference/x-cooltalk"; break;
|
|
|
+ }
|
|
|
+ if (empty($mime)) {
|
|
|
+ $mime = 'application/octet-stream';
|
|
|
+ }
|
|
|
+ $mimetype = $mime;
|
|
|
+ }
|
|
|
+ return $mimetype;
|
|
|
+ }
|
|
|
+
|
|
|
+ public function preset($type = null) {
|
|
|
+ # testing only:
|
|
|
+ //pr ($this->Email);
|
|
|
+ //pr ($this);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * test for a specific error
|
|
|
+ * @param code: 4xx, 5xx, 5xx 5.1.1, 5xx 5.2.2, ...
|
|
|
+ * @return boolean $status (TRUE only if this specific error occured)
|
|
|
+ * 2010-06-08 ms
|
|
|
+ */
|
|
|
+ public function hasError($code) {
|
|
|
+ if (!empty($this->errors)) {
|
|
|
+ foreach ($this->errors as $error) {
|
|
|
+ if (substr($error, 0, strlen($code)) == (string)$code) {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ public function validates() {
|
|
|
+ if (!empty($this->Email->subject)) {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Set the body of the mail as we send it.
|
|
|
+ * Note: the text can be an array, each element will appear as a seperate line in the message body.
|
|
|
+ * @param string/array: message
|
|
|
+ * LEAVE empty if you use $this->set() in combination with templates
|
|
|
+ */
|
|
|
+ public function send($message = null) {
|
|
|
+ $this->_log = array(
|
|
|
+ 'to' => $this->_to,
|
|
|
+ 'from' => $this->_from,
|
|
|
+ 'sender' => $this->_sender,
|
|
|
+ 'replyTo' => $this->_replyTo,
|
|
|
+ 'cc' => $this->_cc,
|
|
|
+ 'subject' => $this->_subject,
|
|
|
+ 'cc' => $this->_cc,
|
|
|
+ 'transport' => $this->_transportName
|
|
|
+ );
|
|
|
+
|
|
|
+ # prep images for inline
|
|
|
+ /*
|
|
|
+ if ($this->_emailFormat !== 'text') {
|
|
|
+ if ($message !== null) {
|
|
|
+ $message = $this->_prepMessage($message);
|
|
|
+ } else {
|
|
|
+ $this->_htmlMessage = $this->_prepMessage($this->_htmlMessage);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ */
|
|
|
+
|
|
|
+ try {
|
|
|
+ $this->_debug = parent::send($message);
|
|
|
+ } catch (Exception $e) {
|
|
|
+ $this->error = $e->getMessage();
|
|
|
+ if (Configure::read('debug') > 0 || env('REMOTE_ADDR') == '127.0.0.1') {
|
|
|
+ $this->error .= ' (line '.$e->getLine().' in '.$e->getFile().')'.PHP_EOL.$e->getTraceAsString();
|
|
|
+ }
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ if (!empty($this->_config['report'])) {
|
|
|
+ $this->_logEmail();
|
|
|
+ }
|
|
|
+
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ protected function _prepMessage($text) {
|
|
|
+
|
|
|
+ return $text;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * @return string
|
|
|
+ */
|
|
|
+ public function getError() {
|
|
|
+ return $this->error;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ protected function _logEmail($append = null) {
|
|
|
+ $res = $this->_log['transport'].
|
|
|
+ ' - '.'TO:'.implode(',', array_keys($this->_log['to'])).
|
|
|
+ '||FROM:'.implode(',', array_keys($this->_log['from'])).
|
|
|
+ '||REPLY:'.implode(',', array_keys($this->_log['replyTo'])).
|
|
|
+ '||S:'.$this->_log['subject'];
|
|
|
+ $type = 'email';
|
|
|
+ if (!empty($this->error)) {
|
|
|
+ $type = 'email_error';
|
|
|
+ $res .= '||ERROR:' . $this->error;
|
|
|
+ }
|
|
|
+ if ($append) {
|
|
|
+ $res .= '||'.$append;
|
|
|
+ }
|
|
|
+ CakeLog::write($type, $res);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * toggle debug mode
|
|
|
+ * 2011-05-27 ms
|
|
|
+ */
|
|
|
+ public function debug($mode = null) {
|
|
|
+ if ($mode) {
|
|
|
+ $this->debug = true;
|
|
|
+ //$this->delivery('debug');
|
|
|
+ } else {
|
|
|
+ $this->debug = false;
|
|
|
+ //$this->delivery($this->deliveryMethod);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public function resetAndSet() {
|
|
|
+ $this->_to = array();
|
|
|
+ $this->_cc = array();
|
|
|
+ $this->_bcc = array();
|
|
|
+ $this->_messageId = true;
|
|
|
+ $this->_subject = '';
|
|
|
+ $this->_headers = array();
|
|
|
+ $this->_viewVars = array();
|
|
|
+ $this->_textMessage = '';
|
|
|
+ $this->_htmlMessage = '';
|
|
|
+ $this->_message = '';
|
|
|
+ $this->_attachments = array();
|
|
|
+
|
|
|
+ $this->from(Configure::read('Config.admin_email'), Configure::read('Config.admin_emailname'));
|
|
|
+ if ($xMailer = Configure::read('Config.x-mailer')) {
|
|
|
+ $this->addHeaders(array('X-Mailer'=>$xMailer));
|
|
|
+ }
|
|
|
+ //$this->errors = array();
|
|
|
+ //$this->charset($this->charset);
|
|
|
+ //$this->sendAs($this->sendAs);
|
|
|
+ //$this->layout($this->layout);
|
|
|
+ //$this->delivery($this->deliveryMethod);
|
|
|
+ }
|
|
|
+
|
|
|
+ public function reset() {
|
|
|
+ parent::reset();
|
|
|
+ $this->error = '';
|
|
|
+ $this->_debug = null;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ public function flashDebug() {
|
|
|
+ $info = $this->Email->Controller->Session->read('Message.email.message');
|
|
|
+ if (empty($info)) {
|
|
|
+ $info = $this->Email->Controller->Session->read('Message.email.message');
|
|
|
+ }
|
|
|
+
|
|
|
+ $info .= BR;
|
|
|
+ $info .= h($this->_logMessage());
|
|
|
+
|
|
|
+ $this->Email->Controller->Session->delete('Message.email');
|
|
|
+ $this->Email->Controller->flashMessage($info, 'info');
|
|
|
+ if (!empty($this->errors)) {
|
|
|
+ $this->Email->Controller->flashMessage(implode(BR, $this->errors), 'error');
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+}
|