📄 pop3mailclient.cs
字号:
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 + -