From cb2bc809ef29f349d38c89e202d821e67bb4c947 Mon Sep 17 00:00:00 2001
From: thomascube <thomas@roundcube.net>
Date: Tue, 21 Sep 2010 14:47:55 -0400
Subject: [PATCH] Fix db_mode check in insert_id()

---
 program/steps/mail/func.inc |  369 ++++++++++++++++++++++++++++++++++++----------------
 1 files changed, 255 insertions(+), 114 deletions(-)

diff --git a/program/steps/mail/func.inc b/program/steps/mail/func.inc
index a63b509..91fd05e 100644
--- a/program/steps/mail/func.inc
+++ b/program/steps/mail/func.inc
@@ -26,8 +26,8 @@
 
 $EMAIL_ADDRESS_PATTERN = '([a-z0-9][a-z0-9\-\.\+\_]*@[a-z0-9][a-z0-9\-\.]*\\.[a-z]{2,5})';
 
-// actions that do not require imap connection
-$NOIMAP_ACTIONS = array('addcontact', 'autocomplete', 'upload', 'display-attachment', 'remove-attachment');
+// actions that do not require imap connection here
+$NOIMAP_ACTIONS = array('addcontact', 'autocomplete', 'upload', 'display-attachment', 'remove-attachment', 'get');
 
 // always instantiate imap object (but not yet connect to server)
 $RCMAIL->imap_init();
@@ -130,7 +130,7 @@
 
   if (!$OUTPUT->ajax_call)
     $OUTPUT->add_label('checkingmail', 'deletemessage', 'movemessagetotrash',
-      'movingmessage', 'copyingmessage', 'copy', 'move');
+      'movingmessage', 'copyingmessage', 'copy', 'move', 'quota');
 
   $OUTPUT->set_pagetitle(rcmail_localize_foldername($mbox_name));
   }
@@ -171,7 +171,9 @@
       && (($f = array_search('from', $a_show_cols)) !== false) && array_search('to', $a_show_cols) === false)
     $a_show_cols[$f] = 'to';
 
-  // make sure 'threads' column is present 
+  // make sure 'threads' and 'subject' columns are present
+  if (!in_array('subject', $a_show_cols))
+    array_unshift($a_show_cols, 'subject');
   if (!in_array('threads', $a_show_cols))
     array_unshift($a_show_cols, 'threads');
 
@@ -223,28 +225,41 @@
 
 /**
  * return javascript commands to add rows to the message list
- * or to replace the whole list (IE only)
  */
-function rcmail_js_message_list($a_headers, $insert_top=FALSE, $head_replace=FALSE)
+function rcmail_js_message_list($a_headers, $insert_top=FALSE, $a_show_cols=null)
 {
   global $CONFIG, $IMAP, $RCMAIL, $OUTPUT;
 
-  if (!empty($_SESSION['list_attrib']['columns']))
-    $a_show_cols = $_SESSION['list_attrib']['columns'];
-  else
-    $a_show_cols = is_array($CONFIG['list_cols']) ? $CONFIG['list_cols'] : array('subject');
+  if (empty($a_show_cols)) {
+    if (!empty($_SESSION['list_attrib']['columns']))
+      $a_show_cols = $_SESSION['list_attrib']['columns'];
+    else
+      $a_show_cols = is_array($CONFIG['list_cols']) ? $CONFIG['list_cols'] : array('subject');
+  }
+  else {
+    if (!is_array($a_show_cols))
+      $a_show_cols = preg_split('/[\s,;]+/', strip_quotes($a_show_cols));
+    $head_replace = true;
+  }
 
   $mbox = $IMAP->get_mailbox_name();
   $delim = $IMAP->get_hierarchy_delimiter();
+
+  // make sure 'threads' and 'subject' columns are present
+  if (!in_array('subject', $a_show_cols))
+    array_unshift($a_show_cols, 'subject');
+  if (!in_array('threads', $a_show_cols))
+    array_unshift($a_show_cols, 'threads');
+
+  $_SESSION['list_attrib']['columns'] = $a_show_cols;
 
   // show 'to' instead of 'from' in sent/draft messages
   if ((strpos($mbox.$delim, $CONFIG['sent_mbox'].$delim)===0 || strpos($mbox.$delim, $CONFIG['drafts_mbox'].$delim)===0)
       && (($f = array_search('from', $a_show_cols)) !== false) && array_search('to', $a_show_cols) === false)
     $a_show_cols[$f] = 'to';
 
-  // make sure 'threads' column is present 
-  if (!in_array('threads', $a_show_cols))
-    array_unshift($a_show_cols, 'threads');
+  // Make sure there are no duplicated columns (#1486999)
+  $a_show_cols = array_unique($a_show_cols);
 
   // Plugins may set header's list_cols/list_flags and other rcube_mail_header variables
   // and list columns
@@ -321,7 +336,7 @@
       $a_msg_flags['forwarded'] = 1;
     if ($header->flagged)
       $a_msg_flags['flagged'] = 1;
-    if(preg_match("/multipart\/m/i", $header->ctype))
+    if (preg_match("/(application\/|multipart\/m)/i", $header->ctype))
       $a_msg_flags['attachment'] = 1;
     $a_msg_flags['mbox'] = $mbox;
 
@@ -407,14 +422,15 @@
  */
 function rcmail_messagecontent_frame($attrib)
   {
-  global $OUTPUT;
+  global $OUTPUT, $RCMAIL;
 
   if (empty($attrib['id']))
     $attrib['id'] = 'rcmailcontentwindow';
 
   $attrib['name'] = $attrib['id'];
 
-  $OUTPUT->set_env('contentframe', $attrib['id']);
+  if ($RCMAIL->config->get('preview_pane'))
+    $OUTPUT->set_env('contentframe', $attrib['id']);
   $OUTPUT->set_env('blankpage', $attrib['src'] ? $OUTPUT->abs_url($attrib['src']) : 'program/blank.gif');
 
   return html::iframe($attrib);
@@ -448,13 +464,10 @@
 
   $quota = rcmail_quota_content($attrib);
 
-  if (is_array($quota)) {
-    $OUTPUT->add_script('$(document).ready(function(){
+  $OUTPUT->add_script('$(document).ready(function(){
 	rcmail.set_quota('.json_serialize($quota).')});', 'foot');
-    $quota = '';
-    }
 
-  return html::span($attrib, $quota);
+  return html::span($attrib, '');
   }
 
 
@@ -462,39 +475,37 @@
   {
   global $COMM_PATH, $RCMAIL;
 
-  $display = isset($_SESSION['quota_display']) ? $_SESSION['quota_display'] : '';
-
   $quota = $RCMAIL->imap->get_quota();
   $quota = $RCMAIL->plugins->exec_hook('quota', $quota);
 
-  if (!$quota['total'] && $RCMAIL->config->get('quota_zero_as_unlimited'))
-    return rcube_label('unlimited');
+  $quota_result = (array) $quota;
+  $quota_result['type'] = isset($_SESSION['quota_display']) ? $_SESSION['quota_display'] : '';
 
-  if ($quota['total'])
-    {
+  if (!$quota['total'] && $RCMAIL->config->get('quota_zero_as_unlimited')) {
+    $quota_result['title'] = rcube_label('unlimited');
+    $quota_result['percent'] = 0;
+    }
+  else if ($quota['total']) {
     if (!isset($quota['percent']))
-      $quota['percent'] = min(100, round(($quota['used']/max(1,$quota['total']))*100));
+      $quota_result['percent'] = min(100, round(($quota['used']/max(1,$quota['total']))*100));
 
-    $quota_result = sprintf('%s / %s (%.0f%%)',
+    $title = sprintf('%s / %s (%.0f%%)',
         show_bytes($quota['used'] * 1024), show_bytes($quota['total'] * 1024),
-        $quota['percent']);
+        $quota_result['percent']);
 
-    if ($display == 'image') {
-      $quota_result = array(
-    	'percent' 	=> $quota['percent'],
-        'title'		=> $quota_result,
-	  );
+    $quota_result['title'] = $title;
 
-      if ($attrib['width'])
-        $quota_result['width'] = $attrib['width'];
-      if ($attrib['height'])
-        $quota_result['height']	= $attrib['height'];
-      }
-
-      return $quota_result;
+    if ($attrib['width'])
+      $quota_result['width'] = $attrib['width'];
+    if ($attrib['height'])
+      $quota_result['height']	= $attrib['height'];
+    }
+  else {
+    $quota_result['title'] = rcube_label('unknown');
+    $quota_result['percent'] = 0;
     }
 
-  return rcube_label('unknown');
+  return $quota_result;
   }
 
 
@@ -630,6 +641,21 @@
   );
   $html = preg_replace($html_search, $html_replace, $html);
 
+  // PCRE errors handling (#1486856), should we use something like for every preg_* use?
+  if ($html === null && ($preg_error = preg_last_error()) != PREG_NO_ERROR) {
+    $errstr = "Could not clean up HTML message! PCRE Error: $preg_error.";
+
+    if ($preg_error == PREG_BACKTRACK_LIMIT_ERROR)
+      $errstr .= " Consider raising pcre.backtrack_limit!";
+    if ($preg_error == PREG_RECURSION_LIMIT_ERROR)
+      $errstr .= " Consider raising pcre.recursion_limit!";
+
+    raise_error(array('code' => 600, 'type' => 'php',
+        'line' => __LINE__, 'file' => __FILE__,
+        'message' => $errstr), true, false);
+    return '';
+  }
+
   // fix (unknown/malformed) HTML tags before "wash"
   $html = preg_replace_callback('/(<[\/]*)([^\s>]+)/', 'rcmail_html_tag_callback', $html);
 
@@ -724,7 +750,7 @@
 
   // plaintext postprocessing
   if ($part->ctype_secondary == 'plain')
-    $body = rcmail_plain_body($body);
+    $body = rcmail_plain_body($body, $part->ctype_parameters['format'] == 'flowed');
 
   // allow post-processing of the message body
   $data = $RCMAIL->plugins->exec_hook('message_part_after', array('type' => $part->ctype_secondary, 'body' => $body) + $data);
@@ -736,75 +762,106 @@
 /**
  * Handle links and citation marks in plain text message
  *
- * @param string  Plain text string 
+ * @param string  Plain text string
+ * @param boolean Text uses format=flowed
+ *
  * @return string Formatted HTML string
  */
-function rcmail_plain_body($body)
+function rcmail_plain_body($body, $flowed=false)
 {
+  global $RCMAIL;
+
   // make links and email-addresses clickable
-  $replacements = new rcube_string_replacer;
+  $replacer = new rcube_string_replacer;
 
   // search for patterns like links and e-mail addresses
-  $body = preg_replace_callback($replacements->link_pattern, array($replacements, 'link_callback'), $body);
-  $body = preg_replace_callback($replacements->mailto_pattern, array($replacements, 'mailto_callback'), $body);
+  $body = preg_replace_callback($replacer->link_pattern, array($replacer, 'link_callback'), $body);
+  $body = preg_replace_callback($replacer->mailto_pattern, array($replacer, 'mailto_callback'), $body);
 
   // split body into single lines
   $a_lines = preg_split('/\r?\n/', $body);
-  $q_lines = array();
   $quote_level = 0;
+  $last = -1;
 
   // find/mark quoted lines...
   for ($n=0, $cnt=count($a_lines); $n < $cnt; $n++) {
-    $q = 0;
-
     if ($a_lines[$n][0] == '>' && preg_match('/^(>+\s*)+/', $a_lines[$n], $regs)) {
       $q = strlen(preg_replace('/\s/', '', $regs[0]));
-        $a_lines[$n] = substr($a_lines[$n], strlen($regs[0]));
+      $a_lines[$n] = substr($a_lines[$n], strlen($regs[0]));
 
       if ($q > $quote_level)
-        $q_lines[$n]['quote'] = $q - $quote_level;
+        $a_lines[$n] = $replacer->get_replacement($replacer->add(
+          str_repeat('<blockquote>', $q - $quote_level))) . $a_lines[$n];
       else if ($q < $quote_level)
-        $q_lines[$n]['endquote'] = $quote_level - $q;
+        $a_lines[$n] = $replacer->get_replacement($replacer->add(
+          str_repeat('</blockquote>', $quote_level - $q))) . $a_lines[$n];
+      else if ($flowed) {
+        // previous line is flowed
+        if (isset($a_lines[$last]) && $a_lines[$n]
+          && $a_lines[$last][strlen($a_lines[$last])-1] == ' ') {
+          // merge lines
+          $a_lines[$last] .= $a_lines[$n];
+          unset($a_lines[$n]);
+        }
+        else
+          $last = $n;
+      }
     }
-    else if ($quote_level > 0)
-      $q_lines[$n]['endquote'] = $quote_level;
+    else {
+      $q = 0;
+      if ($flowed) {
+        // sig separator - line is fixed
+        if ($a_lines[$n] == '-- ') {
+          $last = $n;
+        }
+        else {
+          // remove space-stuffing
+          if ($a_lines[$n][0] == ' ')
+            $a_lines[$n] = substr($a_lines[$n], 1);
+
+          // previous line is flowed?
+          if (isset($a_lines[$last]) && $a_lines[$n]
+            && $a_lines[$last] != '-- '
+            && $a_lines[$last][strlen($a_lines[$last])-1] == ' '
+          ) {
+            $a_lines[$last] .= $a_lines[$n];
+            unset($a_lines[$n]);
+          }
+          else {
+            $last = $n;
+          }
+        }
+        if ($quote_level > 0)
+          $a_lines[$last] = $replacer->get_replacement($replacer->add(
+            str_repeat('</blockquote>', $quote_level))) . $a_lines[$last];
+      }
+      else if ($quote_level > 0)
+        $a_lines[$n] = $replacer->get_replacement($replacer->add(
+          str_repeat('</blockquote>', $quote_level))) . $a_lines[$n];
+    }
 
     $quote_level = $q;
   }
 
   // quote plain text
-  $body = Q(join("\n", $a_lines), 'replace', false);
+  $body = Q(join("\n", $a_lines), '', false);
 
   // colorize signature
-  if (($sp = strrpos($body, '-- ')) !== false)
-    if (($sp == 0 || $body[$sp-1] == "\n") && $body[$sp+3] == "\n") {
-      $body = substr($body, 0, max(0, $sp))
-	.'<span class="sig">'.substr($body, $sp).'</span>';
+  $len = strlen($body);
+  while (($sp = strrpos($body, "-- \n", $sp ? -$len+$sp-1 : 0)) !== false) {
+    if ($sp == 0 || $body[$sp-1] == "\n") {
+      // do not touch blocks with more that X lines
+      if (substr_count($body, "\n", $sp) < $RCMAIL->config->get('sig_max_lines', 15))
+        $body = substr($body, 0, max(0, $sp))
+          .'<span class="sig">'.substr($body, $sp).'</span>';
+      break;
     }
+  }
 
-  // colorize quoted lines
-  $a_lines = preg_split('/\n/', $body);
-  foreach ($q_lines as $i => $q)
-    if ($q['quote'])
-      $a_lines[$i] = str_repeat('<blockquote>', $q['quote']) . $a_lines[$i];
-    else if ($q['endquote'])
-      $a_lines[$i] = str_repeat('</blockquote>', $q['endquote']) . $a_lines[$i];
+  // insert url/mailto links and citation tags
+  $body = $replacer->resolve($body);
 
-  // insert the links for urls and mailtos
-  $body = $replacements->resolve(join("\n", $a_lines));
-    
   return $body;
-}
-
-
-/**
- * add a string to the replacement array and return a replacement string
- */
-function rcmail_str_replacement($str, &$rep)
-{
-  static $count = 0;
-  $rep[$count] = stripslashes($str);
-  return "##string_replacement{".($count++)."}##";
 }
 
 
@@ -933,7 +990,7 @@
  */
 function rcmail_message_body($attrib)
   {
-  global $CONFIG, $OUTPUT, $MESSAGE, $IMAP, $REMOTE_OBJECTS;
+  global $CONFIG, $OUTPUT, $MESSAGE, $IMAP, $RCMAIL, $REMOTE_OBJECTS;
 
   if (!is_array($MESSAGE->parts) && empty($MESSAGE->body))
     return '';
@@ -969,22 +1026,37 @@
           rcmail_message_error($MESSAGE->uid);
         }
 
-        // re-format format=flowed content
-        if ($part->ctype_secondary == "plain" && $part->ctype_parameters['format'] == "flowed")
-          $part->body = rcube_message::unfold_flowed($part->body);
+        $plugin = $RCMAIL->plugins->exec_hook('message_body_prefix', array(
+          'part' => $part, 'prefix' => ''));
 
         $body = rcmail_print_body($part, array('safe' => $safe_mode, 'plain' => !$CONFIG['prefer_html']));
 
-        if ($part->ctype_secondary == 'html')
-          $out .= html::div('message-htmlpart', rcmail_html4inline($body, $attrib['id'], 'div.rcmBody'));
+        if ($part->ctype_secondary == 'html') {
+          $body = rcmail_html4inline($body, $attrib['id'], 'rcmBody', $attrs);
+          $div_attr = array('class' => 'message-htmlpart');
+          $style = array();
+
+          if (!empty($attrs)) {
+            foreach ($attrs as $a_idx => $a_val)
+              $style[] = $a_idx . ': ' . $a_val;
+            if (!empty($style))
+              $div_attr['style'] = implode('; ', $style);
+          }
+
+          $out .= html::div($div_attr, $plugin['prefix'] . $body);
+        }
         else
-          $out .= html::div('message-part', $body);
+          $out .= html::div('message-part', $plugin['prefix'] . $body);
         }
       }
     }
-  else
-    $out .= html::div('message-part', html::tag('pre', array(),
+  else {
+    $plugin = $RCMAIL->plugins->exec_hook('message_body_prefix', array(
+      'part' => $MESSAGE, 'prefix' => ''));
+
+    $out .= html::div('message-part', $plugin['prefix'] . html::tag('pre', array(),
       rcmail_plain_body(Q($MESSAGE->body, 'strict', false))));
+    }
 
   $ctype_primary = strtolower($MESSAGE->structure->ctype_primary);
   $ctype_secondary = strtolower($MESSAGE->structure->ctype_secondary);
@@ -992,11 +1064,16 @@
   // list images after mail body
   if ($CONFIG['inline_images']
       && $ctype_primary == 'multipart'
-      && !empty($MESSAGE->attachments) 
-      && !strstr($message_body, '<html'))
+      && !empty($MESSAGE->attachments))
     {
     foreach ($MESSAGE->attachments as $attach_prop) {
-      if (strpos($attach_prop->mimetype, 'image/') === 0) {
+      // Content-Type: image/*...
+      if (preg_match('/^image\//i', $attach_prop->mimetype) ||
+        // ...or known file extension: many clients are using application/octet-stream
+        ($attach_prop->filename &&
+          preg_match('/^application\/octet-stream$/i', $attach_prop->mimetype) &&
+          preg_match('/\.(jpg|jpeg|png|gif|bmp)$/i', $attach_prop->filename))
+      ) {
         $out .= html::tag('hr') . html::p(array('align' => "center"),
           html::img(array(
             'src' => $MESSAGE->get_part_url($attach_prop->mime_id),
@@ -1035,30 +1112,32 @@
 /**
  * modify a HTML message that it can be displayed inside a HTML page
  */
-function rcmail_html4inline($body, $container_id, $body_id='')
-  {
+function rcmail_html4inline($body, $container_id, $body_id='', &$attributes=null)
+{
   $last_style_pos = 0;
   $body_lc = strtolower($body);
+  $cont_id = $container_id.($body_id ? ' div.'.$body_id : '');
 
   // find STYLE tags
   while (($pos = strpos($body_lc, '<style', $last_style_pos)) && ($pos2 = strpos($body_lc, '</style>', $pos)))
-    {
+  {
     $pos = strpos($body_lc, '>', $pos)+1;
 
     // replace all css definitions with #container [def]
-    $styles = rcmail_mod_css_styles(substr($body, $pos, $pos2-$pos), $container_id.($body_id ? ' '.$body_id : ''));
+    $styles = rcmail_mod_css_styles(
+      substr($body, $pos, $pos2-$pos), $cont_id);
 
     $body = substr($body, 0, $pos) . $styles . substr($body, $pos2);
     $body_lc = strtolower($body);
     $last_style_pos = $pos2;
-    }
+  }
 
   // modify HTML links to open a new window if clicked
   $GLOBALS['rcmail_html_container_id'] = $container_id;
   $body = preg_replace_callback('/<(a|link)\s+([^>]+)>/Ui', 'rcmail_alter_html_link', $body);
   unset($GLOBALS['rcmail_html_container_id']);
 
-  $out = preg_replace(array(
+  $body = preg_replace(array(
       // add comments arround html and other tags
       '/(<!DOCTYPE[^>]*>)/i',
       '/(<\?xml[^>]*>)/i',
@@ -1082,18 +1161,48 @@
       '<!--\\1-->',
       '&lt;?',
       '?&gt;',
-      '<div class="rcmBody"\\1>',
+      '<div class="'.$body_id.'"\\1>',
       '</div>',
       ),
     $body);
 
+  $attributes = array();
+
+  // Handle body attributes that doesn't play nicely with div elements
+  if (preg_match('/<div class="' . preg_quote($body_id, '/') . '" ([^>]+)/', $body, $m)) {
+    $attrs = $m[0];
+    // Get bgcolor, we'll set it as background-color of the message container
+    if (preg_match('/bgcolor=["\']*([a-z0-9#]+)["\']*/', $attrs, $mb)) {
+      $attributes['background-color'] = $mb[1];
+      $attrs = preg_replace('/bgcolor=["\']*([a-z0-9#]+)["\']*/', '', $attrs);
+    }
+    // Get background, we'll set it as background-image of the message container
+    if (preg_match('/background=["\']*([^"\'>\s]+)["\']*/', $attrs, $mb)) {
+      $attributes['background-image'] = 'url('.$mb[1].')';
+      $attrs = preg_replace('/background=["\']*([^"\'>\s]+)["\']*/', '', $attrs);
+    }
+    if (!empty($attributes))
+      $body = preg_replace('/<div class="' . preg_quote($body_id, '/') . '" [^>]+/', rtrim($attrs), $body, 1);
+
+    // handle body styles related to background image
+    if ($attributes['background-image']) {
+      // get body style
+      if (preg_match('/#'.preg_quote($cont_id, '/').'\s+\{([^}]+)}/i', $body, $m)) {
+        // get background related style
+        if (preg_match_all('/(background-position|background-repeat)\s*:\s*([^;]+);/i', $m[1], $ma, PREG_SET_ORDER)) {
+          foreach ($ma as $style)
+            $attributes[$style[1]] = $style[2];
+        }
+      }
+    }
+  }
   // make sure there's 'rcmBody' div, we need it for proper css modification
   // its name is hardcoded in rcmail_message_body() also
-  if (!preg_match('/<div class="rcmBody"/', $out))
-    $out = '<div class="rcmBody">' . $out . '</div>';
+  else
+    $body = '<div class="' . $body_id . '">' . $body . '</div>';
 
-  return $out;
-  }
+  return $body;
+}
 
 
 /**
@@ -1314,7 +1423,7 @@
     return;
 
   $rcmail = rcmail::get_instance();
-  $rcmail->plugins->exec_hook('cleanup_attachments',array());
+  $rcmail->plugins->exec_hook('attachments_cleanup', array());
   $rcmail->session->remove('compose');
   }
 
@@ -1378,10 +1487,6 @@
     $smtp_response = $RCMAIL->smtp->get_response();
     $smtp_error = $RCMAIL->smtp->get_error();
 
-    if (is_resource($msg_body)) {
-      fclose($msg_body);
-    }
-
     // log error
     if (!$sent)
       raise_error(array('code' => 800, 'type' => 'smtp', 'line' => __LINE__, 'file' => __FILE__,
@@ -1437,6 +1542,14 @@
     // remove MDN headers after sending
     unset($headers['Return-Receipt-To'], $headers['Disposition-Notification-To']);
 
+    // get all recipients
+    if ($headers['Cc'])
+      $mailto .= $headers['Cc'];
+    if ($headers['Bcc'])
+      $mailto .= $headers['Bcc'];
+    if (preg_match_all('/<([^@]+@[^>]+)>/', $mailto, $m))
+      $mailto = implode(', ', array_unique($m[1]));
+
     if ($CONFIG['smtp_log']) {
       write_log('sendmail', sprintf("User %s [%s]; Message for %s; %s",
         $RCMAIL->user->get_username(),
@@ -1444,6 +1557,10 @@
         $mailto,
         !empty($smtp_response) ? join('; ', $smtp_response) : ''));
     }
+  }
+
+  if (is_resource($msg_body)) {
+    fclose($msg_body);
   }
 
   $message->_headers = array();
@@ -1482,7 +1599,7 @@
       'From' => $sender,
       'To'   => $message->headers->mdn_to,
       'Subject' => rcube_label('receiptread') . ': ' . $message->subject,
-      'Message-ID' => sprintf('<%s@%s>', md5(uniqid('rcmail'.mt_rand(),true)), $RCMAIL->config->mail_domain($_SESSION['imap_host'])),
+      'Message-ID' => rcmail_gen_message_id(),
       'X-Sender' => $identity['email'],
       'References' => trim($message->headers->references . ' ' . $message->headers->messageID),
     );
@@ -1523,6 +1640,29 @@
   return false;
 }
 
+// Returns unique Message-ID
+function rcmail_gen_message_id()
+{
+  global $RCMAIL;
+
+  $local_part  = md5(uniqid('rcmail'.mt_rand(),true));
+  $domain_part = $RCMAIL->user->get_username('domain');
+
+  // Try to find FQDN, some spamfilters doesn't like 'localhost' (#1486924)
+  if (!preg_match('/\.[a-z]+$/i', $domain_part)) {
+    if (($host = preg_replace('/:[0-9]+$/', '', $_SERVER['HTTP_HOST']))
+      && preg_match('/\.[a-z]+$/i', $host)) {
+        $domain_part = $host;
+    }
+    else if (($host = preg_replace('/:[0-9]+$/', '', $_SERVER['SERVER_NAME']))
+      && preg_match('/\.[a-z]+$/i', $host)) {
+        $domain_part = $host;
+    }
+  }
+
+  return sprintf('<%s@%s>', $local_part, $domain_part);
+}
+
 // Returns RFC2822 formatted current date in user's timezone
 function rcmail_user_date()
 {
@@ -1540,7 +1680,8 @@
 
   $date = time() + $tz * 60 * 60;
   $date = gmdate('r', $date);
-  $date = preg_replace('/[+-][0-9]{4}$/', sprintf('%+05d', $tz * 100), $date);
+  $tz   = sprintf('%+05d', intval($tz) * 100 + ($tz - intval($tz)) * 60);
+  $date = preg_replace('/[+-][0-9]{4}$/', $tz, $date);
 
   return $date;
 }
@@ -1610,4 +1751,4 @@
   'searchform' => array($OUTPUT, 'search_form'),
 ));
 
-?>
+

--
Gitblit v1.9.1