/**
  * 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
  * of the SMTP message.
  *
  * @param Rfc822Header  $rfc822_header
  * @param Rfc822Header  $reply_rfc822_header
  * @param integer      &$raw_length length of the message
  *
  * @return string $header
  */
 function prepareRFC822_Header($rfc822_header, $reply_rfc822_header, &$raw_length)
 {
     global $domain, $version, $username, $skip_SM_header;
     /* if server var SERVER_NAME not available, use $domain */
     if (!sqGetGlobalVar('SERVER_NAME', $SERVER_NAME, SQ_SERVER)) {
         $SERVER_NAME = $domain;
     }
     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);
     $rn = "\r\n";
     /* This creates an RFC 822 date */
     $date = date('D, j M Y H:i:s ', mktime()) . $this->timezone();
     /* Create a message-id */
     $message_id = '<' . $REMOTE_PORT . '.' . $REMOTE_ADDR . '.';
     $message_id .= time() . '.squirrel@' . $SERVER_NAME . '>';
     /* Make an RFC822 Received: line */
     if (isset($REMOTE_HOST)) {
         $received_from = "{$REMOTE_HOST} ([{$REMOTE_ADDR}])";
     } else {
         $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})";
     }
     $header = array();
     if (!isset($skip_SM_header) || !$skip_SM_header) {
         $header[] = "Received: from {$received_from}" . $rn;
         $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;
     if ($reply_rfc822_header->message_id) {
         $rep_message_id = $reply_rfc822_header->message_id;
         //        $this->strip_crlf($message_id);
         $header[] = 'In-Reply-To: ' . $rep_message_id . $rn;
         $references = $this->calculate_references($reply_rfc822_header);
         $header[] = 'References: ' . $references . $rn;
     }
     $header[] = "Date: {$date}" . $rn;
     $header[] = 'Subject: ' . encodeHeader($rfc822_header->subject) . $rn;
     $header[] = 'From: ' . $rfc822_header->getAddr_s('from', ",{$rn} ", true) . $rn;
     // folding address list [From|To|Cc|Bcc] happens by using ",$rn<space>" as delimiter
     // Do not use foldLine for that.
     // RFC2822 if from contains more then 1 address
     if (count($rfc822_header->from) > 1) {
         $header[] = 'Sender: ' . $rfc822_header->getAddr_s('sender', ',', true) . $rn;
     }
     if (count($rfc822_header->to)) {
         $header[] = 'To: ' . $rfc822_header->getAddr_s('to', ",{$rn} ", true) . $rn;
     }
     if (count($rfc822_header->cc)) {
         $header[] = 'Cc: ' . $rfc822_header->getAddr_s('cc', ",{$rn} ", true) . $rn;
     }
     if (count($rfc822_header->reply_to)) {
         $header[] = 'Reply-To: ' . $rfc822_header->getAddr_s('reply_to', ',', true) . $rn;
     }
     /* Sendmail should return true. Default = false */
     $bcc = $this->getBcc();
     if (count($rfc822_header->bcc)) {
         $s = 'Bcc: ' . $rfc822_header->getAddr_s('bcc', ",{$rn} ", true) . $rn;
         if (!$bcc) {
             $raw_length += strlen($s);
         } else {
             $header[] = $s;
         }
     }
     /* Identify SquirrelMail */
     $header[] = 'User-Agent: SquirrelMail/' . $version . $rn;
     /* Do the MIME-stuff */
     $header[] = 'MIME-Version: 1.0' . $rn;
     $contenttype = 'Content-Type: ' . $rfc822_header->content_type->type0 . '/' . $rfc822_header->content_type->type1;
     if (count($rfc822_header->content_type->properties)) {
         foreach ($rfc822_header->content_type->properties as $k => $v) {
             if ($k && $v) {
                 $contenttype .= ';' . $k . '=' . $v;
             }
         }
     }
     $header[] = $contenttype . $rn;
     if ($encoding = $rfc822_header->encoding) {
         $header[] .= 'Content-Transfer-Encoding: ' . $encoding . $rn;
     }
     if ($rfc822_header->dnt) {
         $dnt = $rfc822_header->getAddr_s('dnt');
         /* Pegasus Mail */
         $header[] = 'X-Confirm-Reading-To: ' . $dnt . $rn;
         /* RFC 2298 */
         $header[] = 'Disposition-Notification-To: ' . $dnt . $rn;
     }
     if ($rfc822_header->priority) {
         switch ($rfc822_header->priority) {
             case 1:
                 $header[] = 'X-Priority: 1 (Highest)' . $rn;
                 $header[] = 'Importance: High' . $rn;
                 break;
             case 3:
                 $header[] = 'X-Priority: 3 (Normal)' . $rn;
                 $header[] = 'Importance: Normal' . $rn;
                 break;
             case 5:
                 $header[] = 'X-Priority: 5 (Lowest)' . $rn;
                 $header[] = 'Importance: Low' . $rn;
                 break;
             default:
                 break;
         }
     }
     /* Insert headers from the $more_headers array */
     if (count($rfc822_header->more_headers)) {
         reset($rfc822_header->more_headers);
         foreach ($rfc822_header->more_headers as $k => $v) {
             $header[] = $k . ': ' . $v . $rn;
         }
     }
     $cnt = count($header);
     $hdr_s = '';
     for ($i = 0; $i < $cnt; $i++) {
         $sKey = substr($header[$i], 0, strpos($header[$i], ':'));
         switch ($sKey) {
             case 'Message-ID':
             case 'In-Reply_To':
                 $hdr_s .= $header[$i];
                 break;
             case 'References':
                 $sRefs = substr($header[$i], 12);
                 $aRefs = explode(' ', $sRefs);
                 $sLine = 'References:';
                 foreach ($aRefs as $sReference) {
                     if (strlen($sLine) + strlen($sReference) > 76) {
                         $hdr_s .= $sLine;
                         $sLine = $rn . '    ' . $sReference;
                     } else {
                         $sLine .= ' ' . $sReference;
                     }
                 }
                 $hdr_s .= $sLine;
                 break;
             case 'To':
             case 'Cc':
             case 'Bcc':
             case 'From':
                 $hdr_s .= $header[$i];
                 break;
             default:
                 $hdr_s .= $this->foldLine($header[$i], 78, str_pad('', 4));
                 break;
         }
     }
     $header = $hdr_s;
     $header .= $rn;
     /* One blank line to separate header and body */
     $raw_length += strlen($header);
     return $header;
 }
Пример #2
0
 /**
  * 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
  * of the SMTP message.
  *
  * @param Rfc822Header  $rfc822_header
  * @param Rfc822Header  $reply_rfc822_header
  * @param integer      &$raw_length length of the message
  *
  * @return string $header
  */
 function prepareRFC822_Header(&$rfc822_header, $reply_rfc822_header, &$raw_length)
 {
     global $domain, $version, $username, $encode_header_key, $edit_identity, $hide_auth_header;
     if (!isset($hide_auth_header)) {
         $hide_auth_header = false;
     }
     /* if server var SERVER_NAME not available, use $domain */
     if (!sqGetGlobalVar('SERVER_NAME', $SERVER_NAME, SQ_SERVER)) {
         $SERVER_NAME = $domain;
     }
     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);
     $rn = "\r\n";
     /* This creates an RFC 822 date */
     $date = date('D, j M Y H:i:s ', time()) . $this->timezone();
     /* Create a message-id */
     $message_id = 'MESSAGE ID GENERATION ERROR! PLEASE CONTACT SQUIRRELMAIL DEVELOPERS';
     if (empty($rfc822_header->message_id)) {
         $message_id = '<';
         /* user-specifc data to decrease collision chance */
         $seed_data = $username . '.';
         $seed_data .= !empty($REMOTE_PORT) ? $REMOTE_PORT . '.' : '';
         $seed_data .= !empty($REMOTE_ADDR) ? $REMOTE_ADDR . '.' : '';
         /* add the current time in milliseconds and randomness */
         $seed_data .= uniqid(mt_rand(), true);
         /* put it through one-way hash and add it to the ID */
         $message_id .= md5($seed_data) . '.squirrel@' . $SERVER_NAME . '>';
     }
     /* Make an RFC822 Received: line */
     if (isset($REMOTE_HOST)) {
         $received_from = "{$REMOTE_HOST} ([{$REMOTE_ADDR}])";
     } else {
         $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})";
     }
     $header = array();
     /**
      * SquirrelMail header
      *
      * 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.
      */
     // FIXME: The following headers may generate slightly differently between the message sent to the destination and that stored in the Sent folder because this code will be called before both actions.  This is not necessarily a big problem, but other headers such as Message-ID and Date are preserved between both actions
     if (isset($encode_header_key) && trim($encode_header_key) != '') {
         // use encoded headers, if encryption key is set and not empty
         $header[] = 'X-Squirrel-UserHash: ' . OneTimePadEncrypt($username, base64_encode($encode_header_key)) . $rn;
         $header[] = 'X-Squirrel-FromHash: ' . OneTimePadEncrypt($this->ip2hex($REMOTE_ADDR), base64_encode($encode_header_key)) . $rn;
         if (isset($HTTP_X_FORWARDED_FOR)) {
             $header[] = 'X-Squirrel-ProxyHash:' . OneTimePadEncrypt($this->ip2hex($HTTP_X_FORWARDED_FOR), base64_encode($encode_header_key)) . $rn;
         }
     } else {
         // 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 */
     if (!empty($rfc822_header->message_id)) {
         $header[] = 'Message-ID: ' . $rfc822_header->message_id . $rn;
     } else {
         $header[] = 'Message-ID: ' . $message_id . $rn;
         $rfc822_header->message_id = $message_id;
     }
     if (is_object($reply_rfc822_header) && isset($reply_rfc822_header->message_id) && $reply_rfc822_header->message_id) {
         //if ($reply_rfc822_header->message_id) {
         $rep_message_id = $reply_rfc822_header->message_id;
         $header[] = 'In-Reply-To: ' . $rep_message_id . $rn;
         $rfc822_header->in_reply_to = $rep_message_id;
         $references = $this->calculate_references($reply_rfc822_header);
         $header[] = 'References: ' . $references . $rn;
         $rfc822_header->references = $references;
     }
     if (!empty($rfc822_header->date) && $rfc822_header->date != -1) {
         $header[] = 'Date: ' . $rfc822_header->date . $rn;
     } else {
         $header[] = "Date: {$date}" . $rn;
         $rfc822_header->date = $date;
     }
     $header[] = 'Subject: ' . encodeHeader($rfc822_header->subject) . $rn;
     // folding address list [From|To|Cc|Bcc] happens by using ",$rn<space>"
     // as delimiter
     // Do not use foldLine for that.
     $header[] = 'From: ' . $rfc822_header->getAddr_s('from', ",{$rn} ", true) . $rn;
     // RFC2822 if from contains more then 1 address
     if (count($rfc822_header->from) > 1) {
         $header[] = 'Sender: ' . $rfc822_header->getAddr_s('sender', ',', true) . $rn;
     }
     if (count($rfc822_header->to)) {
         $header[] = 'To: ' . $rfc822_header->getAddr_s('to', ",{$rn} ", true) . $rn;
     }
     if (count($rfc822_header->cc)) {
         $header[] = 'Cc: ' . $rfc822_header->getAddr_s('cc', ",{$rn} ", true) . $rn;
     }
     if (count($rfc822_header->reply_to)) {
         $header[] = 'Reply-To: ' . $rfc822_header->getAddr_s('reply_to', ',', true) . $rn;
     }
     /* Sendmail should return true. Default = false */
     $bcc = $this->getBcc();
     if (count($rfc822_header->bcc)) {
         $s = 'Bcc: ' . $rfc822_header->getAddr_s('bcc', ",{$rn} ", true) . $rn;
         if (!$bcc) {
             $raw_length += strlen($s);
         } else {
             $header[] = $s;
         }
     }
     /* Identify SquirrelMail */
     $header[] = 'User-Agent: SquirrelMail/' . $version . $rn;
     /* Do the MIME-stuff */
     $header[] = 'MIME-Version: 1.0' . $rn;
     $contenttype = 'Content-Type: ' . $rfc822_header->content_type->type0 . '/' . $rfc822_header->content_type->type1;
     if (count($rfc822_header->content_type->properties)) {
         foreach ($rfc822_header->content_type->properties as $k => $v) {
             if ($k && $v) {
                 $contenttype .= ';' . $k . '=' . $v;
             }
         }
     }
     $header[] = $contenttype . $rn;
     if ($encoding = $rfc822_header->encoding) {
         $header[] = 'Content-Transfer-Encoding: ' . $encoding . $rn;
     }
     if ($rfc822_header->dnt) {
         $dnt = $rfc822_header->getAddr_s('dnt');
         /* Pegasus Mail */
         $header[] = 'X-Confirm-Reading-To: ' . $dnt . $rn;
         /* RFC 2298 */
         $header[] = 'Disposition-Notification-To: ' . $dnt . $rn;
     }
     if ($rfc822_header->priority) {
         switch ($rfc822_header->priority) {
             case 1:
                 $header[] = 'X-Priority: 1 (Highest)' . $rn;
                 $header[] = 'Importance: High' . $rn;
                 break;
             case 3:
                 $header[] = 'X-Priority: 3 (Normal)' . $rn;
                 $header[] = 'Importance: Normal' . $rn;
                 break;
             case 5:
                 $header[] = 'X-Priority: 5 (Lowest)' . $rn;
                 $header[] = 'Importance: Low' . $rn;
                 break;
             default:
                 break;
         }
     }
     /* Insert headers from the $more_headers array */
     if (count($rfc822_header->more_headers)) {
         reset($rfc822_header->more_headers);
         foreach ($rfc822_header->more_headers as $k => $v) {
             $header[] = $k . ': ' . $v . $rn;
         }
     }
     $cnt = count($header);
     $hdr_s = '';
     for ($i = 0; $i < $cnt; $i++) {
         $sKey = substr($header[$i], 0, strpos($header[$i], ':'));
         switch ($sKey) {
             case 'Message-ID':
             case 'In-Reply_To':
                 $hdr_s .= $header[$i];
                 break;
             case 'References':
                 $sRefs = substr($header[$i], 12);
                 $aRefs = explode(' ', $sRefs);
                 $sLine = 'References:';
                 foreach ($aRefs as $sReference) {
                     if (trim($sReference) == '') {
                         /* Don't add spaces. */
                     } elseif (strlen($sLine) + strlen($sReference) > 76) {
                         $hdr_s .= $sLine;
                         $sLine = $rn . '    ' . $sReference;
                     } else {
                         $sLine .= ' ' . $sReference;
                     }
                 }
                 $hdr_s .= $sLine;
                 break;
             case 'To':
             case 'Cc':
             case 'Bcc':
             case 'From':
                 $hdr_s .= $header[$i];
                 break;
             default:
                 $hdr_s .= $this->foldLine($header[$i], 78);
                 break;
         }
     }
     $header = $hdr_s;
     $header .= $rn;
     /* One blank line to separate header and body */
     $raw_length += strlen($header);
     return $header;
 }