/**
  * Returns message data.
  *
  * @param string $mailbox  Folder name
  * @param int    $uid      Message UID
  * @param bool   $update   If message doesn't exists in cache it will be fetched
  *                         from IMAP server
  * @param bool   $no_cache Enables internal cache usage
  *
  * @return rcube_message_header Message data
  */
 function get_message($mailbox, $uid, $update = true, $cache = true)
 {
     // Check internal cache
     if ($this->icache['__message'] && $this->icache['__message']['mailbox'] == $mailbox && $this->icache['__message']['object']->uid == $uid) {
         return $this->icache['__message']['object'];
     }
     if ($this->mode & self::MODE_MESSAGE) {
         $sql_result = $this->db->query("SELECT `flags`, `data`" . " FROM {$this->messages_table}" . " WHERE `user_id` = ?" . " AND `mailbox` = ?" . " AND `uid` = ?", $this->userid, $mailbox, (int) $uid);
         if ($sql_arr = $this->db->fetch_assoc($sql_result)) {
             $message = $this->build_message($sql_arr);
             $found = true;
         }
     }
     // Get the message from IMAP server
     if (empty($message) && $update) {
         $message = $this->imap->get_message_headers($uid, $mailbox, true);
         // cache will be updated in close(), see below
     }
     if (!($this->mode & self::MODE_MESSAGE)) {
         return $message;
     }
     // Save the message in internal cache, will be written to DB in close()
     // Common scenario: user opens unseen message
     // - get message (SELECT)
     // - set message headers/structure (INSERT or UPDATE)
     // - set \Seen flag (UPDATE)
     // This way we can skip one UPDATE
     if (!empty($message) && $cache) {
         // Save current message from internal cache
         $this->save_icache();
         $this->icache['__message'] = array('object' => $message, 'mailbox' => $mailbox, 'exists' => $found, 'md5sum' => md5(serialize($message)));
     }
     return $message;
 }