IMAP messages info collection.
        /// <summary>
        /// Default constructor.
        /// </summary>
        /// <param name="session">IMAP session what calls this search.</param>
        /// <param name="folder">IMAP folder name which messages to search.</param>
        /// <param name="matcher">Matcher what must be used to check if message matches searching criterial.</param>
        public IMAP_eArgs_Search(IMAP_Session session,string folder,IMAP_SearchMatcher matcher)
        {
            m_pSession  = session;
            m_Folder    = folder;
            m_pMatcher  = matcher;

            m_pMessages = new IMAP_Messages(folder);
        }
        /// <summary>
        /// Default constructor.
        /// </summary>
        /// <param name="session">IMAP session what calls this search.</param>
        /// <param name="folder">IMAP folder name which messages to search.</param>
        /// <param name="matcher">Matcher what must be used to check if message matches searching criterial.</param>
        public IMAP_eArgs_Search(IMAP_Session session, string folder, IMAP_SearchMatcher matcher)
        {
            m_pSession = session;
            m_Folder   = folder;
            m_pMatcher = matcher;

            m_pMessages = new IMAP_Messages(folder);
        }
Beispiel #3
0
 /// <summary>
 /// Default constructor.
 /// </summary>
 /// <param name="messages"></param>
 /// <param name="messageID">Internal messageID.</param>
 /// <param name="UID">Message UID. NOTE: message uid must increase all the time, for new messages.</param>
 /// <param name="flags">Message flags.</param>
 /// <param name="size">Message size.</param>
 /// <param name="date">Message receive date.</param>
 internal IMAP_Message(IMAP_Messages messages, string messageID, int UID, IMAP_MessageFlags flags, long size, DateTime date)
 {
     m_Messages  = messages;
     m_MessageID = messageID;
     m_UID       = UID;
     m_Flags     = flags;
     m_Size      = size;
     m_Date      = date;
 }
Beispiel #4
0
 /// <summary>
 /// Default constructor.
 /// </summary>
 /// <param name="messages"></param>
 /// <param name="messageID">Internal messageID.</param>
 /// <param name="UID">Message UID. NOTE: message uid must increase all the time, for new messages.</param>
 /// <param name="flags">Message flags.</param>
 /// <param name="size">Message size.</param>
 /// <param name="date">Message receive date.</param>
 internal IMAP_Message(IMAP_Messages messages,string messageID,int UID,IMAP_MessageFlags flags,long size,DateTime date)
 {
     m_Messages  = messages;
     m_MessageID = messageID;
     m_UID       = UID;
     m_Flags     = flags;
     m_Size      = size;
     m_Date      = date;
 }
Beispiel #5
0
        /// <summary>
        /// Raises event 'GetMessagesInfo'.
        /// </summary>
        /// <param name="session">Reference to IMAP session.</param>
        /// <param name="mailbox">Mailbox which messages info to get.</param>
        /// <returns></returns>
        internal IMAP_Messages OnGetMessagesInfo(IMAP_Session session, string mailbox)
        {
            IMAP_Messages messages = new IMAP_Messages(mailbox);

            if (this.GetMessagesInfo != null)
            {
                this.GetMessagesInfo(session, messages);
            }

            return(messages);
        }
Beispiel #6
0
        private void Expunge(string cmdTag)
        {
            /* RFC 3501 6.4.3 EXPUNGE Command

                Arguments:  none

                Responses:  untagged responses: EXPUNGE

                Result:     OK - expunge completed
                            NO - expunge failure: can't expunge (e.g., permission
                                    denied)
                            BAD - command unknown or arguments invalid

                    The EXPUNGE command permanently removes all messages that have the
                    \Deleted flag set from the currently selected mailbox.  Before
                    returning an OK to the client, an untagged EXPUNGE response is
                    sent for each message that is removed.

                The EXPUNGE response reports that the specified message sequence
                number has been permanently removed from the mailbox.  The message
                sequence number for each successive message in the mailbox is
                IMMEDIATELY DECREMENTED BY 1, and this decrement is reflected in
                message sequence numbers in subsequent responses (including other
                untagged EXPUNGE responses).

                Example:    C: A202 EXPUNGE
                            S: * 3 EXPUNGE
                            S: * 3 EXPUNGE
                            S: * 5 EXPUNGE
                            S: * 8 EXPUNGE
                            S: A202 OK EXPUNGE completed

                        Note: In this example, messages 3, 4, 7, and 11 had the
                        \Deleted flag set.  See the description of the EXPUNGE
                        response for further explanation.

            */
            if(!m_Authenticated){
                SendData(cmdTag + " NO Authenticate first !\r\n");
                return;
            }
            if(m_SelectedMailbox.Length == 0){
                SendData(cmdTag + " NO Select mailbox first !\r\n");
                return;
            }

            IMAP_Message[] messages = m_Messages.GetDeleteMessages();
            for(int i=0;i<messages.Length;i++){
                IMAP_Message msg = messages[i];

                string errorText = m_pServer.OnDeleteMessage(this,msg);
                if(errorText == null){
                    SendData("* " + msg.MessageNo + " EXPUNGE\r\n");

                    m_Messages.RemoveMessage(msg);
                }
                else{
                    SendData(cmdTag + " NO " + errorText + "\r\n");
                    return;
                }
            }

            // Refresh m_Messages to reflect deletion
            m_Messages = m_pServer.OnGetMessagesInfo(this,this.SelectedMailbox);

            SendData(cmdTag + " OK EXPUNGE completed\r\n");
        }
        private void IMAP_Server_GetMessagesInfo(object sender, IMAP_Messages e)
        {
            try
            {
                IMAP_Session ses = (IMAP_Session)sender;

                m_pAPI.GetMessagesInfo(ses.UserName,e.Mailbox,e);
            }
            catch(Exception x){
                e.ErrorText = x.Message;
            }
        }
Beispiel #8
0
        private void Examine(string cmdTag,string argsText)
        {
            /* 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
            */
            if(!m_Authenticated){
                SendData(cmdTag + " NO Authenticate first !\r\n");
                return;
            }

            string[] args = ParseParams(argsText);
            if(args.Length != 1){
                SendData(cmdTag + " BAD EXAMINE invalid arguments\r\n");
                return;
            }

            IMAP_Messages messages = m_pServer.OnGetMessagesInfo(this,args[0]);
            if(messages.ErrorText == null){
                messages.ReadOnly = true;
                m_Messages = messages;
                m_SelectedMailbox = argsText;

                SendData("* FLAGS (\\Answered \\Flagged \\Deleted \\Seen \\Draft)\r\n");
                SendData("* " + m_Messages.Count + " EXISTS\r\n");
                SendData("* " + m_Messages.RecentCount + " RECENT\r\n");
                SendData("* OK [UNSEEN " + m_Messages.FirstUnseen + "] Message " + m_Messages.FirstUnseen + " is first unseen\r\n");
                SendData("* OK [UIDVALIDITY " + m_Messages.MailboxUID + "] UIDs valid\r\n");
                SendData("* OK [UIDNEXT " + m_Messages.UID_Next + "] Predicted next UID\r\n");
                SendData("* OK [PERMANENTFLAGS ()] No permanent flags permitted\r\n");
                SendData(cmdTag + " OK [READ-ONLY] EXAMINE Completed\r\n");
            }
            else{
                SendData(cmdTag + " NO " + messages.ErrorText + "\r\n");
            }
        }
Beispiel #9
0
        private void Close(string cmdTag)
        {
            /* 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 from the currently selected
                mailbox all messages that have the \Deleted flag set, and returns
                to authenticated state from 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(!m_Authenticated){
                SendData(cmdTag + " NO Authenticate first !\r\n");
                return;
            }
            if(m_SelectedMailbox.Length == 0){
                SendData(cmdTag + " NO Select mailbox first !\r\n");
                return;
            }

            if(!m_Messages.ReadOnly){
                IMAP_Message[] messages = m_Messages.GetDeleteMessages();
                foreach(IMAP_Message msg in messages){
                    m_pServer.OnDeleteMessage(this,msg);
                }
            }

            m_SelectedMailbox = "";
            m_Messages        = null;

            SendData(cmdTag + " OK CLOSE completed\r\n");
        }
Beispiel #10
0
        private void Select(string cmdTag,string argsText)
        {
            /* 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

            */
            if(!m_Authenticated){
                SendData(cmdTag + " NO Authenticate first !\r\n");
                return;
            }

            string[] args = ParseParams(argsText);
            if(args.Length != 1){
                SendData(cmdTag + " BAD SELECT invalid arguments\r\n");
                return;
            }

            IMAP_Messages messages = m_pServer.OnGetMessagesInfo(this,args[0]);
            if(messages.ErrorText == null){
                m_Messages = messages;
                m_SelectedMailbox = args[0];

                string response = "";
                response += "* FLAGS (\\Answered \\Flagged \\Deleted \\Seen \\Draft)\r\n";
                response += "* " + m_Messages.Count + " EXISTS\r\n";
                response += "* " + m_Messages.RecentCount + " RECENT\r\n";
                response += "* OK [UNSEEN " + m_Messages.FirstUnseen + "] Message " + m_Messages.FirstUnseen + " is first unseen\r\n";
                response += "* OK [UIDVALIDITY " + m_Messages.MailboxUID + "] UIDs valid\r\n";
                response += "* OK [UIDNEXT " + m_Messages.UID_Next + "] Predicted next UID\r\n";
                response += "* OK [PERMANENTFLAGS (\\Answered \\Flagged \\Deleted \\Seen \\Draft)] Available permanent falgs\r\n";
                response += cmdTag + " OK [" + (m_Messages.ReadOnly ? "READ-ONLY" : "READ-WRITE") + "] SELECT Completed\r\n";

                SendData(response);
            }
            else{
                SendData(cmdTag + " NO " + messages.ErrorText + "\r\n");
            }
        }
Beispiel #11
0
        private void Noop(string cmdTag)
        {
            /* RFC 3501 6.1.2 NOOP Command

                Arguments:  none

                Responses:  no specific responses for this command (but see below)

                Result:     OK - noop completed
                            BAD - command unknown or arguments invalid

                The NOOP command always succeeds.  It does nothing.
                Since any command can return a status update as untagged data, the
                NOOP command can be used as a periodic poll for new messages or
                message status updates during a period of inactivity.  The NOOP
                command can also be used to reset any inactivity autologout timer
                on the server.

                Example: C: a002 NOOP
                         S: a002 OK NOOP completed
            */

            // If there is selected mailobx, see if messages status has changed
            if(m_SelectedMailbox.Length > 0){
                // Get status
                IMAP_Messages messages = m_pServer.OnGetMessagesInfo(this,m_SelectedMailbox);

                // messages status has changed
                if(messages.Count != m_Messages.Count || messages.RecentCount != m_Messages.RecentCount){
                    m_Messages = messages;

                    string reply = "";
                           reply += "* " + m_Messages.Count + " EXISTS\r\n";
                           reply += "* " + m_Messages.RecentCount + " RECENT\r\n";

                    SendData(reply);
                }
            }

            SendData(cmdTag + " OK NOOP completed\r\n");
        }
        private void Expunge(string cmdTag)
        {
            /* RFC 3501 6.4.3 EXPUNGE Command

                Arguments:  none

                Responses:  untagged responses: EXPUNGE

                Result:     OK - expunge completed
                            NO - expunge failure: can't expunge (e.g., permission
                                    denied)
                            BAD - command unknown or arguments invalid

                    The EXPUNGE command permanently removes all messages that have the
                    \Deleted flag set from the currently selected mailbox.  Before
                    returning an OK to the client, an untagged EXPUNGE response is
                    sent for each message that is removed.

                Example:    C: A202 EXPUNGE
                            S: * 3 EXPUNGE
                            S: * 3 EXPUNGE
                            S: * 5 EXPUNGE
                            S: * 8 EXPUNGE
                            S: A202 OK EXPUNGE completed

                        Note: In this example, messages 3, 4, 7, and 11 had the
                        \Deleted flag set.  See the description of the EXPUNGE
                        response for further explanation.

            */
            if(!m_Authenticated){
                SendData(cmdTag + " NO Authenticate first !\r\n");
                return;
            }
            if(m_SelectedMailbox.Length == 0){
                SendData(cmdTag + " NO Select mailbox first !\r\n");
                return;
            }

            IMAP_Message[] messages = m_Messages.GetDeleteMessages();
            foreach(IMAP_Message msg in messages){
                string errorText = m_pIMAP_Server.OnDeleteMessage(this,msg);
                if(errorText == null){
                    SendData("* " + msg.MessageNo + " EXPUNGE\r\n");
                }
                else{
                    SendData(cmdTag + " NO " + errorText + "\r\n");
                    return;
                }
            }

            // Refresh m_Messages to reflect deletion
            m_Messages = m_pIMAP_Server.OnGetMessagesInfo(this,this.SelectedMailbox);

            SendData(cmdTag + " OK EXPUNGE completed\r\n");
        }