diff --git a/include/pear/BUNDLE b/include/pear/BUNDLE index 22917abc2caad7086de5ea447757c18f2cd44321..3cee20d1985e7ceb65359c57ccaba721c6a66479 100644 --- a/include/pear/BUNDLE +++ b/include/pear/BUNDLE @@ -1,5 +1,11 @@ Log of pear packages bundled with osTicket +* osTicket v1.9.13, v1.10 * +=========================================================== +Mail_Mime-1.10.0 +Mail_mimeDecode-1.5.5 +Net_SMTP-1.7.1 + * osTicket v1.7.* =========================================================== PEAR-1.9.4 - core class diff --git a/include/pear/Mail/mime.php b/include/pear/Mail/mime.php index 4522e20cd2eab289a3be6b39126c3aafc81e18a3..f2aed691168acb91892b422fa83ec385a8049e90 100644 --- a/include/pear/Mail/mime.php +++ b/include/pear/Mail/mime.php @@ -1,4 +1,5 @@ <?php + /** * The Mail_Mime class is used to create MIME E-mail messages * @@ -7,7 +8,7 @@ * contain plain-text bodies, HTML bodies, attachments, inline * images and specific headers. * - * Compatible with PHP versions 4 and 5 + * Compatible with PHP >= 5 * * LICENSE: This LICENSE is in the BSD license style. * Copyright (c) 2002-2003, Richard Heyes <richard@phpguru.org> @@ -48,7 +49,7 @@ * @author Aleksander Machniak <alec@php.net> * @copyright 2003-2006 PEAR <pear-group@php.net> * @license http://www.opensource.org/licenses/bsd-license.php BSD License - * @version CVS: $Id$ + * @version Release: @package_version@ * @link http://pear.php.net/package/Mail_mime * * This class is based on HTML Mime Mail class from @@ -58,20 +59,7 @@ */ -/** - * require PEAR - * - * This package depends on PEAR to raise errors. - */ require_once 'PEAR.php'; - -/** - * require Mail_mimePart - * - * Mail_mimePart contains the code required to - * create all the different parts a mail can - * consist of. - */ require_once 'Mail/mimePart.php'; @@ -98,49 +86,50 @@ class Mail_mime * Contains the plain text part of the email * * @var string - * @access private */ - var $_txtbody; + protected $txtbody; /** * Contains the html part of the email * * @var string - * @access private */ - var $_htmlbody; + protected $htmlbody; + + /** + * Contains the text/calendar part of the email + * + * @var string + */ + protected $calbody; /** * list of the attached images * * @var array - * @access private */ - var $_html_images = array(); + protected $html_images = array(); /** * list of the attachements * * @var array - * @access private */ - var $_parts = array(); + protected $parts = array(); /** * Headers for the mail * * @var array - * @access private */ - var $_headers = array(); + protected $headers = array(); /** * Build parameters * * @var array - * @access private */ - var $_build_params = array( + protected $build_params = array( // What encoding to use for the headers // Options: quoted-printable or base64 'head_encoding' => 'quoted-printable', @@ -150,18 +139,28 @@ class Mail_mime // What encoding to use for html // Options: 7bit, 8bit, base64, or quoted-printable 'html_encoding' => 'quoted-printable', + // What encoding to use for calendar part + // Options: 7bit, 8bit, base64, or quoted-printable + 'calendar_encoding' => 'quoted-printable', // The character set to use for html 'html_charset' => 'ISO-8859-1', // The character set to use for text 'text_charset' => 'ISO-8859-1', + // The character set to use for calendar part + 'calendar_charset' => 'UTF-8', // The character set to use for headers 'head_charset' => 'ISO-8859-1', // End-of-line sequence 'eol' => "\r\n", // Delay attachment files IO until building the message - 'delay_file_io' => false + 'delay_file_io' => false, + // Default calendar method + 'calendar_method' => 'request', + // multipart part preamble (RFC2046 5.1.1) + 'preamble' => '', ); + /** * Constructor function * @@ -170,21 +169,20 @@ class Mail_mime * See $_build_params. * * @return void - * @access public */ - function Mail_mime($params = array()) + public function __construct($params = array()) { // Backward-compatible EOL setting if (is_string($params)) { - $this->_build_params['eol'] = $params; + $this->build_params['eol'] = $params; } else if (defined('MAIL_MIME_CRLF') && !isset($params['eol'])) { - $this->_build_params['eol'] = MAIL_MIME_CRLF; + $this->build_params['eol'] = MAIL_MIME_CRLF; } // Update build parameters if (!empty($params) && is_array($params)) { while (list($key, $value) = each($params)) { - $this->_build_params[$key] = $value; + $this->build_params[$key] = $value; } } } @@ -196,12 +194,11 @@ class Mail_mime * @param string $value Parameter value * * @return void - * @access public * @since 1.6.0 */ - function setParam($name, $value) + public function setParam($name, $value) { - $this->_build_params[$name] = $value; + $this->build_params[$name] = $value; } /** @@ -210,12 +207,11 @@ class Mail_mime * @param string $name Parameter name * * @return mixed Parameter value - * @access public * @since 1.6.0 */ - function getParam($name) + public function getParam($name) { - return isset($this->_build_params[$name]) ? $this->_build_params[$name] : null; + return isset($this->build_params[$name]) ? $this->build_params[$name] : null; } /** @@ -224,106 +220,116 @@ class Mail_mime * text/plain part that emails clients who don't support * html should show. * - * @param string $data Either a string or - * the file name with the contents + * @param string $data Either a string or the file name with the contents * @param bool $isfile If true the first param should be treated * as a file name, else as a string (default) * @param bool $append If true the text or file is appended to * the existing body, else the old body is * overwritten * - * @return mixed True on success or PEAR_Error object - * @access public + * @return mixed True on success or PEAR_Error object */ - function setTXTBody($data, $isfile = false, $append = false) + public function setTXTBody($data, $isfile = false, $append = false) { - if (!$isfile) { - if (!$append) { - $this->_txtbody = $data; - } else { - $this->_txtbody .= $data; - } - } else { - $cont = $this->_file2str($data); - if (PEAR::isError($cont)) { - return $cont; - } - if (!$append) { - $this->_txtbody = $cont; - } else { - $this->_txtbody .= $cont; - } - } - return true; + return $this->setBody('txtbody', $data, $isfile, $append); } /** * Get message text body * * @return string Text body - * @access public * @since 1.6.0 */ - function getTXTBody() + public function getTXTBody() { - return $this->_txtbody; + return $this->txtbody; } /** * Adds a html part to the mail. * - * @param string $data Either a string or the file name with the - * contents + * @param string $data Either a string or the file name with the contents * @param bool $isfile A flag that determines whether $data is a * filename, or a string(false, default) * - * @return bool True on success - * @access public + * @return bool True on success or PEAR_Error object */ - function setHTMLBody($data, $isfile = false) + public function setHTMLBody($data, $isfile = false) { - if (!$isfile) { - $this->_htmlbody = $data; - } else { - $cont = $this->_file2str($data); - if (PEAR::isError($cont)) { - return $cont; - } - $this->_htmlbody = $cont; - } - - return true; + return $this->setBody('htmlbody', $data, $isfile); } /** * Get message HTML body * * @return string HTML body - * @access public * @since 1.6.0 */ - function getHTMLBody() + public function getHTMLBody() + { + return $this->htmlbody; + } + + /** + * Function to set a body of text/calendar part (not attachment) + * + * @param string $data Either a string or the file name with the contents + * @param bool $isfile If true the first param should be treated + * as a file name, else as a string (default) + * @param bool $append If true the text or file is appended to + * the existing body, else the old body is + * overwritten + * @param string $method iCalendar object method + * @param string $charset iCalendar character set + * @param string $encoding Transfer encoding + * + * @return mixed True on success or PEAR_Error object + * @since 1.9.0 + */ + public function setCalendarBody($data, $isfile = false, $append = false, + $method = 'request', $charset = 'UTF-8', $encoding = 'quoted-printable' + ) { + $result = $this->setBody('calbody', $data, $isfile, $append); + + if ($result === true) { + $this->build_params['calendar_method'] = $method; + $this->build_params['calendar_charset'] = $charset; + $this->build_params['calendar_encoding'] = $encoding; + } + } + + /** + * Get body of calendar part + * + * @return string Calendar part body + * @since 1.9.0 + */ + public function getCalendarBody() { - return $this->_htmlbody; + return $this->calbody; } /** * Adds an image to the list of embedded images. + * Images added this way will be added as related parts of the HTML message. + * + * To correctly match the HTML image with the related attachment + * HTML should refer to it by a filename (specified in $file or $name + * arguments) or by cid:<content-id> (specified in $content_id arg). * * @param string $file The image file name OR image data itself * @param string $c_type The content type - * @param string $name The filename of the image. - * Only used if $file is the image data. + * @param string $name The filename of the image. Used to find + * the image in HTML content. * @param bool $isfile Whether $file is a filename or not. * Defaults to true * @param string $content_id Desired Content-ID of MIME part * Defaults to generated unique ID * - * @return bool True on success - * @access public + * @return bool True on success */ - function addHTMLImage($file, - $c_type='application/octet-stream', + public function addHTMLImage($file, + $c_type = 'application/octet-stream', $name = '', $isfile = true, $content_id = null @@ -332,25 +338,26 @@ class Mail_mime if ($isfile) { // Don't load file into memory - if ($this->_build_params['delay_file_io']) { + if ($this->build_params['delay_file_io']) { $filedata = null; $bodyfile = $file; } else { - if (PEAR::isError($filedata = $this->_file2str($file))) { + if (self::isError($filedata = $this->file2str($file))) { return $filedata; } } - $filename = ($name ? $name : $file); + + $filename = $name ? $name : $file; } else { $filedata = $file; $filename = $name; } if (!$content_id) { - $content_id = md5(uniqid(time())); + $content_id = preg_replace('/[^0-9a-zA-Z]/', '', uniqid(time(), true)); } - $this->_html_images[] = array( + $this->html_images[] = array( 'body' => $filedata, 'body_file' => $bodyfile, 'name' => $filename, @@ -364,8 +371,8 @@ class Mail_mime /** * Adds a file to the list of attachments. * - * @param string $file The file name of the file to attach - * or the file contents itself + * @param mixed $file The file name or the file contents itself, + * it can be also Mail_mimePart object * @param string $c_type The content type * @param string $name The filename of the attachment * Only use if $file is the contents @@ -390,10 +397,9 @@ class Mail_mime * @param array $add_headers Additional part headers. Array keys can be in form * of <header_name>:<parameter_name> * - * @return mixed True on success or PEAR_Error object - * @access public + * @return mixed True on success or PEAR_Error object */ - function addAttachment($file, + public function addAttachment($file, $c_type = 'application/octet-stream', $name = '', $isfile = true, @@ -408,20 +414,25 @@ class Mail_mime $h_charset = null, $add_headers = array() ) { + if ($file instanceof Mail_mimePart) { + $this->parts[] = $file; + return true; + } + $bodyfile = null; if ($isfile) { // Don't load file into memory - if ($this->_build_params['delay_file_io']) { + if ($this->build_params['delay_file_io']) { $filedata = null; $bodyfile = $file; } else { - if (PEAR::isError($filedata = $this->_file2str($file))) { + if (self::isError($filedata = $this->file2str($file))) { return $filedata; } } // Force the name the user supplied, otherwise use $file - $filename = ($name ? $name : $file); + $filename = ($name ? $name : $this->basename($file)); } else { $filedata = $file; $filename = $name; @@ -429,12 +440,10 @@ class Mail_mime if (!strlen($filename)) { $msg = "The supplied filename for the attachment can't be empty"; - $err = PEAR::raiseError($msg); - return $err; + return self::raiseError($msg); } - $filename = $this->_basename($filename); - $this->_parts[] = array( + $this->parts[] = array( 'body' => $filedata, 'body_file' => $bodyfile, 'name' => $filename, @@ -454,35 +463,45 @@ class Mail_mime return true; } + /** + * Checks if the current message has many parts + * + * @return bool True if the message has many parts, False otherwise. + * @since 1.9.0 + */ + public function isMultipart() + { + return count($this->parts) > 0 || count($this->html_images) > 0 + || (strlen($this->htmlbody) > 0 && strlen($this->txtbody) > 0); + } + /** * Get the contents of the given file name as string * * @param string $file_name Path of file to process * - * @return string Contents of $file_name - * @access private + * @return string Contents of $file_name */ - function &_file2str($file_name) + protected function file2str($file_name) { // Check state of file and raise an error properly if (!file_exists($file_name)) { - $err = PEAR::raiseError('File not found: ' . $file_name); - return $err; + return self::raiseError('File not found: ' . $file_name); } if (!is_file($file_name)) { - $err = PEAR::raiseError('Not a regular file: ' . $file_name); - return $err; + return self::raiseError('Not a regular file: ' . $file_name); } if (!is_readable($file_name)) { - $err = PEAR::raiseError('File is not readable: ' . $file_name); - return $err; + return self::raiseError('File is not readable: ' . $file_name); } // Temporarily reset magic_quotes_runtime and read file contents if ($magic_quote_setting = get_magic_quotes_runtime()) { @ini_set('magic_quotes_runtime', 0); } + $cont = file_get_contents($file_name); + if ($magic_quote_setting) { @ini_set('magic_quotes_runtime', $magic_quote_setting); } @@ -494,53 +513,44 @@ class Mail_mime * Adds a text subpart to the mimePart object and * returns it during the build process. * - * @param mixed &$obj The object to add the part to, or - * null if a new object is to be created. - * @param string $text The text to add. + * @param mixed $obj The object to add the part to, or + * anything else if a new object is to be created. * - * @return object The text mimePart object - * @access private + * @return object The text mimePart object */ - function &_addTextPart(&$obj, $text) + protected function addTextPart($obj = null) { - $params['content_type'] = 'text/plain'; - $params['encoding'] = $this->_build_params['text_encoding']; - $params['charset'] = $this->_build_params['text_charset']; - $params['eol'] = $this->_build_params['eol']; - - if (is_object($obj)) { - $ret = $obj->addSubpart($text, $params); - return $ret; - } else { - $ret = new Mail_mimePart($text, $params); - return $ret; - } + return $this->addBodyPart($obj, $this->txtbody, 'text/plain', 'text'); } /** * Adds a html subpart to the mimePart object and * returns it during the build process. * - * @param mixed &$obj The object to add the part to, or - * null if a new object is to be created. + * @param mixed $obj The object to add the part to, or + * anything else if a new object is to be created. * - * @return object The html mimePart object - * @access private + * @return object The html mimePart object */ - function &_addHtmlPart(&$obj) + protected function addHtmlPart($obj = null) { - $params['content_type'] = 'text/html'; - $params['encoding'] = $this->_build_params['html_encoding']; - $params['charset'] = $this->_build_params['html_charset']; - $params['eol'] = $this->_build_params['eol']; + return $this->addBodyPart($obj, $this->htmlbody, 'text/html', 'html'); + } - if (is_object($obj)) { - $ret = $obj->addSubpart($this->_htmlbody, $params); - return $ret; - } else { - $ret = new Mail_mimePart($this->_htmlbody, $params); - return $ret; - } + /** + * Adds a calendar subpart to the mimePart object and + * returns it during the build process. + * + * @param mixed $obj The object to add the part to, or + * anything else if a new object is to be created. + * + * @return object The text mimePart object + */ + protected function addCalendarPart($obj = null) + { + $ctype = 'text/calendar; method='. $this->build_params['calendar_method']; + + return $this->addBodyPart($obj, $this->calbody, $ctype, 'calendar'); } /** @@ -548,18 +558,17 @@ class Mail_mime * the initial content-type and returns it during the * build process. * + * @param array $params Additional part parameters + * * @return object The multipart/mixed mimePart object - * @access private */ - function &_addMixedPart() + protected function addMixedPart($params = array()) { - $params = array(); $params['content_type'] = 'multipart/mixed'; - $params['eol'] = $this->_build_params['eol']; + $params['eol'] = $this->build_params['eol']; // Create empty multipart/mixed Mail_mimePart object to return - $ret = new Mail_mimePart('', $params); - return $ret; + return new Mail_mimePart('', $params); } /** @@ -567,23 +576,23 @@ class Mail_mime * object (or creates one), and returns it during * the build process. * - * @param mixed &$obj The object to add the part to, or - * null if a new object is to be created. + * @param mixed $obj The object to add the part to, or + * anything else if a new object is to be created. * - * @return object The multipart/mixed mimePart object - * @access private + * @return object The multipart/mixed mimePart object */ - function &_addAlternativePart(&$obj) + protected function addAlternativePart($obj = null) { $params['content_type'] = 'multipart/alternative'; - $params['eol'] = $this->_build_params['eol']; + $params['eol'] = $this->build_params['eol']; if (is_object($obj)) { - return $obj->addSubpart('', $params); + $ret = $obj->addSubpart('', $params); } else { $ret = new Mail_mimePart('', $params); - return $ret; } + + return $ret; } /** @@ -591,36 +600,35 @@ class Mail_mime * object (or creates one), and returns it during * the build process. * - * @param mixed &$obj The object to add the part to, or - * null if a new object is to be created + * @param mixed $obj The object to add the part to, or + * anything else if a new object is to be created * - * @return object The multipart/mixed mimePart object - * @access private + * @return object The multipart/mixed mimePart object */ - function &_addRelatedPart(&$obj) + protected function addRelatedPart($obj = null) { $params['content_type'] = 'multipart/related'; - $params['eol'] = $this->_build_params['eol']; + $params['eol'] = $this->build_params['eol']; if (is_object($obj)) { - return $obj->addSubpart('', $params); + $ret = $obj->addSubpart('', $params); } else { $ret = new Mail_mimePart('', $params); - return $ret; } + + return $ret; } /** * Adds an html image subpart to a mimePart object * and returns it during the build process. * - * @param object &$obj The mimePart to add the image to + * @param object $obj The mimePart to add the image to * @param array $value The image information * - * @return object The image mimePart object - * @access private + * @return object The image mimePart object */ - function &_addHtmlImagePart(&$obj, $value) + protected function addHtmlImagePart($obj, $value) { $params['content_type'] = $value['c_type']; $params['encoding'] = 'base64'; @@ -628,7 +636,7 @@ class Mail_mime $params['filename'] = $value['name']; $params['cid'] = $value['cid']; $params['body_file'] = $value['body_file']; - $params['eol'] = $this->_build_params['eol']; + $params['eol'] = $this->build_params['eol']; if (!empty($value['name_encoding'])) { $params['name_encoding'] = $value['name_encoding']; @@ -637,28 +645,30 @@ class Mail_mime $params['filename_encoding'] = $value['filename_encoding']; } - $ret = $obj->addSubpart($value['body'], $params); - return $ret; + return $obj->addSubpart($value['body'], $params); } /** * Adds an attachment subpart to a mimePart object * and returns it during the build process. * - * @param object &$obj The mimePart to add the image to - * @param array $value The attachment information + * @param object $obj The mimePart to add the image to + * @param mixed $value The attachment information array or Mail_mimePart object * - * @return object The image mimePart object - * @access private + * @return object The image mimePart object */ - function &_addAttachmentPart(&$obj, $value) + protected function addAttachmentPart($obj, $value) { - $params['eol'] = $this->_build_params['eol']; + if ($value instanceof Mail_mimePart) { + return $obj->addSubpart($value); + } + + $params['eol'] = $this->build_params['eol']; $params['filename'] = $value['name']; $params['encoding'] = $value['encoding']; $params['content_type'] = $value['c_type']; $params['body_file'] = $value['body_file']; - $params['disposition'] = isset($value['disposition']) ? + $params['disposition'] = isset($value['disposition']) ? $value['disposition'] : 'attachment'; // content charset @@ -669,6 +679,9 @@ class Mail_mime if (!empty($value['headers_charset'])) { $params['headers_charset'] = $value['headers_charset']; } + elseif (isset($this->build_params['head_charset'])) { + $params['headers_charset'] = $this->build_params['head_charset']; + } if (!empty($value['language'])) { $params['language'] = $value['language']; } @@ -688,83 +701,76 @@ class Mail_mime $params['headers'] = $value['add_headers']; } - $ret = $obj->addSubpart($value['body'], $params); - return $ret; + return $obj->addSubpart($value['body'], $params); } /** * Returns the complete e-mail, ready to send using an alternative * mail delivery method. Note that only the mailpart that is made * with Mail_Mime is created. This means that, - * YOU WILL HAVE NO TO: HEADERS UNLESS YOU SET IT YOURSELF + * YOU WILL HAVE NO TO: HEADERS UNLESS YOU SET IT YOURSELF * using the $headers parameter! - * + * * @param string $separation The separation between these two parts. * @param array $params The Build parameters passed to the - * &get() function. See &get for more info. + * get() function. See get() for more info. * @param array $headers The extra headers that should be passed - * to the &headers() function. + * to the headers() method. * See that function for more info. * @param bool $overwrite Overwrite the existing headers with new. * * @return mixed The complete e-mail or PEAR error object - * @access public */ - function getMessage($separation = null, $params = null, $headers = null, + public function getMessage($separation = null, $params = null, $headers = null, $overwrite = false ) { if ($separation === null) { - $separation = $this->_build_params['eol']; + $separation = $this->build_params['eol']; } $body = $this->get($params); - if (PEAR::isError($body)) { + if (self::isError($body)) { return $body; } - $head = $this->txtHeaders($headers, $overwrite); - $mail = $head . $separation . $body; - return $mail; + return $this->txtHeaders($headers, $overwrite) . $separation . $body; } /** * Returns the complete e-mail body, ready to send using an alternative * mail delivery method. - * + * * @param array $params The Build parameters passed to the - * &get() function. See &get for more info. + * get() method. See get() for more info. * * @return mixed The e-mail body or PEAR error object - * @access public * @since 1.6.0 */ - function getMessageBody($params = null) + public function getMessageBody($params = null) { return $this->get($params, null, true); } /** * Writes (appends) the complete e-mail into file. - * + * * @param string $filename Output file location * @param array $params The Build parameters passed to the - * &get() function. See &get for more info. + * get() method. See get() for more info. * @param array $headers The extra headers that should be passed - * to the &headers() function. + * to the headers() function. * See that function for more info. * @param bool $overwrite Overwrite the existing headers with new. * * @return mixed True or PEAR error object - * @access public * @since 1.6.0 */ - function saveMessage($filename, $params = null, $headers = null, $overwrite = false) + public function saveMessage($filename, $params = null, $headers = null, $overwrite = false) { // Check state of file and raise an error properly if (file_exists($filename) && !is_writable($filename)) { - $err = PEAR::raiseError('File is not writable: ' . $filename); - return $err; + return self::raiseError('File is not writable: ' . $filename); } // Temporarily reset magic_quotes_runtime and read file contents @@ -773,15 +779,13 @@ class Mail_mime } if (!($fh = fopen($filename, 'ab'))) { - $err = PEAR::raiseError('Unable to open file: ' . $filename); - return $err; + return self::raiseError('Unable to open file: ' . $filename); } // Write message headers into file (skipping Content-* headers) $head = $this->txtHeaders($headers, $overwrite, true); if (fwrite($fh, $head) === false) { - $err = PEAR::raiseError('Error writing to file: ' . $filename); - return $err; + return self::raiseError('Error writing to file: ' . $filename); } fclose($fh); @@ -797,22 +801,29 @@ class Mail_mime } /** - * Writes (appends) the complete e-mail body into file. - * - * @param string $filename Output file location - * @param array $params The Build parameters passed to the - * &get() function. See &get for more info. + * Writes (appends) the complete e-mail body into file or stream. + * + * @param mixed $filename Output filename or file pointer where to save + * the message instead of returning it + * @param array $params The Build parameters passed to the + * get() method. See get() for more info. * * @return mixed True or PEAR error object - * @access public * @since 1.6.0 */ - function saveMessageBody($filename, $params = null) + public function saveMessageBody($filename, $params = null) { - // Check state of file and raise an error properly - if (file_exists($filename) && !is_writable($filename)) { - $err = PEAR::raiseError('File is not writable: ' . $filename); - return $err; + if (!is_resource($filename)) { + // Check state of file and raise an error properly + if (!file_exists($filename) || !is_writable($filename)) { + return self::raiseError('File is not writable: ' . $filename); + } + + if (!($fh = fopen($filename, 'ab'))) { + return self::raiseError('Unable to open file: ' . $filename); + } + } else { + $fh = $filename; } // Temporarily reset magic_quotes_runtime and read file contents @@ -820,107 +831,128 @@ class Mail_mime @ini_set('magic_quotes_runtime', 0); } - if (!($fh = fopen($filename, 'ab'))) { - $err = PEAR::raiseError('Unable to open file: ' . $filename); - return $err; + // Write the rest of the message into file + $res = $this->get($params, $fh, true); + + if (!is_resource($filename)) { + fclose($fh); } - // Write the rest of the message into file - $res = $this->get($params, $filename, true); + if ($magic_quote_setting) { + @ini_set('magic_quotes_runtime', $magic_quote_setting); + } return $res ? $res : true; } /** - * Builds the multipart message from the list ($this->_parts) and + * Builds the multipart message from the list ($this->parts) and * returns the mime content. * - * @param array $params Build parameters that change the way the email - * is built. Should be associative. See $_build_params. - * @param resource $filename Output file where to save the message instead of - * returning it - * @param boolean $skip_head True if you want to return/save only the message - * without headers + * @param array $params Build parameters that change the way the email + * is built. Should be associative. See $_build_params. + * @param mixed $filename Output filename or file pointer where to save + * the message instead of returning it + * @param boolean $skip_head True if you want to return/save only the message + * without headers * * @return mixed The MIME message content string, null or PEAR error object - * @access public */ - function &get($params = null, $filename = null, $skip_head = false) + public function get($params = null, $filename = null, $skip_head = false) { if (isset($params)) { while (list($key, $value) = each($params)) { - $this->_build_params[$key] = $value; + $this->build_params[$key] = $value; } } - if (isset($this->_headers['From'])) { + if (isset($this->headers['From'])) { // Bug #11381: Illegal characters in domain ID - if (preg_match('#(@[0-9a-zA-Z\-\.]+)#', $this->_headers['From'], $matches)) { + if (preg_match('#(@[0-9a-zA-Z\-\.]+)#', $this->headers['From'], $matches)) { $domainID = $matches[1]; } else { $domainID = '@localhost'; } - foreach ($this->_html_images as $i => $img) { - $cid = $this->_html_images[$i]['cid']; + + foreach ($this->html_images as $i => $img) { + $cid = $this->html_images[$i]['cid']; if (!preg_match('#'.preg_quote($domainID).'$#', $cid)) { - $this->_html_images[$i]['cid'] = $cid . $domainID; + $this->html_images[$i]['cid'] = $cid . $domainID; } } } - if (count($this->_html_images) && isset($this->_htmlbody)) { - foreach ($this->_html_images as $key => $value) { - $regex = array(); - $regex[] = '#(\s)((?i)src|background|href(?-i))\s*=\s*(["\']?)' . - preg_quote($value['name'], '#') . '\3#'; - $regex[] = '#(?i)url(?-i)\(\s*(["\']?)' . - preg_quote($value['name'], '#') . '\1\s*\)#'; + if (count($this->html_images) && isset($this->htmlbody)) { + foreach ($this->html_images as $key => $value) { + $rval = preg_quote($value['name'], '#'); + $regex = array( + '#(\s)((?i)src|background|href(?-i))\s*=\s*(["\']?)' . $rval . '\3#', + '#(?i)url(?-i)\(\s*(["\']?)' . $rval . '\1\s*\)#', + ); - $rep = array(); - $rep[] = '\1\2=\3cid:' . $value['cid'] .'\3'; - $rep[] = 'url(\1cid:' . $value['cid'] . '\1)'; + $rep = array( + '\1\2=\3cid:' . $value['cid'] .'\3', + 'url(\1cid:' . $value['cid'] . '\1)', + ); - $this->_htmlbody = preg_replace($regex, $rep, $this->_htmlbody); - $this->_html_images[$key]['name'] - = $this->_basename($this->_html_images[$key]['name']); + $this->htmlbody = preg_replace($regex, $rep, $this->htmlbody); + $this->html_images[$key]['name'] + = $this->basename($this->html_images[$key]['name']); } } - $this->_checkParams(); + $this->checkParams(); - $null = null; - $attachments = count($this->_parts) ? true : false; - $html_images = count($this->_html_images) ? true : false; - $html = strlen($this->_htmlbody) ? true : false; - $text = (!$html && strlen($this->_txtbody)) ? true : false; + $attachments = count($this->parts) > 0; + $html_images = count($this->html_images) > 0; + $html = strlen($this->htmlbody) > 0; + $calendar = strlen($this->calbody) > 0; + $has_text = strlen($this->txtbody) > 0; + $text = !$html && $has_text; + $mixed_params = array('preamble' => $this->build_params['preamble']); switch (true) { + case $calendar && !$attachments && !$text && !$html: + $message = $this->addCalendarPart(); + break; + + case $calendar && !$attachments: + $message = $this->addAlternativePart($mixed_params); + if ($has_text) { + $this->addTextPart($message); + } + if ($html) { + $this->addHtmlPart($message); + } + $this->addCalendarPart($message); + break; + case $text && !$attachments: - $message =& $this->_addTextPart($null, $this->_txtbody); + $message = $this->addTextPart(); break; case !$text && !$html && $attachments: - $message =& $this->_addMixedPart(); - for ($i = 0; $i < count($this->_parts); $i++) { - $this->_addAttachmentPart($message, $this->_parts[$i]); + $message = $this->addMixedPart($mixed_params); + for ($i = 0; $i < count($this->parts); $i++) { + $this->addAttachmentPart($message, $this->parts[$i]); } break; case $text && $attachments: - $message =& $this->_addMixedPart(); - $this->_addTextPart($message, $this->_txtbody); - for ($i = 0; $i < count($this->_parts); $i++) { - $this->_addAttachmentPart($message, $this->_parts[$i]); + $message = $this->addMixedPart($mixed_params); + $this->addTextPart($message); + for ($i = 0; $i < count($this->parts); $i++) { + $this->addAttachmentPart($message, $this->parts[$i]); } break; case $html && !$attachments && !$html_images: - if (isset($this->_txtbody)) { - $message =& $this->_addAlternativePart($null); - $this->_addTextPart($message, $this->_txtbody); - $this->_addHtmlPart($message); + if (isset($this->txtbody)) { + $message = $this->addAlternativePart(); + $this->addTextPart($message); + $this->addHtmlPart($message); } else { - $message =& $this->_addHtmlPart($null); + $message = $this->addHtmlPart(); } break; @@ -930,23 +962,23 @@ class Mail_mime // * Content-Type: multipart/related; // * html // * image... - if (isset($this->_txtbody)) { - $message =& $this->_addAlternativePart($null); - $this->_addTextPart($message, $this->_txtbody); - - $ht =& $this->_addRelatedPart($message); - $this->_addHtmlPart($ht); - for ($i = 0; $i < count($this->_html_images); $i++) { - $this->_addHtmlImagePart($ht, $this->_html_images[$i]); + if (isset($this->txtbody)) { + $message = $this->addAlternativePart(); + $this->addTextPart($message); + + $ht = $this->addRelatedPart($message); + $this->addHtmlPart($ht); + for ($i = 0; $i < count($this->html_images); $i++) { + $this->addHtmlImagePart($ht, $this->html_images[$i]); } } else { // * Content-Type: multipart/related; // * html // * image... - $message =& $this->_addRelatedPart($null); - $this->_addHtmlPart($message); - for ($i = 0; $i < count($this->_html_images); $i++) { - $this->_addHtmlImagePart($message, $this->_html_images[$i]); + $message = $this->addRelatedPart(); + $this->addHtmlPart($message); + for ($i = 0; $i < count($this->html_images); $i++) { + $this->addHtmlImagePart($message, $this->html_images[$i]); } } /* @@ -956,62 +988,60 @@ class Mail_mime // * text // * html // * image... - $message =& $this->_addRelatedPart($null); - if (isset($this->_txtbody)) { - $alt =& $this->_addAlternativePart($message); - $this->_addTextPart($alt, $this->_txtbody); - $this->_addHtmlPart($alt); + $message = $this->addRelatedPart(); + if (isset($this->txtbody)) { + $alt = $this->addAlternativePart($message); + $this->addTextPart($alt); + $this->addHtmlPart($alt); } else { - $this->_addHtmlPart($message); + $this->addHtmlPart($message); } - for ($i = 0; $i < count($this->_html_images); $i++) { - $this->_addHtmlImagePart($message, $this->_html_images[$i]); + for ($i = 0; $i < count($this->html_images); $i++) { + $this->addHtmlImagePart($message, $this->html_images[$i]); } */ break; case $html && $attachments && !$html_images: - $message =& $this->_addMixedPart(); - if (isset($this->_txtbody)) { - $alt =& $this->_addAlternativePart($message); - $this->_addTextPart($alt, $this->_txtbody); - $this->_addHtmlPart($alt); + $message = $this->addMixedPart($mixed_params); + if (isset($this->txtbody)) { + $alt = $this->addAlternativePart($message); + $this->addTextPart($alt); + $this->addHtmlPart($alt); } else { - $this->_addHtmlPart($message); + $this->addHtmlPart($message); } - for ($i = 0; $i < count($this->_parts); $i++) { - $this->_addAttachmentPart($message, $this->_parts[$i]); + for ($i = 0; $i < count($this->parts); $i++) { + $this->addAttachmentPart($message, $this->parts[$i]); } break; case $html && $attachments && $html_images: - $message =& $this->_addMixedPart(); - if (isset($this->_txtbody)) { - $alt =& $this->_addAlternativePart($message); - $this->_addTextPart($alt, $this->_txtbody); - $rel =& $this->_addRelatedPart($alt); + $message = $this->addMixedPart($mixed_params); + if (isset($this->txtbody)) { + $alt = $this->addAlternativePart($message); + $this->addTextPart($alt); + $rel = $this->addRelatedPart($alt); } else { - $rel =& $this->_addRelatedPart($message); + $rel = $this->addRelatedPart($message); } - $this->_addHtmlPart($rel); - for ($i = 0; $i < count($this->_html_images); $i++) { - $this->_addHtmlImagePart($rel, $this->_html_images[$i]); + $this->addHtmlPart($rel); + for ($i = 0; $i < count($this->html_images); $i++) { + $this->addHtmlImagePart($rel, $this->html_images[$i]); } - for ($i = 0; $i < count($this->_parts); $i++) { - $this->_addAttachmentPart($message, $this->_parts[$i]); + for ($i = 0; $i < count($this->parts); $i++) { + $this->addAttachmentPart($message, $this->parts[$i]); } break; - } if (!isset($message)) { - $ret = null; - return $ret; + return null; } // Use saved boundary - if (!empty($this->_build_params['boundary'])) { - $boundary = $this->_build_params['boundary']; + if (!empty($this->build_params['boundary'])) { + $boundary = $this->build_params['boundary']; } else { $boundary = null; } @@ -1020,20 +1050,18 @@ class Mail_mime if ($filename) { // Append mimePart message headers and body into file $headers = $message->encodeToFile($filename, $boundary, $skip_head); - if (PEAR::isError($headers)) { + if (self::isError($headers)) { return $headers; } - $this->_headers = array_merge($this->_headers, $headers); - $ret = null; - return $ret; + $this->headers = array_merge($this->headers, $headers); + return null; } else { $output = $message->encode($boundary, $skip_head); - if (PEAR::isError($output)) { + if (self::isError($output)) { return $output; } - $this->_headers = array_merge($this->_headers, $output['headers']); - $body = $output['body']; - return $body; + $this->headers = array_merge($this->headers, $output['headers']); + return $output['body']; } } @@ -1047,11 +1075,10 @@ class Mail_mime * @param bool $overwrite Overwrite already existing headers. * @param bool $skip_content Don't return content headers: Content-Type, * Content-Disposition and Content-Transfer-Encoding - * - * @return array Assoc array with the mime headers - * @access public + * + * @return array Assoc array with the mime headers */ - function &headers($xtra_headers = null, $overwrite = false, $skip_content = false) + public function headers($xtra_headers = null, $overwrite = false, $skip_content = false) { // Add mime version header $headers['MIME-Version'] = '1.0'; @@ -1061,7 +1088,7 @@ class Mail_mime // we got them when called before get() or something in the message // has been changed after get() [#14780] if (!$skip_content) { - $headers += $this->_contentHeaders(); + $headers += $this->contentHeaders(); } if (!empty($xtra_headers)) { @@ -1069,22 +1096,22 @@ class Mail_mime } if ($overwrite) { - $this->_headers = array_merge($this->_headers, $headers); + $this->headers = array_merge($this->headers, $headers); } else { - $this->_headers = array_merge($headers, $this->_headers); + $this->headers = array_merge($headers, $this->headers); } - $headers = $this->_headers; + $headers = $this->headers; if ($skip_content) { unset($headers['Content-Type']); unset($headers['Content-Transfer-Encoding']); unset($headers['Content-Disposition']); - } else if (!empty($this->_build_params['ctype'])) { - $headers['Content-Type'] = $this->_build_params['ctype']; + } else if (!empty($this->build_params['ctype'])) { + $headers['Content-Type'] = $this->build_params['ctype']; } - $encodedHeaders = $this->_encodeHeaders($headers); + $encodedHeaders = $this->encodeHeaders($headers); return $encodedHeaders; } @@ -1098,10 +1125,9 @@ class Mail_mime * @param bool $skip_content Don't return content headers: Content-Type, * Content-Disposition and Content-Transfer-Encoding * - * @return string Plain text headers - * @access public + * @return string Plain text headers */ - function txtHeaders($xtra_headers = null, $overwrite = false, $skip_content = false) + public function txtHeaders($xtra_headers = null, $overwrite = false, $skip_content = false) { $headers = $this->headers($xtra_headers, $overwrite, $skip_content); @@ -1114,7 +1140,7 @@ class Mail_mime } $ret = ''; - $eol = $this->_build_params['eol']; + $eol = $this->build_params['eol']; foreach ($headers as $key => $val) { if (is_array($val)) { @@ -1132,29 +1158,29 @@ class Mail_mime /** * Sets message Content-Type header. * Use it to build messages with various content-types e.g. miltipart/raport - * not supported by _contentHeaders() function. + * not supported by contentHeaders() function. * * @param string $type Type name * @param array $params Hash array of header parameters * * @return void - * @access public * @since 1.7.0 */ - function setContentType($type, $params = array()) + public function setContentType($type, $params = array()) { $header = $type; - $eol = !empty($this->_build_params['eol']) - ? $this->_build_params['eol'] : "\r\n"; + $eol = !empty($this->build_params['eol']) + ? $this->build_params['eol'] : "\r\n"; // add parameters $token_regexp = '#([^\x21\x23-\x27\x2A\x2B\x2D' . '\x2E\x30-\x39\x41-\x5A\x5E-\x7E])#'; + if (is_array($params)) { foreach ($params as $name => $value) { if ($name == 'boundary') { - $this->_build_params['boundary'] = $value; + $this->build_params['boundary'] = $value; } if (!preg_match($token_regexp, $value)) { $header .= ";$eol $name=$value"; @@ -1166,15 +1192,15 @@ class Mail_mime } // add required boundary parameter if not defined - if (preg_match('/^multipart\//i', $type)) { - if (empty($this->_build_params['boundary'])) { - $this->_build_params['boundary'] = '=_' . md5(rand() . microtime()); + if (stripos($type, 'multipart/') === 0) { + if (empty($this->build_params['boundary'])) { + $this->build_params['boundary'] = '=_' . md5(rand() . microtime()); } - $header .= ";$eol boundary=\"".$this->_build_params['boundary']."\""; + $header .= ";$eol boundary=\"".$this->build_params['boundary']."\""; } - $this->_build_params['ctype'] = $header; + $this->build_params['ctype'] = $header; } /** @@ -1183,11 +1209,10 @@ class Mail_mime * @param string $subject String to set the subject to. * * @return void - * @access public */ - function setSubject($subject) + public function setSubject($subject) { - $this->_headers['Subject'] = $subject; + $this->headers['Subject'] = $subject; } /** @@ -1196,11 +1221,10 @@ class Mail_mime * @param string $email The email address to use * * @return void - * @access public */ - function setFrom($email) + public function setFrom($email) { - $this->_headers['From'] = $email; + $this->headers['From'] = $email; } /** @@ -1210,14 +1234,13 @@ class Mail_mime * @param string $email The email direction to add * * @return void - * @access public */ - function addTo($email) + public function addTo($email) { - if (isset($this->_headers['To'])) { - $this->_headers['To'] .= ", $email"; + if (isset($this->headers['To'])) { + $this->headers['To'] .= ", $email"; } else { - $this->_headers['To'] = $email; + $this->headers['To'] = $email; } } @@ -1228,14 +1251,13 @@ class Mail_mime * @param string $email The email direction to add * * @return void - * @access public */ - function addCc($email) + public function addCc($email) { - if (isset($this->_headers['Cc'])) { - $this->_headers['Cc'] .= ", $email"; + if (isset($this->headers['Cc'])) { + $this->headers['Cc'] .= ", $email"; } else { - $this->_headers['Cc'] = $email; + $this->headers['Cc'] = $email; } } @@ -1246,14 +1268,13 @@ class Mail_mime * @param string $email The email direction to add * * @return void - * @access public */ - function addBcc($email) + public function addBcc($email) { - if (isset($this->_headers['Bcc'])) { - $this->_headers['Bcc'] .= ", $email"; + if (isset($this->headers['Bcc'])) { + $this->headers['Bcc'] .= ", $email"; } else { - $this->_headers['Bcc'] = $email; + $this->headers['Bcc'] = $email; } } @@ -1261,20 +1282,19 @@ class Mail_mime * Since the PHP send function requires you to specify * recipients (To: header) separately from the other * headers, the To: header is not properly encoded. - * To fix this, you can use this public method to - * encode your recipients before sending to the send - * function + * To fix this, you can use this public method to encode + * your recipients before sending to the send function. * * @param string $recipients A comma-delimited list of recipients * - * @return string Encoded data - * @access public + * @return string Encoded data */ - function encodeRecipients($recipients) + public function encodeRecipients($recipients) { - $input = array("To" => $recipients); - $retval = $this->_encodeHeaders($input); - return $retval["To"] ; + $input = array('To' => $recipients); + $retval = $this->encodeHeaders($input); + + return $retval['To'] ; } /** @@ -1283,14 +1303,14 @@ class Mail_mime * @param array $input The header data to encode * @param array $params Extra build parameters * - * @return array Encoded data - * @access private + * @return array Encoded data */ - function _encodeHeaders($input, $params = array()) + protected function encodeHeaders($input, $params = array()) { - $build_params = $this->_build_params; - while (list($key, $value) = each($params)) { - $build_params[$key] = $value; + $build_params = $this->build_params; + + if (!empty($params)) { + $build_params = array_merge($build_params, $params); } foreach ($input as $hdr_name => $hdr_value) { @@ -1301,11 +1321,13 @@ class Mail_mime $build_params['head_charset'], $build_params['head_encoding'] ); } - } else { + } else if ($hdr_value !== null) { $input[$hdr_name] = $this->encodeHeader( $hdr_name, $hdr_value, $build_params['head_charset'], $build_params['head_encoding'] ); + } else { + unset($input[$hdr_name]); } } @@ -1320,27 +1342,24 @@ class Mail_mime * @param string $charset Character set name * @param string $encoding Encoding name (base64 or quoted-printable) * - * @return string Encoded header data (without a name) - * @access public + * @return string Encoded header data (without a name) * @since 1.5.3 */ - function encodeHeader($name, $value, $charset, $encoding) + public function encodeHeader($name, $value, $charset, $encoding) { - $mime_part = new Mail_mimePart; - return $mime_part->encodeHeader( - $name, $value, $charset, $encoding, $this->_build_params['eol'] + return Mail_mimePart::encodeHeader( + $name, $value, $charset, $encoding, $this->build_params['eol'] ); } /** - * Get file's basename (locale independent) + * Get file's basename (locale independent) * * @param string $filename Filename * - * @return string Basename - * @access private + * @return string Basename */ - function _basename($filename) + protected function basename($filename) { // basename() is not unicode safe and locale dependent if (stristr(PHP_OS, 'win') || stristr(PHP_OS, 'netware')) { @@ -1354,18 +1373,27 @@ class Mail_mime * Get Content-Type and Content-Transfer-Encoding headers of the message * * @return array Headers array - * @access private */ - function _contentHeaders() + protected function contentHeaders() { - $attachments = count($this->_parts) ? true : false; - $html_images = count($this->_html_images) ? true : false; - $html = strlen($this->_htmlbody) ? true : false; - $text = (!$html && strlen($this->_txtbody)) ? true : false; + $attachments = count($this->parts) > 0; + $html_images = count($this->html_images) > 0; + $html = strlen($this->htmlbody) > 0; + $calendar = strlen($this->calbody) > 0; + $has_text = strlen($this->txtbody) > 0; + $text = !$html && $has_text; $headers = array(); // See get() switch (true) { + case $calendar && !$attachments && !$html && !$has_text: + $headers['Content-Type'] = 'text/calendar'; + break; + + case $calendar && !$attachments: + $headers['Content-Type'] = 'multipart/alternative'; + break; + case $text && !$attachments: $headers['Content-Type'] = 'text/plain'; break; @@ -1377,16 +1405,16 @@ class Mail_mime $headers['Content-Type'] = 'multipart/mixed'; break; - case $html && !$attachments && !$html_images && isset($this->_txtbody): - case $html && !$attachments && $html_images && isset($this->_txtbody): + case $html && !$attachments && !$html_images && $has_text: + case $html && !$attachments && $html_images && $has_text: $headers['Content-Type'] = 'multipart/alternative'; break; - case $html && !$attachments && !$html_images && !isset($this->_txtbody): + case $html && !$attachments && !$html_images && !$has_text: $headers['Content-Type'] = 'text/html'; break; - case $html && !$attachments && $html_images && !isset($this->_txtbody): + case $html && !$attachments && $html_images && !$has_text: $headers['Content-Type'] = 'multipart/related'; break; @@ -1394,41 +1422,61 @@ class Mail_mime return $headers; } - $this->_checkParams(); + $this->checkParams(); - $eol = !empty($this->_build_params['eol']) - ? $this->_build_params['eol'] : "\r\n"; + $eol = !empty($this->build_params['eol']) + ? $this->build_params['eol'] : "\r\n"; if ($headers['Content-Type'] == 'text/plain') { // single-part message: add charset and encoding - $charset = 'charset=' . $this->_build_params['text_charset']; - // place charset parameter in the same line, if possible - // 26 = strlen("Content-Type: text/plain; ") - $headers['Content-Type'] - .= (strlen($charset) + 26 <= 76) ? "; $charset" : ";$eol $charset"; + if ($this->build_params['text_charset']) { + $charset = 'charset=' . $this->build_params['text_charset']; + // place charset parameter in the same line, if possible + // 26 = strlen("Content-Type: text/plain; ") + $headers['Content-Type'] + .= (strlen($charset) + 26 <= 76) ? "; $charset" : ";$eol $charset"; + } + $headers['Content-Transfer-Encoding'] - = $this->_build_params['text_encoding']; + = $this->build_params['text_encoding']; } else if ($headers['Content-Type'] == 'text/html') { // single-part message: add charset and encoding - $charset = 'charset=' . $this->_build_params['html_charset']; - // place charset parameter in the same line, if possible - $headers['Content-Type'] - .= (strlen($charset) + 25 <= 76) ? "; $charset" : ";$eol $charset"; + if ($this->build_params['html_charset']) { + $charset = 'charset=' . $this->build_params['html_charset']; + // place charset parameter in the same line, if possible + $headers['Content-Type'] + .= (strlen($charset) + 25 <= 76) ? "; $charset" : ";$eol $charset"; + } + $headers['Content-Transfer-Encoding'] + = $this->build_params['html_encoding']; + } + else if ($headers['Content-Type'] == 'text/calendar') { + // single-part message: add charset and encoding + if ($this->build_params['calendar_charset']) { + $charset = 'charset=' . $this->build_params['calendar_charset']; + $headers['Content-Type'] .= "; $charset"; + } + + if ($this->build_params['calendar_method']) { + $method = 'method=' . $this->build_params['calendar_method']; + $headers['Content-Type'] .= "; $method"; + } + $headers['Content-Transfer-Encoding'] - = $this->_build_params['html_encoding']; + = $this->build_params['calendar_encoding']; } else { // multipart message: and boundary - if (!empty($this->_build_params['boundary'])) { - $boundary = $this->_build_params['boundary']; - } else if (!empty($this->_headers['Content-Type']) - && preg_match('/boundary="([^"]+)"/', $this->_headers['Content-Type'], $m) + if (!empty($this->build_params['boundary'])) { + $boundary = $this->build_params['boundary']; + } else if (!empty($this->headers['Content-Type']) + && preg_match('/boundary="([^"]+)"/', $this->headers['Content-Type'], $m) ) { $boundary = $m[1]; } else { $boundary = '=_' . md5(rand() . microtime()); } - $this->_build_params['boundary'] = $boundary; + $this->build_params['boundary'] = $boundary; $headers['Content-Type'] .= ";$eol boundary=\"$boundary\""; } @@ -1439,38 +1487,143 @@ class Mail_mime * Validate and set build parameters * * @return void - * @access private */ - function _checkParams() + protected function checkParams() { $encodings = array('7bit', '8bit', 'base64', 'quoted-printable'); - $this->_build_params['text_encoding'] - = strtolower($this->_build_params['text_encoding']); - $this->_build_params['html_encoding'] - = strtolower($this->_build_params['html_encoding']); + $this->build_params['text_encoding'] + = strtolower($this->build_params['text_encoding']); + $this->build_params['html_encoding'] + = strtolower($this->build_params['html_encoding']); + $this->build_params['calendar_encoding'] + = strtolower($this->build_params['calendar_encoding']); - if (!in_array($this->_build_params['text_encoding'], $encodings)) { - $this->_build_params['text_encoding'] = '7bit'; + if (!in_array($this->build_params['text_encoding'], $encodings)) { + $this->build_params['text_encoding'] = '7bit'; + } + if (!in_array($this->build_params['html_encoding'], $encodings)) { + $this->build_params['html_encoding'] = '7bit'; } - if (!in_array($this->_build_params['html_encoding'], $encodings)) { - $this->_build_params['html_encoding'] = '7bit'; + if (!in_array($this->build_params['calendar_encoding'], $encodings)) { + $this->build_params['calendar_encoding'] = '7bit'; } // text body - if ($this->_build_params['text_encoding'] == '7bit' - && !preg_match('/ascii/i', $this->_build_params['text_charset']) - && preg_match('/[^\x00-\x7F]/', $this->_txtbody) + if ($this->build_params['text_encoding'] == '7bit' + && !preg_match('/ascii/i', $this->build_params['text_charset']) + && preg_match('/[^\x00-\x7F]/', $this->txtbody) ) { - $this->_build_params['text_encoding'] = 'quoted-printable'; + $this->build_params['text_encoding'] = 'quoted-printable'; } // html body - if ($this->_build_params['html_encoding'] == '7bit' - && !preg_match('/ascii/i', $this->_build_params['html_charset']) - && preg_match('/[^\x00-\x7F]/', $this->_htmlbody) + if ($this->build_params['html_encoding'] == '7bit' + && !preg_match('/ascii/i', $this->build_params['html_charset']) + && preg_match('/[^\x00-\x7F]/', $this->htmlbody) ) { - $this->_build_params['html_encoding'] = 'quoted-printable'; + $this->build_params['html_encoding'] = 'quoted-printable'; + } + // calendar body + if ($this->build_params['calendar_encoding'] == '7bit' + && !preg_match('/ascii/i', $this->build_params['calendar_charset']) + && preg_match('/[^\x00-\x7F]/', $this->calbody) + ) { + $this->build_params['calendar_encoding'] = 'quoted-printable'; } } -} // End of class + /** + * Set body of specified message part + * + * @param string $type One of: txtbody, calbody, htmlbody + * @param string $data Either a string or the file name with the contents + * @param bool $isfile If true the first param should be treated + * as a file name, else as a string (default) + * @param bool $append If true the text or file is appended to + * the existing body, else the old body is + * overwritten + * + * @return mixed True on success or PEAR_Error object + */ + protected function setBody($type, $data, $isfile = false, $append = false) + { + if (!$isfile) { + if (!$append) { + $this->{$type} = $data; + } else { + $this->{$type} .= $data; + } + } else { + $cont = $this->file2str($data); + if (self::isError($cont)) { + return $cont; + } + + if (!$append) { + $this->{$type} = $cont; + } else { + $this->{$type} .= $cont; + } + } + + return true; + } + + /** + * Adds a subpart to the mimePart object and + * returns it during the build process. + * + * @param mixed $obj The object to add the part to, or + * anything else if a new object is to be created. + * @param string $body Part body + * @param string $ctype Part content type + * @param string $type Internal part type + * + * @return object The mimePart object + */ + protected function addBodyPart($obj, $body, $ctype, $type) + { + $params['content_type'] = $ctype; + $params['encoding'] = $this->build_params[$type . '_encoding']; + $params['charset'] = $this->build_params[$type . '_charset']; + $params['eol'] = $this->build_params['eol']; + + if (is_object($obj)) { + $ret = $obj->addSubpart($body, $params); + } else { + $ret = new Mail_mimePart($body, $params); + } + + return $ret; + } + + /** + * PEAR::isError implementation + * + * @param mixed $data Object + * + * @return bool True if object is an instance of PEAR_Error + */ + public static function isError($data) + { + // PEAR::isError() is not PHP 5.4 compatible (see Bug #19473) + if (is_a($data, 'PEAR_Error')) { + return true; + } + + return false; + } + + /** + * PEAR::raiseError implementation + * + * @param string $message A text error message + * + * @return PEAR_Error Instance of PEAR_Error + */ + public static function raiseError($message) + { + // PEAR::raiseError() is not PHP 5.4 compatible + return new PEAR_Error($message); + } +} diff --git a/include/pear/Mail/mimePart.php b/include/pear/Mail/mimePart.php index a839402f7a6648c1ffe6ef61284770190c8933f1..6ac85a2f8b9b9287754e65af2477ee8d4e4ef686 100644 --- a/include/pear/Mail/mimePart.php +++ b/include/pear/Mail/mimePart.php @@ -8,7 +8,7 @@ * of mime mail. * This class however allows full control over the email. * - * Compatible with PHP versions 4 and 5 + * Compatible with PHP version 5 * * LICENSE: This LICENSE is in the BSD license style. * Copyright (c) 2002-2003, Richard Heyes <richard@phpguru.org> @@ -24,8 +24,8 @@ * - Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * - Neither the name of the authors, nor the names of its contributors - * may be used to endorse or promote products derived from this + * - Neither the name of the authors, nor the names of its contributors + * may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" @@ -48,10 +48,16 @@ * @author Aleksander Machniak <alec@php.net> * @copyright 2003-2006 PEAR <pear-group@php.net> * @license http://www.opensource.org/licenses/bsd-license.php BSD License - * @version CVS: $Id$ + * @version Release: @package_version@ * @link http://pear.php.net/package/Mail_mime */ +/** + * require PEAR + * + * This package depends on PEAR to raise errors. + */ +require_once 'PEAR.php'; /** * The Mail_mimePart class is used to create MIME E-mail messages @@ -76,98 +82,97 @@ class Mail_mimePart { /** - * The encoding type of this part - * - * @var string - * @access private - */ - var $_encoding; + * The encoding type of this part + * + * @var string + */ + protected $encoding; /** - * An array of subparts - * - * @var array - * @access private - */ - var $_subparts; + * An array of subparts + * + * @var array + */ + protected $subparts; /** - * The output of this part after being built - * - * @var string - * @access private - */ - var $_encoded; + * The output of this part after being built + * + * @var string + */ + protected $encoded; /** - * Headers for this part - * - * @var array - * @access private - */ - var $_headers; + * Headers for this part + * + * @var array + */ + protected $headers; + + /** + * The body of this part (not encoded) + * + * @var string + */ + protected $body; /** - * The body of this part (not encoded) - * - * @var string - * @access private - */ - var $_body; + * The location of file with body of this part (not encoded) + * + * @var string + */ + protected $body_file; /** - * The location of file with body of this part (not encoded) - * - * @var string - * @access private - */ - var $_body_file; + * The short text of multipart part preamble (RFC2046 5.1.1) + * + * @var string + */ + protected $preamble; /** - * The end-of-line sequence - * - * @var string - * @access private - */ - var $_eol = "\r\n"; + * The end-of-line sequence + * + * @var string + */ + protected $eol = "\r\n"; /** - * Constructor. - * - * Sets up the object. - * - * @param string $body The body of the mime part if any. - * @param array $params An associative array of optional parameters: - * content_type - The content type for this part eg multipart/mixed - * encoding - The encoding to use, 7bit, 8bit, - * base64, or quoted-printable - * charset - Content character set - * cid - Content ID to apply - * disposition - Content disposition, inline or attachment - * filename - Filename parameter for content disposition - * description - Content description - * name_encoding - Encoding of the attachment name (Content-Type) - * By default filenames are encoded using RFC2231 - * Here you can set RFC2047 encoding (quoted-printable - * or base64) instead - * filename_encoding - Encoding of the attachment filename (Content-Disposition) - * See 'name_encoding' - * headers_charset - Charset of the headers e.g. filename, description. - * If not set, 'charset' will be used - * eol - End of line sequence. Default: "\r\n" - * headers - Hash array with additional part headers. Array keys can be - * in form of <header_name>:<parameter_name> - * body_file - Location of file with part's body (instead of $body) - * - * @access public - */ - function Mail_mimePart($body = '', $params = array()) + * Constructor. + * + * Sets up the object. + * + * @param string $body The body of the mime part if any. + * @param array $params An associative array of optional parameters: + * content_type - The content type for this part eg multipart/mixed + * encoding - The encoding to use, 7bit, 8bit, + * base64, or quoted-printable + * charset - Content character set + * cid - Content ID to apply + * disposition - Content disposition, inline or attachment + * filename - Filename parameter for content disposition + * description - Content description + * name_encoding - Encoding of the attachment name (Content-Type) + * By default filenames are encoded using RFC2231 + * Here you can set RFC2047 encoding (quoted-printable + * or base64) instead + * filename_encoding - Encoding of the attachment filename (Content-Disposition) + * See 'name_encoding' + * headers_charset - Charset of the headers e.g. filename, description. + * If not set, 'charset' will be used + * eol - End of line sequence. Default: "\r\n" + * headers - Hash array with additional part headers. Array keys can be + * in form of <header_name>:<parameter_name> + * body_file - Location of file with part's body (instead of $body) + * preamble - short text of multipart part preamble (RFC2046 5.1.1) + */ + public function __construct($body = '', $params = array()) { if (!empty($params['eol'])) { - $this->_eol = $params['eol']; + $this->eol = $params['eol']; } else if (defined('MAIL_MIMEPART_CRLF')) { // backward-copat. - $this->_eol = MAIL_MIMEPART_CRLF; + $this->eol = MAIL_MIMEPART_CRLF; } // Additional part headers @@ -178,7 +183,7 @@ class Mail_mimePart foreach ($params as $key => $value) { switch ($key) { case 'encoding': - $this->_encoding = $value; + $this->encoding = $value; $headers['Content-Transfer-Encoding'] = $value; break; @@ -191,7 +196,11 @@ class Mail_mimePart break; case 'body_file': - $this->_body_file = $value; + $this->body_file = $value; + break; + + case 'preamble': + $this->preamble = $value; break; // for backward compatibility @@ -214,7 +223,7 @@ class Mail_mimePart if ((strlen($headers['Content-Type']) + strlen($charset) + 16) <= 76) { $headers['Content-Type'] .= '; '; } else { - $headers['Content-Type'] .= ';' . $this->_eol . ' '; + $headers['Content-Type'] .= ';' . $this->eol . ' '; } $headers['Content-Type'] .= $charset; @@ -229,10 +238,9 @@ class Mail_mimePart $h_language = !empty($params['language']) ? $params['language'] : null; $h_encoding = !empty($params['name_encoding']) ? $params['name_encoding'] : null; - if (!empty($params['filename'])) { - $headers['Content-Type'] .= ';' . $this->_eol; - $headers['Content-Type'] .= $this->_buildHeaderParam( + $headers['Content-Type'] .= ';' . $this->eol; + $headers['Content-Type'] .= $this->buildHeaderParam( 'name', $params['filename'], $h_charset, $h_language, $h_encoding ); } @@ -241,24 +249,24 @@ class Mail_mimePart if (!empty($params['disposition'])) { $headers['Content-Disposition'] = $params['disposition']; if (!empty($params['filename'])) { - $headers['Content-Disposition'] .= ';' . $this->_eol; - $headers['Content-Disposition'] .= $this->_buildHeaderParam( + $headers['Content-Disposition'] .= ';' . $this->eol; + $headers['Content-Disposition'] .= $this->buildHeaderParam( 'filename', $params['filename'], $h_charset, $h_language, !empty($params['filename_encoding']) ? $params['filename_encoding'] : null ); } // add attachment size - $size = $this->_body_file ? filesize($this->_body_file) : strlen($body); + $size = $this->body_file ? filesize($this->body_file) : strlen($body); if ($size) { - $headers['Content-Disposition'] .= ';' . $this->_eol . ' size=' . $size; + $headers['Content-Disposition'] .= ';' . $this->eol . ' size=' . $size; } } if (!empty($params['description'])) { $headers['Content-Description'] = $this->encodeHeader( 'Content-Description', $params['description'], $h_charset, $h_encoding, - $this->_eol + $this->eol ); } @@ -269,9 +277,9 @@ class Mail_mimePart $header = $items[0]; $param = $items[1]; if (isset($headers[$header])) { - $headers[$header] .= ';' . $this->_eol; + $headers[$header] .= ';' . $this->eol; } - $headers[$header] .= $this->_buildHeaderParam( + $headers[$header] .= $this->buildHeaderParam( $param, $value, $h_charset, $h_language, $h_encoding ); unset($headers[$key]); @@ -279,14 +287,14 @@ class Mail_mimePart } // Default encoding - if (!isset($this->_encoding)) { - $this->_encoding = '7bit'; + if (!isset($this->encoding)) { + $this->encoding = '7bit'; } // Assign stuff to member variables - $this->_encoded = array(); - $this->_headers = $headers; - $this->_body = $body; + $this->encoded = array(); + $this->headers = $headers; + $this->body = $body; } /** @@ -298,24 +306,27 @@ class Mail_mimePart * @return An associative array containing two elements, * body and headers. The headers element is itself * an indexed array. On error returns PEAR error object. - * @access public */ - function encode($boundary=null) + public function encode($boundary=null) { - $encoded =& $this->_encoded; + $encoded =& $this->encoded; - if (count($this->_subparts)) { + if (count($this->subparts)) { $boundary = $boundary ? $boundary : '=_' . md5(rand() . microtime()); - $eol = $this->_eol; + $eol = $this->eol; - $this->_headers['Content-Type'] .= ";$eol boundary=\"$boundary\""; + $this->headers['Content-Type'] .= ";$eol boundary=\"$boundary\""; - $encoded['body'] = ''; + $encoded['body'] = ''; - for ($i = 0; $i < count($this->_subparts); $i++) { + if ($this->preamble) { + $encoded['body'] .= $this->preamble . $eol . $eol; + } + + for ($i = 0; $i < count($this->subparts); $i++) { $encoded['body'] .= '--' . $boundary . $eol; - $tmp = $this->_subparts[$i]->encode(); - if (PEAR::isError($tmp)) { + $tmp = $this->subparts[$i]->encode(); + if (is_a($tmp, 'PEAR_Error')) { return $tmp; } foreach ($tmp['headers'] as $key => $value) { @@ -325,20 +336,19 @@ class Mail_mimePart } $encoded['body'] .= '--' . $boundary . '--' . $eol; - - } else if ($this->_body) { - $encoded['body'] = $this->_getEncodedData($this->_body, $this->_encoding); - } else if ($this->_body_file) { + } else if ($this->body) { + $encoded['body'] = $this->getEncodedData($this->body, $this->encoding); + } else if ($this->body_file) { // Temporarily reset magic_quotes_runtime for file reads and writes if ($magic_quote_setting = get_magic_quotes_runtime()) { @ini_set('magic_quotes_runtime', 0); } - $body = $this->_getEncodedDataFromFile($this->_body_file, $this->_encoding); + $body = $this->getEncodedDataFromFile($this->body_file, $this->encoding); if ($magic_quote_setting) { @ini_set('magic_quotes_runtime', $magic_quote_setting); } - if (PEAR::isError($body)) { + if (is_a($body, 'PEAR_Error')) { return $body; } $encoded['body'] = $body; @@ -347,34 +357,38 @@ class Mail_mimePart } // Add headers to $encoded - $encoded['headers'] =& $this->_headers; + $encoded['headers'] =& $this->headers; return $encoded; } /** - * Encodes and saves the email into file. File must exist. - * Data will be appended to the file. + * Encodes and saves the email into file or stream. + * Data will be appended to the file/stream. * - * @param string $filename Output file location + * @param mixed $filename Existing file location + * or file pointer resource * @param string $boundary Pre-defined boundary string * @param boolean $skip_head True if you don't want to save headers * * @return array An associative array containing message headers * or PEAR error object - * @access public * @since 1.6.0 */ - function encodeToFile($filename, $boundary=null, $skip_head=false) + public function encodeToFile($filename, $boundary = null, $skip_head = false) { - if (file_exists($filename) && !is_writable($filename)) { - $err = PEAR::raiseError('File is not writeable: ' . $filename); - return $err; - } + if (!is_resource($filename)) { + if (file_exists($filename) && !is_writable($filename)) { + $err = self::raiseError('File is not writeable: ' . $filename); + return $err; + } - if (!($fh = fopen($filename, 'ab'))) { - $err = PEAR::raiseError('Unable to open file: ' . $filename); - return $err; + if (!($fh = fopen($filename, 'ab'))) { + $err = self::raiseError('Unable to open file: ' . $filename); + return $err; + } + } else { + $fh = $filename; } // Temporarily reset magic_quotes_runtime for file reads and writes @@ -382,15 +396,17 @@ class Mail_mimePart @ini_set('magic_quotes_runtime', 0); } - $res = $this->_encodePartToFile($fh, $boundary, $skip_head); + $res = $this->encodePartToFile($fh, $boundary, $skip_head); - fclose($fh); + if (!is_resource($filename)) { + fclose($fh); + } if ($magic_quote_setting) { @ini_set('magic_quotes_runtime', $magic_quote_setting); } - return PEAR::isError($res) ? $res : $this->_headers; + return is_a($res, 'PEAR_Error') ? $res : $this->headers; } /** @@ -401,19 +417,18 @@ class Mail_mimePart * @param boolean $skip_head True if you don't want to save headers * * @return array True on sucess or PEAR error object - * @access private */ - function _encodePartToFile($fh, $boundary=null, $skip_head=false) + protected function encodePartToFile($fh, $boundary = null, $skip_head = false) { - $eol = $this->_eol; + $eol = $this->eol; - if (count($this->_subparts)) { + if (count($this->subparts)) { $boundary = $boundary ? $boundary : '=_' . md5(rand() . microtime()); - $this->_headers['Content-Type'] .= ";$eol boundary=\"$boundary\""; + $this->headers['Content-Type'] .= ";$eol boundary=\"$boundary\""; } if (!$skip_head) { - foreach ($this->_headers as $key => $value) { + foreach ($this->headers as $key => $value) { fwrite($fh, $key . ': ' . $value . $eol); } $f_eol = $eol; @@ -421,26 +436,31 @@ class Mail_mimePart $f_eol = ''; } - if (count($this->_subparts)) { - for ($i = 0; $i < count($this->_subparts); $i++) { + if (count($this->subparts)) { + if ($this->preamble) { + fwrite($fh, $f_eol . $this->preamble . $eol); + $f_eol = $eol; + } + + for ($i = 0; $i < count($this->subparts); $i++) { fwrite($fh, $f_eol . '--' . $boundary . $eol); - $res = $this->_subparts[$i]->_encodePartToFile($fh); - if (PEAR::isError($res)) { + $res = $this->subparts[$i]->encodePartToFile($fh); + if (is_a($res, 'PEAR_Error')) { return $res; } $f_eol = $eol; } fwrite($fh, $eol . '--' . $boundary . '--' . $eol); - - } else if ($this->_body) { - fwrite($fh, $f_eol . $this->_getEncodedData($this->_body, $this->_encoding)); - } else if ($this->_body_file) { + } else if ($this->body) { + fwrite($fh, $f_eol); + fwrite($fh, $this->getEncodedData($this->body, $this->encoding)); + } else if ($this->body_file) { fwrite($fh, $f_eol); - $res = $this->_getEncodedDataFromFile( - $this->_body_file, $this->_encoding, $fh + $res = $this->getEncodedDataFromFile( + $this->body_file, $this->encoding, $fh ); - if (PEAR::isError($res)) { + if (is_a($res, 'PEAR_Error')) { return $res; } } @@ -452,20 +472,23 @@ class Mail_mimePart * Adds a subpart to current mime part and returns * a reference to it * - * @param string $body The body of the subpart, if any. - * @param array $params The parameters for the subpart, same - * as the $params argument for constructor. + * @param mixed $body The body of the subpart or Mail_mimePart object + * @param array $params The parameters for the subpart, same + * as the $params argument for constructor * - * @return Mail_mimePart A reference to the part you just added. It is - * crucial if using multipart/* in your subparts that - * you use =& in your script when calling this function, - * otherwise you will not be able to add further subparts. - * @access public + * @return Mail_mimePart A reference to the part you just added. */ - function &addSubpart($body, $params) + public function addSubpart($body, $params = null) { - $this->_subparts[] = new Mail_mimePart($body, $params); - return $this->_subparts[count($this->_subparts) - 1]; + if ($body instanceof Mail_mimePart) { + $part = $body; + } else { + $part = new Mail_mimePart($body, $params); + } + + $this->subparts[] = $part; + + return $part; } /** @@ -475,18 +498,17 @@ class Mail_mimePart * @param string $encoding The encoding type to use, 7bit, base64, * or quoted-printable. * - * @return string - * @access private + * @return string Encoded data string */ - function _getEncodedData($data, $encoding) + protected function getEncodedData($data, $encoding) { switch ($encoding) { case 'quoted-printable': - return $this->_quotedPrintableEncode($data); + return self::quotedPrintableEncode($data, 76, $this->eol); break; case 'base64': - return rtrim(chunk_split(base64_encode($data), 76, $this->_eol)); + return rtrim(chunk_split(base64_encode($data), 76, $this->eol)); break; case '8bit': @@ -506,17 +528,16 @@ class Mail_mimePart * stored into it instead of returning it * * @return string Encoded data or PEAR error object - * @access private */ - function _getEncodedDataFromFile($filename, $encoding, $fh=null) + protected function getEncodedDataFromFile($filename, $encoding, $fh = null) { if (!is_readable($filename)) { - $err = PEAR::raiseError('Unable to read file: ' . $filename); + $err = self::raiseError('Unable to read file: ' . $filename); return $err; } if (!($fd = fopen($filename, 'rb'))) { - $err = PEAR::raiseError('Could not open file: ' . $filename); + $err = self::raiseError('Could not open file: ' . $filename); return $err; } @@ -525,7 +546,7 @@ class Mail_mimePart switch ($encoding) { case 'quoted-printable': while (!feof($fd)) { - $buffer = $this->_quotedPrintableEncode(fgets($fd)); + $buffer = self::quotedPrintableEncode(fgets($fd), 76, $this->eol); if ($fh) { fwrite($fh, $buffer); } else { @@ -541,7 +562,7 @@ class Mail_mimePart // because base64 encoding is memory expensive $buffer = fread($fd, 57 * 9198); // ca. 0.5 MB $buffer = base64_encode($buffer); - $buffer = chunk_split($buffer, 76, $this->_eol); + $buffer = chunk_split($buffer, 76, $this->eol); if (feof($fd)) { $buffer = rtrim($buffer); } @@ -580,14 +601,12 @@ class Mail_mimePart * @param string $input The data to encode * @param int $line_max Optional max line length. Should * not be more than 76 chars + * @param string $eol End-of-line sequence. Default: "\r\n" * * @return string Encoded data - * - * @access private */ - function _quotedPrintableEncode($input , $line_max = 76) + public static function quotedPrintableEncode($input , $line_max = 76, $eol = "\r\n") { - $eol = $this->_eol; /* // imap_8bit() is extremely fast, but doesn't handle properly some characters if (function_exists('imap_8bit') && $line_max == 76) { @@ -648,7 +667,7 @@ class Mail_mimePart } /** - * Encodes the paramater of a header. + * Encodes the parameter of a header. * * @param string $name The name of the header-parameter * @param string $value The value of the paramter @@ -659,11 +678,9 @@ class Mail_mimePart * @param int $maxLength The maximum length of a line. Defauls to 75 * * @return string - * - * @access private */ - function _buildHeaderParam($name, $value, $charset=null, $language=null, - $encoding=null, $maxLength=75 + protected function buildHeaderParam($name, $value, $charset = null, + $language = null, $encoding = null, $maxLength = 75 ) { // RFC 2045: // value needs encoding if contains non-ASCII chars or is longer than 78 chars @@ -686,13 +703,13 @@ class Mail_mimePart // RFC2047: use quoted-printable/base64 encoding if ($encoding == 'quoted-printable' || $encoding == 'base64') { - return $this->_buildRFC2047Param($name, $value, $charset, $encoding); + return $this->buildRFC2047Param($name, $value, $charset, $encoding); } // RFC2231: $encValue = preg_replace_callback( '/([^\x21\x23\x24\x26\x2B\x2D\x2E\x30-\x39\x41-\x5A\x5E-\x7E])/', - array($this, '_encodeReplaceCallback'), $value + array($this, 'encodeReplaceCallback'), $value ); $value = "$charset'$language'$encValue"; @@ -720,7 +737,7 @@ class Mail_mimePart $headCount++; } - $headers = implode(';' . $this->_eol, $headers); + $headers = implode(';' . $this->eol, $headers); return $headers; } @@ -734,10 +751,9 @@ class Mail_mimePart * @param int $maxLength Encoded parameter max length. Default: 76 * * @return string Parameter line - * @access private */ - function _buildRFC2047Param($name, $value, $charset, - $encoding='quoted-printable', $maxLength=76 + protected function buildRFC2047Param($name, $value, $charset, + $encoding = 'quoted-printable', $maxLength = 76 ) { // WARNING: RFC 2047 says: "An 'encoded-word' MUST NOT be used in // parameter of a MIME Content-Type or Content-Disposition field", @@ -759,7 +775,7 @@ class Mail_mimePart $_quote = substr($value, 0, $real_len); $value = substr($value, $real_len); - $quoted .= $prefix . $_quote . $suffix . $this->_eol . ' '; + $quoted .= $prefix . $_quote . $suffix . $this->eol . ' '; $add_len = strlen($prefix . $suffix) + 4; // 2 x SPACE, '"', ';' $len = strlen($value) + $add_len; } @@ -782,7 +798,7 @@ class Mail_mimePart $_quote = $matches[1]; } - $quoted .= $prefix . $_quote . $suffix . $this->_eol . ' '; + $quoted .= $prefix . $_quote . $suffix . $this->eol . ' '; $value = substr($value, strlen($_quote)); $add_len = strlen($prefix . $suffix) + 4; // 2 x SPACE, '"', ';' $len = strlen($value) + $add_len; @@ -803,18 +819,18 @@ class Mail_mimePart * @param string $encoding Encoding name (base64 or quoted-printable) * @param string $eol End-of-line sequence. Default: "\r\n" * - * @return string Encoded header data (without a name) - * @access public + * @return string Encoded header data (without a name) * @since 1.6.1 */ - function encodeHeader($name, $value, $charset='ISO-8859-1', - $encoding='quoted-printable', $eol="\r\n" + public static function encodeHeader($name, $value, $charset = 'ISO-8859-1', + $encoding = 'quoted-printable', $eol = "\r\n" ) { // Structured headers $comma_headers = array( 'from', 'to', 'cc', 'bcc', 'sender', 'reply-to', 'resent-from', 'resent-to', 'resent-cc', 'resent-bcc', 'resent-sender', 'resent-reply-to', + 'mail-reply-to', 'mail-followup-to', 'return-receipt-to', 'disposition-notification-to', ); $other_headers = array( @@ -838,7 +854,7 @@ class Mail_mimePart // Simple e-mail address regexp $email_regexp = '([^\s<]+|("[^\r\n"]+"))@\S+'; - $parts = Mail_mimePart::_explodeQuotedString($separator, $value); + $parts = Mail_mimePart::explodeQuotedString("[\t$separator]", $value); $value = ''; foreach ($parts as $part) { @@ -849,7 +865,7 @@ class Mail_mimePart continue; } if ($value) { - $value .= $separator==',' ? $separator.' ' : ' '; + $value .= $separator == ',' ? $separator . ' ' : ' '; } else { $value = $name . ': '; } @@ -868,7 +884,7 @@ class Mail_mimePart // check if phrase requires quoting if ($word) { // non-ASCII: require encoding - if (preg_match('#([\x80-\xFF]){1}#', $word)) { + if (preg_match('#([^\s\x21-\x7E]){1}#', $word)) { if ($word[0] == '"' && $word[strlen($word)-1] == '"') { // de-quote quoted-string, encoding changes // string to atom @@ -907,11 +923,10 @@ class Mail_mimePart $value = preg_replace( '/^'.$name.':('.preg_quote($eol, '/').')* /', '', $value ); - } else { // Unstructured header // non-ASCII: require encoding - if (preg_match('#([\x80-\xFF]){1}#', $value)) { + if (preg_match('#([^\s\x21-\x7E]){1}#', $value)) { if ($value[0] == '"' && $value[strlen($value)-1] == '"') { // de-quote quoted-string, encoding changes // string to atom @@ -942,10 +957,9 @@ class Mail_mimePart * @param string $delimiter Delimiter expression string for preg_match() * @param string $string Input string * - * @return array String tokens array - * @access private + * @return array String tokens array */ - function _explodeQuotedString($delimiter, $string) + protected static function explodeQuotedString($delimiter, $string) { $result = array(); $strlen = strlen($string); @@ -974,11 +988,10 @@ class Mail_mimePart * @param int $prefix_len Prefix length. Default: 0 * @param string $eol End-of-line sequence. Default: "\r\n" * - * @return string Encoded header data - * @access public + * @return string Encoded header data * @since 1.6.1 */ - function encodeHeaderValue($value, $charset, $encoding, $prefix_len=0, $eol="\r\n") + public static function encodeHeaderValue($value, $charset, $encoding, $prefix_len = 0, $eol = "\r\n") { // #17311: Use multibyte aware method (requires mbstring extension) if ($result = Mail_mimePart::encodeMB($value, $charset, $encoding, $prefix_len, $eol)) { @@ -1012,7 +1025,7 @@ class Mail_mimePart $value = substr($value, $cutpoint); $cutpoint = $maxLength; // RFC 2047 specifies that any split header should - // be seperated by a CRLF SPACE. + // be separated by a CRLF SPACE. if ($output) { $output .= $eol . ' '; } @@ -1054,7 +1067,7 @@ class Mail_mimePart } // RFC 2047 specifies that any split header should - // be seperated by a CRLF SPACE + // be separated by a CRLF SPACE if ($output) { $output .= $eol . ' '; } @@ -1074,11 +1087,10 @@ class Mail_mimePart * * @param string $str String to encode * - * @return string Encoded string - * @access public + * @return string Encoded string * @since 1.6.0 */ - function encodeQP($str) + public static function encodeQP($str) { // Bug #17226 RFC 2047 restricts some characters // if the word is inside a phrase, permitted chars are only: @@ -1087,7 +1099,7 @@ class Mail_mimePart // "=", "_", "?" must be encoded $regexp = '/([\x22-\x29\x2C\x2E\x3A-\x40\x5B-\x60\x7B-\x7E\x80-\xFF])/'; $str = preg_replace_callback( - $regexp, array('Mail_mimePart', '_qpReplaceCallback'), $str + $regexp, array('Mail_mimePart', 'qpReplaceCallback'), $str ); return str_replace(' ', '_', $str); @@ -1104,11 +1116,10 @@ class Mail_mimePart * @param int $prefix_len Prefix length. Default: 0 * @param string $eol End-of-line sequence. Default: "\r\n" * - * @return string Encoded string - * @access public + * @return string Encoded string * @since 1.8.0 */ - function encodeMB($str, $charset, $encoding, $prefix_len=0, $eol="\r\n") + public static function encodeMB($str, $charset, $encoding, $prefix_len=0, $eol="\r\n") { if (!function_exists('mb_substr') || !function_exists('mb_strlen')) { return; @@ -1172,7 +1183,7 @@ class Mail_mimePart $char_len = 1; } else { $char = preg_replace_callback( - $regexp, array('Mail_mimePart', '_qpReplaceCallback'), $char + $regexp, array('Mail_mimePart', 'qpReplaceCallback'), $char ); $char_len = strlen($char); } @@ -1203,10 +1214,9 @@ class Mail_mimePart * * @param array $matches Preg_replace's matches array * - * @return string Encoded character string - * @access private + * @return string Encoded character string */ - function _qpReplaceCallback($matches) + protected static function qpReplaceCallback($matches) { return sprintf('=%02X', ord($matches[1])); } @@ -1217,12 +1227,23 @@ class Mail_mimePart * * @param array $matches Preg_replace's matches array * - * @return string Encoded character string - * @access private + * @return string Encoded character string */ - function _encodeReplaceCallback($matches) + protected static function encodeReplaceCallback($matches) { return sprintf('%%%02X', ord($matches[1])); } -} // End of class + /** + * PEAR::raiseError implementation + * + * @param string $message A text error message + * + * @return PEAR_Error Instance of PEAR_Error + */ + public static function raiseError($message) + { + // PEAR::raiseError() is not PHP 5.4 compatible + return new PEAR_Error($message); + } +} diff --git a/include/pear/Net/SMTP.php b/include/pear/Net/SMTP.php index 8d0682f361d85593954d67895e64c2dcb23bea93..8f4e92b7532a0c51f97219017a246574d3d17d8c 100644 --- a/include/pear/Net/SMTP.php +++ b/include/pear/Net/SMTP.php @@ -1,14 +1,14 @@ <?php -/* vim: set expandtab softtabstop=4 tabstop=4 shiftwidth=4: */ +/** vim: set expandtab softtabstop=4 tabstop=4 shiftwidth=4: */ // +----------------------------------------------------------------------+ -// | PHP Version 4 | +// | PHP Version 5 and 7 | // +----------------------------------------------------------------------+ -// | Copyright (c) 1997-2003 The PHP Group | +// | Copyright (c) 1997-2015 Jon Parise and Chuck Hagenbuch | // +----------------------------------------------------------------------+ -// | This source file is subject to version 2.02 of the PHP license, | +// | This source file is subject to version 3.01 of the PHP license, | // | that is bundled with this package in the file LICENSE, and is | // | available at through the world-wide-web at | -// | http://www.php.net/license/2_02.txt. | +// | http://www.php.net/license/3_01.txt. | // | If you did not receive a copy of the PHP license and are unable to | // | obtain it through the world-wide-web, please send a note to | // | license@php.net so we can mail you a copy immediately. | @@ -17,52 +17,46 @@ // | Jon Parise <jon@php.net> | // | Damian Alejandro Fernandez Sosa <damlists@cnba.uba.ar> | // +----------------------------------------------------------------------+ -// -// $Id: SMTP.php 314875 2011-08-13 17:03:30Z jon $ require_once 'PEAR.php'; require_once 'Net/Socket.php'; /** * Provides an implementation of the SMTP protocol using PEAR's - * Net_Socket:: class. + * Net_Socket class. * * @package Net_SMTP * @author Chuck Hagenbuch <chuck@horde.org> * @author Jon Parise <jon@php.net> * @author Damian Alejandro Fernandez Sosa <damlists@cnba.uba.ar> * - * @example basic.php A basic implementation of the Net_SMTP package. + * @example basic.php A basic implementation of the Net_SMTP package. */ class Net_SMTP { /** * The server to connect to. * @var string - * @access public */ - var $host = 'localhost'; + public $host = 'localhost'; /** * The port to connect to. * @var int - * @access public */ - var $port = 25; + public $port = 25; /** * The value to give when sending EHLO or HELO. * @var string - * @access public */ - var $localhost = 'localhost'; + public $localhost = 'localhost'; /** * List of supported authentication methods, in preferential order. * @var array - * @access public */ - var $auth_methods = array(); + public $auth_methods = array(); /** * Use SMTP command pipelining (specified in RFC 2920) if the SMTP @@ -73,80 +67,69 @@ class Net_SMTP * SMTP server but return immediately. * * @var bool - * @access public */ - var $pipelining = false; + public $pipelining = false; /** * Number of pipelined commands. * @var int - * @access private */ - var $_pipelined_commands = 0; + protected $pipelined_commands = 0; /** * Should debugging output be enabled? * @var boolean - * @access private */ - var $_debug = false; + protected $debug = false; /** * Debug output handler. * @var callback - * @access private */ - var $_debug_handler = null; + protected $debug_handler = null; /** * The socket resource being used to connect to the SMTP server. * @var resource - * @access private */ - var $_socket = null; + protected $socket = null; /** * Array of socket options that will be passed to Net_Socket::connect(). * @see stream_context_create() * @var array - * @access private */ - var $_socket_options = null; + protected $socket_options = null; /** * The socket I/O timeout value in seconds. * @var int - * @access private */ - var $_timeout = 0; + protected $timeout = 0; /** * The most recent server response code. * @var int - * @access private */ - var $_code = -1; + protected $code = -1; /** * The most recent server response arguments. * @var array - * @access private */ - var $_arguments = array(); + protected $arguments = array(); /** * Stores the SMTP server's greeting string. * @var string - * @access private */ - var $_greeting = null; + protected $greeting = null; /** * Stores detected features of the SMTP server. * @var array - * @access private */ - var $_esmtp = array(); + protected $esmtp = array(); /** * Instantiates a new Net_SMTP object, overriding any defaults @@ -159,19 +142,18 @@ class Net_SMTP * $smtp = new Net_SMTP('ssl://mail.host.com', 465); * $smtp->connect(); * - * @param string $host The server to connect to. - * @param integer $port The port to connect to. - * @param string $localhost The value to give when sending EHLO or HELO. - * @param boolean $pipeling Use SMTP command pipelining - * @param integer $timeout Socket I/O timeout in seconds. + * @param string $host The server to connect to. + * @param integer $port The port to connect to. + * @param string $localhost The value to give when sending EHLO or HELO. + * @param boolean $pipelining Use SMTP command pipelining + * @param integer $timeout Socket I/O timeout in seconds. * @param array $socket_options Socket stream_context_create() options. * - * @access public - * @since 1.0 + * @since 1.0 */ - function Net_SMTP($host = null, $port = null, $localhost = null, - $pipelining = false, $timeout = 0, $socket_options = null) - { + public function __construct($host = null, $port = null, $localhost = null, + $pipelining = false, $timeout = 0, $socket_options = null + ) { if (isset($host)) { $this->host = $host; } @@ -181,65 +163,65 @@ class Net_SMTP if (isset($localhost)) { $this->localhost = $localhost; } - $this->pipelining = $pipelining; - $this->_socket = new Net_Socket(); - $this->_socket_options = $socket_options; - $this->_timeout = $timeout; + $this->pipelining = $pipelining; + $this->socket = new Net_Socket(); + $this->socket_options = $socket_options; + $this->timeout = $timeout; /* Include the Auth_SASL package. If the package is available, we * enable the authentication methods that depend upon it. */ if (@include_once 'Auth/SASL.php') { - $this->setAuthMethod('CRAM-MD5', array($this, '_authCram_MD5')); - $this->setAuthMethod('DIGEST-MD5', array($this, '_authDigest_MD5')); + $this->setAuthMethod('CRAM-MD5', array($this, 'authCramMD5')); + $this->setAuthMethod('DIGEST-MD5', array($this, 'authDigestMD5')); } /* These standard authentication methods are always available. */ - $this->setAuthMethod('LOGIN', array($this, '_authLogin'), false); - $this->setAuthMethod('PLAIN', array($this, '_authPlain'), false); + $this->setAuthMethod('LOGIN', array($this, 'authLogin'), false); + $this->setAuthMethod('PLAIN', array($this, 'authPlain'), false); } /** * Set the socket I/O timeout value in seconds plus microseconds. * - * @param integer $seconds Timeout value in seconds. - * @param integer $microseconds Additional value in microseconds. + * @param integer $seconds Timeout value in seconds. + * @param integer $microseconds Additional value in microseconds. * - * @access public - * @since 1.5.0 + * @since 1.5.0 */ - function setTimeout($seconds, $microseconds = 0) { - return $this->_socket->setTimeout($seconds, $microseconds); + public function setTimeout($seconds, $microseconds = 0) + { + return $this->socket->setTimeout($seconds, $microseconds); } /** * Set the value of the debugging flag. * - * @param boolean $debug New value for the debugging flag. + * @param boolean $debug New value for the debugging flag. + * @param callback $handler Debug handler callback * - * @access public - * @since 1.1.0 + * @since 1.1.0 */ - function setDebug($debug, $handler = null) + public function setDebug($debug, $handler = null) { - $this->_debug = $debug; - $this->_debug_handler = $handler; + $this->debug = $debug; + $this->debug_handler = $handler; } /** * Write the given debug text to the current debug output handler. * - * @param string $message Debug mesage text. + * @param string $message Debug mesage text. * - * @access private - * @since 1.3.3 + * @since 1.3.3 */ - function _debug($message) + protected function debug($message) { - if ($this->_debug) { - if ($this->_debug_handler) { - call_user_func_array($this->_debug_handler, - array(&$this, $message)); + if ($this->debug) { + if ($this->debug_handler) { + call_user_func_array( + $this->debug_handler, array(&$this, $message) + ); } else { echo "DEBUG: $message\n"; } @@ -249,23 +231,21 @@ class Net_SMTP /** * Send the given string of data to the server. * - * @param string $data The string of data to send. + * @param string $data The string of data to send. * - * @return mixed The number of bytes that were actually written, - * or a PEAR_Error object on failure. + * @return mixed The number of bytes that were actually written, + * or a PEAR_Error object on failure. * - * @access private - * @since 1.1.0 + * @since 1.1.0 */ - function _send($data) + protected function send($data) { - $this->_debug("Send: $data"); + $this->debug("Send: $data"); - $result = $this->_socket->write($data); + $result = $this->socket->write($data); if (!$result || PEAR::isError($result)) { - $msg = ($result) ? $result->getMessage() : "unknown error"; - return PEAR::raiseError("Failed to write to socket: $msg", - null, PEAR_ERROR_RETURN); + $msg = $result ? $result->getMessage() : "unknown error"; + return PEAR::raiseError("Failed to write to socket: $msg"); } return $result; @@ -276,81 +256,77 @@ class Net_SMTP * arguments. A carriage return / linefeed (CRLF) sequence will * be appended to each command string before it is sent to the * SMTP server - an error will be thrown if the command string - * already contains any newline characters. Use _send() for + * already contains any newline characters. Use send() for * commands that must contain newlines. * - * @param string $command The SMTP command to send to the server. - * @param string $args A string of optional arguments to append - * to the command. + * @param string $command The SMTP command to send to the server. + * @param string $args A string of optional arguments to append + * to the command. * - * @return mixed The result of the _send() call. + * @return mixed The result of the send() call. * - * @access private - * @since 1.1.0 + * @since 1.1.0 */ - function _put($command, $args = '') + protected function put($command, $args = '') { if (!empty($args)) { $command .= ' ' . $args; } if (strcspn($command, "\r\n") !== strlen($command)) { - return PEAR::raiseError('Commands cannot contain newlines', - null, PEAR_ERROR_RETURN); + return PEAR::raiseError('Commands cannot contain newlines'); } - return $this->_send($command . "\r\n"); + return $this->send($command . "\r\n"); } /** * Read a reply from the SMTP server. The reply consists of a response * code and a response message. * - * @param mixed $valid The set of valid response codes. These - * may be specified as an array of integer - * values or as a single integer value. - * @param bool $later Do not parse the response now, but wait - * until the last command in the pipelined - * command group + * @param mixed $valid The set of valid response codes. These + * may be specified as an array of integer + * values or as a single integer value. + * @param bool $later Do not parse the response now, but wait + * until the last command in the pipelined + * command group * - * @return mixed True if the server returned a valid response code or - * a PEAR_Error object is an error condition is reached. + * @return mixed True if the server returned a valid response code or + * a PEAR_Error object is an error condition is reached. * - * @access private - * @since 1.1.0 + * @since 1.1.0 * - * @see getResponse + * @see getResponse */ - function _parseResponse($valid, $later = false) + protected function parseResponse($valid, $later = false) { - $this->_code = -1; - $this->_arguments = array(); + $this->code = -1; + $this->arguments = array(); if ($later) { - $this->_pipelined_commands++; + $this->pipelined_commands++; return true; } - for ($i = 0; $i <= $this->_pipelined_commands; $i++) { - while ($line = $this->_socket->readLine()) { - $this->_debug("Recv: $line"); + for ($i = 0; $i <= $this->pipelined_commands; $i++) { + while ($line = $this->socket->readLine()) { + $this->debug("Recv: $line"); /* If we receive an empty line, the connection was closed. */ if (empty($line)) { $this->disconnect(); - return PEAR::raiseError('Connection was closed', - null, PEAR_ERROR_RETURN); + return PEAR::raiseError('Connection was closed'); } /* Read the code and store the rest in the arguments array. */ $code = substr($line, 0, 3); - $this->_arguments[] = trim(substr($line, 4)); + $this->arguments[] = trim(substr($line, 4)); /* Check the syntax of the response code. */ if (is_numeric($code)) { - $this->_code = (int)$code; + $this->code = (int)$code; } else { - $this->_code = -1; + $this->code = -1; break; } @@ -361,38 +337,36 @@ class Net_SMTP } } - $this->_pipelined_commands = 0; + $this->pipelined_commands = 0; /* Compare the server's response code with the valid code/codes. */ - if (is_int($valid) && ($this->_code === $valid)) { + if (is_int($valid) && ($this->code === $valid)) { return true; - } elseif (is_array($valid) && in_array($this->_code, $valid, true)) { + } elseif (is_array($valid) && in_array($this->code, $valid, true)) { return true; } - return PEAR::raiseError('Invalid response code received from server', - $this->_code, PEAR_ERROR_RETURN); + return PEAR::raiseError('Invalid response code received from server', $this->code); } /** * Issue an SMTP command and verify its response. * - * @param string $command The SMTP command string or data. - * @param mixed $valid The set of valid response codes. These - * may be specified as an array of integer - * values or as a single integer value. + * @param string $command The SMTP command string or data. + * @param mixed $valid The set of valid response codes. These + * may be specified as an array of integer + * values or as a single integer value. * - * @return mixed True on success or a PEAR_Error object on failure. + * @return mixed True on success or a PEAR_Error object on failure. * - * @access public - * @since 1.6.0 + * @since 1.6.0 */ - function command($command, $valid) + public function command($command, $valid) { - if (PEAR::isError($error = $this->_put($command))) { + if (PEAR::isError($error = $this->put($command))) { return $error; } - if (PEAR::isError($error = $this->_parseResponse($valid))) { + if (PEAR::isError($error = $this->parseResponse($valid))) { return $error; } @@ -402,76 +376,76 @@ class Net_SMTP /** * Return a 2-tuple containing the last response from the SMTP server. * - * @return array A two-element array: the first element contains the - * response code as an integer and the second element - * contains the response's arguments as a string. + * @return array A two-element array: the first element contains the + * response code as an integer and the second element + * contains the response's arguments as a string. * - * @access public - * @since 1.1.0 + * @since 1.1.0 */ - function getResponse() + public function getResponse() { - return array($this->_code, join("\n", $this->_arguments)); + return array($this->code, join("\n", $this->arguments)); } /** * Return the SMTP server's greeting string. * - * @return string A string containing the greeting string, or null if a - * greeting has not been received. + * @return string A string containing the greeting string, or null if + * a greeting has not been received. * - * @access public - * @since 1.3.3 + * @since 1.3.3 */ - function getGreeting() + public function getGreeting() { - return $this->_greeting; + return $this->greeting; } /** * Attempt to connect to the SMTP server. * - * @param int $timeout The timeout value (in seconds) for the - * socket connection attempt. - * @param bool $persistent Should a persistent socket connection - * be used? + * @param int $timeout The timeout value (in seconds) for the + * socket connection attempt. + * @param bool $persistent Should a persistent socket connection + * be used? * * @return mixed Returns a PEAR_Error with an error message on any * kind of failure, or true on success. - * @access public - * @since 1.0 + * @since 1.0 */ - function connect($timeout = null, $persistent = false) + public function connect($timeout = null, $persistent = false) { - $this->_greeting = null; - $result = $this->_socket->connect($this->host, $this->port, - $persistent, $timeout, - $this->_socket_options); + $this->greeting = null; + + $result = $this->socket->connect( + $this->host, $this->port, $persistent, $timeout, $this->socket_options + ); + if (PEAR::isError($result)) { - return PEAR::raiseError('Failed to connect socket: ' . - $result->getMessage()); + return PEAR::raiseError( + 'Failed to connect socket: ' . $result->getMessage() + ); } /* - * Now that we're connected, reset the socket's timeout value for - * future I/O operations. This allows us to have different socket - * timeout values for the initial connection (our $timeout parameter) + * Now that we're connected, reset the socket's timeout value for + * future I/O operations. This allows us to have different socket + * timeout values for the initial connection (our $timeout parameter) * and all other socket operations. */ - if ($this->_timeout > 0) { - if (PEAR::isError($error = $this->setTimeout($this->_timeout))) { + if ($this->timeout > 0) { + if (PEAR::isError($error = $this->setTimeout($this->timeout))) { return $error; } } - if (PEAR::isError($error = $this->_parseResponse(220))) { + if (PEAR::isError($error = $this->parseResponse(220))) { return $error; } /* Extract and store a copy of the server's greeting string. */ - list(, $this->_greeting) = $this->getResponse(); + list(, $this->greeting) = $this->getResponse(); - if (PEAR::isError($error = $this->_negotiate())) { + if (PEAR::isError($error = $this->negotiate())) { return $error; } @@ -483,20 +457,20 @@ class Net_SMTP * * @return mixed Returns a PEAR_Error with an error message on any * kind of failure, or true on success. - * @access public - * @since 1.0 + * @since 1.0 */ - function disconnect() + public function disconnect() { - if (PEAR::isError($error = $this->_put('QUIT'))) { + if (PEAR::isError($error = $this->put('QUIT'))) { return $error; } - if (PEAR::isError($error = $this->_parseResponse(221))) { + if (PEAR::isError($error = $this->parseResponse(221))) { return $error; } - if (PEAR::isError($error = $this->_socket->disconnect())) { - return PEAR::raiseError('Failed to disconnect socket: ' . - $error->getMessage()); + if (PEAR::isError($error = $this->socket->disconnect())) { + return PEAR::raiseError( + 'Failed to disconnect socket: ' . $error->getMessage() + ); } return true; @@ -509,41 +483,34 @@ class Net_SMTP * @return mixed Returns a PEAR_Error with an error message on any * kind of failure, or true on success. * - * @access private - * @since 1.1.0 + * @since 1.1.0 */ - function _negotiate() + protected function negotiate() { - if (PEAR::isError($error = $this->_put('EHLO', $this->localhost))) { + if (PEAR::isError($error = $this->put('EHLO', $this->localhost))) { return $error; } - if (PEAR::isError($this->_parseResponse(250))) { - /* If we receive a 503 response, we're already authenticated. */ - if ($this->_code === 503) { - return true; - } - + if (PEAR::isError($this->parseResponse(250))) { /* If the EHLO failed, try the simpler HELO command. */ - if (PEAR::isError($error = $this->_put('HELO', $this->localhost))) { + if (PEAR::isError($error = $this->put('HELO', $this->localhost))) { return $error; } - if (PEAR::isError($this->_parseResponse(250))) { - return PEAR::raiseError('HELO was not accepted: ', $this->_code, - PEAR_ERROR_RETURN); + if (PEAR::isError($this->parseResponse(250))) { + return PEAR::raiseError('HELO was not accepted', $this->code); } return true; } - foreach ($this->_arguments as $argument) { - $verb = strtok($argument, ' '); - $arguments = substr($argument, strlen($verb) + 1, - strlen($argument) - strlen($verb) - 1); - $this->_esmtp[$verb] = $arguments; + foreach ($this->arguments as $argument) { + $verb = strtok($argument, ' '); + $len = strlen($verb); + $arguments = substr($argument, $len + 1, strlen($argument) - $len - 1); + $this->esmtp[$verb] = $arguments; } - if (!isset($this->_esmtp['PIPELINING'])) { + if (!isset($this->esmtp['PIPELINING'])) { $this->pipelining = false; } @@ -554,15 +521,14 @@ class Net_SMTP * Returns the name of the best authentication method that the server * has advertised. * - * @return mixed Returns a string containing the name of the best - * supported authentication method or a PEAR_Error object - * if a failure condition is encountered. - * @access private - * @since 1.1.0 + * @return mixed Returns a string containing the name of the best + * supported authentication method or a PEAR_Error object + * if a failure condition is encountered. + * @since 1.1.0 */ - function _getBestAuthMethod() + protected function getBestAuthMethod() { - $available_methods = explode(' ', $this->_esmtp['AUTH']); + $available_methods = explode(' ', $this->esmtp['AUTH']); foreach ($this->auth_methods as $method => $callback) { if (in_array($method, $available_methods)) { @@ -570,44 +536,53 @@ class Net_SMTP } } - return PEAR::raiseError('No supported authentication methods', - null, PEAR_ERROR_RETURN); + return PEAR::raiseError('No supported authentication methods'); } /** * Attempt to do SMTP authentication. * - * @param string The userid to authenticate as. - * @param string The password to authenticate with. - * @param string The requested authentication method. If none is - * specified, the best supported method will be used. - * @param bool Flag indicating whether or not TLS should be attempted. - * @param string An optional authorization identifier. If specified, this - * identifier will be used as the authorization proxy. + * @param string $uid The userid to authenticate as. + * @param string $pwd The password to authenticate with. + * @param string $method The requested authentication method. If none is + * specified, the best supported method will be used. + * @param bool $tls Flag indicating whether or not TLS should be attempted. + * @param string $authz An optional authorization identifier. If specified, this + * identifier will be used as the authorization proxy. * * @return mixed Returns a PEAR_Error with an error message on any * kind of failure, or true on success. - * @access public - * @since 1.0 + * @since 1.0 */ - function auth($uid, $pwd , $method = '', $tls = true, $authz = '') + public function auth($uid, $pwd , $method = '', $tls = true, $authz = '') { /* We can only attempt a TLS connection if one has been requested, - * we're running PHP 5.1.0 or later, have access to the OpenSSL - * extension, are connected to an SMTP server which supports the - * STARTTLS extension, and aren't already connected over a secure + * we're running PHP 5.1.0 or later, have access to the OpenSSL + * extension, are connected to an SMTP server which supports the + * STARTTLS extension, and aren't already connected over a secure * (SSL) socket connection. */ - if ($tls && version_compare(PHP_VERSION, '5.1.0', '>=') && - extension_loaded('openssl') && isset($this->_esmtp['STARTTLS']) && - strncasecmp($this->host, 'ssl://', 6) !== 0) { + if ($tls && version_compare(PHP_VERSION, '5.1.0', '>=') + && extension_loaded('openssl') && isset($this->esmtp['STARTTLS']) + && strncasecmp($this->host, 'ssl://', 6) !== 0 + ) { /* Start the TLS connection attempt. */ - if (PEAR::isError($result = $this->_put('STARTTLS'))) { + if (PEAR::isError($result = $this->put('STARTTLS'))) { return $result; } - if (PEAR::isError($result = $this->_parseResponse(220))) { + if (PEAR::isError($result = $this->parseResponse(220))) { return $result; } - if (PEAR::isError($result = $this->_socket->enableCrypto(true, STREAM_CRYPTO_METHOD_TLS_CLIENT))) { + if (isset($this->socket_options['ssl']['crypto_method'])) { + $crypto_method = $this->socket_options['ssl']['crypto_method']; + } else { + /* STREAM_CRYPTO_METHOD_TLS_ANY_CLIENT constant does not exist + * and STREAM_CRYPTO_METHOD_SSLv23_CLIENT constant is + * inconsistent across PHP versions. */ + $crypto_method = STREAM_CRYPTO_METHOD_TLS_CLIENT + | @STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT + | @STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT; + } + if (PEAR::isError($result = $this->socket->enableCrypto(true, $crypto_method))) { return $result; } elseif ($result !== true) { return PEAR::raiseError('STARTTLS failed'); @@ -615,17 +590,17 @@ class Net_SMTP /* Send EHLO again to recieve the AUTH string from the * SMTP server. */ - $this->_negotiate(); + $this->negotiate(); } - if (empty($this->_esmtp['AUTH'])) { + if (empty($this->esmtp['AUTH'])) { return PEAR::raiseError('SMTP server does not support authentication'); } /* If no method has been specified, get the name of the best * supported method advertised by the SMTP server. */ if (empty($method)) { - if (PEAR::isError($method = $this->_getBestAuthMethod())) { + if (PEAR::isError($method = $this->getBestAuthMethod())) { /* Return the PEAR_Error object from _getBestAuthMethod(). */ return $method; } @@ -648,9 +623,9 @@ class Net_SMTP list($object, $method) = $this->auth_methods[$method]; $result = $object->{$method}($uid, $pwd, $authz, $this); } else { - $func = $this->auth_methods[$method]; + $func = $this->auth_methods[$method]; $result = $func($uid, $pwd, $authz, $this); - } + } /* If an error was encountered, return the PEAR_Error object. */ if (PEAR::isError($result)) { @@ -663,19 +638,18 @@ class Net_SMTP /** * Add a new authentication method. * - * @param string The authentication method name (e.g. 'PLAIN') - * @param mixed The authentication callback (given as the name of a - * function or as an (object, method name) array). - * @param bool Should the new method be prepended to the list of - * available methods? This is the default behavior, - * giving the new method the highest priority. + * @param string $name The authentication method name (e.g. 'PLAIN') + * @param mixed $callback The authentication callback (given as the name of a + * function or as an (object, method name) array). + * @param bool $prepend Should the new method be prepended to the list of + * available methods? This is the default behavior, + * giving the new method the highest priority. * - * @return mixed True on success or a PEAR_Error object on failure. + * @return mixed True on success or a PEAR_Error object on failure. * - * @access public - * @since 1.6.0 + * @since 1.6.0 */ - function setAuthMethod($name, $callback, $prepend = true) + public function setAuthMethod($name, $callback, $prepend = true) { if (!is_string($name)) { return PEAR::raiseError('Method name is not a string'); @@ -686,13 +660,15 @@ class Net_SMTP } if (is_array($callback)) { - if (!is_object($callback[0]) || !is_string($callback[1])) + if (!is_object($callback[0]) || !is_string($callback[1])) { return PEAR::raiseError('Bad mMethod callback array'); + } } if ($prepend) { - $this->auth_methods = array_merge(array($name => $callback), - $this->auth_methods); + $this->auth_methods = array_merge( + array($name => $callback), $this->auth_methods + ); } else { $this->auth_methods[$name] = $callback; } @@ -703,51 +679,50 @@ class Net_SMTP /** * Authenticates the user using the DIGEST-MD5 method. * - * @param string The userid to authenticate as. - * @param string The password to authenticate with. - * @param string The optional authorization proxy identifier. + * @param string $uid The userid to authenticate as. + * @param string $pwd The password to authenticate with. + * @param string $authz The optional authorization proxy identifier. * * @return mixed Returns a PEAR_Error with an error message on any * kind of failure, or true on success. - * @access private - * @since 1.1.0 + * @since 1.1.0 */ - function _authDigest_MD5($uid, $pwd, $authz = '') + protected function authDigestMD5($uid, $pwd, $authz = '') { - if (PEAR::isError($error = $this->_put('AUTH', 'DIGEST-MD5'))) { + if (PEAR::isError($error = $this->put('AUTH', 'DIGEST-MD5'))) { return $error; } /* 334: Continue authentication request */ - if (PEAR::isError($error = $this->_parseResponse(334))) { + if (PEAR::isError($error = $this->parseResponse(334))) { /* 503: Error: already authenticated */ - if ($this->_code === 503) { + if ($this->code === 503) { return true; } return $error; } - $challenge = base64_decode($this->_arguments[0]); - $digest = &Auth_SASL::factory('digestmd5'); - $auth_str = base64_encode($digest->getResponse($uid, $pwd, $challenge, - $this->host, "smtp", - $authz)); + $digest = Auth_SASL::factory('digest-md5'); + $challenge = base64_decode($this->arguments[0]); + $auth_str = base64_encode( + $digest->getResponse($uid, $pwd, $challenge, $this->host, "smtp", $authz) + ); - if (PEAR::isError($error = $this->_put($auth_str))) { + if (PEAR::isError($error = $this->put($auth_str))) { return $error; } /* 334: Continue authentication request */ - if (PEAR::isError($error = $this->_parseResponse(334))) { + if (PEAR::isError($error = $this->parseResponse(334))) { return $error; } /* We don't use the protocol's third step because SMTP doesn't * allow subsequent authentication, so we just silently ignore * it. */ - if (PEAR::isError($error = $this->_put(''))) { + if (PEAR::isError($error = $this->put(''))) { return $error; } /* 235: Authentication successful */ - if (PEAR::isError($error = $this->_parseResponse(235))) { + if (PEAR::isError($error = $this->parseResponse(235))) { return $error; } } @@ -755,39 +730,38 @@ class Net_SMTP /** * Authenticates the user using the CRAM-MD5 method. * - * @param string The userid to authenticate as. - * @param string The password to authenticate with. - * @param string The optional authorization proxy identifier. + * @param string $uid The userid to authenticate as. + * @param string $pwd The password to authenticate with. + * @param string $authz The optional authorization proxy identifier. * * @return mixed Returns a PEAR_Error with an error message on any * kind of failure, or true on success. - * @access private - * @since 1.1.0 + * @since 1.1.0 */ - function _authCRAM_MD5($uid, $pwd, $authz = '') + protected function authCRAMMD5($uid, $pwd, $authz = '') { - if (PEAR::isError($error = $this->_put('AUTH', 'CRAM-MD5'))) { + if (PEAR::isError($error = $this->put('AUTH', 'CRAM-MD5'))) { return $error; } /* 334: Continue authentication request */ - if (PEAR::isError($error = $this->_parseResponse(334))) { + if (PEAR::isError($error = $this->parseResponse(334))) { /* 503: Error: already authenticated */ - if ($this->_code === 503) { + if ($this->code === 503) { return true; } return $error; } - $challenge = base64_decode($this->_arguments[0]); - $cram = &Auth_SASL::factory('crammd5'); - $auth_str = base64_encode($cram->getResponse($uid, $pwd, $challenge)); + $challenge = base64_decode($this->arguments[0]); + $cram = Auth_SASL::factory('cram-md5'); + $auth_str = base64_encode($cram->getResponse($uid, $pwd, $challenge)); - if (PEAR::isError($error = $this->_put($auth_str))) { + if (PEAR::isError($error = $this->put($auth_str))) { return $error; } /* 235: Authentication successful */ - if (PEAR::isError($error = $this->_parseResponse(235))) { + if (PEAR::isError($error = $this->parseResponse(235))) { return $error; } } @@ -795,43 +769,42 @@ class Net_SMTP /** * Authenticates the user using the LOGIN method. * - * @param string The userid to authenticate as. - * @param string The password to authenticate with. - * @param string The optional authorization proxy identifier. + * @param string $uid The userid to authenticate as. + * @param string $pwd The password to authenticate with. + * @param string $authz The optional authorization proxy identifier. * * @return mixed Returns a PEAR_Error with an error message on any * kind of failure, or true on success. - * @access private - * @since 1.1.0 + * @since 1.1.0 */ - function _authLogin($uid, $pwd, $authz = '') + protected function authLogin($uid, $pwd, $authz = '') { - if (PEAR::isError($error = $this->_put('AUTH', 'LOGIN'))) { + if (PEAR::isError($error = $this->put('AUTH', 'LOGIN'))) { return $error; } /* 334: Continue authentication request */ - if (PEAR::isError($error = $this->_parseResponse(334))) { + if (PEAR::isError($error = $this->parseResponse(334))) { /* 503: Error: already authenticated */ - if ($this->_code === 503) { + if ($this->code === 503) { return true; } return $error; } - if (PEAR::isError($error = $this->_put(base64_encode($uid)))) { + if (PEAR::isError($error = $this->put(base64_encode($uid)))) { return $error; } /* 334: Continue authentication request */ - if (PEAR::isError($error = $this->_parseResponse(334))) { + if (PEAR::isError($error = $this->parseResponse(334))) { return $error; } - if (PEAR::isError($error = $this->_put(base64_encode($pwd)))) { + if (PEAR::isError($error = $this->put(base64_encode($pwd)))) { return $error; } /* 235: Authentication successful */ - if (PEAR::isError($error = $this->_parseResponse(235))) { + if (PEAR::isError($error = $this->parseResponse(235))) { return $error; } @@ -841,24 +814,23 @@ class Net_SMTP /** * Authenticates the user using the PLAIN method. * - * @param string The userid to authenticate as. - * @param string The password to authenticate with. - * @param string The optional authorization proxy identifier. + * @param string $uid The userid to authenticate as. + * @param string $pwd The password to authenticate with. + * @param string $authz The optional authorization proxy identifier. * * @return mixed Returns a PEAR_Error with an error message on any * kind of failure, or true on success. - * @access private - * @since 1.1.0 + * @since 1.1.0 */ - function _authPlain($uid, $pwd, $authz = '') + protected function authPlain($uid, $pwd, $authz = '') { - if (PEAR::isError($error = $this->_put('AUTH', 'PLAIN'))) { + if (PEAR::isError($error = $this->put('AUTH', 'PLAIN'))) { return $error; } /* 334: Continue authentication request */ - if (PEAR::isError($error = $this->_parseResponse(334))) { + if (PEAR::isError($error = $this->parseResponse(334))) { /* 503: Error: already authenticated */ - if ($this->_code === 503) { + if ($this->code === 503) { return true; } return $error; @@ -866,12 +838,12 @@ class Net_SMTP $auth_str = base64_encode($authz . chr(0) . $uid . chr(0) . $pwd); - if (PEAR::isError($error = $this->_put($auth_str))) { + if (PEAR::isError($error = $this->put($auth_str))) { return $error; } /* 235: Authentication successful */ - if (PEAR::isError($error = $this->_parseResponse(235))) { + if (PEAR::isError($error = $this->parseResponse(235))) { return $error; } @@ -881,19 +853,18 @@ class Net_SMTP /** * Send the HELO command. * - * @param string The domain name to say we are. + * @param string $domain The domain name to say we are. * * @return mixed Returns a PEAR_Error with an error message on any * kind of failure, or true on success. - * @access public - * @since 1.0 + * @since 1.0 */ - function helo($domain) + public function helo($domain) { - if (PEAR::isError($error = $this->_put('HELO', $domain))) { + if (PEAR::isError($error = $this->put('HELO', $domain))) { return $error; } - if (PEAR::isError($error = $this->_parseResponse(250))) { + if (PEAR::isError($error = $this->parseResponse(250))) { return $error; } @@ -904,44 +875,39 @@ class Net_SMTP * Return the list of SMTP service extensions advertised by the server. * * @return array The list of SMTP service extensions. - * @access public * @since 1.3 */ - function getServiceExtensions() + public function getServiceExtensions() { - return $this->_esmtp; + return $this->esmtp; } /** * Send the MAIL FROM: command. * - * @param string $sender The sender (reverse path) to set. - * @param string $params String containing additional MAIL parameters, - * such as the NOTIFY flags defined by RFC 1891 - * or the VERP protocol. + * @param string $sender The sender (reverse path) to set. + * @param string $params String containing additional MAIL parameters, + * such as the NOTIFY flags defined by RFC 1891 + * or the VERP protocol. * - * If $params is an array, only the 'verp' option - * is supported. If 'verp' is true, the XVERP - * parameter is appended to the MAIL command. If - * the 'verp' value is a string, the full - * XVERP=value parameter is appended. + * If $params is an array, only the 'verp' option + * is supported. If 'verp' is true, the XVERP + * parameter is appended to the MAIL command. + * If the 'verp' value is a string, the full + * XVERP=value parameter is appended. * * @return mixed Returns a PEAR_Error with an error message on any * kind of failure, or true on success. - * @access public - * @since 1.0 + * @since 1.0 */ - function mailFrom($sender, $params = null) + public function mailFrom($sender, $params = null) { $args = "FROM:<$sender>"; /* Support the deprecated array form of $params. */ if (is_array($params) && isset($params['verp'])) { - /* XVERP */ if ($params['verp'] === true) { $args .= ' XVERP'; - - /* XVERP=something */ } elseif (trim($params['verp'])) { $args .= ' XVERP=' . $params['verp']; } @@ -949,10 +915,10 @@ class Net_SMTP $args .= ' ' . $params; } - if (PEAR::isError($error = $this->_put('MAIL', $args))) { + if (PEAR::isError($error = $this->put('MAIL', $args))) { return $error; } - if (PEAR::isError($error = $this->_parseResponse(250, $this->pipelining))) { + if (PEAR::isError($error = $this->parseResponse(250, $this->pipelining))) { return $error; } @@ -969,20 +935,19 @@ class Net_SMTP * @return mixed Returns a PEAR_Error with an error message on any * kind of failure, or true on success. * - * @access public - * @since 1.0 + * @since 1.0 */ - function rcptTo($recipient, $params = null) + public function rcptTo($recipient, $params = null) { $args = "TO:<$recipient>"; if (is_string($params)) { $args .= ' ' . $params; } - if (PEAR::isError($error = $this->_put('RCPT', $args))) { + if (PEAR::isError($error = $this->put('RCPT', $args))) { return $error; } - if (PEAR::isError($error = $this->_parseResponse(array(250, 251), $this->pipelining))) { + if (PEAR::isError($error = $this->parseResponse(array(250, 251), $this->pipelining))) { return $error; } @@ -996,38 +961,34 @@ class Net_SMTP * easier overloading for the cases where it is desirable to * customize the quoting behavior. * - * @param string $data The message text to quote. The string must be passed + * @param string &$data The message text to quote. The string must be passed * by reference, and the text will be modified in place. * - * @access public - * @since 1.2 + * @since 1.2 */ - function quotedata(&$data) + public function quotedata(&$data) { - /* Change Unix (\n) and Mac (\r) linefeeds into - * Internet-standard CRLF (\r\n) linefeeds. */ - $data = preg_replace(array('/(?<!\r)\n/','/\r(?!\n)/'), "\r\n", $data); - /* Because a single leading period (.) signifies an end to the - * data, legitimate leading periods need to be "doubled" - * (e.g. '..'). */ - $data = str_replace("\n.", "\n..", $data); + * data, legitimate leading periods need to be "doubled" ('..'). */ + $data = preg_replace('/^\./m', '..', $data); + + /* Change Unix (\n) and Mac (\r) linefeeds into CRLF's (\r\n). */ + $data = preg_replace('/(?:\r\n|\n|\r(?!\n))/', "\r\n", $data); } /** * Send the DATA command. * - * @param mixed $data The message data, either as a string or an open + * @param mixed $data The message data, either as a string or an open * file resource. * @param string $headers The message headers. If $headers is provided, * $data is assumed to contain only body data. * * @return mixed Returns a PEAR_Error with an error message on any * kind of failure, or true on success. - * @access public - * @since 1.0 + * @since 1.0 */ - function data($data, $headers = null) + public function data($data, $headers = null) { /* Verify that $data is a supported type. */ if (!is_string($data) && !is_resource($data)) { @@ -1053,24 +1014,24 @@ class Net_SMTP * that no fixed maximum message size is in force". Furthermore, it * says that if "the parameter is omitted no information is conveyed * about the server's fixed maximum message size". */ - $limit = (isset($this->_esmtp['SIZE'])) ? $this->_esmtp['SIZE'] : 0; + $limit = (isset($this->esmtp['SIZE'])) ? $this->esmtp['SIZE'] : 0; if ($limit > 0 && $size >= $limit) { $this->disconnect(); return PEAR::raiseError('Message size exceeds server limit'); } /* Initiate the DATA command. */ - if (PEAR::isError($error = $this->_put('DATA'))) { + if (PEAR::isError($error = $this->put('DATA'))) { return $error; } - if (PEAR::isError($error = $this->_parseResponse(354))) { + if (PEAR::isError($error = $this->parseResponse(354))) { return $error; } /* If we have a separate headers string, send it first. */ if (!is_null($headers)) { $this->quotedata($headers); - if (PEAR::isError($result = $this->_send($headers . "\r\n\r\n"))) { + if (PEAR::isError($result = $this->send($headers . "\r\n\r\n"))) { return $result; } } @@ -1091,10 +1052,12 @@ class Net_SMTP } } $this->quotedata($line); - if (PEAR::isError($result = $this->_send($line))) { + if (PEAR::isError($result = $this->send($line))) { return $result; } } + + $last = $line; } else { /* * Break up the data by sending one chunk (up to 512k) at a time. @@ -1123,22 +1086,27 @@ class Net_SMTP $this->quotedata($chunk); /* If we run into a problem along the way, abort. */ - if (PEAR::isError($result = $this->_send($chunk))) { + if (PEAR::isError($result = $this->send($chunk))) { return $result; } /* Advance the offset to the end of this chunk. */ $offset = $end; } + + $last = $chunk; } + /* Don't add another CRLF sequence if it's already in the data */ + $terminator = (substr($last, -2) == "\r\n" ? '' : "\r\n") . ".\r\n"; + /* Finally, send the DATA terminator sequence. */ - if (PEAR::isError($result = $this->_send("\r\n.\r\n"))) { + if (PEAR::isError($result = $this->send($terminator))) { return $result; } /* Verify that the data was successfully received by the server. */ - if (PEAR::isError($error = $this->_parseResponse(250, $this->pipelining))) { + if (PEAR::isError($error = $this->parseResponse(250, $this->pipelining))) { return $error; } @@ -1148,134 +1116,79 @@ class Net_SMTP /** * Send the SEND FROM: command. * - * @param string The reverse path to send. + * @param string $path The reverse path to send. * * @return mixed Returns a PEAR_Error with an error message on any * kind of failure, or true on success. - * @access public - * @since 1.2.6 + * @since 1.2.6 */ - function sendFrom($path) + public function sendFrom($path) { - if (PEAR::isError($error = $this->_put('SEND', "FROM:<$path>"))) { + if (PEAR::isError($error = $this->put('SEND', "FROM:<$path>"))) { return $error; } - if (PEAR::isError($error = $this->_parseResponse(250, $this->pipelining))) { + if (PEAR::isError($error = $this->parseResponse(250, $this->pipelining))) { return $error; } return true; } - /** - * Backwards-compatibility wrapper for sendFrom(). - * - * @param string The reverse path to send. - * - * @return mixed Returns a PEAR_Error with an error message on any - * kind of failure, or true on success. - * - * @access public - * @since 1.0 - * @deprecated 1.2.6 - */ - function send_from($path) - { - return sendFrom($path); - } - /** * Send the SOML FROM: command. * - * @param string The reverse path to send. + * @param string $path The reverse path to send. * * @return mixed Returns a PEAR_Error with an error message on any * kind of failure, or true on success. - * @access public - * @since 1.2.6 + * @since 1.2.6 */ - function somlFrom($path) + public function somlFrom($path) { - if (PEAR::isError($error = $this->_put('SOML', "FROM:<$path>"))) { + if (PEAR::isError($error = $this->put('SOML', "FROM:<$path>"))) { return $error; } - if (PEAR::isError($error = $this->_parseResponse(250, $this->pipelining))) { + if (PEAR::isError($error = $this->parseResponse(250, $this->pipelining))) { return $error; } return true; } - /** - * Backwards-compatibility wrapper for somlFrom(). - * - * @param string The reverse path to send. - * - * @return mixed Returns a PEAR_Error with an error message on any - * kind of failure, or true on success. - * - * @access public - * @since 1.0 - * @deprecated 1.2.6 - */ - function soml_from($path) - { - return somlFrom($path); - } - /** * Send the SAML FROM: command. * - * @param string The reverse path to send. + * @param string $path The reverse path to send. * * @return mixed Returns a PEAR_Error with an error message on any * kind of failure, or true on success. - * @access public - * @since 1.2.6 + * @since 1.2.6 */ - function samlFrom($path) + public function samlFrom($path) { - if (PEAR::isError($error = $this->_put('SAML', "FROM:<$path>"))) { + if (PEAR::isError($error = $this->put('SAML', "FROM:<$path>"))) { return $error; } - if (PEAR::isError($error = $this->_parseResponse(250, $this->pipelining))) { + if (PEAR::isError($error = $this->parseResponse(250, $this->pipelining))) { return $error; } return true; } - /** - * Backwards-compatibility wrapper for samlFrom(). - * - * @param string The reverse path to send. - * - * @return mixed Returns a PEAR_Error with an error message on any - * kind of failure, or true on success. - * - * @access public - * @since 1.0 - * @deprecated 1.2.6 - */ - function saml_from($path) - { - return samlFrom($path); - } - /** * Send the RSET command. * * @return mixed Returns a PEAR_Error with an error message on any * kind of failure, or true on success. - * @access public * @since 1.0 */ - function rset() + public function rset() { - if (PEAR::isError($error = $this->_put('RSET'))) { + if (PEAR::isError($error = $this->put('RSET'))) { return $error; } - if (PEAR::isError($error = $this->_parseResponse(250, $this->pipelining))) { + if (PEAR::isError($error = $this->parseResponse(250, $this->pipelining))) { return $error; } @@ -1285,20 +1198,19 @@ class Net_SMTP /** * Send the VRFY command. * - * @param string The string to verify + * @param string $string The string to verify * * @return mixed Returns a PEAR_Error with an error message on any * kind of failure, or true on success. - * @access public - * @since 1.0 + * @since 1.0 */ - function vrfy($string) + public function vrfy($string) { /* Note: 251 is also a valid response code */ - if (PEAR::isError($error = $this->_put('VRFY', $string))) { + if (PEAR::isError($error = $this->put('VRFY', $string))) { return $error; } - if (PEAR::isError($error = $this->_parseResponse(array(250, 252)))) { + if (PEAR::isError($error = $this->parseResponse(array(250, 252)))) { return $error; } @@ -1310,15 +1222,14 @@ class Net_SMTP * * @return mixed Returns a PEAR_Error with an error message on any * kind of failure, or true on success. - * @access public - * @since 1.0 + * @since 1.0 */ - function noop() + public function noop() { - if (PEAR::isError($error = $this->_put('NOOP'))) { + if (PEAR::isError($error = $this->put('NOOP'))) { return $error; } - if (PEAR::isError($error = $this->_parseResponse(250))) { + if (PEAR::isError($error = $this->parseResponse(250))) { return $error; } @@ -1329,14 +1240,12 @@ class Net_SMTP * Backwards-compatibility method. identifySender()'s functionality is * now handled internally. * - * @return boolean This method always return true. + * @return boolean This method always return true. * - * @access public - * @since 1.0 + * @since 1.0 */ - function identifySender() + public function identifySender() { return true; } - }