Пример #1
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;
 }
Пример #2
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;
		}
Пример #3
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);
        }
Пример #4
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;
		}
Пример #5
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){
				m_pSocket.SendLine(cmdTag + " NO Authenticate first !");
				return;
			}

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

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

				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 [READ-ONLY] EXAMINE Completed\r\n";

				m_pSocket.SendData(response);
			}
			else{
				m_pSocket.SendLine(cmdTag + " NO " + messages.ErrorText);
			}
		}
Пример #6
0
		//--- End of non-Authenticated State 


		//--- Authenticated State ------

		#region function Select

		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){
				m_pSocket.SendLine(cmdTag + " NO Authenticate first !");
				return;
			}

			string[] args = ParseParams(argsText);
			if(args.Length != 1){
				m_pSocket.SendLine(cmdTag + " BAD SELECT invalid arguments");
				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 flags\r\n";
				response += cmdTag + " OK [" + (m_Messages.ReadOnly ? "READ-ONLY" : "READ-WRITE") + "] SELECT Completed\r\n";

				m_pSocket.SendData(response);
			}
			else{
				m_pSocket.SendLine(cmdTag + " NO " + messages.ErrorText);
			}
		}
Пример #7
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";

					m_pSocket.SendData(reply);
				}
			}

			m_pSocket.SendLine(cmdTag + " OK NOOP completed");
		}
Пример #8
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){
				m_pSocket.SendLine(cmdTag + " NO Authenticate first !");
				return;
			}
			if(m_SelectedMailbox.Length == 0){
				m_pSocket.SendLine(cmdTag + " NO Select mailbox first !");
				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){
					m_pSocket.SendLine("* " + msg.MessageNo + " EXPUNGE");

					m_Messages.RemoveMessage(msg);
				}
				else{
					m_pSocket.SendLine(cmdTag + " NO " + errorText);
					return;
				}
			}

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

			m_pSocket.SendLine(cmdTag + " OK EXPUNGE completed");
		}
Пример #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){
				m_pSocket.SendLine(cmdTag + " NO Authenticate first !");
				return;
			}			
			if(m_SelectedMailbox.Length == 0){
				m_pSocket.SendLine(cmdTag + " NO Select mailbox first !");
				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;

			m_pSocket.SendLine(cmdTag + " OK CLOSE completed");
		}