modifing PEAR Mail so we can use return paths
| From: | Alex Hayes | Date: | Tue, 27 May 2003 01:39:23 +0000 |
| Subject: | modifing PEAR Mail so we can use return paths | ||
| Groups: | php.pear.dev | ||
| Request: | Send a blank email to pear-dev+get-16735@lists.php.net to get a copy of this message | ||
hello everyone...
Perhaps this has already been suggested (or perhaps im going down the wrong
path.....?), however I couldnt find anything on the dev mailing list..
I think that there can be changes made to the PEAR's Mail class(s) that
would allow people to define the Return-Path properly without it being
overwritten as the From path as currently happens.
For example if I set the headers as follows;
$hdrs = array('To' => 'Alex Hayes <alex@alution.com>',
'Return-Path' => 'bounce.processor@alution.com',
'From' => 'MY NEWS STUF...
<alexhayes@alution.com>',
'Subject' => 'Hello');
The Return-Path doesnt get used properly. This is because the implementation
of the mail classes IE. Mail/sendmail.php overwrite the return path by using
the -f argument, as follows...
$mail = popen($this->sendmail_path . (!empty($this->sendmail_args) ? ' ' .
$this->sendmail_args : '') . " -f$from -- $recipients", 'w');
As most will realise, the -f$from will overwrite the return path to whatever
$from is equal to. I believe that it would be more sensible to use the
return path that was defined by the header. This is also the same for some
other mail backends, such as qmail.
I realise that it is possible to send on non bounces to human addresses in
most mta's, however I think that it would make more sense, if the
return-path specified in the header was actually the return-path used....
This will not effect backwards compatibility as we can do the following in
Mail.php... Hopefully someone can notice my changes... il put /* CHANGE */
/* / CHANGE */ around them...
>> (...)-----------------------------
function prepareHeaders($headers)
{
// Look out for the From: value to use along the way.
$text_headers = ''; // text representation of headers
$from = null;
foreach ($headers as $key => $val) {
if ($key == 'From') {
include_once 'Mail/RFC822.php';
$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.
return false;
}
$text_headers .= $key . ': ' . $val . "\n";
} else if ($key == 'Received') {
// put Received: headers at the top, since Receieved:
// after Subject: in the header order is somtimes used
// as a spam trap.
$text_headers = $key . ': ' . $val . "\n" . $text_headers;
/* CHANGE */
} else if ($key == 'Return-Path') {
// NOTE: we now try and get the Return-Path, so that if we
need to we can
// bounce the message back to the Return-Path rather
than the from address
// which can be useful. If there is no Return-Path
specified however,
// the Return-Path should default to the From address.
include_once 'Mail/RFC822.php';
$return_path_arr = Mail_RFC822::parseAddressList($val,
'localhost', false);
$return_path = $return_path_arr[0]->mailbox . '@' .
$return_path_arr[0]->host;
if (strstr($return_path, ' ')) {
// Reject outright envelope From addresses with spaces.
return false;
}
$text_headers .= $key . ': ' . $val . "\n";
/* / CHANGE */
} else {
$text_headers .= $key . ': ' . $val . "\n";
}
}
/* CHANGE */
// If there is no return path set, defaults to the From address.
if(!is_set($return_path)) {
$return_path = $from;
}
return array($from, $text_headers, $return_path);
/* /CHANGE */
-----------------------------(...)<<
Then with our sendmail implementation of the mail class we can do the
following...
>> (...)-----------------------------
function send($recipients, $headers, $body)
{
$recipients = escapeShellCmd(implode(' ',
$this->parseRecipients($recipients)));
/* CHANGE */
list($from, $text_headers, $return_path) =
$this->prepareHeaders($headers);
/* / CHANGE */
if (!isset($from)) {
return new PEAR_Error('No from address given.');
} elseif (strstr($from, ' ') ||
strstr($from, ';') ||
strstr($from, '&') ||
strstr($from, '`')) {
return new PEAR_Error('From address specified with dangerous
characters.');
}
$result = 0;
if (@is_executable($this->sendmail_path)) {
$from = escapeShellCmd($from);
/* CHANGE */
$return_path = escapeShellCmd($return_path);
$mail = popen($this->sendmail_path .
(!empty($this->sendmail_args) ? ' ' . $this->sendmail_args : '') .
" -f$return_path -- $recipients", 'w');
/* /CHANGE */
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');
}
if ($result != 0) {
return new PEAR_Error('sendmail returned error code ' .
$result);
}
return true;
}
-----------------------------(...)<<
If this was done for a reason then that is fine... maybe i totally missed
the point.... Also in question is whether or not we should check for
dangerous characters in the return-path, as is done with the from path...
any suggestions?
thanks alex