forgot table tag
[squirrelmail.git] / functions / smtp.php
index 5e75527d6bfbf9584f022de6282066fb44887690..830b14ec36e393b2c557df6ae960e386dada297b 100644 (file)
@@ -12,9 +12,9 @@
  * $Id$
  */
 
-require_once('../functions/addressbook.php');
-require_once('../functions/plugin.php');
-require_once('../functions/prefs.php');
+require_once(SM_PATH . 'functions/addressbook.php');
+require_once(SM_PATH . 'functions/plugin.php');
+require_once(SM_PATH . 'functions/prefs.php');
 
 global $username, $popuser, $domain;
 
@@ -77,7 +77,6 @@ function expandAddrs ($array) {
     return $array;
 }
 
-
 /* looks up aliases in the addressbook and expands them to
  * the RFC 821 valid RCPT address. ie <user@example.com>
  * Adds @$domain if it wasn't in the address book and if it
@@ -110,8 +109,8 @@ function expandRcptAddrs ($array) {
 
 /* Attach the files that are due to be attached
  */
-function attachFiles ($fp, $session, $rn="\r\n") {
-    global $attachments, $attachment_dir, $username;
+function attachFiles ($fp, $session, $rn="\r\n", $checkdot = false) {
+    global $attachments, $attachment_dir, $username, $languages, $squirrelmail_language;
 
     $length = 0;
 
@@ -129,10 +128,16 @@ function attachFiles ($fp, $session, $rn="\r\n") {
                 $header = '--' . mimeBoundary() . "$rn";
                 if ( isset($info['remotefilename']) 
                      && $info['remotefilename'] != '') {
+                    $remotefilename = $info['remotefilename'];
+                    if (isset($languages[$squirrelmail_language]['XTRA_CODE']) && 
+                      function_exists($languages[$squirrelmail_language]['XTRA_CODE'])) {
+                        $remotefilename = 
+                            $languages[$squirrelmail_language]['XTRA_CODE']('encode', $remotefilename);
+                    }
                     $header .= "Content-Type: $filetype; name=\"" .
-                        $info['remotefilename'] . "\"$rn";
+                        encodeHeader($remotefilename) . "\"$rn";
                     $header .= "Content-Disposition: attachment; filename=\""
-                        . $info['remotefilename'] . "\"$rn";
+                        . encodeHeader($remotefilename) . "\"$rn";
                 } else {
                     $header .= "Content-Type: $filetype$rn";
                 }
@@ -147,34 +152,61 @@ function attachFiles ($fp, $session, $rn="\r\n") {
                 $file = fopen ($filename, 'rb');
                 if (substr($filetype, 0, 5) == 'text/' ||
                     substr($filetype, 0, 8) == 'message/' ) {
-                    $header .= "$rn";
-                    fputs ($fp, $header);
+                    $header .= $rn;
+                    if ($fp) {
+                       fputs ($fp, $header);
+                   }
                     $length += strlen($header);
+
+                   if ($checkdot) {
+                       $checkdot_begin=true;
+                   } else {
+                       $checkdot_begin=false;
+                   }
+
                     while ($tmp = fgets($file, 4096)) {
                         $tmp = str_replace("\r\n", "\n", $tmp);
                         $tmp = str_replace("\r", "\n", $tmp);
                         if ($rn == "\r\n"){
                             $tmp = str_replace("\n", "\r\n", $tmp);
                         }
-                        /**
-                         * Check if the last line has newline ($rn) in it
-                         * and append if it doesn't.
-                         */
-                        if (feof($fp) && !strstr($tmp, "$rn")){
-                            $tmp .= "$rn";
+                       if ($tmp{0} == '.' && $checkdot_begin) {
+                           $tmp = '.' . $tmp;
+                       }
+                       if ($checkdot) {
+                           $tmp = str_replace("\n.","\n..",$tmp);
+                       }
+                       
+                       $tmp_length = strlen($tmp);
+                       if ($tmp_length && $tmp{$tmp_length-1} == "\n" && $checkdot) {
+                           $checkdot_begin = true;
+                       } else {
+                           $checkdot_begin = false;
+                       }
+                       
+                       
+                        if ($fp) {
+                            fputs($fp, $tmp);
+                        }
+                        $length += $tmp_length;
+                    }
+                    if (substr($tmp, $tmp_length - strlen($rn), strlen($rn)) != $rn) {
+                        if ($fp) {
+                            fputs($fp, $rn);
                         }
-                        fputs($fp, $tmp);
-                        $length += strlen($tmp);
+                       $length += strlen($rn);
                     }
+
+
                 } else {
                     $header .= "Content-Transfer-Encoding: base64" 
                         . "$rn" . "$rn";
-                    fputs ($fp, $header);
+                    if ($fp) fputs ($fp, $header);
                     $length += strlen($header);
                     while ($tmp = fread($file, 570)) {
                         $encoded = chunk_split(base64_encode($tmp));
                         $length += strlen($encoded);
-                        fputs ($fp, $encoded);
+                        if ($fp) fputs ($fp, $encoded);
                     }
                 }
                 fclose ($file);
@@ -187,7 +219,7 @@ function attachFiles ($fp, $session, $rn="\r\n") {
 /* Delete files that are uploaded for attaching
  */
 function deleteAttachments($session) {
-    global $username, $attachments, $attachment_dir;
+    global $username, $attachments, $attachment_dir, $data_dir;
     $hashed_attachment_dir = getHashedDir($username, $attachment_dir);
 
     $rem_attachments = array();
@@ -202,6 +234,7 @@ function deleteAttachments($session) {
         }
     }
     $attachments = $rem_attachments;
+    setPref($data_dir, $username, 'attachments', serialize($attachments));
 }
 
 /* Return a nice MIME-boundary
@@ -245,18 +278,33 @@ function timezone () {
 }
 
 /* Print all the needed RFC822 headers */
-function write822Header ($fp, $t, $c, $b, $subject, $more_headers, $session, $rn="\r\n") {
-    global $REMOTE_ADDR, $SERVER_NAME, $REMOTE_PORT;
-    global $data_dir, $username, $popuser, $domain, $version, $useSendmail;
-    global $default_charset, $HTTP_VIA, $HTTP_X_FORWARDED_FOR;
-    global $REMOTE_HOST, $identity;
+function write822Header ($fp, $t, $c, $b, $subject, $body, $more_headers, $session, $rn="\r\n") {
+    global $data_dir, $username, $popuser, $domain, $version, $useSendmail,
+        $default_charset, $identity, $_SERVER;
 
     /* Storing the header to make sure the header is the same
      * everytime the header is printed.
      */
-    static $header, $headerlength;
+
+    /* get those globals */
+    $REMOTE_ADDR = $_SERVER['REMOTE_ADDR'];
+    $SERVER_NAME = $_SERVER['SERVER_NAME'];
+    $REMOTE_PORT = $_SERVER['REMOTE_PORT'];
+
+    if(isset($_SERVER['REMOTE_HOST'])) {
+        $REMOTE_HOST = $_SERVER['REMOTE_HOST'];
+    }
+    if(isset($_SERVER['HTTP_VIA'])) {
+        $HTTP_VIA = $_SERVER['HTTP_VIA'];
+    }
+    if(isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
+        $HTTP_X_FORWARDED_FOR = $_SERVER['HTTP_X_FORWARDED_FOR'];
+    }
+
+    static $header, $headerlength, $headerrn;
     
     if ($header == '') {
+               $headerrn = $rn;
         $to = expandAddrs(parseAddrs($t));
         $cc = expandAddrs(parseAddrs($c));
         $bcc = expandAddrs(parseAddrs($b));
@@ -372,23 +420,39 @@ function write822Header ($fp, $t, $c, $b, $subject, $more_headers, $session, $rn
             $header .= mimeBoundary();
             $header .= "\"$rn";
         } else {
+            if (strtolower($default_charset) == 'iso-2022-jp') {
+                if (mb_detect_encoding($body) == 'ASCII') {
+                    $header .= 'Content-Type: text/plain; US-ASCII' . $rn;
+                    $header .= "Content-Transfer-Encoding: 8bit" . $rn;
+                } else {
+                    $header .= 'Content-Type: '.$contentType . $rn;
+                    $header .= "Content-Transfer-Encoding: 7bit" . $rn;
+                }
+            } else {
             $header .= 'Content-Type: ' . $contentType . $rn;
             $header .= "Content-Transfer-Encoding: 8bit" . $rn;
         }
+        }
         $header .= $rn; // One blank line to separate header and body
         
         $headerlength = strlen($header);
     }     
+
+       if ($headerrn != $rn) {
+               $header = str_replace($headerrn, $rn, $header);
+        $headerlength = strlen($header);
+               $headerrn = $rn;
+       }
     
     /* Write the header */
-    fputs ($fp, $header);
+    if ($fp) fputs ($fp, $header);
     
     return $headerlength;
 }
 
 /* Send the body
  */
-function writeBody ($fp, $passedBody, $session, $rn="\r\n") {
+function writeBody ($fp, $passedBody, $session, $rn="\r\n", $checkdot = false) {
     global $default_charset;
 
     $attachmentlength = 0;
@@ -403,27 +467,48 @@ function writeBody ($fp, $passedBody, $session, $rn="\r\n") {
             $body .= "Content-Type: text/plain" . $rn;
         }
         
-        $body .= "Content-Transfer-Encoding: 8bit" . $rn . $rn;
-        $body .= $passedBody . $rn . $rn;
-        fputs ($fp, $body);
+        if (strtolower($default_charset) == 'iso-2022-jp') {
+            if (mb_detect_encoding($passedBody) == 'ASCII') {
+                $body .= "Content-Transfer-Encoding: 8bit" . $rn . $rn .
+                         $passedBody . $rn . $rn;
+            } else {
+                $body .= "Content-Transfer-Encoding: 7bit\r\n\r\n" .
+                         mb_convert_encoding($passedBody, 'JIS') . "\r\n\r\n";
+            }
+        } else {
+        $body .= "Content-Transfer-Encoding: 8bit" . $rn . $rn .
+                 $passedBody . $rn . $rn;
+        }
+        if ($fp) {
+           fputs ($fp, $body);
+       }
         
-        $attachmentlength = attachFiles($fp, $session, $rn);
+        $attachmentlength = attachFiles($fp, $session, $rn, $checkdot);
         
         if (!isset($postbody)) { 
             $postbody = ""; 
         }
         $postbody .= $rn . "--" . mimeBoundary() . "--" . $rn . $rn;
-        fputs ($fp, $postbody);
+        if ($fp) fputs ($fp, $postbody);
     } else {
-        $body = $passedBody . $rn;
-        fputs ($fp, $body);
+        if (strtolower($default_charset) == 'iso-2022-jp') {
+            $body = mb_convert_encoding($passedBody, 'JIS') . $rn;
+        } else {
+            $body = $passedBody . $rn;
+       }
+        if ($fp) {
+           fputs ($fp, $body);
+       }
         $postbody = $rn;
-        fputs ($fp, $postbody);
+        if ($fp) {
+           fputs ($fp, $postbody);
+       }
     }
 
     return (strlen($body) + strlen($postbody) + $attachmentlength);
 }
 
+
 /* Send mail using the sendmail command
  */
 function sendSendmail($t, $c, $b, $subject, $body, $more_headers, $session) {
@@ -448,9 +533,9 @@ function sendSendmail($t, $c, $b, $subject, $body, $more_headers, $session) {
         $fp = popen (escapeshellcmd("$sendmail_path -t -f$envelopefrom"), "w");
     }
     
-    $headerlength = write822Header ($fp, $t, $c, $b, $subject, 
+    $headerlength = write822Header ($fp, $t, $c, $b, $subject, $body,  
                                     $more_headers, $session, "\n");
-    $bodylength = writeBody($fp, $body, $session, "\n");
+    $bodylength = writeBody($fp, $body, $session, "\n", true);
     
     pclose($fp);
 
@@ -606,8 +691,8 @@ function sendSMTP($t, $c, $b, $subject, $body, $more_headers, $session) {
 
     /* Send the message */
     $headerlength = write822Header ($smtpConnection, $t, $c, $b, 
-                                    $subject, $more_headers, $session);
-    $bodylength = writeBody($smtpConnection, $body, $session);
+                                    $subject, $body, $more_headers, $session);
+    $bodylength = writeBody($smtpConnection, $body, $session,"\r\n", true);
     
     fputs($smtpConnection, ".\r\n"); /* end the DATA part */
     $tmp = fgets($smtpConnection, 1024);
@@ -716,14 +801,14 @@ function errorCheck($line, $smtpConnection, $verbose = false) {
     }
 
     if ($status == 0) {
-        include_once('../functions/page_header.php');
+        include_once(SM_PATH . 'functions/page_header.php');
         if ($compose_new_win == '1') {
             compose_Header($color, 'None');
         }
         else {
             displayPageHeader($color, 'None');
         }
-        include_once('../functions/display_messages.php');
+        include_once(SM_PATH . 'functions/display_messages.php');
         $lines = nl2br(htmlspecialchars($lines));
         $msg  = $message . "<br>\nServer replied: $lines";
         plain_error_message($msg, $color);
@@ -739,7 +824,7 @@ function calculate_references($refs, $inreplyto, $old_reply_to) {
     $refer = "";
     for ($i=1;$i<count($refs[0]);$i++) {
         if (!empty($refs[0][$i])) {
-            if (preg_match("/^References:(.+)$/", $refs[0][$i], $regs)) {
+            if (preg_match("/^References:(.+)$/UAi", $refs[0][$i], $regs)) {
                 $refer = trim($regs[1]);
             }
             else {   
@@ -747,6 +832,14 @@ function calculate_references($refs, $inreplyto, $old_reply_to) {
             }
         }
     }
+    $refer_a = explode(' ', $refer);
+    $refer = '';
+    foreach ($refer_a as $ref) {
+       $ref = trim($ref);
+       if ($ref && $ref{0} == '<' && $ref{(strlen($ref)-1)} == '>') {
+          $refer .= $ref . ' ';
+       }
+    }
     $refer = trim($refer);
     if (strlen($refer) > 2) {
         $refer .= ' ' . $inreplyto;
@@ -768,7 +861,7 @@ function sendMessage($t, $c, $b, $subject, $body, $reply_id, $MDN,
     global $useSendmail, $msg_id, $is_reply, $mailbox, $onetimepad,
         $data_dir, $username, $domain, $key, $version, $sent_folder, 
         $imapServerAddress, $imapPort, $default_use_priority, $more_headers, 
-        $request_mdn, $request_dr;
+        $request_mdn, $request_dr, $uid_support;
 
     $more_headers = Array();
     
@@ -779,14 +872,14 @@ function sendMessage($t, $c, $b, $subject, $body, $reply_id, $MDN,
 
     if (isset($reply_id) && $reply_id) {
         sqimap_mailbox_select ($imap_stream, $mailbox);
-        sqimap_messages_flag ($imap_stream, $reply_id, $reply_id, 'Answered');
+        sqimap_messages_flag ($imap_stream, $reply_id, $reply_id, 'Answered', true);
 
         /* Insert In-Reply-To and References headers if the
          * message-id of the message we reply to is set (longer than "<>")
          * The References header should really be the old Referenced header
          * with the message ID appended, and now it is (jmunro)
          */
-       $sid = sqimap_session_id(); 
+       $sid = sqimap_session_id($uid_support); 
        $query = "$sid FETCH $reply_id (BODY.PEEK[HEADER.FIELDS (Message-Id In-Reply-To)])\r\n";
        fputs ($imap_stream, $query);
        $read = sqimap_read_data($imap_stream, $sid, true, $response, $message);
@@ -826,37 +919,42 @@ function sendMessage($t, $c, $b, $subject, $body, $reply_id, $MDN,
     if ( $requestRecipt > 0) {
         $more_headers = array_merge($more_headers, createReceiptHeaders($requestRecipt));
     }
-
-    /* In order to remove the problem of users not able to create
-     * messages with "." on a blank line, RFC821 has made provision
-     * in section 4.5.2 (Transparency).
-     */
-    $body = ereg_replace("\n\\.", "\n..", $body);
-    $body = ereg_replace("^\\.", "..", $body);
-
-    /* this is to catch all plain \n instances and
-     * replace them with \r\n.  All newlines were converted
-     * into just \n inside the compose.php file.
-     * But only if delimiter is, in fact, \r\n.
-     */
-    
     if ($MDN) {
         $more_headers["Content-Type"] = "multipart/report; ".
             "report-type=disposition-notification;";
     }
-
+    $imap_body = $body; 
     if ($useSendmail) {
-        $length = sendSendmail($t, $c, $b, $subject, $body, $more_headers, 
+        /* In order to remove the problem of users not able to create
+         * messages with "." on a blank line, RFC821 has made provision
+         * in section 4.5.2 (Transparency).
+         */
+        if (($body && $body{0} == '.')) {
+            $body = '.' . $body;
+        }
+        $body = str_replace("\n.","\n..",$body);
+         $length = sendSendmail($t, $c, $b, $subject, $body, $more_headers, 
                                $session);
     } else {
-        $body = ereg_replace("\n", "\r\n", $body);
+       /* In order to remove the problem of users not able to create
+        * messages with "." on a blank line, RFC821 has made provision
+        * in section 4.5.2 (Transparency).
+        */
+       if (($body && $body{0} == '.')) {
+           $body = '.' . $body;
+       }
+       $body = str_replace("\n.","\n..",$body);
         $length = sendSMTP($t, $c, $b, $subject, $body, $more_headers, 
                            $session);
     }
     if (sqimap_mailbox_exists ($imap_stream, $sent_folder)) {
-        if ($useSendmail) $body = ereg_replace("\n", "\r\n", $body);
+        $body = $imap_body;
+        $body = ereg_replace("\n", "\r\n", $body);
+       $headerlength = write822Header (false, $t, $c, $b, $subject, $body, $more_headers, $session, "\r\n");
+       $bodylength = writeBody(false, $body, $session, "\r\n");
+       $length = $headerlength + $bodylength;
         sqimap_append ($imap_stream, $sent_folder, $length);
-        write822Header ($imap_stream, $t, $c, $b, $subject, $more_headers, 
+        write822Header ($imap_stream, $t, $c, $b, $subject, $body, $more_headers, 
                         $session);
         writeBody ($imap_stream, $body, $session);
         sqimap_append_done ($imap_stream);
@@ -868,7 +966,6 @@ function sendMessage($t, $c, $b, $subject, $body, $reply_id, $MDN,
     if ($length) {
         ClearAttachments($session);
     }
-
     return $length;
 }
 
@@ -877,17 +974,16 @@ function createPriorityHeaders($prio) {
     $prio_headers['X-Priority'] = $prio;
 
     switch($prio) {
-    case 1: $prio_headers['Importance'] = 'High';
-        $prio_headers['X-MSMail-Priority'] = 'High';
+    case 1: 
+        $prio_headers['Importance'] = 'High';
         break;
 
-    case 3: $prio_headers['Importance'] = 'Normal';
-        $prio_headers['X-MSMail-Priority'] = 'Normal';
+    case 3: 
+        $prio_headers['Importance'] = 'Normal';
         break;
 
     case 5:
         $prio_headers['Importance'] = 'Low';
-        $prio_headers['X-MSMail-Priority'] = 'Low';
         break;
     }
     return  $prio_headers;