Happy New Year
[squirrelmail.git] / src / compose.php
index 23c47c06b68a429901711b31684f95e56d0ae435..afc20be3ef486d353e985dbf0fc92ef6bbe4aa32 100644 (file)
@@ -10,7 +10,7 @@
  *    - Send mail
  *    - Save As Draft
  *
- * @copyright 1999-2012 The SquirrelMail Project Team
+ * @copyright 1999-2020 The SquirrelMail Project Team
  * @license http://opensource.org/licenses/gpl-license.php GNU Public License
  * @version $Id$
  * @package squirrelmail
@@ -41,6 +41,7 @@ require_once(SM_PATH . 'class/deliver/Deliver.class.php');
 require_once(SM_PATH . 'functions/addressbook.php');
 require_once(SM_PATH . 'functions/forms.php');
 require_once(SM_PATH . 'functions/identity.php');
+global $imap_stream_options; // in case not defined in config
 
 /* --------------------- Get globals ------------------------------------- */
 
@@ -54,7 +55,8 @@ sqgetGlobalVar('compose_messages',  $compose_messages,  SQ_SESSION);
 // compose_messages only useful in SESSION when a forward-as-attachment
 // has been preconstructed for us and passed in via that mechanism; once
 // we have it, we can clear it from the SESSION
-sqsession_unregister('compose_messages');
+// -- No, this is useful in other scenarios, too -- removing:
+// sqsession_unregister('compose_messages');
 
 // Turn on delayed error handling in case we wind up redirecting below
 $oErrorHandler->setDelayedErrors(true);
@@ -72,6 +74,7 @@ if (isset($send) && $send) {
 }
 sqgetGlobalVar('session',$session, $SQ_GLOBAL);
 sqgetGlobalVar('mailbox',$mailbox, $SQ_GLOBAL);
+sqgetGlobalVar('identity',$orig_identity, $SQ_GLOBAL);
 if(!sqgetGlobalVar('identity',$identity, $SQ_GLOBAL)) {
     $identity=0;
 }
@@ -172,8 +175,12 @@ function replyAllString($header) {
     /**
      * 1) Remove the addresses we'll be sending the message 'to'
      */
-    if (isset($header->reply_to)) {
+    if (isset($header->reply_to) && is_array($header->reply_to) && count($header->reply_to)) {
         $excl_ar = $header->getAddr_a('reply_to');
+    } else if (is_object($header->reply_to)) { /* unneccesarry, just for failsafe purpose */
+        $excl_ar = $header->getAddr_a('reply_to');
+    } else {
+        $excl_ar = $header->getAddr_a('from');
     }
     /**
      * 2) Remove our identities from the CC list (they still can be in the
@@ -244,6 +251,7 @@ function getReplyCitation($orig_from, $orig_date) {
         $full_reply_citation = sprintf(_("%s wrote:"),$sOrig_from);
         break;
     case 'quote_who':
+        // TODO: the words "quote" and "who" are translated in 1.4.x so why not here?  This isn't a real HTML tag...
         $start = '<quote who="';
         $end   = '">';
         $full_reply_citation = $start . $sOrig_from . $end;
@@ -403,8 +411,25 @@ if (!empty($compose_messages[$session])) {
 // should never directly manipulate an object like this
 if (!empty($attachments)) {
     $attachments = unserialize(urldecode($attachments));
-    if (!empty($attachments) && is_array($attachments))
-        $composeMessage->entities = $attachments;
+    if (!empty($attachments) && is_array($attachments)) {
+        // sanitize the "att_local_name" since it is user-supplied and used to access the file system
+        // it must be alpha-numeric and 32 characters long (see the use of GenerateRandomString() below)
+        foreach ($attachments as $i => $attachment) {
+            if (empty($attachment->att_local_name) || strlen($attachment->att_local_name) !== 32) {
+                unset($attachments[$i]);
+                continue;
+            }
+            // probably marginal difference between (ctype_alnum + function_exists) and preg_match
+            if (function_exists('ctype_alnum')) {
+                if (!ctype_alnum($attachment->att_local_name))
+                    unset($attachments[$i]);
+            }
+            else if (preg_match('/[^0-9a-zA-Z]/', $attachment->att_local_name))
+                unset($attachments[$i]);
+        }
+        if (!empty($attachments))
+            $composeMessage->entities = $attachments;
+    }
 }
 
 if (empty($mailbox)) {
@@ -415,7 +440,7 @@ if ($draft) {
 
     // validate security token
     //
-    sm_validate_security_token($submitted_token, 3600, TRUE);
+    sm_validate_security_token($submitted_token, -1, TRUE);
 
     /*
      * Set $default_charset to correspond with the user's selection
@@ -429,7 +454,7 @@ if ($draft) {
         $draft_message = _("Draft Email Saved");
         /* If this is a resumed draft, then delete the original */
         if(isset($delete_draft)) {
-            $imap_stream = sqimap_login($username, false, $imapServerAddress, $imapPort, false);
+            $imap_stream = sqimap_login($username, false, $imapServerAddress, $imapPort, false, $imap_stream_options);
             sqimap_mailbox_select($imap_stream, $draft_folder);
             // force bypass_trash=true because message should be saved when deliverMessage() returns true.
             // in current implementation of sqimap_msgs_list_flag() single message id can
@@ -474,7 +499,7 @@ if ($send) {
 
     // validate security token
     //
-    sm_validate_security_token($submitted_token, 3600, TRUE);
+    sm_validate_security_token($submitted_token, -1, TRUE);
 
     if (isset($_FILES['attachfile']) &&
             $_FILES['attachfile']['tmp_name'] &&
@@ -542,7 +567,7 @@ if ($send) {
 
         /* if it is resumed draft, delete draft message */
         if ( isset($delete_draft)) {
-            $imap_stream = sqimap_login($username, false, $imapServerAddress, $imapPort, false);
+            $imap_stream = sqimap_login($username, false, $imapServerAddress, $imapPort, false, $imap_stream_options);
             sqimap_mailbox_select($imap_stream, $draft_folder);
             // bypass_trash=true because message should be saved when deliverMessage() returns true.
             // in current implementation of sqimap_msgs_list_flag() single message id can
@@ -571,8 +596,14 @@ if ($send) {
             exit();
         } else {
             if ( !isset($pageheader_sent) || !$pageheader_sent ) {
-                header("Location: $location/right_main.php?mailbox=$urlMailbox".
-                    "&startMessage=$startMessage&mail_sent=$mail_sent");
+                global $return_to_message_after_reply;
+                if (($action === 'reply' || $action === 'reply_all' || $action === 'forward' || $action === 'forward_as_attachment')
+                 && $return_to_message_after_reply && $passed_id)
+                    header("Location: $location/read_body.php?passed_id=$passed_id&mailbox=$urlMailbox".
+                            "&startMessage=$startMessage&mail_sent=$mail_sent");
+                else
+                    header("Location: $location/right_main.php?mailbox=$urlMailbox".
+                            "&startMessage=$startMessage&mail_sent=$mail_sent");
             } else {
 //FIXME: DON'T ECHO HTML FROM CORE!
                 echo '   <br><br><div style="text-align: center;"><a href="' . $location
@@ -601,7 +632,7 @@ if ($send) {
 
     // validate security token
     //
-    sm_validate_security_token($submitted_token, 3600, TRUE);
+    sm_validate_security_token($submitted_token, -1, TRUE);
 
     if ($compose_new_win == '1') {
         compose_Header($color, $mailbox);
@@ -650,7 +681,7 @@ if ($send) {
 
     // validate security token
     //
-    sm_validate_security_token($submitted_token, 3600, TRUE);
+    sm_validate_security_token($submitted_token, -1, TRUE);
 
     if ($compose_new_win == '1') {
         compose_Header($color, $mailbox);
@@ -666,7 +697,7 @@ elseif (isset($sigappend)) {
 
     // validate security token
     //
-    sm_validate_security_token($submitted_token, 3600, TRUE);
+    sm_validate_security_token($submitted_token, -1, TRUE);
 
     $signature = $idents[$identity]['signature'];
 
@@ -681,7 +712,7 @@ elseif (isset($sigappend)) {
 
     // validate security token
     //
-    sm_validate_security_token($submitted_token, 3600, TRUE);
+    sm_validate_security_token($submitted_token, -1, TRUE);
 
     if ($compose_new_win == '1') {
         compose_Header($color, $mailbox);
@@ -752,6 +783,12 @@ elseif (isset($sigappend)) {
     if (isset($subject)) {
         $values['subject'] = $subject;
     }
+    if (isset($mailprio)) {
+        $values['mailprio'] = $mailprio;
+    }
+    if (isset($orig_identity)) {
+        $values['identity'] = $orig_identity;
+    }
     showInputForm($session, $values);
 }
 
@@ -773,10 +810,10 @@ function getforwardSubject($subject)
 function newMail ($mailbox='', $passed_id='', $passed_ent_id='', $action='', $session='') {
     global $editor_size, $default_use_priority, $body, $idents,
         $use_signature, $data_dir, $username,
-        $key, $imapServerAddress, $imapPort, 
+        $key, $imapServerAddress, $imapPort, $imap_stream_options,
         $composeMessage, $body_quote, $request_mdn, $request_dr,
         $mdn_user_support, $languages, $squirrelmail_language,
-        $default_charset, $do_not_reply_to_self;
+        $default_charset, $do_not_reply_to_self, $compose_messages;
 
     /*
      * Set $default_charset to correspond with the user's selection
@@ -790,7 +827,7 @@ function newMail ($mailbox='', $passed_id='', $passed_ent_id='', $action='', $se
 
     if ($passed_id) {
         $imapConnection = sqimap_login($username, false, $imapServerAddress,
-                $imapPort, 0);
+                $imapPort, 0, $imap_stream_options);
 
         sqimap_mailbox_select($imapConnection, $mailbox);
         $message = sqimap_get_message($imapConnection, $passed_id, $mailbox);
@@ -884,16 +921,11 @@ function newMail ($mailbox='', $passed_id='', $passed_ent_id='', $action='', $se
         if (count($idents) > 1) {
             foreach($idents as $nr=>$data) {
                 $enc_from_name = '"'.$data['full_name'].'" <'. $data['email_address'].'>';
-                if(strtolower($enc_from_name) == strtolower($orig_from)) {
-                    $identity = $nr;
-                    // don't stop!  need to build $identities array for idents match below
-                    //break;
-                }
                 $identities[] = $enc_from_name;
             }
 
             $identity_match = $orig_header->findAddress($identities);
-            if ($identity_match) {
+            if ($identity_match !== FALSE) {
                 $identity = $identity_match;
             }
         }
@@ -923,6 +955,11 @@ function newMail ($mailbox='', $passed_id='', $passed_ent_id='', $action='', $se
                 // rewrap the body to clean up quotations and line lengths
                 sqBodyWrap($body, $editor_size);
                 $composeMessage = getAttachments($message, $composeMessage, $passed_id, $entities, $imapConnection);
+                if (!empty($orig_header->x_sm_flag_reply))
+                    $composeMessage->rfc822_header->more_headers['X-SM-Flag-Reply'] = $orig_header->x_sm_flag_reply;
+//TODO: completely unclear if should be using $compose_session instead of $session below
+                $compose_messages[$session] = $composeMessage;
+                sqsession_register($compose_messages,'compose_messages');
                 break;
             case ('edit_as_new'):
                 $send_to = decodeHeader($orig_header->getAddr_s('to'),false,false,true);
@@ -1005,10 +1042,12 @@ function newMail ($mailbox='', $passed_id='', $passed_ent_id='', $action='', $se
                             // if this is a reply-all, the original recipient
                             // is already in the CC field, so we can just blank
                             // the recipient (TO field) (as long as the CC field
-                            // isn't empty that is) and we're done
+                            // isn't empty that is)... but then move the CC into
+                            // the TO, so TO isn't empty
                             //
-                            if ($action == 'reply_all') {
-                                if (!empty($send_to_cc)) $send_to = '';
+                            if ($action == 'reply_all' && !empty($send_to_cc)) {
+                                $orig_to = $send_to_cc;
+                                $send_to_cc = '';
                                 break;
                             }
 
@@ -1028,25 +1067,27 @@ function newMail ($mailbox='', $passed_id='', $passed_ent_id='', $action='', $se
                     }
 
                     // if the reply was addressed back to ourselves,
-                    // we will send it to the TO of the previous message,
-                    // first making sure that that address wasn't also
-                    // one of our identities
+                    // we will send it to the TO of the previous message
                     //
                     if (!empty($orig_to)) {
 
-                        foreach($idents as $id) {
-                            if (!empty($id['email_address'])
-                             && strpos($orig_to, $id['email_address']) !== FALSE) {
-                                $orig_to = '';
-                                break;
-                            }
-                        }
+                        $send_to = $orig_to;
 
-                        // if $orig_to still not empty, we can use it
+                        // in this case, we also want to reset the FROM
+                        // identity as well (it should match the original
+                        // *FROM* header instead of TO or CC)
                         //
-                        if (!empty($orig_to)) {
-                            $send_to = $orig_to;
+                        if (count($idents) > 1) {
+                            $identity = '';
+                            foreach($idents as $i => $id) {
+                                if (!empty($id['email_address'])
+                                 && strpos($orig_from, $id['email_address']) !== FALSE) {
+                                    $identity = $i;
+                                    break;
+                                }
+                            }
                         }
+
                     }
 
                 }
@@ -1346,10 +1387,10 @@ function showInputForm ($session, $values=false) {
     $oTemplate->assign('identity_def', $identity);
     $oTemplate->assign('input_onfocus', 'onfocus="'.join(' ', $onfocus_array).'"');
 
-    $oTemplate->assign('to', htmlspecialchars($send_to));
-    $oTemplate->assign('cc', htmlspecialchars($send_to_cc));
-    $oTemplate->assign('bcc', htmlspecialchars($send_to_bcc));
-    $oTemplate->assign('subject', htmlspecialchars($subject));
+    $oTemplate->assign('to', sm_encode_html_special_chars($send_to));
+    $oTemplate->assign('cc', sm_encode_html_special_chars($send_to_cc));
+    $oTemplate->assign('bcc', sm_encode_html_special_chars($send_to_bcc));
+    $oTemplate->assign('subject', sm_encode_html_special_chars($subject));
 
     // access keys...
     //
@@ -1385,9 +1426,9 @@ function showInputForm ($session, $values=false) {
             } else {
                 $body_str = "\n\n".($prefix_sig==true? "-- \n":'').decodeHeader($signature,false,false);
             }
-            $body_str .= "\n\n".htmlspecialchars(decodeHeader($body,false,false));
+            $body_str .= "\n\n".sm_encode_html_special_chars(decodeHeader($body,false,false));
         } else {
-            $body_str = "\n\n".htmlspecialchars(decodeHeader($body,false,false));
+            $body_str = "\n\n".sm_encode_html_special_chars(decodeHeader($body,false,false));
             // FIXME: test is specific to ja_JP translation implementation. See above comments.
             if ($default_charset == 'iso-2022-jp') {
                 $body_str .= "\n\n".($prefix_sig==true? "-- \n":'').mb_convert_encoding($signature, 'EUC-JP');
@@ -1396,7 +1437,7 @@ function showInputForm ($session, $values=false) {
             }
         }
     } else {
-        $body_str = htmlspecialchars(decodeHeader($body,false,false));
+        $body_str = sm_encode_html_special_chars(decodeHeader($body,false,false));
     }
 
     $oTemplate->assign('editor_width', (int)$editor_size);
@@ -1678,10 +1719,10 @@ function getByteSize($ini_size) {
  */
 function deliverMessage(&$composeMessage, $draft=false) {
     global $send_to, $send_to_cc, $send_to_bcc, $mailprio, $subject, $body,
-        $username, $identity, $idents, $data_dir,
+        $username, $identity, $idents, $data_dir, $compose_messages, $session,
         $request_mdn, $request_dr, $default_charset, $useSendmail,
         $domain, $action, $default_move_to_sent, $move_to_sent,
-        $imapServerAddress, $imapPort, $sent_folder, $key;
+        $imapServerAddress, $imapPort, $imap_stream_options, $sent_folder, $key;
 
     $rfc822_header = $composeMessage->rfc822_header;
 
@@ -1774,17 +1815,30 @@ function deliverMessage(&$composeMessage, $draft=false) {
        it over to deliver; plugin authors note that $composeMessage
        is sent and modified by reference since 1.5.2 */
     do_hook('compose_send', $composeMessage);
+//TODO: need to migrate to the following, but it neessitates changes in existing plugins, since the args are now an array
+    //$temp = array(&$composeMessage, &$draft);
+    //do_hook('compose_send', $temp);
+
+    // remove special header if present and prepare to mark
+    // a message that a draft was composed in reply to
+    if (!empty($composeMessage->rfc822_header->x_sm_flag_reply) && !$draft) {
+        global $passed_id, $mailbox;
+        // tricks the code below that marks the reply
+        list($action, $passed_id, $mailbox) = explode('::', $rfc822_header->x_sm_flag_reply, 3);
+        unset($composeMessage->rfc822_header->x_sm_flag_reply);
+        unset($composeMessage->rfc822_header->more_headers['X-SM-Flag-Reply']);
+    }
 
     if (!$useSendmail && !$draft) {
         require_once(SM_PATH . 'class/deliver/Deliver_SMTP.class.php');
         $deliver = new Deliver_SMTP();
-        global $smtpServerAddress, $smtpPort, $pop_before_smtp, $pop_before_smtp_host;
+        global $smtpServerAddress, $smtpPort, $smtp_stream_options, $pop_before_smtp, $pop_before_smtp_host;
 
         $authPop = (isset($pop_before_smtp) && $pop_before_smtp) ? true : false;
         if (empty($pop_before_smtp_host)) $pop_before_smtp_host = $smtpServerAddress;
         get_smtp_user($user, $pass);
         $stream = $deliver->initStream($composeMessage,$domain,0,
-                $smtpServerAddress, $smtpPort, $user, $pass, $authPop, $pop_before_smtp_host);
+                $smtpServerAddress, $smtpPort, $user, $pass, $authPop, $pop_before_smtp_host, $smtp_stream_options);
     } elseif (!$draft) {
         require_once(SM_PATH . 'class/deliver/Deliver_SendMail.class.php');
         global $sendmail_path, $sendmail_args;
@@ -1801,17 +1855,27 @@ function deliverMessage(&$composeMessage, $draft=false) {
     } elseif ($draft) {
         global $draft_folder;
         $imap_stream = sqimap_login($username, false, $imapServerAddress,
-                $imapPort, 0);
+                $imapPort, 0, $imap_stream_options);
         if (sqimap_mailbox_exists ($imap_stream, $draft_folder)) {
+//TODO: this can leak private information about folders and message IDs if messages are accessed/sent from another client --- should this feature be optional?
+            // make note of the message to mark as having been replied to
+            global $passed_id, $mailbox;
+            if ($action == 'reply' || $action == 'reply_all' || $action == 'forward' || $action == 'forward_as_attachment') {
+                $composeMessage->rfc822_header->more_headers['X-SM-Flag-Reply'] = $action . '::' . $passed_id . '::' . $mailbox;
+            }
+
             require_once(SM_PATH . 'class/deliver/Deliver_IMAP.class.php');
             $imap_deliver = new Deliver_IMAP();
             $success = $imap_deliver->mail($composeMessage, $imap_stream, $reply_id, $reply_ent_id, $imap_stream, $draft_folder);
             sqimap_logout($imap_stream);
             unset ($imap_deliver);
             $composeMessage->purgeAttachments();
+//TODO: completely unclear if should be using $compose_session instead of $session below
+            unset($compose_messages[$session]);
+            sqsession_register($compose_messages,'compose_messages');
             return $success;
         } else {
-            $msg  = '<br />'.sprintf(_("Error: Draft folder %s does not exist."), htmlspecialchars($draft_folder));
+            $msg  = '<br />'.sprintf(_("Error: Draft folder %s does not exist."), sm_encode_html_special_chars($draft_folder));
             plain_error_message($msg);
             return false;
         }
@@ -1832,12 +1896,12 @@ function deliverMessage(&$composeMessage, $draft=false) {
             $msg .= '<br />'
                   . _("Server replied:") . ' '
                   . (isset($deliver->dlv_ret_nr) ? $deliver->dlv_ret_nr . ' ' : '')
-                  . nl2br(htmlspecialchars($deliver->dlv_server_msg));
+                  . nl2br(sm_encode_html_special_chars($deliver->dlv_server_msg));
         }
         plain_error_message($msg);
     } else {
         unset ($deliver);
-        $imap_stream = sqimap_login($username, false, $imapServerAddress, $imapPort, 0);
+        $imap_stream = sqimap_login($username, false, $imapServerAddress, $imapPort, 0, $imap_stream_options);
 
 
         // mark as replied or forwarded if applicable
@@ -1846,60 +1910,64 @@ function deliverMessage(&$composeMessage, $draft=false) {
 
         if ($action=='reply' || $action=='reply_all' || $action=='forward' || $action=='forward_as_attachment') {
             require(SM_PATH . 'functions/mailbox_display.php');
-            $aMailbox = sqm_api_mailbox_select($imap_stream, $iAccount, $mailbox,array('setindex' => $what, 'offset' => $startMessage),array());
-            switch($action) {
-            case 'reply':
-            case 'reply_all':
-                // check if we are allowed to set the \\Answered flag
-                if (in_array('\\answered',$aMailbox['PERMANENTFLAGS'], true)) {
-                    $aUpdatedMsgs = sqimap_toggle_flag($imap_stream, array($passed_id), '\\Answered', true, false);
-                    if (isset($aUpdatedMsgs[$passed_id]['FLAGS'])) {
-                        /**
-                        * Only update the cached headers if the header is
-                        * cached.
-                        */
-                        if (isset($aMailbox['MSG_HEADERS'][$passed_id])) {
-                            $aMailbox['MSG_HEADERS'][$passed_id]['FLAGS'] = $aMsg['FLAGS'];
+            // select errors here could be due to a draft reply being sent
+            // after the original message's mailbox is moved or deleted
+            $aMailbox = sqm_api_mailbox_select($imap_stream, $iAccount, $mailbox,array('setindex' => $what, 'offset' => $startMessage),array(), false);
+            // a non-empty return from above means we can proceed
+            if (!empty($aMailbox)) {
+                switch($action) {
+                case 'reply':
+                case 'reply_all':
+                    // check if we are allowed to set the \\Answered flag
+                    if (in_array('\\answered',$aMailbox['PERMANENTFLAGS'], true)) {
+                        $aUpdatedMsgs = sqimap_toggle_flag($imap_stream, array($passed_id), '\\Answered', true, false);
+                        if (isset($aUpdatedMsgs[$passed_id]['FLAGS'])) {
+                            /**
+                            * Only update the cached headers if the header is
+                            * cached.
+                            */
+                            if (isset($aMailbox['MSG_HEADERS'][$passed_id])) {
+                                $aMailbox['MSG_HEADERS'][$passed_id]['FLAGS'] = $aMsg['FLAGS'];
+                            }
                         }
                     }
-                }
-                break;
-            case 'forward':
-            case 'forward_as_attachment':
-                // check if we are allowed to set the $Forwarded flag (RFC 4550 paragraph 2.8)
-                if (in_array('$forwarded',$aMailbox['PERMANENTFLAGS'], true) ||
-                    in_array('\\*',$aMailbox['PERMANENTFLAGS'])) {
-
-                    // when forwarding as an attachment from the message
-                    // list, passed_id is not used, need to get UID(s)
-                    // from the query string
-                    //
-                    if (empty($passed_id) && !empty($fwduid))
-                        $ids = explode('_', $fwduid);
-                    else
-                        $ids = array($passed_id);
-
-                    $aUpdatedMsgs = sqimap_toggle_flag($imap_stream, $ids, '$Forwarded', true, false);
-
-                    foreach ($ids as $id) {
-                        if (isset($aUpdatedMsgs[$id]['FLAGS'])) {
-                            if (isset($aMailbox['MSG_HEADERS'][$id])) {
-                                $aMailbox['MSG_HEADERS'][$id]['FLAGS'] = $aMsg['FLAGS'];
+                    break;
+                case 'forward':
+                case 'forward_as_attachment':
+                    // check if we are allowed to set the $Forwarded flag (RFC 4550 paragraph 2.8)
+                    if (in_array('$forwarded',$aMailbox['PERMANENTFLAGS'], true) ||
+                        in_array('\\*',$aMailbox['PERMANENTFLAGS'])) {
+
+                        // when forwarding as an attachment from the message
+                        // list, passed_id is not used, need to get UID(s)
+                        // from the query string
+                        //
+                        if (empty($passed_id) && !empty($fwduid))
+                            $ids = explode('_', $fwduid);
+                        else
+                            $ids = array($passed_id);
+
+                        $aUpdatedMsgs = sqimap_toggle_flag($imap_stream, $ids, '$Forwarded', true, false);
+
+                        foreach ($ids as $id) {
+                            if (isset($aUpdatedMsgs[$id]['FLAGS'])) {
+                                if (isset($aMailbox['MSG_HEADERS'][$id])) {
+                                    $aMailbox['MSG_HEADERS'][$id]['FLAGS'] = $aMsg['FLAGS'];
+                                }
                             }
                         }
                     }
+                    break;
                 }
-                break;
-            }
 
-            /**
-             * Write mailbox with updated seen flag information back to cache.
-             */
-            if(isset($aUpdatedMsgs[$passed_id])) {
-                $mailbox_cache[$iAccount.'_'.$aMailbox['NAME']] = $aMailbox;
-                sqsession_register($mailbox_cache,'mailbox_cache');
+                /**
+                 * Write mailbox with updated seen flag information back to cache.
+                 */
+                if(isset($aUpdatedMsgs[$passed_id])) {
+                    $mailbox_cache[$iAccount.'_'.$aMailbox['NAME']] = $aMailbox;
+                    sqsession_register($mailbox_cache,'mailbox_cache');
+                }
             }
-
         }
 
 
@@ -1942,6 +2010,9 @@ function deliverMessage(&$composeMessage, $draft=false) {
         // final cleanup
         //
         $composeMessage->purgeAttachments();
+//TODO: completely unclear if should be using $compose_session instead of $session below
+        unset($compose_messages[$session]);
+        sqsession_register($compose_messages,'compose_messages');
         sqimap_logout($imap_stream);
 
     }