Subversion Repositories Applications.papyrus

Compare Revisions

Ignore whitespace Rev 609 → Rev 610

/trunk/api/pear/Mail/null.php
New file
0,0 → 1,60
<?php
//
// +----------------------------------------------------------------------+
// | PHP Version 4 |
// +----------------------------------------------------------------------+
// | Copyright (c) 1997-2003 The PHP Group |
// +----------------------------------------------------------------------+
// | This source file is subject to version 2.02 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. |
// | 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. |
// +----------------------------------------------------------------------+
// | Author: Phil Kernick <philk@rotfl.com.au> |
// +----------------------------------------------------------------------+
//
// $Id: null.php,v 1.1 2005-11-24 16:15:46 florian Exp $
//
 
/**
* Null implementation of the PEAR Mail:: interface.
* @access public
* @package Mail
* @version $Revision: 1.1 $
*/
class Mail_null extends Mail {
 
/**
* Implements Mail_null::send() function. Silently discards all
* mail.
*
* @param mixed $recipients Either a comma-seperated list of recipients
* (RFC822 compliant), or an array of recipients,
* each RFC822 valid. This may contain recipients not
* specified in the headers, for Bcc:, resending
* messages, etc.
*
* @param array $headers The array of headers to send with the mail, in an
* associative array, where the array key is the
* header name (ie, 'Subject'), and the array value
* is the header value (ie, 'test'). The header
* produced from those values would be 'Subject:
* test'.
*
* @param string $body The full text of the message body, including any
* Mime parts, etc.
*
* @return mixed Returns true on success, or a PEAR_Error
* containing a descriptive error message on
* failure.
* @access public
*/
function send($recipients, $headers, $body)
{
return true;
}
 
}
/trunk/api/pear/Mail/sendmail.php
New file
0,0 → 1,145
<?php
//
// +----------------------------------------------------------------------+
// | PHP Version 4 |
// +----------------------------------------------------------------------+
// | Copyright (c) 1997-2003 The PHP Group |
// +----------------------------------------------------------------------+
// | This source file is subject to version 2.02 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. |
// | 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. |
// +----------------------------------------------------------------------+
// | Author: Chuck Hagenbuch <chuck@horde.org> |
// +----------------------------------------------------------------------+
 
/**
* Sendmail implementation of the PEAR Mail:: interface.
* @access public
* @package Mail
* @version $Revision: 1.1 $
*/
class Mail_sendmail extends Mail {
 
/**
* The location of the sendmail or sendmail wrapper binary on the
* filesystem.
* @var string
*/
var $sendmail_path = '/usr/sbin/sendmail';
 
/**
* Any extra command-line parameters to pass to the sendmail or
* sendmail wrapper binary.
* @var string
*/
var $sendmail_args = '';
 
/**
* Constructor.
*
* Instantiates a new Mail_sendmail:: object based on the parameters
* passed in. It looks for the following parameters:
* sendmail_path The location of the sendmail binary on the
* filesystem. Defaults to '/usr/sbin/sendmail'.
*
* sendmail_args Any extra parameters to pass to the sendmail
* or sendmail wrapper binary.
*
* If a parameter is present in the $params array, it replaces the
* default.
*
* @param array $params Hash containing any parameters different from the
* defaults.
* @access public
*/
function Mail_sendmail($params)
{
if (isset($params['sendmail_path'])) $this->sendmail_path = $params['sendmail_path'];
if (isset($params['sendmail_args'])) $this->sendmail_args = $params['sendmail_args'];
 
/*
* Because we need to pass message headers to the sendmail program on
* the commandline, we can't guarantee the use of the standard "\r\n"
* separator. Instead, we use the system's native line separator.
*/
$this->sep = (strpos(PHP_OS, 'WIN') === false) ? "\n" : "\r\n";
}
 
/**
* Implements Mail::send() function using the sendmail
* command-line binary.
*
* @param mixed $recipients Either a comma-seperated list of recipients
* (RFC822 compliant), or an array of recipients,
* each RFC822 valid. This may contain recipients not
* specified in the headers, for Bcc:, resending
* messages, etc.
*
* @param array $headers The array of headers to send with the mail, in an
* associative array, where the array key is the
* header name (ie, 'Subject'), and the array value
* is the header value (ie, 'test'). The header
* produced from those values would be 'Subject:
* test'.
*
* @param string $body The full text of the message body, including any
* Mime parts, etc.
*
* @return mixed Returns true on success, or a PEAR_Error
* containing a descriptive error message on
* failure.
* @access public
*/
function send($recipients, $headers, $body)
{
$recipients = $this->parseRecipients($recipients);
if (PEAR::isError($recipients)) {
return $recipients;
}
$recipients = escapeShellCmd(implode(' ', $recipients));
 
$headerElements = $this->prepareHeaders($headers);
if (PEAR::isError($headerElements)) {
return $headerElements;
}
list($from, $text_headers) = $headerElements;
 
if (!isset($from)) {
return PEAR::raiseError('No from address given.');
} elseif (strpos($from, ' ') !== false ||
strpos($from, ';') !== false ||
strpos($from, '&') !== false ||
strpos($from, '`') !== false) {
return PEAR::raiseError('From address specified with dangerous characters.');
}
 
$result = 0;
if (@is_file($this->sendmail_path)) {
$from = escapeShellCmd($from);
$mail = popen($this->sendmail_path . (!empty($this->sendmail_args) ? ' ' . $this->sendmail_args : '') . " -f$from -- $recipients", 'w');
fputs($mail, $text_headers);
fputs($mail, $this->sep); // newline to end the headers section
fputs($mail, $body);
$result = pclose($mail);
if (version_compare(phpversion(), '4.2.3') == -1) {
// With older php versions, we need to shift the
// pclose result to get the exit code.
$result = $result >> 8 & 0xFF;
}
} else {
return PEAR::raiseError('sendmail [' . $this->sendmail_path . '] is not a valid file');
}
 
if ($result != 0) {
return PEAR::raiseError('sendmail returned error code ' . $result,
$result);
}
 
return true;
}
 
}
/trunk/api/pear/Mail/mail.php
New file
0,0 → 1,130
<?php
//
// +----------------------------------------------------------------------+
// | PHP Version 4 |
// +----------------------------------------------------------------------+
// | Copyright (c) 1997-2003 The PHP Group |
// +----------------------------------------------------------------------+
// | This source file is subject to version 2.02 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. |
// | 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. |
// +----------------------------------------------------------------------+
// | Author: Chuck Hagenbuch <chuck@horde.org> |
// +----------------------------------------------------------------------+
//
// $Id: mail.php,v 1.1 2005-11-24 16:15:46 florian Exp $
 
/**
* internal PHP-mail() implementation of the PEAR Mail:: interface.
* @package Mail
* @version $Revision: 1.1 $
*/
class Mail_mail extends Mail {
 
/**
* Any arguments to pass to the mail() function.
* @var string
*/
var $_params = '';
 
/**
* Constructor.
*
* Instantiates a new Mail_mail:: object based on the parameters
* passed in.
*
* @param array $params Extra arguments for the mail() function.
*/
function Mail_mail($params = null)
{
/* The other mail implementations accept parameters as arrays.
* In the interest of being consistent, explode an array into
* a string of parameter arguments. */
if (is_array($params)) {
$this->_params = join(' ', $params);
} else {
$this->_params = $params;
}
 
/* Because the mail() function may pass headers as command
* line arguments, we can't guarantee the use of the standard
* "\r\n" separator. Instead, we use the system's native line
* separator. */
$this->sep = (strpos(PHP_OS, 'WIN') === false) ? "\n" : "\r\n";
}
 
/**
* Implements Mail_mail::send() function using php's built-in mail()
* command.
*
* @param mixed $recipients Either a comma-seperated list of recipients
* (RFC822 compliant), or an array of recipients,
* each RFC822 valid. This may contain recipients not
* specified in the headers, for Bcc:, resending
* messages, etc.
*
* @param array $headers The array of headers to send with the mail, in an
* associative array, where the array key is the
* header name (ie, 'Subject'), and the array value
* is the header value (ie, 'test'). The header
* produced from those values would be 'Subject:
* test'.
*
* @param string $body The full text of the message body, including any
* Mime parts, etc.
*
* @return mixed Returns true on success, or a PEAR_Error
* containing a descriptive error message on
* failure.
*
* @access public
*/
function send($recipients, $headers, $body)
{
// If we're passed an array of recipients, implode it.
if (is_array($recipients)) {
$recipients = implode(', ', $recipients);
}
 
// Get the Subject out of the headers array so that we can
// pass it as a seperate argument to mail().
$subject = '';
if (isset($headers['Subject'])) {
$subject = $headers['Subject'];
unset($headers['Subject']);
}
 
// Flatten the headers out.
$headerElements = $this->prepareHeaders($headers);
if (PEAR::isError($headerElements)) {
return $headerElements;
}
list(, $text_headers) = $headerElements;
 
/*
* We only use mail()'s optional fifth parameter if the additional
* parameters have been provided and we're not running in safe mode.
*/
if (empty($this->_params) || ini_get('safe_mode')) {
$result = mail($recipients, $subject, $body, $text_headers);
} else {
$result = mail($recipients, $subject, $body, $text_headers,
$this->_params);
}
 
/*
* If the mail() function returned failure, we need to create a
* PEAR_Error object and return it instead of the boolean result.
*/
if ($result === false) {
$result = PEAR::raiseError('mail() returned failure');
}
 
return $result;
}
 
}
/trunk/api/pear/Mail/smtp.php
New file
0,0 → 1,323
<?php
//
// +----------------------------------------------------------------------+
// | PHP Version 4 |
// +----------------------------------------------------------------------+
// | Copyright (c) 1997-2003 The PHP Group |
// +----------------------------------------------------------------------+
// | This source file is subject to version 2.02 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. |
// | 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. |
// +----------------------------------------------------------------------+
// | Authors: Chuck Hagenbuch <chuck@horde.org> |
// | Jon Parise <jon@php.net> |
// +----------------------------------------------------------------------+
 
/**
* SMTP implementation of the PEAR Mail interface. Requires the Net_SMTP class.
* @access public
* @package Mail
* @version $Revision: 1.1 $
*/
class Mail_smtp extends Mail {
 
/**
* SMTP connection object.
*
* @var object
* @access private
*/
var $_smtp = null;
 
/**
* The SMTP host to connect to.
* @var string
*/
var $host = 'localhost';
 
/**
* The port the SMTP server is on.
* @var integer
*/
var $port = 25;
 
/**
* Should SMTP authentication be used?
*
* This value may be set to true, false or the name of a specific
* authentication method.
*
* If the value is set to true, the Net_SMTP package will attempt to use
* the best authentication method advertised by the remote SMTP server.
*
* @var mixed
*/
var $auth = false;
 
/**
* The username to use if the SMTP server requires authentication.
* @var string
*/
var $username = '';
 
/**
* The password to use if the SMTP server requires authentication.
* @var string
*/
var $password = '';
 
/**
* Hostname or domain that will be sent to the remote SMTP server in the
* HELO / EHLO message.
*
* @var string
*/
var $localhost = 'localhost';
 
/**
* SMTP connection timeout value. NULL indicates no timeout.
*
* @var integer
*/
var $timeout = null;
 
/**
* Whether to use VERP or not. If not a boolean, the string value
* will be used as the VERP separators.
*
* @var mixed boolean or string
*/
var $verp = false;
 
/**
* Turn on Net_SMTP debugging?
*
* @var boolean $debug
*/
var $debug = false;
 
/**
* Indicates whether or not the SMTP connection should persist over
* multiple calls to the send() method.
*
* @var boolean
*/
var $persist = false;
 
/**
* Constructor.
*
* Instantiates a new Mail_smtp:: object based on the parameters
* passed in. It looks for the following parameters:
* host The server to connect to. Defaults to localhost.
* port The port to connect to. Defaults to 25.
* auth SMTP authentication. Defaults to none.
* username The username to use for SMTP auth. No default.
* password The password to use for SMTP auth. No default.
* localhost The local hostname / domain. Defaults to localhost.
* timeout The SMTP connection timeout. Defaults to none.
* verp Whether to use VERP or not. Defaults to false.
* debug Activate SMTP debug mode? Defaults to false.
* persist Should the SMTP connection persist?
*
* If a parameter is present in the $params array, it replaces the
* default.
*
* @param array Hash containing any parameters different from the
* defaults.
* @access public
*/
function Mail_smtp($params)
{
if (isset($params['host'])) $this->host = $params['host'];
if (isset($params['port'])) $this->port = $params['port'];
if (isset($params['auth'])) $this->auth = $params['auth'];
if (isset($params['username'])) $this->username = $params['username'];
if (isset($params['password'])) $this->password = $params['password'];
if (isset($params['localhost'])) $this->localhost = $params['localhost'];
if (isset($params['timeout'])) $this->timeout = $params['timeout'];
if (isset($params['verp'])) $this->verp = $params['verp'];
if (isset($params['debug'])) $this->debug = (boolean)$params['debug'];
if (isset($params['persist'])) $this->persist = (boolean)$params['persist'];
 
register_shutdown_function(array(&$this, '_Mail_smtp'));
}
 
/**
* Destructor implementation to ensure that we disconnect from any
* potentially-alive persistent SMTP connections.
*/
function _Mail_smtp()
{
$this->disconnect();
}
 
/**
* Implements Mail::send() function using SMTP.
*
* @param mixed $recipients Either a comma-seperated list of recipients
* (RFC822 compliant), or an array of recipients,
* each RFC822 valid. This may contain recipients not
* specified in the headers, for Bcc:, resending
* messages, etc.
*
* @param array $headers The array of headers to send with the mail, in an
* associative array, where the array key is the
* header name (e.g., 'Subject'), and the array value
* is the header value (e.g., 'test'). The header
* produced from those values would be 'Subject:
* test'.
*
* @param string $body The full text of the message body, including any
* Mime parts, etc.
*
* @return mixed Returns true on success, or a PEAR_Error
* containing a descriptive error message on
* failure.
* @access public
*/
function send($recipients, $headers, $body)
{
include_once 'Net/SMTP.php';
 
/* If we don't already have an SMTP object, create one. */
if (is_object($this->_smtp) === false) {
$this->_smtp =& new Net_SMTP($this->host, $this->port,
$this->localhost);
 
/* If we still don't have an SMTP object at this point, fail. */
if (is_object($this->_smtp) === false) {
return PEAR::raiseError('Failed to create a Net_SMTP object');
}
 
/* Configure the SMTP connection. */
if ($this->debug) {
$this->_smtp->setDebug(true);
}
 
/* Attempt to connect to the configured SMTP server. */
if (PEAR::isError($res = $this->_smtp->connect($this->timeout))) {
$error = $this->_error('Failed to connect to ' .
$this->host . ':' . $this->port,
$res);
return PEAR::raiseError($error);
}
 
/* Attempt to authenticate if authentication has been enabled. */
if ($this->auth) {
$method = is_string($this->auth) ? $this->auth : '';
 
if (PEAR::isError($res = $this->_smtp->auth($this->username,
$this->password,
$method))) {
$error = $this->_error("$method authentication failure",
$res);
$this->_smtp->rset();
return PEAR::raiseError($error);
}
}
}
 
$headerElements = $this->prepareHeaders($headers);
if (PEAR::isError($headerElements)) {
$this->_smtp->rset();
return $headerElements;
}
list($from, $textHeaders) = $headerElements;
 
/* Since few MTAs are going to allow this header to be forged
* unless it's in the MAIL FROM: exchange, we'll use
* Return-Path instead of From: if it's set. */
if (!empty($headers['Return-Path'])) {
$from = $headers['Return-Path'];
}
 
if (!isset($from)) {
$this->_smtp->rset();
return PEAR::raiseError('No From: address has been provided');
}
 
$args['verp'] = $this->verp;
if (PEAR::isError($res = $this->_smtp->mailFrom($from, $args))) {
$error = $this->_error("Failed to set sender: $from", $res);
$this->_smtp->rset();
return PEAR::raiseError($error);
}
 
$recipients = $this->parseRecipients($recipients);
if (PEAR::isError($recipients)) {
$this->_smtp->rset();
return $recipients;
}
 
foreach ($recipients as $recipient) {
if (PEAR::isError($res = $this->_smtp->rcptTo($recipient))) {
$error = $this->_error("Failed to add recipient: $recipient",
$res);
$this->_smtp->rset();
return PEAR::raiseError($error);
}
}
 
/* Send the message's headers and the body as SMTP data. */
if (PEAR::isError($res = $this->_smtp->data("$textHeaders\r\n$body"))) {
$error = $this->_error('Failed to send data', $res);
$this->_smtp->rset();
return PEAR::raiseError($error);
}
 
/* If persistent connections are disabled, destroy our SMTP object. */
if ($this->persist === false) {
$this->disconnect();
}
 
return true;
}
 
/**
* Disconnect and destroy the current SMTP connection.
*
* @return boolean True if the SMTP connection no longer exists.
*
* @since 1.1.9
* @access public
*/
function disconnect()
{
/* If we have an SMTP object, disconnect and destroy it. */
if (is_object($this->_smtp) && $this->_smtp->disconnect()) {
$this->_smtp = null;
}
 
/* We are disconnected if we no longer have an SMTP object. */
return ($this->_smtp === null);
}
 
/**
* Build a standardized string describing the current SMTP error.
*
* @param string $text Custom string describing the error context.
* @param object $error Reference to the current PEAR_Error object.
*
* @return string A string describing the current SMTP error.
*
* @since 1.1.7
* @access private
*/
function _error($text, &$error)
{
/* Split the SMTP response into a code and a response string. */
list($code, $response) = $this->_smtp->getResponse();
 
/* Build our standardized error string. */
$msg = $text;
$msg .= ' [SMTP: ' . $error->getMessage();
$msg .= " (code: $code, response: $response)]";
 
return $msg;
}
}
/trunk/api/pear/Mail/RFC822.php
New file
0,0 → 1,923
<?php
// +-----------------------------------------------------------------------+
// | Copyright (c) 2001-2002, Richard Heyes |
// | All rights reserved. |
// | |
// | Redistribution and use in source and binary forms, with or without |
// | modification, are permitted provided that the following conditions |
// | are met: |
// | |
// | o Redistributions of source code must retain the above copyright |
// | notice, this list of conditions and the following disclaimer. |
// | o 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.|
// | o The names of the authors may not 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" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
// | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
// | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
// | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
// | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
// | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
// | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
// | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
// | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
// | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
// | |
// +-----------------------------------------------------------------------+
// | Authors: Richard Heyes <richard@phpguru.org> |
// | Chuck Hagenbuch <chuck@horde.org> |
// +-----------------------------------------------------------------------+
 
/**
* RFC 822 Email address list validation Utility
*
* What is it?
*
* This class will take an address string, and parse it into it's consituent
* parts, be that either addresses, groups, or combinations. Nested groups
* are not supported. The structure it returns is pretty straight forward,
* and is similar to that provided by the imap_rfc822_parse_adrlist(). Use
* print_r() to view the structure.
*
* How do I use it?
*
* $address_string = 'My Group: "Richard" <richard@localhost> (A comment), ted@example.com (Ted Bloggs), Barney;';
* $structure = Mail_RFC822::parseAddressList($address_string, 'example.com', true)
* print_r($structure);
*
* @author Richard Heyes <richard@phpguru.org>
* @author Chuck Hagenbuch <chuck@horde.org>
* @version $Revision: 1.1 $
* @license BSD
* @package Mail
*/
class Mail_RFC822 {
 
/**
* The address being parsed by the RFC822 object.
* @var string $address
*/
var $address = '';
 
/**
* The default domain to use for unqualified addresses.
* @var string $default_domain
*/
var $default_domain = 'localhost';
 
/**
* Should we return a nested array showing groups, or flatten everything?
* @var boolean $nestGroups
*/
var $nestGroups = true;
 
/**
* Whether or not to validate atoms for non-ascii characters.
* @var boolean $validate
*/
var $validate = true;
 
/**
* The array of raw addresses built up as we parse.
* @var array $addresses
*/
var $addresses = array();
 
/**
* The final array of parsed address information that we build up.
* @var array $structure
*/
var $structure = array();
 
/**
* The current error message, if any.
* @var string $error
*/
var $error = null;
 
/**
* An internal counter/pointer.
* @var integer $index
*/
var $index = null;
 
/**
* The number of groups that have been found in the address list.
* @var integer $num_groups
* @access public
*/
var $num_groups = 0;
 
/**
* A variable so that we can tell whether or not we're inside a
* Mail_RFC822 object.
* @var boolean $mailRFC822
*/
var $mailRFC822 = true;
 
/**
* A limit after which processing stops
* @var int $limit
*/
var $limit = null;
 
/**
* Sets up the object. The address must either be set here or when
* calling parseAddressList(). One or the other.
*
* @access public
* @param string $address The address(es) to validate.
* @param string $default_domain Default domain/host etc. If not supplied, will be set to localhost.
* @param boolean $nest_groups Whether to return the structure with groups nested for easier viewing.
* @param boolean $validate Whether to validate atoms. Turn this off if you need to run addresses through before encoding the personal names, for instance.
*
* @return object Mail_RFC822 A new Mail_RFC822 object.
*/
function Mail_RFC822($address = null, $default_domain = null, $nest_groups = null, $validate = null, $limit = null)
{
if (isset($address)) $this->address = $address;
if (isset($default_domain)) $this->default_domain = $default_domain;
if (isset($nest_groups)) $this->nestGroups = $nest_groups;
if (isset($validate)) $this->validate = $validate;
if (isset($limit)) $this->limit = $limit;
}
 
/**
* Starts the whole process. The address must either be set here
* or when creating the object. One or the other.
*
* @access public
* @param string $address The address(es) to validate.
* @param string $default_domain Default domain/host etc.
* @param boolean $nest_groups Whether to return the structure with groups nested for easier viewing.
* @param boolean $validate Whether to validate atoms. Turn this off if you need to run addresses through before encoding the personal names, for instance.
*
* @return array A structured array of addresses.
*/
function parseAddressList($address = null, $default_domain = null, $nest_groups = null, $validate = null, $limit = null)
{
if (!isset($this) || !isset($this->mailRFC822)) {
$obj = new Mail_RFC822($address, $default_domain, $nest_groups, $validate, $limit);
return $obj->parseAddressList();
}
 
if (isset($address)) $this->address = $address;
if (isset($default_domain)) $this->default_domain = $default_domain;
if (isset($nest_groups)) $this->nestGroups = $nest_groups;
if (isset($validate)) $this->validate = $validate;
if (isset($limit)) $this->limit = $limit;
 
$this->structure = array();
$this->addresses = array();
$this->error = null;
$this->index = null;
 
// Unfold any long lines in $this->address.
$this->address = preg_replace('/\r?\n/', "\r\n", $this->address);
$this->address = preg_replace('/\r\n(\t| )+/', ' ', $this->address);
 
while ($this->address = $this->_splitAddresses($this->address));
 
if ($this->address === false || isset($this->error)) {
require_once 'PEAR.php';
return PEAR::raiseError($this->error);
}
 
// Validate each address individually. If we encounter an invalid
// address, stop iterating and return an error immediately.
foreach ($this->addresses as $address) {
$valid = $this->_validateAddress($address);
 
if ($valid === false || isset($this->error)) {
require_once 'PEAR.php';
return PEAR::raiseError($this->error);
}
 
if (!$this->nestGroups) {
$this->structure = array_merge($this->structure, $valid);
} else {
$this->structure[] = $valid;
}
}
 
return $this->structure;
}
 
/**
* Splits an address into separate addresses.
*
* @access private
* @param string $address The addresses to split.
* @return boolean Success or failure.
*/
function _splitAddresses($address)
{
if (!empty($this->limit) && count($this->addresses) == $this->limit) {
return '';
}
 
if ($this->_isGroup($address) && !isset($this->error)) {
$split_char = ';';
$is_group = true;
} elseif (!isset($this->error)) {
$split_char = ',';
$is_group = false;
} elseif (isset($this->error)) {
return false;
}
 
// Split the string based on the above ten or so lines.
$parts = explode($split_char, $address);
$string = $this->_splitCheck($parts, $split_char);
 
// If a group...
if ($is_group) {
// If $string does not contain a colon outside of
// brackets/quotes etc then something's fubar.
 
// First check there's a colon at all:
if (strpos($string, ':') === false) {
$this->error = 'Invalid address: ' . $string;
return false;
}
 
// Now check it's outside of brackets/quotes:
if (!$this->_splitCheck(explode(':', $string), ':')) {
return false;
}
 
// We must have a group at this point, so increase the counter:
$this->num_groups++;
}
 
// $string now contains the first full address/group.
// Add to the addresses array.
$this->addresses[] = array(
'address' => trim($string),
'group' => $is_group
);
 
// Remove the now stored address from the initial line, the +1
// is to account for the explode character.
$address = trim(substr($address, strlen($string) + 1));
 
// If the next char is a comma and this was a group, then
// there are more addresses, otherwise, if there are any more
// chars, then there is another address.
if ($is_group && substr($address, 0, 1) == ','){
$address = trim(substr($address, 1));
return $address;
 
} elseif (strlen($address) > 0) {
return $address;
 
} else {
return '';
}
 
// If you got here then something's off
return false;
}
 
/**
* Checks for a group at the start of the string.
*
* @access private
* @param string $address The address to check.
* @return boolean Whether or not there is a group at the start of the string.
*/
function _isGroup($address)
{
// First comma not in quotes, angles or escaped:
$parts = explode(',', $address);
$string = $this->_splitCheck($parts, ',');
 
// Now we have the first address, we can reliably check for a
// group by searching for a colon that's not escaped or in
// quotes or angle brackets.
if (count($parts = explode(':', $string)) > 1) {
$string2 = $this->_splitCheck($parts, ':');
return ($string2 !== $string);
} else {
return false;
}
}
 
/**
* A common function that will check an exploded string.
*
* @access private
* @param array $parts The exloded string.
* @param string $char The char that was exploded on.
* @return mixed False if the string contains unclosed quotes/brackets, or the string on success.
*/
function _splitCheck($parts, $char)
{
$string = $parts[0];
 
for ($i = 0; $i < count($parts); $i++) {
if ($this->_hasUnclosedQuotes($string)
|| $this->_hasUnclosedBrackets($string, '<>')
|| $this->_hasUnclosedBrackets($string, '[]')
|| $this->_hasUnclosedBrackets($string, '()')
|| substr($string, -1) == '\\') {
if (isset($parts[$i + 1])) {
$string = $string . $char . $parts[$i + 1];
} else {
$this->error = 'Invalid address spec. Unclosed bracket or quotes';
return false;
}
} else {
$this->index = $i;
break;
}
}
 
return $string;
}
 
/**
* Checks if a string has an unclosed quotes or not.
*
* @access private
* @param string $string The string to check.
* @return boolean True if there are unclosed quotes inside the string, false otherwise.
*/
function _hasUnclosedQuotes($string)
{
$string = explode('"', $string);
$string_cnt = count($string);
 
for ($i = 0; $i < (count($string) - 1); $i++)
if (substr($string[$i], -1) == '\\')
$string_cnt--;
 
return ($string_cnt % 2 === 0);
}
 
/**
* Checks if a string has an unclosed brackets or not. IMPORTANT:
* This function handles both angle brackets and square brackets;
*
* @access private
* @param string $string The string to check.
* @param string $chars The characters to check for.
* @return boolean True if there are unclosed brackets inside the string, false otherwise.
*/
function _hasUnclosedBrackets($string, $chars)
{
$num_angle_start = substr_count($string, $chars[0]);
$num_angle_end = substr_count($string, $chars[1]);
 
$this->_hasUnclosedBracketsSub($string, $num_angle_start, $chars[0]);
$this->_hasUnclosedBracketsSub($string, $num_angle_end, $chars[1]);
 
if ($num_angle_start < $num_angle_end) {
$this->error = 'Invalid address spec. Unmatched quote or bracket (' . $chars . ')';
return false;
} else {
return ($num_angle_start > $num_angle_end);
}
}
 
/**
* Sub function that is used only by hasUnclosedBrackets().
*
* @access private
* @param string $string The string to check.
* @param integer &$num The number of occurences.
* @param string $char The character to count.
* @return integer The number of occurences of $char in $string, adjusted for backslashes.
*/
function _hasUnclosedBracketsSub($string, &$num, $char)
{
$parts = explode($char, $string);
for ($i = 0; $i < count($parts); $i++){
if (substr($parts[$i], -1) == '\\' || $this->_hasUnclosedQuotes($parts[$i]))
$num--;
if (isset($parts[$i + 1]))
$parts[$i + 1] = $parts[$i] . $char . $parts[$i + 1];
}
 
return $num;
}
 
/**
* Function to begin checking the address.
*
* @access private
* @param string $address The address to validate.
* @return mixed False on failure, or a structured array of address information on success.
*/
function _validateAddress($address)
{
$is_group = false;
$addresses = array();
 
if ($address['group']) {
$is_group = true;
 
// Get the group part of the name
$parts = explode(':', $address['address']);
$groupname = $this->_splitCheck($parts, ':');
$structure = array();
 
// And validate the group part of the name.
if (!$this->_validatePhrase($groupname)){
$this->error = 'Group name did not validate.';
return false;
} else {
// Don't include groups if we are not nesting
// them. This avoids returning invalid addresses.
if ($this->nestGroups) {
$structure = new stdClass;
$structure->groupname = $groupname;
}
}
 
$address['address'] = ltrim(substr($address['address'], strlen($groupname . ':')));
}
 
// If a group then split on comma and put into an array.
// Otherwise, Just put the whole address in an array.
if ($is_group) {
while (strlen($address['address']) > 0) {
$parts = explode(',', $address['address']);
$addresses[] = $this->_splitCheck($parts, ',');
$address['address'] = trim(substr($address['address'], strlen(end($addresses) . ',')));
}
} else {
$addresses[] = $address['address'];
}
 
// Check that $addresses is set, if address like this:
// Groupname:;
// Then errors were appearing.
if (!count($addresses)){
$this->error = 'Empty group.';
return false;
}
 
// Trim the whitespace from all of the address strings.
array_map('trim', $addresses);
 
// Validate each mailbox.
// Format could be one of: name <geezer@domain.com>
// geezer@domain.com
// geezer
// ... or any other format valid by RFC 822.
for ($i = 0; $i < count($addresses); $i++) {
if (!$this->validateMailbox($addresses[$i])) {
if (empty($this->error)) {
$this->error = 'Validation failed for: ' . $addresses[$i];
}
return false;
}
}
 
// Nested format
if ($this->nestGroups) {
if ($is_group) {
$structure->addresses = $addresses;
} else {
$structure = $addresses[0];
}
 
// Flat format
} else {
if ($is_group) {
$structure = array_merge($structure, $addresses);
} else {
$structure = $addresses;
}
}
 
return $structure;
}
 
/**
* Function to validate a phrase.
*
* @access private
* @param string $phrase The phrase to check.
* @return boolean Success or failure.
*/
function _validatePhrase($phrase)
{
// Splits on one or more Tab or space.
$parts = preg_split('/[ \\x09]+/', $phrase, -1, PREG_SPLIT_NO_EMPTY);
 
$phrase_parts = array();
while (count($parts) > 0){
$phrase_parts[] = $this->_splitCheck($parts, ' ');
for ($i = 0; $i < $this->index + 1; $i++)
array_shift($parts);
}
 
foreach ($phrase_parts as $part) {
// If quoted string:
if (substr($part, 0, 1) == '"') {
if (!$this->_validateQuotedString($part)) {
return false;
}
continue;
}
 
// Otherwise it's an atom:
if (!$this->_validateAtom($part)) return false;
}
 
return true;
}
 
/**
* Function to validate an atom which from rfc822 is:
* atom = 1*<any CHAR except specials, SPACE and CTLs>
*
* If validation ($this->validate) has been turned off, then
* validateAtom() doesn't actually check anything. This is so that you
* can split a list of addresses up before encoding personal names
* (umlauts, etc.), for example.
*
* @access private
* @param string $atom The string to check.
* @return boolean Success or failure.
*/
function _validateAtom($atom)
{
if (!$this->validate) {
// Validation has been turned off; assume the atom is okay.
return true;
}
 
// Check for any char from ASCII 0 - ASCII 127
if (!preg_match('/^[\\x00-\\x7E]+$/i', $atom, $matches)) {
return false;
}
 
// Check for specials:
if (preg_match('/[][()<>@,;\\:". ]/', $atom)) {
return false;
}
 
// Check for control characters (ASCII 0-31):
if (preg_match('/[\\x00-\\x1F]+/', $atom)) {
return false;
}
 
return true;
}
 
/**
* Function to validate quoted string, which is:
* quoted-string = <"> *(qtext/quoted-pair) <">
*
* @access private
* @param string $qstring The string to check
* @return boolean Success or failure.
*/
function _validateQuotedString($qstring)
{
// Leading and trailing "
$qstring = substr($qstring, 1, -1);
 
// Perform check, removing quoted characters first.
return !preg_match('/[\x0D\\\\"]/', preg_replace('/\\\\./', '', $qstring));
}
 
/**
* Function to validate a mailbox, which is:
* mailbox = addr-spec ; simple address
* / phrase route-addr ; name and route-addr
*
* @access public
* @param string &$mailbox The string to check.
* @return boolean Success or failure.
*/
function validateMailbox(&$mailbox)
{
// A couple of defaults.
$phrase = '';
$comment = '';
$comments = array();
 
// Catch any RFC822 comments and store them separately.
$_mailbox = $mailbox;
while (strlen(trim($_mailbox)) > 0) {
$parts = explode('(', $_mailbox);
$before_comment = $this->_splitCheck($parts, '(');
if ($before_comment != $_mailbox) {
// First char should be a (.
$comment = substr(str_replace($before_comment, '', $_mailbox), 1);
$parts = explode(')', $comment);
$comment = $this->_splitCheck($parts, ')');
$comments[] = $comment;
 
// +1 is for the trailing )
$_mailbox = substr($_mailbox, strpos($_mailbox, $comment)+strlen($comment)+1);
} else {
break;
}
}
 
foreach ($comments as $comment) {
$mailbox = str_replace("($comment)", '', $mailbox);
}
 
$mailbox = trim($mailbox);
 
// Check for name + route-addr
if (substr($mailbox, -1) == '>' && substr($mailbox, 0, 1) != '<') {
$parts = explode('<', $mailbox);
$name = $this->_splitCheck($parts, '<');
 
$phrase = trim($name);
$route_addr = trim(substr($mailbox, strlen($name.'<'), -1));
 
if ($this->_validatePhrase($phrase) === false || ($route_addr = $this->_validateRouteAddr($route_addr)) === false) {
return false;
}
 
// Only got addr-spec
} else {
// First snip angle brackets if present.
if (substr($mailbox, 0, 1) == '<' && substr($mailbox, -1) == '>') {
$addr_spec = substr($mailbox, 1, -1);
} else {
$addr_spec = $mailbox;
}
 
if (($addr_spec = $this->_validateAddrSpec($addr_spec)) === false) {
return false;
}
}
 
// Construct the object that will be returned.
$mbox = new stdClass();
 
// Add the phrase (even if empty) and comments
$mbox->personal = $phrase;
$mbox->comment = isset($comments) ? $comments : array();
 
if (isset($route_addr)) {
$mbox->mailbox = $route_addr['local_part'];
$mbox->host = $route_addr['domain'];
$route_addr['adl'] !== '' ? $mbox->adl = $route_addr['adl'] : '';
} else {
$mbox->mailbox = $addr_spec['local_part'];
$mbox->host = $addr_spec['domain'];
}
 
$mailbox = $mbox;
return true;
}
 
/**
* This function validates a route-addr which is:
* route-addr = "<" [route] addr-spec ">"
*
* Angle brackets have already been removed at the point of
* getting to this function.
*
* @access private
* @param string $route_addr The string to check.
* @return mixed False on failure, or an array containing validated address/route information on success.
*/
function _validateRouteAddr($route_addr)
{
// Check for colon.
if (strpos($route_addr, ':') !== false) {
$parts = explode(':', $route_addr);
$route = $this->_splitCheck($parts, ':');
} else {
$route = $route_addr;
}
 
// If $route is same as $route_addr then the colon was in
// quotes or brackets or, of course, non existent.
if ($route === $route_addr){
unset($route);
$addr_spec = $route_addr;
if (($addr_spec = $this->_validateAddrSpec($addr_spec)) === false) {
return false;
}
} else {
// Validate route part.
if (($route = $this->_validateRoute($route)) === false) {
return false;
}
 
$addr_spec = substr($route_addr, strlen($route . ':'));
 
// Validate addr-spec part.
if (($addr_spec = $this->_validateAddrSpec($addr_spec)) === false) {
return false;
}
}
 
if (isset($route)) {
$return['adl'] = $route;
} else {
$return['adl'] = '';
}
 
$return = array_merge($return, $addr_spec);
return $return;
}
 
/**
* Function to validate a route, which is:
* route = 1#("@" domain) ":"
*
* @access private
* @param string $route The string to check.
* @return mixed False on failure, or the validated $route on success.
*/
function _validateRoute($route)
{
// Split on comma.
$domains = explode(',', trim($route));
 
foreach ($domains as $domain) {
$domain = str_replace('@', '', trim($domain));
if (!$this->_validateDomain($domain)) return false;
}
 
return $route;
}
 
/**
* Function to validate a domain, though this is not quite what
* you expect of a strict internet domain.
*
* domain = sub-domain *("." sub-domain)
*
* @access private
* @param string $domain The string to check.
* @return mixed False on failure, or the validated domain on success.
*/
function _validateDomain($domain)
{
// Note the different use of $subdomains and $sub_domains
$subdomains = explode('.', $domain);
 
while (count($subdomains) > 0) {
$sub_domains[] = $this->_splitCheck($subdomains, '.');
for ($i = 0; $i < $this->index + 1; $i++)
array_shift($subdomains);
}
 
foreach ($sub_domains as $sub_domain) {
if (!$this->_validateSubdomain(trim($sub_domain)))
return false;
}
 
// Managed to get here, so return input.
return $domain;
}
 
/**
* Function to validate a subdomain:
* subdomain = domain-ref / domain-literal
*
* @access private
* @param string $subdomain The string to check.
* @return boolean Success or failure.
*/
function _validateSubdomain($subdomain)
{
if (preg_match('|^\[(.*)]$|', $subdomain, $arr)){
if (!$this->_validateDliteral($arr[1])) return false;
} else {
if (!$this->_validateAtom($subdomain)) return false;
}
 
// Got here, so return successful.
return true;
}
 
/**
* Function to validate a domain literal:
* domain-literal = "[" *(dtext / quoted-pair) "]"
*
* @access private
* @param string $dliteral The string to check.
* @return boolean Success or failure.
*/
function _validateDliteral($dliteral)
{
return !preg_match('/(.)[][\x0D\\\\]/', $dliteral, $matches) && $matches[1] != '\\';
}
 
/**
* Function to validate an addr-spec.
*
* addr-spec = local-part "@" domain
*
* @access private
* @param string $addr_spec The string to check.
* @return mixed False on failure, or the validated addr-spec on success.
*/
function _validateAddrSpec($addr_spec)
{
$addr_spec = trim($addr_spec);
 
// Split on @ sign if there is one.
if (strpos($addr_spec, '@') !== false) {
$parts = explode('@', $addr_spec);
$local_part = $this->_splitCheck($parts, '@');
$domain = substr($addr_spec, strlen($local_part . '@'));
 
// No @ sign so assume the default domain.
} else {
$local_part = $addr_spec;
$domain = $this->default_domain;
}
 
if (($local_part = $this->_validateLocalPart($local_part)) === false) return false;
if (($domain = $this->_validateDomain($domain)) === false) return false;
 
// Got here so return successful.
return array('local_part' => $local_part, 'domain' => $domain);
}
 
/**
* Function to validate the local part of an address:
* local-part = word *("." word)
*
* @access private
* @param string $local_part
* @return mixed False on failure, or the validated local part on success.
*/
function _validateLocalPart($local_part)
{
$parts = explode('.', $local_part);
$words = array();
 
// Split the local_part into words.
while (count($parts) > 0){
$words[] = $this->_splitCheck($parts, '.');
for ($i = 0; $i < $this->index + 1; $i++) {
array_shift($parts);
}
}
 
// Validate each word.
foreach ($words as $word) {
// If this word contains an unquoted space, it is invalid. (6.2.4)
if (strpos($word, ' ') && $word[0] !== '"')
{
return false;
}
 
if ($this->_validatePhrase(trim($word)) === false) return false;
}
 
// Managed to get here, so return the input.
return $local_part;
}
 
/**
* Returns an approximate count of how many addresses are in the
* given string. This is APPROXIMATE as it only splits based on a
* comma which has no preceding backslash. Could be useful as
* large amounts of addresses will end up producing *large*
* structures when used with parseAddressList().
*
* @param string $data Addresses to count
* @return int Approximate count
*/
function approximateCount($data)
{
return count(preg_split('/(?<!\\\\),/', $data));
}
 
/**
* This is a email validating function separate to the rest of the
* class. It simply validates whether an email is of the common
* internet form: <user>@<domain>. This can be sufficient for most
* people. Optional stricter mode can be utilised which restricts
* mailbox characters allowed to alphanumeric, full stop, hyphen
* and underscore.
*
* @param string $data Address to check
* @param boolean $strict Optional stricter mode
* @return mixed False if it fails, an indexed array
* username/domain if it matches
*/
function isValidInetAddress($data, $strict = false)
{
$regex = $strict ? '/^([.0-9a-z_+-]+)@(([0-9a-z-]+\.)+[0-9a-z]{2,4})$/i' : '/^([*+!.&#$|\'\\%\/0-9a-z^_`{}=?~:-]+)@(([0-9a-z-]+\.)+[0-9a-z]{2,4})$/i';
if (preg_match($regex, trim($data), $matches)) {
return array($matches[1], $matches[2]);
} else {
return false;
}
}
 
}
/trunk/api/pear/Mail.php
New file
0,0 → 1,211
<?php
//
// +----------------------------------------------------------------------+
// | PHP Version 4 |
// +----------------------------------------------------------------------+
// | Copyright (c) 1997-2003 The PHP Group |
// +----------------------------------------------------------------------+
// | This source file is subject to version 2.02 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. |
// | 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. |
// +----------------------------------------------------------------------+
// | Author: Chuck Hagenbuch <chuck@horde.org> |
// +----------------------------------------------------------------------+
//
// $Id: Mail.php,v 1.1 2005-11-24 16:15:46 florian Exp $
 
require_once 'PEAR.php';
 
/**
* PEAR's Mail:: interface. Defines the interface for implementing
* mailers under the PEAR hierarchy, and provides supporting functions
* useful in multiple mailer backends.
*
* @access public
* @version $Revision: 1.1 $
* @package Mail
*/
class Mail
{
/**
* Line terminator used for separating header lines.
* @var string
*/
var $sep = "\r\n";
 
/**
* Provides an interface for generating Mail:: objects of various
* types
*
* @param string $driver The kind of Mail:: object to instantiate.
* @param array $params The parameters to pass to the Mail:: object.
* @return object Mail a instance of the driver class or if fails a PEAR Error
* @access public
*/
function &factory($driver, $params = array())
{
$driver = strtolower($driver);
@include_once 'Mail/' . $driver . '.php';
$class = 'Mail_' . $driver;
if (class_exists($class)) {
$mailer = new $class($params);
return $mailer;
} else {
return PEAR::raiseError('Unable to find class for driver ' . $driver);
}
}
 
/**
* Implements Mail::send() function using php's built-in mail()
* command.
*
* @param mixed $recipients Either a comma-seperated list of recipients
* (RFC822 compliant), or an array of recipients,
* each RFC822 valid. This may contain recipients not
* specified in the headers, for Bcc:, resending
* messages, etc.
*
* @param array $headers The array of headers to send with the mail, in an
* associative array, where the array key is the
* header name (ie, 'Subject'), and the array value
* is the header value (ie, 'test'). The header
* produced from those values would be 'Subject:
* test'.
*
* @param string $body The full text of the message body, including any
* Mime parts, etc.
*
* @return mixed Returns true on success, or a PEAR_Error
* containing a descriptive error message on
* failure.
* @access public
* @deprecated use Mail_mail::send instead
*/
function send($recipients, $headers, $body)
{
// if we're passed an array of recipients, implode it.
if (is_array($recipients)) {
$recipients = implode(', ', $recipients);
}
 
// get the Subject out of the headers array so that we can
// pass it as a seperate argument to mail().
$subject = '';
if (isset($headers['Subject'])) {
$subject = $headers['Subject'];
unset($headers['Subject']);
}
 
// flatten the headers out.
list(,$text_headers) = Mail::prepareHeaders($headers);
 
return mail($recipients, $subject, $body, $text_headers);
 
}
 
/**
* Take an array of mail headers and return a string containing
* text usable in sending a message.
*
* @param array $headers The array of headers to prepare, in an associative
* array, where the array key is the header name (ie,
* 'Subject'), and the array value is the header
* value (ie, 'test'). The header produced from those
* values would be 'Subject: test'.
*
* @return mixed Returns false if it encounters a bad address,
* otherwise returns an array containing two
* elements: Any From: address found in the headers,
* and the plain text version of the headers.
* @access private
*/
function prepareHeaders($headers)
{
$lines = array();
$from = null;
 
foreach ($headers as $key => $value) {
if (strcasecmp($key, 'From') === 0) {
include_once 'Mail/RFC822.php';
$parser = &new Mail_RFC822();
$addresses = $parser->parseAddressList($value, 'localhost', false);
if (PEAR::isError($addresses)) {
return $addresses;
}
 
$from = $addresses[0]->mailbox . '@' . $addresses[0]->host;
 
// Reject envelope From: addresses with spaces.
if (strstr($from, ' ')) {
return false;
}
 
$lines[] = $key . ': ' . $value;
} elseif (strcasecmp($key, 'Received') === 0) {
$received = array();
if (is_array($value)) {
foreach ($value as $line) {
$received[] = $key . ': ' . $line;
}
}
else {
$received[] = $key . ': ' . $value;
}
// Put Received: headers at the top. Spam detectors often
// flag messages with Received: headers after the Subject:
// as spam.
$lines = array_merge($received, $lines);
} else {
// If $value is an array (i.e., a list of addresses), convert
// it to a comma-delimited string of its elements (addresses).
if (is_array($value)) {
$value = implode(', ', $value);
}
$lines[] = $key . ': ' . $value;
}
}
 
return array($from, join($this->sep, $lines) . $this->sep);
}
 
/**
* Take a set of recipients and parse them, returning an array of
* bare addresses (forward paths) that can be passed to sendmail
* or an smtp server with the rcpt to: command.
*
* @param mixed Either a comma-seperated list of recipients
* (RFC822 compliant), or an array of recipients,
* each RFC822 valid.
*
* @return array An array of forward paths (bare addresses).
* @access private
*/
function parseRecipients($recipients)
{
include_once 'Mail/RFC822.php';
 
// if we're passed an array, assume addresses are valid and
// implode them before parsing.
if (is_array($recipients)) {
$recipients = implode(', ', $recipients);
}
 
// Parse recipients, leaving out all personal info. This is
// for smtp recipients, etc. All relevant personal information
// should already be in the headers.
$addresses = Mail_RFC822::parseAddressList($recipients, 'localhost', false);
$recipients = array();
if (is_array($addresses)) {
foreach ($addresses as $ob) {
$recipients[] = $ob->mailbox . '@' . $ob->host;
}
}
 
return $recipients;
}
 
}