chagenbu Wed Feb 7 12:22:59 2001 EDT
Added files:
/php4/pear/Mail RFC822.php SMTP.php Sendmail.php
Removed files:
/php4/pear/Mail rfc822.php sendmail.php smtp.php
Modified files:
/php4/pear Mail.php Makefile.in
Log:
may as well go by the capitalization we agreed on sooner rather than later.
Index: php4/pear/Mail.php
diff -u php4/pear/Mail.php:1.8 php4/pear/Mail.php:1.9
--- php4/pear/Mail.php:1.8 Tue Jan 9 17:01:52 2001
+++ php4/pear/Mail.php Wed Feb 7 12:22:59 2001
@@ -33,16 +33,20 @@
* @param array The parameters to pass to the Mail:: object.
* @access public
*/
- function factory($mailer_type, $params = array())
+ function factory($driver, $params = array())
{
- $mailer_type = strtolower($mailer_type);
- $classfile = PEAR_INSTALL_DIR . '/Mail/' . $mailer_type . '.php';
- if (@is_readable($classfile)) {
- include_once $classfile;
- $class = 'Mail_' . $mailer_type;
+ if (@include_once 'Mail/' . $driver . '.php') {
+ $class = 'Mail_' . $driver;
+ } elseif (@include_once 'Mail/' . strtoupper($driver) . '.php') {
+ $class = 'Mail_' . strtoupper($driver);
+ } elseif (@include_once 'Mail/' . ucfirst($driver) . '.php') {
+ $class = 'Mail_' . ucfirst($driver);
+ }
+
+ if (isset($class)) {
return new $class($params);
} else {
- return new PEAR_Error('unable to find classfile: ' . $classfile);
+ return new PEAR_Error('Unable to find class for driver ' . $driver);
}
}
@@ -116,9 +120,9 @@
foreach ($headers as $key => $val) {
if ($key == 'From') {
- include_once 'Mail/rfc822.php';
+ include_once 'Mail/RFC822.php';
- $from_arr = Mail_rfc822::parseAddressList($val, 'localhost', false);
+ $from_arr = Mail_RFC822::parseAddressList($val, 'localhost', false);
$from = $from_arr[0]->mailbox . '@' . $from_arr[0]->host;
if (strstr($from, ' ')) {
// Reject outright envelope From addresses with spaces.
@@ -152,7 +156,7 @@
*/
function parseRecipients($recipients)
{
- include_once 'Mail/rfc822.php';
+ include_once 'Mail/RFC822.php';
// if we're passed an array, assume addresses are valid and
// implode them before parsing.
@@ -163,7 +167,7 @@
// 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);
+ $addresses = Mail_RFC822::parseAddressList($recipients, 'localhost', false);
$recipients = array();
if (is_array($addresses)) {
foreach ($addresses as $ob) {
Index: php4/pear/Makefile.in
diff -u php4/pear/Makefile.in:1.66 php4/pear/Makefile.in:1.67
--- php4/pear/Makefile.in:1.66 Tue Jan 23 13:09:55 2001
+++ php4/pear/Makefile.in Wed Feb 7 12:22:59 2001
@@ -68,9 +68,9 @@
Log/sql.php \
Log/syslog.php \
Mail.php \
- Mail/rfc822.php \
- Mail/sendmail.php \
- Mail/smtp.php \
+ Mail/RFC822.php \
+ Mail/Sendmail.php \
+ Mail/SMTP.php \
Math/Fraction.php \
Math/Util.php \
Net/Curl.php \
Index: php4/pear/Mail/RFC822.php
+++ php4/pear/Mail/RFC822.php
<?php
//
// +----------------------------------------------------------------------+
// | PHP version 4.0 |
// +----------------------------------------------------------------------+
// | Copyright (c) 1997-2001 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 |
// | [EMAIL PROTECTED] so we can mail you a copy immediately. |
// +----------------------------------------------------------------------+
// | Authors: Richard Heyes <[EMAIL PROTECTED]> |
// | Chuck Hagenbuch <[EMAIL PROTECTED]> |
// +----------------------------------------------------------------------+
/**
* RFC 822 Email address list validation Utility
*
* @author Richard Heyes <[EMAIL PROTECTED]>
* @author Chuck Hagenbuch <[EMAIL PROTECTED]>
* @version $Revision: 1.1 $
*/
class Mail_RFC822 {
// Properties (All private)
var $address = null;
var $default_host = 'localhost';
var $nestGroups = true;
var $addresses = array();
var $structure = array();
var $error = null;
var $index = null;
var $num_groups = 0;
var $mailRFC822 = true;
/**
* Sets up the object. The address must either be set here or when
* calling parseAddressList(). One or the other.
*
* @access public
* @param $address The address(es) to validate.
* @param $default_host (Optional) Default domain/host etc. If not supplied,
will be set to localhost.
* @param $nest_groups (Optional) Whether to return the structure with groups
nested for easier viewing.
*/
function Mail_RFC822($address = null, $default_host = null, $nest_groups = null)
{
if (isset($address)) $this->address = $address;
if (isset($default_host)) $this->default_host = $default_host;
if (isset($nest_groups)) $this->nestGroups = $nest_groups;
}
/**
* Starts the whole process. The address must either be set here
* or when creating the object. One or the other.
*
* @access public
* @param $address The address(es) to validate.
* @param $default_host (Optional) Default domain/host etc.
* @param $nest_groups (Optional) Whether to return the structure with groups
nested for easier viewing.
*/
function parseAddressList($address = null, $default_host = null, $nest_groups =
null)
{
if (!isset($this->mailRFC822)) {
$obj = new Mail_RFC822($address, $default_host, $nest_groups);
return $obj->parseAddressList();
}
if (isset($address)) $this->address = $address;
if (isset($default_host)) $this->default_host = $default_host;
if (isset($nest_groups)) $this->nestGroups = $nest_groups;
$this->structure = array();
$this->addresses = array();
$this->error = null;
$this->index = null;
if (!$this->splitAddresses($this->address) || isset($this->error)) {
return (array)$this->error;
}
for ($i = 0; $i < count($this->addresses); $i++){
if (($return = $this->validateAddress($this->addresses[$i])) === false
|| isset($this->error)) {
return (array)$this->error;
}
if (!$this->nestGroups) {
$this->structure = array_merge($this->structure, $return);
} else {
$this->structure[] = $return;
}
}
return $this->structure;
}
/**
* Splits an address into seperate addresses.
*
* @access private
* @param $address The addresses to split.
*/
function splitAddresses($address = '')
{
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));
$this->splitAddresses($address);
return true;
} elseif (strlen($address) > 0) {
$this->splitAddresses($address);
return true;
} else {
return true;
}
// If you got here then something's off
return false;
}
/**
* Checks for a group at the start of the string.
*
* @access private
* @param $address The address to check.
*/
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 $parts The exloded string.
* @param $char The char that was exploded on.
*/
function splitCheck($parts, $char)
{
$string = $parts[0];
for ($i = 0; $i < count($parts); $i++) {
if ($this->hasUnclosedQuotes($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 The string to check.
*/
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 The string to check.
* @param $chars The characters to check for.
*/
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 The string to check.
* @param $num The number of occurences.
* @param $char The character to count.
*/
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 $address The address to validate.
*/
function validateAddress($address)
{
$is_group = false;
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 (!isset($addresses)){
$this->error[] = 'Empty group.';
return false;
}
for ($i = 0; $i < count($addresses); $i++) {
$addresses[$i] = trim($addresses[$i]);
}
// Validate each mailbox.
// Format could be one of: name <[EMAIL PROTECTED]>
// [EMAIL PROTECTED]
// geezer
// ... or any other format valid by RFC 822.
array_walk($addresses, array($this, 'validateMailbox'));
// 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 $phrase The phrase to check.
*/
function validatePhrase($phrase)
{
// Splits on one or more Tab or space.
$parts = preg_split('/[ \\x09]+/', $phrase, 0, 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);
}
for ($i = 0; $i < count($phrase_parts); $i++) {
// If quoted string:
if (substr($phrase_parts[$i], 0, 1) == '"') {
if (!$this->validateQuotedString($phrase_parts[$i]))
return false;
continue;
}
// Otherwise it's an atom:
if (!$this->validateAtom($phrase_parts[$i])) return false;
}
return true;
}
/**
* Function to validate an atom which from rfc822 is:
* atom = 1*<any CHAR except specials, SPACE and CTLs>
*
* @access private
* @param $atom The string to check.
*/
function validateAtom($atom)
{
// 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 $qstring The string to check.
*/
function validateQuotedString($qstring)
{
// Leading and trailing "
$qstring = substr($qstring, 1, -1);
// Perform check.
return !(preg_match('/(.)[\x0D\\\\"]/', $qstring, $matches) && $matches[1] !=
'\\');
}
/**
* Function to validate a mailbox, which is:
* mailbox = addr-spec ; simple address
* / phrase route-addr ; name and route-addr
*
* @access private
* @param $mailbox The string to check.
*/
function validateMailbox(&$mailbox)
{
// A couple of defaults.
$phrase = '';
// 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();
$phrase !== '' ? $mbox->personal = $phrase : '';
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;
}
/**
* 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 $route_addr The string to check.
*/
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 $route The string to check.
*/
function validateRoute($route)
{
// Split on comma.
$domains = explode(',', trim($route));
for ($i = 0; $i < count($domains); $i++) {
$domains[$i] = str_replace('@', '', trim($domains[$i]));
if (!$this->validateDomain($domains[$i])) 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 $domain The string to check.
*/
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);
}
for ($i = 0; $i < count($sub_domains); $i++) {
if (!$this->validateSubdomain(trim($sub_domains[$i])))
return false;
}
// Managed to get here, so return input.
return $domain;
}
/**
* Function to validate a subdomain:
* subdomain = domain-ref / domain-literal
*
* @access private
* @param $subdomain The string to check.
*/
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 $dliteral The string to check.
*/
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 $addr_spec The string to check.
*/
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_host;
}
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 $local_part
*/
function validateLocalPart($local_part)
{
$parts = explode('.', $local_part);
// 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.
for ($i = 0; $i < count($words); $i++) {
if ($this->validatePhrase(trim($words[$i])) === false) return false;
}
// Managed to get here, so return the input.
return $local_part;
}
}
?>
Index: php4/pear/Mail/SMTP.php
+++ php4/pear/Mail/SMTP.php
<?php
//
// +----------------------------------------------------------------------+
// | PHP version 4.0 |
// +----------------------------------------------------------------------+
// | Copyright (c) 1997-2001 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 |
// | [EMAIL PROTECTED] so we can mail you a copy immediately. |
// +----------------------------------------------------------------------+
// | Authors: Chuck Hagenbuch <[EMAIL PROTECTED]> |
// +----------------------------------------------------------------------+
require_once 'Mail.php';
/**
* SMTP implementation of the PEAR Mail:: interface. Requires the PEAR
* Net_SMTP:: class.
*/
class Mail_SMTP extends Mail {
/**
* The SMTP host to connect to.
* @var string
*/
var $host = 'localhost';
/**
* The port the SMTP server is on.
* @var int
*/
var $port = 25;
/**
* Whether or not to attempt to authenticate to the SMTP server.
* @var boolean
*/
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 = '';
/**
* 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 Whether or not to use SMTP auth. Defaults to false.
* username The username to use for SMTP auth. No default.
* password The password to use for SMTP auth. No default.
*
* If a parameter is present in the $params array, it replaces the
* default.
*
* @param array Hash containing any parameters different from the
* defaults.
*/
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'];
}
/**
* Implements Mail::send() function using SMTP.
*
* @param mixed 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 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 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 (!($smtp = new Net_SMTP($this->host, $this->port))) { return new
PEAR_Error('unable to instantiate Net_SMTP object'); }
if (!$smtp->connect()) { return new PEAR_Error('unable to connect to smtp
server ' . $this->host . ':' . $this->port); }
if ($this->auth) {
if (!$smtp->auth($this->username, $this->password)) { return new
PEAR_Error('unable to authenticate to smtp server'); }
if (!$smtp->identifySender()) { return new PEAR_Error('unable to identify
smtp server'); }
}
list($from, $text_headers) = $this->prepareHeaders($headers);
if (!isset($from)) {
return new PEAR_Error('No from address given');
}
if (!($smtp->mailFrom($from))) { return new PEAR_Error('unable to set sender
to [' . $from . ']'); }
$recipients = $this->parseRecipients($recipients);
foreach($recipients as $recipient) {
if (!$smtp->rcptTo($recipient)) { return new PEAR_Error('unable to add
recipient [' . $recipient . ']'); }
}
if (!$smtp->data($text_headers . "\n" . $body)) { return new
PEAR_Error('unable to send data'); }
$smtp->disconnect();
return true;
}
}
?>
Index: php4/pear/Mail/Sendmail.php
+++ php4/pear/Mail/Sendmail.php
<?php
//
// +----------------------------------------------------------------------+
// | PHP version 4.0 |
// +----------------------------------------------------------------------+
// | Copyright (c) 1997-2001 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 |
// | [EMAIL PROTECTED] so we can mail you a copy immediately. |
// +----------------------------------------------------------------------+
// | Authors: Chuck Hagenbuch <[EMAIL PROTECTED]> |
// +----------------------------------------------------------------------+
require_once 'Mail.php';
/**
* Sendmail implementation of the PEAR Mail:: interface.
*/
class Mail_Sendmail extends Mail {
/**
* The location of the sendmail binary on the filesystem.
* @var string
*/
var $sendmail_path = '/usr/sbin/sendmail';
/**
* 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'.
*
* If a parameter is present in the $params array, it replaces the
* default.
*
* @param array Hash containing any parameters different from the
* defaults.
*/
function Mail_Sendmail($params)
{
if (isset($params['sendmail_path'])) $this->sendmail_path =
$params['sendmail_path'];
}
/**
* Implements Mail::send() function using the sendmail
* command-line binary.
*
* @param mixed 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 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 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 = escapeShellCmd(implode(' ',
$this->parseRecipients($recipients)));
list($from, $text_headers) = $this->prepareHeaders($headers);
if (!isset($from)) {
return new PEAR_Error('No from address given');
}
$result = 0;
if (@is_executable($this->sendmail_path)) {
$from = '"' . escapeShellCmd($from) . '"';
$mail = popen($this->sendmail_path . " -i -f$from -- $recipients", 'w');
fputs($mail, $text_headers);
fputs($mail, "\n"); // newline to end the headers section
fputs($mail, $body);
$result = pclose($mail) >> 8 & 0xFF; // need to shift the pclose result to
get the exit code
} else {
return new PEAR_Error('sendmail [' . $this->sendmail_path . '] not
executable');
}
// Return.
if ($result != 0) {
return new PEAR_Error('sendmail returned error code ' . $result);
}
return true;
}
}
?>
--
PHP CVS Mailing List (http://www.php.net/)
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]
To contact the list administrators, e-mail: [EMAIL PROTECTED]