/// <summary>
        /// Open a mailbox if not already open.
        /// </summary>
        /// <param name="fullName">
        /// Fully qualified mailbox name.
        /// </param>
        /// <param name="readOnly">
        /// When <c>true</c> the IMap "EXAMINE" command is used, otherwiese the
        /// "SELECT" command.
        /// </param>
        /// <param name="returnDetails">
        /// When <c>true</c> an IMap request is always made and the <paramref name="info"/>
        /// data returns valid message counts.
        /// </param>
        /// <param name="info">
        /// Always returns the mailbox name, message counts are only set when
        /// <paramref name="returnDetails"/> is set.
        /// </param>
        /// <returns>
        /// True <c>true</c> on success.
        /// </returns>
        /// <remarks>
        /// If the mailbox is still open, <paramref name="returnDetails"/> is not set
        /// and if the read only state will not change no IMap commmand ist sent.  The
        /// neccessary information about the validity of the current mailbox is provided
        /// by <see cref="ZIMapTransport.LastSelectTag"/>.
        /// </remarks>
        public bool MailboxOpen(string fullName, bool readOnly, 
                                bool returnDetails, out MailBox info)
        {
            info = new MailBox();
            if(factory == null) return false;

            // recent mailbox still valid? But not if returnDetails is set...
            if(mailboxName != null)
            {   if(returnDetails || mailboxReadonly != readOnly || mailboxName != fullName)
                    mailboxName = null;
                else if(connection.TransportLayer.LastSelectTag != mailboxTag)
                    mailboxName = null;
                else
                {   MonitorInfo("MailboxOpen: still valid: " + fullName);
                    info.Name = fullName;
                    return true;
                }
            }

            // run a SELECT or EXAMINE command
            ZIMapCommand.Select cmd =
                (ZIMapCommand.Select)factory.CreateByName(readOnly ? "EXAMINE" : "SELECT");
            if(cmd == null) return false;
            progress.Update(0);

            cmd.Queue(fullName);
            if(!cmd.CheckSuccess())
            {   MonitorError("MailboxOpen: command failed: " + cmd.Result.Message);
                cmd.Dispose();
                return false;
            }
            readOnly = cmd.IsReadOnly;
            if(returnDetails)
            {   if(!cmd.Parse())
                {   MonitorError("MailboxOpen: got invalid data");
                    cmd.Dispose();
                    return false;
                }
                info.Messages = cmd.Messages;
                info.Recent   = cmd.Recent;
                info.Unseen   = cmd.Unseen;
            }
            info.Name = fullName;

            // save state ...
            uint nsid = Server.FindNamespace(fullName);
            mailboxNamespace = Server[nsid];
            mailboxName = fullName;
            mailboxReadonly = readOnly;
            mailboxTag = cmd.Tag;
            cmd.Dispose();
            progress.Done();
            return true;
        }
        public bool MailboxClose(bool waitForResult)
        {
            mailboxName = null;  mailboxTag = 0;  mailboxNamespace = null;
            if(connection.TransportLayer.LastSelectTag == 0)
                return true;

            connection.TransportLayer.LastSelectTag = 0;
            ZIMapCommand.Close cmd = new ZIMapCommand.Close(Factory);
            if(cmd == null) return false;

            cmd.Queue();
            if(!Factory.EnableAutoDispose) waitForResult = true;
            if(!waitForResult) return cmd.Execute(false);

            bool bok = cmd.Result.Succeeded;
            cmd.Dispose();
            return bok;
        }