⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pop3mailclient.cs

📁 《征服Ajax》原书的例题源码
💻 CS
📖 第 1 页 / 共 2 页
字号:
          if (executeCommand("QUIT", out response)) {
            //server says everything is ok
            setPop3ConnectionState(Pop3ConnectionStateEnum.Closed);
          } else {
            //server says there is a problem
            CallWarning("Disconnect", response, "negative response from server while closing connection: " + response);
            setPop3ConnectionState(Pop3ConnectionStateEnum.Disconnected);
          }
        } finally {
          //close connection
          if (pop3Stream!=null) {
            pop3Stream.Close();
          }

          pop3StreamReader.Close();
        }
      }
    }


    /// <summary>
    /// Delete message from server.
    /// The POP3 server marks the message as deleted.  Any future
    /// reference to the message-number associated with the message
    /// in a POP3 command generates an error.  The POP3 server does
    /// not actually delete the message until the POP3 session
    /// enters the UPDATE state.
    /// </summary>
    /// <param name="msg_number"></param>
    /// <returns></returns>
    public bool DeleteEmail(int msg_number) {
      EnsureState(Pop3ConnectionStateEnum.Connected);
      string response;
      if (!executeCommand("DELE " + msg_number.ToString(), out response)) {
        CallWarning("DeleteEmail", response, "negative response for email (Id: {0}) delete request", msg_number);
        return false;
      }
      return true;
    }


    /// <summary>
    /// Get a list of all Email IDs available in mailbox
    /// </summary>
    /// <returns></returns>
    public bool GetEmailIdList(out List<int> EmailIds) {
      EnsureState(Pop3ConnectionStateEnum.Connected);
      EmailIds = new List<int>();

      //get server response status line
      string response;
      if (!executeCommand("LIST", out response)) {
        CallWarning("GetEmailIdList", response, "negative response for email list request");
        return false;
      }

      //get every email id
      int EmailId;
      while (readMultiLine(out response)) {
        if (int.TryParse(response.Split(' ')[0], out EmailId)) {
          EmailIds.Add(EmailId);
        } else {
          CallWarning("GetEmailIdList", response, "first characters should be integer (EmailId)");
        }
      }
      TraceFrom("{0} email ids received", EmailIds.Count);
      return true;
    }


    /// <summary>
    /// get size of one particular email
    /// </summary>
    /// <param name="msg_number"></param>
    /// <returns></returns>
    public int GetEmailSize(int msg_number) {
      EnsureState(Pop3ConnectionStateEnum.Connected);
      string response;
      executeCommand("LIST " + msg_number.ToString(), out response);
      int EmailSize = 0;
      string[] responseSplit = response.Split(' ');
      if (responseSplit.Length<2 || !int.TryParse(responseSplit[2], out EmailSize)) {
        CallWarning("GetEmailSize", response, "'+OK int int' format expected (EmailId, EmailSize)");
      }

      return EmailSize;
    }


    /// <summary>
    /// Get a list with the unique IDs of all Email available in mailbox.
    /// 
    /// Explanation:
    /// EmailIds for the same email can change between sessions, whereas the unique Email id
    /// never changes for an email.
    /// </summary>
    /// <param name="EmailIds"></param>
    /// <returns></returns>
    public bool GetUniqueEmailIdList(out List<EmailUid> EmailIds) {
      EnsureState(Pop3ConnectionStateEnum.Connected);
      EmailIds = new List<EmailUid>();

      //get server response status line
      string response;
      if (!executeCommand("UIDL ", out response)) {
        CallWarning("GetUniqueEmailIdList", response, "negative response for email list request");
        return false;
      }

      //get every email unique id
      int EmailId;
      while (readMultiLine(out response)) {
        string[] responseSplit = response.Split(' ');
        if (responseSplit.Length<2) {
          CallWarning("GetUniqueEmailIdList", response, "response not in format 'int string'");
        } else if (!int.TryParse(responseSplit[0], out EmailId)) {
          CallWarning("GetUniqueEmailIdList", response, "first characters should be integer (Unique EmailId)");
        } else {
          EmailIds.Add(new EmailUid(EmailId, responseSplit[1]));
        }
      }
      TraceFrom("{0} unique email ids received", EmailIds.Count);
      return true;
    }


    /// <summary>
    /// get a list with all currently available messages and the UIDs
    /// </summary>
    /// <param name="EmailIds">EmailId Uid list</param>
    /// <returns>false: server sent negative response (didn't send list)</returns>
    public bool GetUniqueEmailIdList(out SortedList<string, int> EmailIds) {
      EnsureState(Pop3ConnectionStateEnum.Connected);
      EmailIds = new SortedList<string, int>();

      //get server response status line
      string response;
      if (!executeCommand("UIDL", out response)) {
        CallWarning("GetUniqueEmailIdList", response, "negative response for email list request");
        return false;
      }

      //get every email unique id
      int EmailId;
      while (readMultiLine(out response)) {
        string[] responseSplit = response.Split(' ');
        if (responseSplit.Length<2) {
          CallWarning("GetUniqueEmailIdList", response, "response not in format 'int string'");
        } else if (!int.TryParse(responseSplit[0], out EmailId)) {
          CallWarning("GetUniqueEmailIdList", response, "first characters should be integer (Unique EmailId)");
        } else {
          EmailIds.Add(responseSplit[1], EmailId);
        }
      }
      TraceFrom("{0} unique email ids received", EmailIds.Count);
      return true;
    }


    /// <summary>
    /// get size of one particular email
    /// </summary>
    /// <param name="msg_number"></param>
    /// <returns></returns>
    public int GetUniqueEmailId(EmailUid msg_number) {
      EnsureState(Pop3ConnectionStateEnum.Connected);
      string response;
      executeCommand("LIST " + msg_number.ToString(), out response);
      int EmailSize = 0;
      string[] responseSplit = response.Split(' ');
      if (responseSplit.Length<2 || !int.TryParse(responseSplit[2], out EmailSize)) {
        CallWarning("GetEmailSize", response, "'+OK int int' format expected (EmailId, EmailSize)");
      }

      return EmailSize;
    }


    /// <summary>
    /// Sends an 'empty' command to the POP3 server. Server has to respond with +OK
    /// </summary>
    /// <returns>true: server responds as expected</returns>
    public bool NOOP() {
      EnsureState(Pop3ConnectionStateEnum.Connected);
      string response;
      if (!executeCommand("NOOP", out response)) {
        CallWarning("NOOP", response, "negative response for NOOP request");
        return false;
      }
      return true;
    }

    /// <summary>
    /// Should the raw content, the US-ASCII code as received, be traced
    /// GetRawEmail will switch it on when it starts and off once finished
    /// 
    /// Inheritors might use it to get the raw email
    /// </summary>
    protected bool isTraceRawEmail = false;


    /// <summary>
    /// contains one MIME part of the email in US-ASCII, needs to be translated in .NET string (Unicode)
    /// contains the complete email in US-ASCII, needs to be translated in .NET string (Unicode)
    /// For speed reasons, reuse StringBuilder
    /// </summary>
    protected StringBuilder RawEmailSB;


    /// <summary>
    /// Reads the complete text of a message
    /// </summary>
    /// <param name="MessageNo">Email to retrieve</param>
    /// <param name="EmailText">ASCII string of complete message</param>
    /// <returns></returns>
    public bool GetRawEmail(int MessageNo, out string EmailText) {
      //send 'RETR int' command to server
      if (!SendRetrCommand(MessageNo)) {
        EmailText = null;
        return false;
      }

      //get the lines
      string response;
      int LineCounter = 0;
      //empty StringBuilder
      if (RawEmailSB==null) {
        RawEmailSB = new StringBuilder(100000);
      } else {
        RawEmailSB.Length = 0;
      }
      isTraceRawEmail = true;
      while (readMultiLine(out response)) {
        LineCounter += 1;
      }
      EmailText = RawEmailSB.ToString();
      TraceFrom("email with {0} lines,  {1} chars received", LineCounter.ToString(), EmailText.Length);
      return true;
    }


    /// <summary>
    /// Unmark any emails from deletion. The server only deletes email really
    /// once the connection is properly closed.
    /// </summary>
    /// <returns>true: emails are unmarked from deletion</returns>
    public bool UndeleteAllEmails() {
      EnsureState(Pop3ConnectionStateEnum.Connected);
      string response;
      return executeCommand("RSET", out response);
    }


    /// <summary>
    /// Get mailbox statistics
    /// </summary>
    public bool GetMailboxStats(out int NumberOfMails, out int MailboxSize) {
      EnsureState(Pop3ConnectionStateEnum.Connected);

      //interpret response
      string response;
      NumberOfMails = 0;
      MailboxSize =0;
      if (executeCommand("STAT", out response)) {
        //got a positive response
        string[] responseParts = response.Split(' ');
        if (responseParts.Length<2) {
          //response format wrong
          throw new Pop3Exception("Server " + popServer + " sends illegally formatted response." +
            "\nExpected format: +OK int int" +
            "\nReceived response: " + response);
        }
        NumberOfMails = int.Parse(responseParts[1]);
        MailboxSize   = int.Parse(responseParts[2]);
        return true;
      }
      return false;
    }


    /// <summary>
    /// Send RETR command to POP 3 server to fetch one particular message
    /// </summary>
    /// <param name="MessageNo">ID of message required</param>
    /// <returns>false: negative server respond, message not delivered</returns>
    protected bool SendRetrCommand(int MessageNo) {
      EnsureState(Pop3ConnectionStateEnum.Connected);
      // retrieve mail with message number
      string response;
      if (!executeCommand("RETR "+ MessageNo.ToString(), out response)) {
        CallWarning("GetRawEmail", response, "negative response for email (ID: {0}) request", MessageNo);
        return false;
      }
      return true;
    }


    //Helper methods
    //--------------

    /// <summary>
    /// sends the 4 letter command to POP3 server (adds CRLF) and waits for the
    /// response of the server
    /// </summary>
    /// <param name="command">command to be sent to server</param>
    /// <param name="response">answer from server</param>
    /// <returns>false: server sent negative acknowledge, i.e. server could not execute command</returns>
    private bool executeCommand(string command, out string response) {
      //send command to server
      byte[] commandBytes = System.Text.Encoding.ASCII.GetBytes((command + CRLF).ToCharArray());
      CallTrace("Tx '{0}'", command);
      bool isSupressThrow = false;
      try {
        pop3Stream.Write(commandBytes, 0, commandBytes.Length);
      } catch (IOException ex) {
        //Unable to write data to the transport connection. Check if reconnection should be tried
        isSupressThrow = executeReconnect(ex, command, commandBytes);
        if (!isSupressThrow) {
          throw;
        }
      }
      pop3Stream.Flush();

      //read response from server
      response = null;
      try {
        response = pop3StreamReader.ReadLine();
      } catch (IOException ex) {
        //Unable to write data to the transport connection. Check if reconnection should be tried
        isSupressThrow = executeReconnect(ex, command, commandBytes);
        if (isSupressThrow) {
          //wait for response one more time
          response = pop3StreamReader.ReadLine();
        } else {
          throw;
        }
      }
      if (response==null) {
        isSupressThrow = executeReconnect(new IOException("Timeout", new SocketException(10053)), command, commandBytes);
        if (isSupressThrow) {
          //wait for response one more time
          response = pop3StreamReader.ReadLine();
        }
        if (response==null) {
          throw new Pop3Exception("Server "+ popServer + " has not responded, timeout has occurred.");
        }
      }
      CallTrace("Rx '{0}'", response);
      return (response.Length>0 && response[0]=='+');
    }


    /// <summary>
    /// Reconnect, if there is a timeout exception and isAutoReconnect is true
    /// </summary>
    private bool executeReconnect(IOException ex, string command, byte[] commandBytes) {
      if (ex.InnerException!=null && ex.InnerException is SocketException) {
        //SocketException
        SocketException innerEx = (SocketException)ex.InnerException;
        if (innerEx.ErrorCode==10053) {
          //probably timeout: An established connection was aborted by the software in your host machine.
          CallWarning("ExecuteCommand", "", "probably timeout occurred");
          if (isAutoReconnect) {
            //try to reconnect and send one more time
            isTimeoutReconnect = true;
            try {
              CallTrace("   try to auto reconnect");
              Connect();

              CallTrace("   reconnect successful, try to resend command");
              CallTrace("Tx '{0}'", command);
              pop3Stream.Write(commandBytes, 0, commandBytes.Length);
              pop3Stream.Flush();
              return true;
            } finally {
              isTimeoutReconnect = false;
            }
          }
        }
      }
      return false;
    }


    /// <summary>
    /// read single line response from POP3 server. 
    /// <example>Example server response: +OK asdfkjahsf</example>
    /// </summary>
    /// <param name="response">response from POP3 server</param>
    /// <returns>true: positive response</returns>
    protected bool readSingleLine(out string response) {
      response = null;
      try {
        response = pop3StreamReader.ReadLine();
      } catch (Exception ex) {
        string s = ex.Message;
      }
      if (response==null) {
        throw new Pop3Exception("Server "+ popServer + " has not responded, timeout has occurred.");
      }
      CallTrace("Rx '{0}'", response);
      return (response.Length>0 && response[0]=='+');
    }


    /// <summary>
    /// read one line in multiline mode from the POP3 server. 
    /// </summary>
    /// <param name="response">line received</param>
    /// <returns>false: end of message</returns>
    /// <returns></returns>
    protected bool readMultiLine(out string response) {
      response = null;
      response = pop3StreamReader.ReadLine();
      if (response==null) {
        throw new Pop3Exception("Server "+ popServer + " has not responded, probably timeout has occurred.");
      }
      if (isTraceRawEmail) {
        //collect all responses as received
        RawEmailSB.Append(response + CRLF);
      }
      //check for byte stuffing, i.e. if a line starts with a '.', another '.' is added, unless
      //it is the last line
      if (response.Length>0 && response[0]=='.') {
        if (response==".") {
          //closing line found
          return false;
        }
        //remove the first '.'
        response = response.Substring(1, response.Length-1);
      }
      return true;
    }

  }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -