Source for file Deliver.class.php
Documentation is available at Deliver.class.php
* This contains all the functions needed to send messages through
* @author Marc Groot Koerkamp
* @copyright © 1999-2006 The SquirrelMail Project Team
* @license http://opensource.org/licenses/gpl-license.php GNU Public License
* @version $Id: Deliver.class.php,v 1.65 2006/07/15 12:00:44 tokul Exp $
* Deliver Class - called to actually deliver the message
* This class is called by compose.php and other code that needs
* to send messages. All delivery functionality should be centralized
* Do not place UI code in this class, as UI code should be placed in templates
* @author Marc Groot Koerkamp
* function mail - send the message parts to the SMTP stream
* @param Message $message Message class to send
* @param resource $stream file handle to the SMTP stream
* @return integer $raw_length
function mail($message, $stream=
false) {
$rfc822_header =
$message->rfc822_header;
if (count($message->entities)) {
$rfc822_header->content_type->properties['boundary']=
'"'.
$boundary.
'"';
$reply_rfc822_header =
(isset
($message->reply_rfc822_header)
?
$message->reply_rfc822_header :
'');
$this->writeBody($message, $stream, $raw_length, $boundary);
* function writeBody - generate and write the mime boundaries around each part to the stream
* Recursively formats and writes the MIME boundaries of the $message
* @param Message $message Message object to transform
* @param resource $stream SMTP output stream
* @param integer &$length_raw raw length of the message (part)
* @param string $boundary custom boundary to call, usually for subparts
function writeBody($message, $stream, &$length_raw, $boundary=
'') {
// calculate boundary in case of multidimensional mime structures
if ($boundary &&
$message->entity_id &&
count($message->entities)) {
if (strpos($boundary,'_part_')) {
// the next four lines use strrev to reverse any nested boundaries
// because RFC 2046 (5.1.1) says that if a line starts with the outer
// boundary string (doesn't matter what the line ends with), that
// can be considered a match for the outer boundary; thus the nested
// boundary needs to be unique from the outer one
} else if (strpos($boundary,'_trap_')) {
$boundary_new =
strrev($boundary .
'_part_'.
$message->entity_id);
$boundary_new =
$boundary;
if ($boundary &&
!$message->rfc822_header) {
$s =
'--'.
$boundary.
"\r\n";
for ($i=
0, $entCount=
count($message->entities);$i<
$entCount;$i++
) {
$msg =
$this->writeBody($message->entities[$i], $stream, $length_raw, $boundary_new);
if ($i ==
$entCount-
1) $last =
true;
if ($boundary &&
$last) {
$s =
"--".
$boundary_new.
"--\r\n\r\n";
* function writeBodyPart - write each individual mimepart
* Recursively called by WriteBody to write each mime part to the SMTP stream
* @param Message $message Message object to transform
* @param resource $stream SMTP output stream
* @param integer &$length length of the message part
if ($message->mime_header) {
$type0 =
$message->mime_header->type0;
$type0 =
$message->rfc822_header->content_type->type0;
$body_part_trailing =
$last =
'';
if ($message->body_part) {
$body_part =
$message->body_part;
} elseif ($message->att_local_name) {
$filename =
$message->att_local_name;
$file =
fopen ($filename, 'rb');
while ($body_part =
fgets($file, 4096)) {
if ($message->body_part) {
$body_part =
$message->body_part;
} elseif ($message->att_local_name) {
$filename =
$message->att_local_name;
$file =
fopen ($filename, 'rb');
while ($tmp =
fread($file, 570)) {
// Up to 4.3.10 chunk_split always appends a newline,
// while in 4.3.11 it doesn't if the string to split
// is shorter than the chunk length.
if( substr($body_part, -
1 , 1 ) !=
"\n" )
$body_part_trailing =
'';
if ($last &&
substr($last,-
1) !=
"\n") {
$body_part_trailing =
"\r\n";
if ($body_part_trailing) {
$length +=
strlen($body_part_trailing);
* function clean_crlf - change linefeeds and newlines to legal characters
* The SMTP format only allows CRLF as line terminators.
* This function replaces illegal teminators with the correct terminator.
* @param string &$s string to clean linefeeds on
* function strip_crlf - strip linefeeds and newlines from a string
* The SMTP format only allows CRLF as line terminators.
* This function strips all line terminators from the string.
* @param string &$s string to clean linefeeds on
* function preWriteToStream - reserved for extended functionality
* This function is not yet implemented.
* Reserved for extended functionality.
* @param string &$s string to operate on
* function writeToStream - write data to the SMTP stream
* @param resource $stream SMTP output stream
* @param string $data string with data to send to the SMTP stream
* function initStream - reserved for extended functionality
* This function is not yet implemented.
* Reserved for extended functionality.
* @param Message $message Message object
* @param string $host host name or IP to connect to
* @param string $user username to log into the SMTP server with
* @param string $pass password to log into the SMTP server with
* @return handle $stream file handle resource to SMTP stream
function initStream($message, $length=
0, $host=
'', $port=
'', $user=
'', $pass=
'') {
* function getBCC - reserved for extended functionality
* This function is not yet implemented.
* Reserved for extended functionality.
* function prepareMIME_Header - creates the mime header
* @param Message $message Message object to act on
* @param string $boundary mime boundary from fn MimeBoundary
* @return string $header properly formatted mime header
$mime_header =
$message->mime_header;
$contenttype =
'Content-Type: '.
$mime_header->type0 .
'/'.
if (count($message->entities)) {
$contenttype .=
';' .
'boundary="'.
$boundary.
'"';
if (isset
($mime_header->parameters['name'])) {
$contenttype .=
'; name="'.
if (isset
($mime_header->parameters['charset'])) {
$charset =
$mime_header->parameters['charset'];
$contenttype .=
'; charset="'.
$header[] =
$contenttype .
$rn;
if ($mime_header->description) {
$header[] =
'Content-Description: ' .
$mime_header->description .
$rn;
if ($mime_header->encoding) {
$header[] =
'Content-Transfer-Encoding: ' .
$mime_header->encoding .
$rn;
if ($mime_header->type0 ==
'text' ||
$mime_header->type0 ==
'message') {
$header[] =
'Content-Transfer-Encoding: 8bit' .
$rn;
$header[] =
'Content-Transfer-Encoding: base64' .
$rn;
$header[] =
'Content-ID: ' .
$mime_header->id .
$rn;
if ($mime_header->disposition) {
$disposition =
$mime_header->disposition;
$contentdisp =
'Content-Disposition: ' .
$disposition->name;
if ($disposition->getProperty('filename')) {
$contentdisp .=
'; filename="'.
$header[] =
$contentdisp .
$rn;
$header[] =
'Content-MD5: ' .
$mime_header->md5 .
$rn;
if ($mime_header->language) {
$header[] =
'Content-Language: ' .
$mime_header->language .
$rn;
for ($i =
0 ; $i <
$cnt ; $i++
) {
$header .=
$rn; /* One blank line to separate mimeheader and body-entity */
* function prepareRFC822_Header - prepares the RFC822 header string from Rfc822Header object(s)
* This function takes the Rfc822Header object(s) and formats them
* into the RFC822Header string to send to the SMTP server as part
* @param Rfc822Header $rfc822_header
* @param Rfc822Header $reply_rfc822_header
* @param integer &$raw_length length of the message
/* if server var SERVER_NAME not available, use $domain */
if(!sqGetGlobalVar('SERVER_NAME', $SERVER_NAME, SQ_SERVER)) {
sqGetGlobalVar('REMOTE_ADDR', $REMOTE_ADDR, SQ_SERVER);
sqGetGlobalVar('REMOTE_PORT', $REMOTE_PORT, SQ_SERVER);
sqGetGlobalVar('REMOTE_HOST', $REMOTE_HOST, SQ_SERVER);
sqGetGlobalVar('HTTP_VIA', $HTTP_VIA, SQ_SERVER);
sqGetGlobalVar('HTTP_X_FORWARDED_FOR', $HTTP_X_FORWARDED_FOR, SQ_SERVER);
/* This creates an RFC 822 date */
/* Create a message-id */
$message_id =
'<' .
$REMOTE_PORT .
'.';
if (isset
($encode_header_key) &&
trim($encode_header_key)!=
'') {
// use encrypted form of remote address
$message_id.=
$REMOTE_ADDR;
$message_id .=
'.' .
time() .
'.squirrel@' .
$SERVER_NAME .
'>';
/* Make an RFC822 Received: line */
if (isset
($REMOTE_HOST)) {
$received_from =
"$REMOTE_HOST ([$REMOTE_ADDR])";
$received_from =
$REMOTE_ADDR;
if (isset
($HTTP_VIA) || isset
($HTTP_X_FORWARDED_FOR)) {
if (!isset
($HTTP_X_FORWARDED_FOR) ||
$HTTP_X_FORWARDED_FOR ==
'') {
$HTTP_X_FORWARDED_FOR =
'unknown';
$received_from .=
" (proxying for $HTTP_X_FORWARDED_FOR)";
* This Received: header provides information that allows to track
* user and machine that was used to send email. Don't remove it
* unless you understand all possible forging issues or your
* webmail installation does not prevent changes in user's email address.
* See SquirrelMail bug tracker #847107 for more details about it.
* Add $hide_squirrelmail_header as a candidate for config_local.php
* to allow completely hiding SquirrelMail participation in message
* processing; This is dangerous, especially if users can modify their
* account information, as it makes mapping a sent message back to the
* original sender almost impossible.
$show_sm_header =
( defined('hide_squirrelmail_header') ?
! hide_squirrelmail_header :
1 );
if (isset
($encode_header_key) &&
trim($encode_header_key)!=
'') {
// use encoded headers, if encryption key is set and not empty
if (isset
($HTTP_X_FORWARDED_FOR))
// use default received headers
$header[] =
"Received: from $received_from" .
$rn;
if ($edit_identity ||
! isset
($hide_auth_header) ||
! $hide_auth_header)
$header[] =
" (SquirrelMail authenticated user $username)" .
$rn;
$header[] =
" by $SERVER_NAME with HTTP;" .
$rn;
$header[] =
" $date" .
$rn;
/* Insert the rest of the header fields */
$header[] =
'Message-ID: '.
$message_id .
$rn;
isset
($reply_rfc822_header->message_id) &&
$reply_rfc822_header->message_id) {