📄 pop3.cpp
字号:
//if we haven't executed the STAT command then do it now
int nNumberOfMails = m_nNumberOfMails;
int nTotalMailSize;
if (!m_bStatRetrieved)
{
if (!Statistics(nNumberOfMails, nTotalMailSize))
return FALSE;
else
m_bStatRetrieved = TRUE;
}
//Send the UIDL command
char sBuf[10];
strcpy(sBuf, "UIDL\r\n");
int nCmdLength = strlen(sBuf);
if (!m_Pop.Send(sBuf, nCmdLength))
{
TRACE(_T("Failed in call to send UIDL command\n"));
return FALSE;
}
//And check the response
m_bUIDLRetrieved = ReadUIDLResponse(nNumberOfMails);
return m_bUIDLRetrieved;
}
BOOL CPop3Connection::Reset()
{
//Must be connected to perform a "RSET"
ASSERT(m_bConnected);
//Send the RSET command
char sBuf[10];
strcpy(sBuf, "RSET\r\n");
int nCmdLength = strlen(sBuf);
if (!m_Pop.Send(sBuf, nCmdLength))
{
TRACE(_T("Failed in call to send RSET command\n"));
return FALSE;
}
//And check the command
return ReadCommandResponse();
}
BOOL CPop3Connection::Noop()
{
//Must be connected to perform a "NOOP"
ASSERT(m_bConnected);
//Send the NOOP command
char sBuf[10];
strcpy(sBuf, "NOOP\r\n");
int nCmdLength = strlen(sBuf);
if (!m_Pop.Send(sBuf, nCmdLength))
{
TRACE(_T("Failed in call to send NOOP command\n"));
return FALSE;
}
//And check the response
return ReadCommandResponse();
}
BOOL CPop3Connection::Retrieve(int nMsg, CPop3Message& message)
{
//Must be connected to retrieve a message
ASSERT(m_bConnected);
//work out the size of the message to retrieve
DWORD dwSize;
if (GetMessageSize(nMsg, dwSize))
{
//Send the RETR command
char sBuf[20];
sprintf(sBuf, "RETR %d\r\n", nMsg);
int nCmdLength = strlen(sBuf);
if (!m_Pop.Send(sBuf, nCmdLength))
{
TRACE(_T("Failed in call to send RETR command\n"));
return FALSE;
}
//And check the command
return ReadReturnResponse(message, dwSize);
}
else
return FALSE;
}
BOOL CPop3Connection::GetMessageHeader(int nMsg, CPop3Message& message)
{
// Must be connected to retrieve a message
ASSERT(m_bConnected);
// make sure the message actually exists
DWORD dwSize;
if (GetMessageSize(nMsg, dwSize))
{
// Send the TOP command
char sBuf[16];
sprintf(sBuf, "TOP %d 0\r\n", nMsg);
int nCmdLength = strlen(sBuf);
if (!m_Pop.Send(sBuf, nCmdLength))
{
TRACE(_T("Failed in call to send TOP command\n"));
return FALSE;
}
// And check the command
return ReadReturnResponse(message, dwSize);
}
else
return FALSE;
}
BOOL CPop3Connection::ReadCommandResponse()
{
char sBuf[1000];
return ReadResponse(sBuf, sizeof(sBuf), "\r\n");
}
BOOL CPop3Connection::ReadReturnResponse(CPop3Message& message, DWORD dwSize)
{
//Must be connected to perform a "RETR"
ASSERT(m_bConnected);
//We need a flexible sized receiver buffer here
int nSize = dwSize + 100;
char* sBuf = new char[nSize];
if (!ReadResponse(sBuf, nSize, "\r\n.\r\n"))
{
TRACE(_T("Error retrieving the RETR response"));
return FALSE;
}
//determine if the response is an error
if (strnicmp(sBuf,"+OK", 3) != 0)
{
SetLastError(WSAEPROTONOSUPPORT);
TRACE(_T("POP3 server did not respond correctly to the RETR response\n"));
delete []sBuf;
return FALSE;
}
else
{
//remove the first line which contains the +OK from the message
char* pszFirst = GetFirstCharInResponse(sBuf);
VERIFY(pszFirst);
//transfer the message contents to the message class
int nMessageSize = sBuf - pszFirst + strlen(sBuf);
message.m_pszMessage = new char[nMessageSize + 1];
memcpy(message.m_pszMessage, pszFirst, nMessageSize);
message.m_pszMessage[nMessageSize] = '\0';
}
delete []sBuf;
return TRUE;
}
BOOL CPop3Connection::ReadListResponse(int nNumberOfMails)
{
//Must be connected to perform a "LIST"
ASSERT(m_bConnected);
//We need a flexible sized receiver buffer here
int nSize = 14 * nNumberOfMails + 100;
char* sBuf = new char[nSize];
//retrieve the reponse
if (!ReadResponse(sBuf, nSize, "\r\n.\r\n"))
{
TRACE(_T("Error retrieving the LIST response\n"));
delete []sBuf;
return FALSE;
}
//determine if the response is an error
if (strnicmp(sBuf,"+OK", 3) != 0)
{
SetLastError(WSAEPROTONOSUPPORT);
TRACE(_T("POP3 server did not respond correctly to the LIST response\n"));
delete[] sBuf;
return FALSE;
}
else
{
//Retrieve the message sizes and put them
//into the m_msgSizes array
m_msgSizes.RemoveAll();
m_msgSizes.SetSize(0, nNumberOfMails);
//then parse the LIST response
char* pszSize = GetFirstCharInResponse(sBuf);
VERIFY(pszSize);
for (; *pszSize != '.'; pszSize++)
if (*pszSize == '\t' || *pszSize == ' ')
m_msgSizes.Add(atoi(pszSize));
}
delete[] sBuf;
return TRUE;
}
BOOL CPop3Connection::ReadUIDLResponse(int nNumberOfMails)
{
//Must be connected to perform a "LIST"
ASSERT(m_bConnected);
//We need a flexible sized receiver buffer here
int nSize = 1000 * nNumberOfMails + 100;
char* sBuf = new char[nSize];
//retrieve the reponse
if (!ReadResponse(sBuf, nSize, "\r\n.\r\n"))
{
TRACE(_T("Error retrieving the UIDL response\n"));
delete []sBuf;
return FALSE;
}
//determine if the response is an error
if (strnicmp(sBuf,"+OK", 3) != 0)
{
SetLastError(WSAEPROTONOSUPPORT);
TRACE(_T("POP3 server did not respond correctly to the UIDL response\n"));
delete[] sBuf;
return FALSE;
}
else
{
//Retrieve the message ID's and put them
//into the m_msgIDs array
m_msgIDs.RemoveAll();
m_msgIDs.SetSize(0, nNumberOfMails);
//then parse the UIDL response
char* pszSize = GetFirstCharInResponse(sBuf);
VERIFY(pszSize);
for (; *pszSize != '.'; pszSize++)
{
char* pszBegin = pszSize;
while (*pszSize != '\n' && *pszSize != '.')
{
++pszSize;
}
if (*pszSize == '.')
continue;
char sMsg[15];
char sID[1000];
*pszSize = '\0';
sscanf(pszBegin, "%s %s", sMsg, sID);
m_msgIDs.Add(CString(sID));
}
}
delete[] sBuf;
return TRUE;
}
LPSTR CPop3Connection::GetFirstCharInResponse(LPSTR pszData) const
{
while ((*pszData != '\n') && *pszData)
++pszData;
//skip over the "\n" onto the next line
if (*pszData)
++pszData;
return pszData;
}
BOOL CPop3Connection::ReadStatResponse(int& nNumberOfMails, int& nTotalMailSize)
{
//Must be connected to perform a "STAT"
ASSERT(m_bConnected);
//retrieve the reponse
char sBuf[100];
if (!ReadResponse(sBuf, sizeof(sBuf), "\r\n"))
{
TRACE(_T("Error retrieving the STAT response"));
return FALSE;
}
//determine if the response is an error
if (strncmp(sBuf,"+OK", 3) != 0)
{
TRACE(_T("POP3 server did not respond correctly to the STAT response\n"));
return FALSE;
}
else
{
//Parse out the Number of Mails and Total mail size values
BOOL bGetNumber = TRUE;
for (char* pszNum=sBuf; *pszNum!='\0'; pszNum++)
{
if (*pszNum=='\t' || *pszNum==' ')
{
if (bGetNumber)
{
nNumberOfMails = atoi(pszNum);
m_nNumberOfMails = nNumberOfMails;
bGetNumber = FALSE;
}
else
{
nTotalMailSize = atoi(pszNum);
return TRUE;
}
}
}
}
return FALSE;
}
BOOL CPop3Connection::ReadResponse(LPSTR pszBuffer, int nBuf, LPSTR pszTerminator)
{
//paramater validity checking
ASSERT(pszBuffer);
ASSERT(nBuf);
//must have been created first
ASSERT(m_bConnected);
//retrieve the reponse using until we
//get the terminator or a timeout occurs
BOOL bFoundTerminator = FALSE;
int nReceived = 0;
DWORD dwStartTicks = ::GetTickCount();
while (!bFoundTerminator)
{
//timeout has occured
if ((::GetTickCount() - dwStartTicks) > m_dwTimeout)
{
pszBuffer[nReceived] = '\0';
SetLastError(WSAETIMEDOUT);
m_sLastCommandResponse = pszBuffer; //Hive away the last command reponse
return FALSE;
}
//check the socket for readability
BOOL bReadible;
if (!m_Pop.IsReadible(bReadible))
{
pszBuffer[nReceived] = '\0';
m_sLastCommandResponse = pszBuffer; //Hive away the last command reponse
return FALSE;
}
else if (!bReadible) //no data to receive, just loop around
{
Sleep(100); //Wait for 100 ms prior to looping around,
//helps to improve performance of system
continue;
}
//receive the data from the socket
int nData = m_Pop.Receive(pszBuffer+nReceived, nBuf-nReceived);
if (nData == SOCKET_ERROR)
{
pszBuffer[nReceived] = '\0';
m_sLastCommandResponse = pszBuffer; //Hive away the last command reponse
return FALSE;
}
else
{
if (nData)
dwStartTicks = ::GetTickCount(); //Reset the idle timeout
nReceived += nData; //Increment the count of data received
}
pszBuffer[nReceived] = '\0'; //temporarily NULL terminate the string
//so that strstr works
bFoundTerminator = (strstr(pszBuffer, pszTerminator) != NULL);
}
//Remove the terminator from the response data
pszBuffer[nReceived - strlen(pszTerminator)] = '\0';
//determine if the response is an error
BOOL bSuccess = (strnicmp(pszBuffer,"+OK", 3) == 0);
if (!bSuccess)
{
SetLastError(WSAEPROTONOSUPPORT);
m_sLastCommandResponse = pszBuffer; //Hive away the last command reponse
}
return bSuccess;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -