/// <summary>
        /// Cleans up any resource being used.
        /// </summary>
        public override void Dispose()
        {
            if(this.IsDisposed){
                return;
            }
            base.Dispose();

            m_pAuthentications = null;
            m_pCapabilities = null;
            m_pUser = null;
            m_pSelectedFolder = null;
            if(m_pResponseSender != null){
                m_pResponseSender.Dispose();
            }

            // Release events
            this.Started         = null;
            this.Login           = null;
            this.Namespace       = null;
            this.List            = null;
            this.Create          = null;
            this.Delete          = null;
            this.Rename          = null;
            this.LSub            = null;
            this.Subscribe       = null;
            this.Unsubscribe     = null;
            this.Select          = null;
            this.GetMessagesInfo = null;
            this.Append          = null;
            this.GetQuotaRoot    = null;
            this.GetQuota        = null;
            this.GetAcl          = null;
            this.SetAcl          = null;
            this.DeleteAcl       = null;
            this.ListRights      = null;
            this.MyRights        = null;
            this.Fetch           = null;
            this.Search          = null;
            this.Store           = null;
            this.Copy            = null;
            this.Expunge         = null;
        }
        /// <summary>
        /// Updates current slected folder status and sends currently selected folder changes versus current folder state.
        /// </summary>
        private void UpdateSelectedFolderAndSendChanges()
        {
            if(m_pSelectedFolder == null){
                return;
            }
                        
            IMAP_e_MessagesInfo e = OnGetMessagesInfo(m_pSelectedFolder.Folder);
            
            int currentExists = m_pSelectedFolder.MessagesInfo.Length;
            // Create ID indexed lookup table for new messages.
            Dictionary<string,string> newMessagesLookup = new Dictionary<string,string>();
            foreach(IMAP_MessageInfo msgInfo in e.MessagesInfo){
                newMessagesLookup.Add(msgInfo.ID,null);
            }
            
            StringBuilder retVal = new StringBuilder();
            // Check deleted messages, send "* n EXPUNGE" for each deleted message.
            foreach(IMAP_MessageInfo msgInfo in m_pSelectedFolder.MessagesInfo){
                // Message deleted.
                if(!newMessagesLookup.ContainsKey(msgInfo.ID)){
                    retVal.Append("* " + m_pSelectedFolder.GetSeqNo(msgInfo) + " EXPUNGE\r\n");
                    m_pSelectedFolder.RemoveMessage(msgInfo);
                }
            }

            // Send EXISTS if current count differs from existing.
            if(currentExists != e.MessagesInfo.Count){
                retVal.Append("* " + e.MessagesInfo.Count + " EXISTS\r\n");
            }

            // Send STATUS change responses.
            if(retVal.Length > 0){
                WriteLine(retVal.ToString());                
            }

            // Create new selected folder based on new messages info.
            m_pSelectedFolder = new _SelectedFolder(m_pSelectedFolder.Folder,m_pSelectedFolder.IsReadOnly,e.MessagesInfo);
        }
        private void EXAMINE(string cmdTag,string cmdText)
        {
            /* RFC 3501 6.3.2. EXAMINE Command.
                Arguments:  mailbox name

                Responses:  REQUIRED untagged responses: FLAGS, EXISTS, RECENT
                            REQUIRED OK untagged responses:  UNSEEN,  PERMANENTFLAGS,
                            UIDNEXT, UIDVALIDITY

                Result:     OK - examine completed, now in selected state
                            NO - examine failure, now in authenticated state: no
                                 such mailbox, can't access mailbox
                            BAD - command unknown or arguments invalid

                The EXAMINE command is identical to SELECT and returns the same
                output; however, the selected mailbox is identified as read-only.
                No changes to the permanent state of the mailbox, including
                per-user state, are permitted; in particular, EXAMINE MUST NOT
                cause messages to lose the \Recent flag.

                The text of the tagged OK response to the EXAMINE command MUST
                begin with the "[READ-ONLY]" response code.

                Example:    C: A932 EXAMINE blurdybloop
                            S: * 17 EXISTS
                            S: * 2 RECENT
                            S: * OK [UNSEEN 8] Message 8 is first unseen
                            S: * OK [UIDVALIDITY 3857529045] UIDs valid
                            S: * OK [UIDNEXT 4392] Predicted next UID
                            S: * FLAGS (\Answered \Flagged \Deleted \Seen \Draft)
                            S: * OK [PERMANENTFLAGS ()] No permanent flags permitted
                            S: A932 OK [READ-ONLY] EXAMINE completed
            */

            /* 5738 3.2.  UTF8 Parameter to SELECT and EXAMINE
                The "UTF8=ACCEPT" capability also indicates that the server supports
                the "UTF8" parameter to SELECT and EXAMINE.  When a mailbox is
                selected with the "UTF8" parameter, it alters the behavior of all
                IMAP commands related to message sizes, message headers, and MIME
                body headers so they refer to the message with UTF-8 headers.  If the
                mailstore is not UTF-8 header native and the SELECT or EXAMINE
                command with UTF-8 header modifier succeeds, then the server MUST
                return results as if the mailstore were UTF-8 header native with
                upconversion requirements as described in Section 8.  The server MAY
                reject the SELECT or EXAMINE command with the [NOT-UTF-8] response
                code, unless the "UTF8=ALL" or "UTF8=ONLY" capability is advertised.

                Servers MAY include mailboxes that can only be selected or examined
                if the "UTF8" parameter is provided.  However, such mailboxes MUST
                NOT be included in the output of an unextended LIST, LSUB, or
                equivalent command.  If a client attempts to SELECT or EXAMINE such
                mailboxes without the "UTF8" parameter, the server MUST reject the
                command with a [UTF-8-ONLY] response code.  As a result, such
                mailboxes will not be accessible by IMAP clients written prior to
                this specification and are discouraged unless the server advertises
                "UTF8=ONLY" or the server implements IMAP4 LIST Command Extensions
   
                    utf8-select-param = "UTF8"
                        ;; Conforms to <select-param> from RFC 4466

                    C: a SELECT newmailbox (UTF8)
                    S: ...
                    S: a OK SELECT completed
                    C: b FETCH 1 (SIZE ENVELOPE BODY)
                    S: ... < UTF-8 header native results >
                    S: b OK FETCH completed

                    C: c EXAMINE legacymailbox (UTF8)
                    S: c NO [NOT-UTF-8] Mailbox does not support UTF-8 access
            */

            if(!this.IsAuthenticated){
                m_pResponseSender.SendResponseAsync(new IMAP_r_ServerStatus(cmdTag,"NO","Authentication required."));

                return;
            }
            
            // Store start time
			long startTime = DateTime.Now.Ticks;

            // Unselect folder if any selected.
            if(m_pSelectedFolder != null){
                m_pSelectedFolder = null;
            }

            string[] args = TextUtils.SplitQuotedString(cmdText,' ');
            if(args.Length >= 2){
                // At moment we don't support UTF-8 mailboxes.
                if(string.Equals(args[1],"(UTF8)",StringComparison.InvariantCultureIgnoreCase)){
                    m_pResponseSender.SendResponseAsync(new IMAP_r_ServerStatus(cmdTag,"NO",new IMAP_t_orc_Unknown("NOT-UTF-8"),"Mailbox does not support UTF-8 access."));
                }
                else{
                    m_pResponseSender.SendResponseAsync(new IMAP_r_ServerStatus(cmdTag,"BAD","Error in arguments."));
                }

                return;
            }

            string folder = TextUtils.UnQuoteString(IMAP_Utils.DecodeMailbox(cmdText));

            IMAP_e_Select e = OnSelect(cmdTag,folder);
            if(e.ErrorResponse == null){                 
                IMAP_e_MessagesInfo eMessagesInfo = OnGetMessagesInfo(folder);

                m_pResponseSender.SendResponseAsync(new IMAP_r_u_Exists(eMessagesInfo.Exists));
                m_pResponseSender.SendResponseAsync(new IMAP_r_u_Recent(eMessagesInfo.Recent));
                if(eMessagesInfo.FirstUnseen > -1){
                    m_pResponseSender.SendResponseAsync(new IMAP_r_u_ServerStatus("OK",new IMAP_t_orc_Unseen(eMessagesInfo.FirstUnseen),"Message " + eMessagesInfo.FirstUnseen + " is the first unseen."));
                }
                m_pResponseSender.SendResponseAsync(new IMAP_r_u_ServerStatus("OK",new IMAP_t_orc_UidNext((int)eMessagesInfo.UidNext),"Predicted next message UID."));
                m_pResponseSender.SendResponseAsync(new IMAP_r_u_ServerStatus("OK",new IMAP_t_orc_UidValidity(e.FolderUID),"Folder UID value."));
                m_pResponseSender.SendResponseAsync(new IMAP_r_u_Flags(e.Flags.ToArray()));
                m_pResponseSender.SendResponseAsync(new IMAP_r_u_ServerStatus("OK",new IMAP_t_orc_PermanentFlags(e.PermanentFlags.ToArray()),"Avaliable permanent flags."));
                m_pResponseSender.SendResponseAsync(new IMAP_r_ServerStatus(cmdTag,"OK",new IMAP_t_orc_ReadOnly(),"EXAMINE completed in " + ((DateTime.Now.Ticks - startTime) / (decimal)10000000).ToString("f2") + " seconds."));

                m_pSelectedFolder = new _SelectedFolder(folder,e.IsReadOnly,eMessagesInfo.MessagesInfo);
                m_pSelectedFolder.Reindex();
            }
            else{
                m_pResponseSender.SendResponseAsync(e.ErrorResponse);
            }
        }
        private void CLOSE(string cmdTag,string cmdText)
        {
            /* RFC 3501 6.4.2. CLOSE Command.
                Arguments:  none

                Responses:  no specific responses for this command

                Result:     OK - close completed, now in authenticated state
                            BAD - command unknown or arguments invalid

                The CLOSE command permanently removes all messages that have the
                \Deleted flag set from the currently selected mailbox, and returns
                to the authenticated state from the selected state.  No untagged
                EXPUNGE responses are sent.

                No messages are removed, and no error is given, if the mailbox is
                selected by an EXAMINE command or is otherwise selected read-only.

                Even if a mailbox is selected, a SELECT, EXAMINE, or LOGOUT
                command MAY be issued without previously issuing a CLOSE command.
                The SELECT, EXAMINE, and LOGOUT commands implicitly close the
                currently selected mailbox without doing an expunge.  However,
                when many messages are deleted, a CLOSE-LOGOUT or CLOSE-SELECT
                sequence is considerably faster than an EXPUNGE-LOGOUT or
                EXPUNGE-SELECT because no untagged EXPUNGE responses (which the
                client would probably ignore) are sent.

                Example:    C: A341 CLOSE
                            S: A341 OK CLOSE completed
            */

            if(!this.IsAuthenticated){
                m_pResponseSender.SendResponseAsync(new IMAP_r_ServerStatus(cmdTag,"NO","Authentication required."));

                return;
            }
            if(m_pSelectedFolder == null){
                m_pResponseSender.SendResponseAsync(new IMAP_r_ServerStatus(cmdTag,"NO","Error: This command is valid only in selected state."));

                return;
            }

            if(m_pSelectedFolder != null && !m_pSelectedFolder.IsReadOnly){
                foreach(IMAP_MessageInfo msgInfo in m_pSelectedFolder.MessagesInfo){
                    if(msgInfo.ContainsFlag("Deleted")){
                        OnExpunge(msgInfo,new IMAP_r_ServerStatus("dummy","OK","This is CLOSE command expunge, so this response is not used."));
                    }
                }
            }
            m_pSelectedFolder = null;
            
            m_pResponseSender.SendResponseAsync(new IMAP_r_ServerStatus(cmdTag,"OK","CLOSE completed."));
        }
        private void SELECT(string cmdTag,string cmdText)
        {
            /* RFC 3501 6.3.1. SELECT Command.
                Arguments:  mailbox name

                Responses:  REQUIRED untagged responses: FLAGS, EXISTS, RECENT
                            REQUIRED OK untagged responses:  UNSEEN,  PERMANENTFLAGS,
                            UIDNEXT, UIDVALIDITY

                Result:     OK - select completed, now in selected state
                            NO - select failure, now in authenticated state: no
                                 such mailbox, can't access mailbox
                            BAD - command unknown or arguments invalid

                The SELECT command selects a mailbox so that messages in the
                mailbox can be accessed.  Before returning an OK to the client,
                the server MUST send the following untagged data to the client.
                Note that earlier versions of this protocol only required the
                FLAGS, EXISTS, and RECENT untagged data; consequently, client
                implementations SHOULD implement default behavior for missing data
                as discussed with the individual item.

                    FLAGS       Defined flags in the mailbox.  See the description
                                of the FLAGS response for more detail.

                    <n> EXISTS  The number of messages in the mailbox.  See the
                                description of the EXISTS response for more detail.

                    <n> RECENT  The number of messages with the \Recent flag set.
                                See the description of the RECENT response for more
                                detail.

                    OK [UNSEEN <n>]
                                The message sequence number of the first unseen
                                message in the mailbox.  If this is missing, the
                                client can not make any assumptions about the first
                                unseen message in the mailbox, and needs to issue a
                                SEARCH command if it wants to find it.

                    OK [PERMANENTFLAGS (<list of flags>)]
                                A list of message flags that the client can change
                                permanently.  If this is missing, the client should
                                assume that all flags can be changed permanently.

                    OK [UIDNEXT <n>]
                                The next unique identifier value.  Refer to section
                                2.3.1.1 for more information.  If this is missing,
                                the client can not make any assumptions about the
                                next unique identifier value.

                    OK [UIDVALIDITY <n>]
                                The unique identifier validity value.  Refer to
                                section 2.3.1.1 for more information.  If this is
                                missing, the server does not support unique
                                identifiers.

                Only one mailbox can be selected at a time in a connection;
                simultaneous access to multiple mailboxes requires multiple
                connections.  The SELECT command automatically deselects any
                currently selected mailbox before attempting the new selection.
                Consequently, if a mailbox is selected and a SELECT command that
                fails is attempted, no mailbox is selected.

                If the client is permitted to modify the mailbox, the server
                SHOULD prefix the text of the tagged OK response with the
                "[READ-WRITE]" response code.

                If the client is not permitted to modify the mailbox but is
                permitted read access, the mailbox is selected as read-only, and
                the server MUST prefix the text of the tagged OK response to
                SELECT with the "[READ-ONLY]" response code.  Read-only access
                through SELECT differs from the EXAMINE command in that certain
                read-only mailboxes MAY permit the change of permanent state on a
                per-user (as opposed to global) basis.  Netnews messages marked in
                a server-based .newsrc file are an example of such per-user
                permanent state that can be modified with read-only mailboxes.

                Example:    C: A142 SELECT INBOX
                            S: * 172 EXISTS
                            S: * 1 RECENT
                            S: * OK [UNSEEN 12] Message 12 is first unseen
                            S: * OK [UIDVALIDITY 3857529045] UIDs valid
                            S: * OK [UIDNEXT 4392] Predicted next UID
                            S: * FLAGS (\Answered \Flagged \Deleted \Seen \Draft)
                            S: * OK [PERMANENTFLAGS (\Deleted \Seen \*)] Limited
                            S: A142 OK [READ-WRITE] SELECT completed
            */

            /* 5738 3.2.  UTF8 Parameter to SELECT and EXAMINE
                The "UTF8=ACCEPT" capability also indicates that the server supports
                the "UTF8" parameter to SELECT and EXAMINE.  When a mailbox is
                selected with the "UTF8" parameter, it alters the behavior of all
                IMAP commands related to message sizes, message headers, and MIME
                body headers so they refer to the message with UTF-8 headers.  If the
                mailstore is not UTF-8 header native and the SELECT or EXAMINE
                command with UTF-8 header modifier succeeds, then the server MUST
                return results as if the mailstore were UTF-8 header native with
                upconversion requirements as described in Section 8.  The server MAY
                reject the SELECT or EXAMINE command with the [NOT-UTF-8] response
                code, unless the "UTF8=ALL" or "UTF8=ONLY" capability is advertised.

                Servers MAY include mailboxes that can only be selected or examined
                if the "UTF8" parameter is provided.  However, such mailboxes MUST
                NOT be included in the output of an unextended LIST, LSUB, or
                equivalent command.  If a client attempts to SELECT or EXAMINE such
                mailboxes without the "UTF8" parameter, the server MUST reject the
                command with a [UTF-8-ONLY] response code.  As a result, such
                mailboxes will not be accessible by IMAP clients written prior to
                this specification and are discouraged unless the server advertises
                "UTF8=ONLY" or the server implements IMAP4 LIST Command Extensions
   
                    utf8-select-param = "UTF8"
                        ;; Conforms to <select-param> from RFC 4466

                    C: a SELECT newmailbox (UTF8)
                    S: ...
                    S: a OK SELECT completed
                    C: b FETCH 1 (SIZE ENVELOPE BODY)
                    S: ... < UTF-8 header native results >
                    S: b OK FETCH completed

                    C: c EXAMINE legacymailbox (UTF8)
                    S: c NO [NOT-UTF-8] Mailbox does not support UTF-8 access
            */

            // Store start time
			long startTime = DateTime.Now.Ticks;

            if(!this.IsAuthenticated){
                m_pResponseSender.SendResponseAsync(new IMAP_r_ServerStatus(cmdTag,"NO","Authentication required."));

                return;
            }
                        
            // Unselect folder if any selected.
            if(m_pSelectedFolder != null){
                m_pSelectedFolder = null;
            }

            string[] args = TextUtils.SplitQuotedString(cmdText,' ');
            if(args.Length >= 2){
                // At moment we don't support UTF-8 mailboxes.
                if(string.Equals(args[1],"(UTF8)",StringComparison.InvariantCultureIgnoreCase)){
                    m_pResponseSender.SendResponseAsync(new IMAP_r_ServerStatus(cmdTag,"NO",new IMAP_t_orc_Unknown("NOT-UTF-8"),"Mailbox does not support UTF-8 access."));
                }
                else{
                    m_pResponseSender.SendResponseAsync(new IMAP_r_ServerStatus(cmdTag,"BAD","Error in arguments."));
                }

                return;
            }

            try{
                string folder = TextUtils.UnQuoteString(IMAP_Utils.DecodeMailbox(cmdText));

                IMAP_e_Select e = OnSelect(cmdTag,folder);
                if(e.ErrorResponse == null){
                    IMAP_e_MessagesInfo eMessagesInfo = OnGetMessagesInfo(folder);

                    m_pResponseSender.SendResponseAsync(new IMAP_r_u_Exists(eMessagesInfo.Exists));
                    m_pResponseSender.SendResponseAsync(new IMAP_r_u_Recent(eMessagesInfo.Recent));
                    if(eMessagesInfo.FirstUnseen > -1){
                        m_pResponseSender.SendResponseAsync(new IMAP_r_u_ServerStatus("OK",new IMAP_t_orc_Unseen(eMessagesInfo.FirstUnseen),"Message " + eMessagesInfo.FirstUnseen + " is the first unseen."));
                    }
                    m_pResponseSender.SendResponseAsync(new IMAP_r_u_ServerStatus("OK",new IMAP_t_orc_UidNext((int)eMessagesInfo.UidNext),"Predicted next message UID."));
                    m_pResponseSender.SendResponseAsync(new IMAP_r_u_ServerStatus("OK",new IMAP_t_orc_UidValidity(e.FolderUID),"Folder UID value."));
                    m_pResponseSender.SendResponseAsync(new IMAP_r_u_Flags(e.Flags.ToArray()));
                    m_pResponseSender.SendResponseAsync(new IMAP_r_u_ServerStatus("OK",new IMAP_t_orc_PermanentFlags(e.PermanentFlags.ToArray()),"Avaliable permanent flags."));
                    m_pResponseSender.SendResponseAsync(new IMAP_r_ServerStatus(cmdTag,"OK",new IMAP_t_orc_Unknown(e.IsReadOnly ? "READ-ONLY" : "READ-WRITE"),"SELECT completed in " + ((DateTime.Now.Ticks - startTime) / (decimal)10000000).ToString("f2") + " seconds."));

                    m_pSelectedFolder = new _SelectedFolder(folder,e.IsReadOnly,eMessagesInfo.MessagesInfo);
                    m_pSelectedFolder.Reindex();
                }
                else{
                    m_pResponseSender.SendResponseAsync(e.ErrorResponse);
                }
            }
            catch(Exception x){
                m_pResponseSender.SendResponseAsync(new IMAP_r_ServerStatus(cmdTag,"NO","NO Error: " + x.Message));
            }
        }