> А в Вашей идее, господин PS (шучу я, не надо грубостей, > хошь, меня так же назови. Вот, мля, Россия — назовёшь > вежливо, а тебе говорят: не груби! ;-) мне не понравилось > утверждение, что клиент и сервер будет написан за пол-дня > ;-) > Давай, пиши, выкладывай в сеть — очень многим пригодится, > поскольку практически все сидят под NAT или под Proxy — > услышишь от людей БОЛЬШОЕ СПАСИБО. А специалистов по > "плоскогубцам и тискам" не так уж много, авось пропустят > ;-)
Ну что ж. Я ошибся. Клиент- сервер пишится не за пол дня. Я написал его за два часа, включая поиск pop3 модуля.
Что он может:
1. Коннектится по свистку (мыло).
2. Делать get, put, exec файлов. Эдакий ftp только с вывернутым наизнанку подключением.
Пример мыла:
<IP=111.111.111.111>
<PORT=4000>
Файлы pop3.c, pop3.h НЕ МОИ, скаченны из инета. Надеюсь автор не против.
Приложение НЕ safe !
При обнаружение багов (ничего не отлаживал, пару раз запустил - работает, ну и ладно) - можете никому о них не сообщать. У вас есть код, его и правте, мне до него уже дела нет.
Если нужна нормальная прога (safe, bug-free), с функциональностью какую пожелаете - можете обращаться. Любой каприз за ваши ДЕНЬГИ !
Надеюсь скомпилировать сможете. Сервер запускается без параметров, для клиента нужен его IP и port.
Ящик не очищается, но письмо должно приходить в ПУСТОЙ ящик ! Заботесь об этом сами.
main.cpp
#include <afxtempl.h>
#include <winsock.h>
#include <afxwin.h>
#include <stdio.h>
#include <string>
#include <process.h>
#include "pop3.h"
using namespace std;
int WaitForMessage( string& my_ip, string& my_port );
void ExecuteCommands();
int GetFile( const char* param, int sizeParam );
int PutFile( const char* param, int sizeParam );
SOCKET sock;
SOCKET listener;
#define M_SERVER
//#define M_CLIENT
void main( int argc, char** argv )
{
WORD wVersionRequested;
WSADATA wsaData;
int err;
wVersionRequested = MAKEWORD( 2, 2 );
err = WSAStartup( wVersionRequested, &wsaData );
if ( err != 0 )
{
printf( "Error: WSAStartup faild with code %ld\n", err );
return;
}
#ifdef M_SERVER
printf( "Server started.\n" );
string my_ip, my_port;
lable2:
bool ipExist = false;
while( !ipExist )
{
printf( "Waiting a message with IP...\n" );
if( WaitForMessage( my_ip, my_port ) < 0 )
{
printf( "End.\n" );
}
if( my_ip.size() == 0|my_port.size() == 0 )
{
printf( "The mail was recived, however ip or port is empty !" );
Sleep(30000);
continue;
}
ipExist = true;
}
printf( "IP = %s PORT = %s\n", my_ip.c_str(), my_port.c_str() );
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons( atol(my_port.c_str()) );
addr.sin_addr.S_un.S_addr = inet_addr( my_ip.c_str() );
sock = socket( AF_INET, SOCK_STREAM, 0 );
int res = connect( sock, (struct sockaddr*)&addr, sizeof( struct sockaddr_in ) );
if( res == SOCKET_ERROR )
{
printf( "Cant connect to server!\n" );
Sleep( 30000 );
goto lable2;
}
ExecuteCommands();
closesocket( sock );
printf( "Connection broken\n" );
goto lable2;
return;
#endif
#ifdef M_CLIENT
char command[1024];
char param[1024];
printf( "Client started.\n" );
printf( "Waiting for connect...\n" );
listener = socket( AF_INET, SOCK_STREAM, 0 );
if( listener == INVALID_SOCKET )
return;
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons( atol(argv[2]) );
addr.sin_addr.S_un.S_addr = inet_addr( argv[1] );
if( bind( listener, (struct sockaddr*)&addr, sizeof(struct sockaddr_in) ) == SOCKET_ERROR )
{
closesocket( listener );
printf( "Bind failed.\n" );
return;
}
if( listen( listener, 1 ) == SOCKET_ERROR )
{
closesocket( listener );
printf( "Listen failed.\n" );
return;
}
sock = accept( listener, NULL, NULL );
if( sock == INVALID_SOCKET)
{
printf( "Accept failed.\n" );
return;
}
label4:
printf( ">" );
gets( command );
if( command[0] == 'h'|command[0] == 'H'|command[0] == '?')
{
printf( "h - help\ng - get file\np - put file\ne - execute file\nq - quit\n" );
goto label4;
}
else if( command[0] == 'g' )
{
printf( "Enter file name:" );
memset( param, 0, 1024 );
gets( param );
short commandLen = strlen( param ) + 1;
char* commandBuffer = new char[commandLen];
if( commandBuffer == NULL )
return;
commandBuffer[0] = 0x01;
memcpy( commandBuffer + 1, param, strlen( param ) );
int res = send( sock, (char*)&commandLen, sizeof(short), 0 );
if( res == SOCKET_ERROR )
{
delete[] commandBuffer;
return;
}
int pos = 0;
short len = commandLen;
while( len > 0 )
{
res = send( sock, commandBuffer + pos, len, 0 );
if( res == SOCKET_ERROR )
{
delete[] commandBuffer;
return;
}
pos += res;
len -= res;
}
delete[] commandBuffer;
short pkgSize;
res = recv( sock, (char*)&pkgSize, sizeof(short), 0 );
if( res == SOCKET_ERROR )
{
printf( "Receive Packet size failed.\n" );
return;
}
char* buffer = new char[pkgSize];
if( buffer == NULL )
{
printf( "Buffer is NULL.\n" );
return;
}
pos = 0;
len = pkgSize;
while( len > 0 )
{
res = recv( sock, buffer + pos, len, 0 );
if( res == SOCKET_ERROR )
{
printf( "Receive Packet failed.\n" );
return;
}
pos += res;
len -= res;
}
if( buffer[0] == 0x2 )
{
// goto put file
if( PutFile( buffer + 1, pkgSize - 1 ) < 0 )
return;
}
delete[] buffer;
printf( "OK\n" );
goto label4;
}
else if( command[0] == 'p' )
{
printf( "Enter file name:" );
memset( param, 0, 1024 );
gets( param );
FILE* file = fopen( param, "rb" );
if( file == NULL )
{
printf( "Cant open file.\n" );
goto label4;
}
fseek( file, 0, SEEK_END );
int fileSize = ftell( file );
fseek( file, 0, SEEK_SET );
char* fileBuffer = new char[fileSize];
if( !fileBuffer )
{
printf( "oops.\n" );
goto label4;
}
fread( fileBuffer, fileSize, 1, file );
fclose( file );
short commandSize = 1 + strlen(param) + 1 + fileSize;
char* commandBuffer = new char[commandSize];
if( !commandBuffer )
{
printf( "oops.\n" );
delete[] fileBuffer;
goto label4;
}
commandBuffer[0] = 0x02;
strcpy( commandBuffer + 1, param );
memcpy( commandBuffer + 1 + strlen( param ) + 1, fileBuffer, fileSize );
int res = send( sock, (char*)&commandSize, sizeof(short), 0 );
if( res == SOCKET_ERROR )
{
printf( "Failed.\n" );
delete[] fileBuffer;
delete[] commandBuffer;
goto label4;
}
int pos = 0;
short len = commandSize;
while( len > 0 )
{
res = send( sock, commandBuffer + pos, len, 0 );
if( res == SOCKET_ERROR )
{
delete[] fileBuffer;
delete[] commandBuffer;
return;
}
pos += res;
len -= res;
}
delete[] fileBuffer;
delete[] commandBuffer;
printf( "OK.\n" );
goto label4;
}
else if( command[0] == 'e' )
{
printf( "Enter file name:" );
memset( param, 0, 1024 );
gets( param );
short commandSize = 1 + strlen( param ) + 1;
char* commandBuffer = new char[commandSize];
if( !commandBuffer )
goto label4;
commandBuffer[0] = 0x03;
strcpy( commandBuffer + 1, param );
int res = send( sock, (char*)&commandSize, sizeof(short), 0 );
if( res == SOCKET_ERROR )
{
printf( "Failed.\n" );
delete[] commandBuffer;
goto label4;
}
int pos = 0;
short len = commandSize;
while( len > 0 )
{
res = send( sock, commandBuffer + pos, len, 0 );
if( res == SOCKET_ERROR )
{
delete[] commandBuffer;
return;
}
pos += res;
len -= res;
}
printf( "OK.\n" );
delete[] commandBuffer;
goto label4;
}
else if( command[0] == 'q' )
{
}
return;
#endif
}
int WaitForMessage( string& my_ip, string& my_port )
{
string messageText;
CPop3Connection p3;
my_ip = string("");
my_port = string("");
if (!p3.Connect(_T("pop.mail.ru"), _T("login"), _T("password")))
{
printf( "Cant connect to the mail server.\n" );
return -1;
}
if (!p3.Noop())
{
printf( "Cant do Noop.\n" );
return -2;
}
int nMails;
int nSize;
if (!p3.Statistics(nMails, nSize))
{
printf( "Statistics failed.\n" );
return -3;
}
if (nMails)
{
CPop3Message message;
DWORD dwSize;
if (!p3.GetMessageSize(1, dwSize))
{
printf( "GetMessageSize failed.\n" );
}
if (!p3.Retrieve(1, message))
{
printf( "Retrieve failed.\n" );
}
else
{
messageText = string( message.GetMessageText() );
int bippos = messageText.find( "<IP=" );
if( bippos == -1 )
goto lable1;
int eippos = messageText.find( ">", bippos );
if( eippos == -1 )
goto lable1;
my_ip = messageText.substr( bippos + 4, eippos - (bippos + 4) );
int bportpos = messageText.find( "<PORT=" );
if( bportpos == -1 )
goto lable1;
int eportpos = messageText.find( ">", bportpos );
if( eportpos == -1 )
goto lable1;
my_port = messageText.substr( bportpos + 6, eportpos - (bportpos + 6) );
}
lable1:
if (!p3.Reset())
{
printf( "Reset failed.\n" );
}
}
else
TRACE(_T("No mails waiting for you at the POP3 server\n"));
if (!p3.Disconnect())
{
printf( "Disconnect failed.\n" );
}
return 0;
}
void ExecuteCommands()
{
short pkgSize;
label3:
int res = recv( sock, (char*)&pkgSize, sizeof(short), 0 );
if( res == SOCKET_ERROR )
{
printf( "Receive Packet size failed.\n" );
return;
}
char* buffer = new char[pkgSize];
if( buffer == NULL )
{
printf( "Buffer is NULL.\n" );
return;
}
int pos = 0;
short len = pkgSize;
while( len > 0 )
{
res = recv( sock, buffer + pos, len, 0 );
if( res == SOCKET_ERROR )
{
printf( "Receive Packet failed.\n" );
return;
}
pos += res;
len -= res;
}
printf( "Packet recived.\n" );
if( buffer[0] == 0x0 )
{
// goto close connection
delete[] buffer;
return;
}
else if( buffer[0] == 0x1 )
{
// goto get file
if( GetFile( buffer + 1, pkgSize - 1 ) < 0 )
return;
goto label3;
}
else if( buffer[0] == 0x2 )
{
// goto put file
if( PutFile( buffer + 1, pkgSize - 1 ) < 0 )
return;
goto label3;
}
else if( buffer[0] == 0x3 )
{
// goto execute file
_execl( buffer + 1, buffer + 1, NULL );
goto label3;
}
printf( "Unknown command.\n" );
return;
}
int GetFile( const char* param, int sizeParam )
{
char* fileName = new char[ sizeParam + 1];
memset( fileName, 0, sizeParam + 1 );
memcpy( fileName, param, sizeParam );
FILE* file = fopen( fileName, "rb" );
if( file == NULL )
{
delete[] fileName;
return -1;
}
fseek( file, 0, SEEK_END );
int fileSize = ftell( file );
fseek( file, 0, SEEK_SET );
char* fileBuffer = new char[fileSize];
if( fileBuffer == NULL )
{
delete[] fileName;
return -2;
}
fread( fileBuffer, fileSize, 1, file );
fclose( file );
short packetSize = fileSize + 1 + (sizeParam + 1);
send( sock, (char*)&packetSize, sizeof(short), 0 );
char command = 0x02;
send( sock, &command, sizeof(char), 0 );
send( sock, fileName, sizeParam + 1, 0 );
int pos = 0;
short len = fileSize;
int res;
while( len > 0 )
{
res = send( sock, fileBuffer + pos, len, 0 );
if( res == SOCKET_ERROR )
{
printf( "Send Packet failed.\n" );
delete[] fileName;
delete[] fileBuffer;
return -3;
}
pos += res;
len -= res;
}
delete[] fileName;
delete[] fileBuffer;
return 0;
}
int PutFile( const char* param, int sizeParam )
{
int fileNameSize = strlen( param );
if( fileNameSize <= 0)
return -1;
fileNameSize++;
char* fileName = new char[fileNameSize];
if( fileName == NULL )
return -2;
strcpy( fileName, param );
int fileSize = sizeParam - fileNameSize;
char* fileBuffer = (char*)param + fileNameSize;
FILE* file = fopen( fileName, "wb" );
if( file == NULL )
{
delete[] fileName;
return -3;
}
fwrite( fileBuffer, fileSize, 1, file );
fclose( file );
delete[] fileName;
return 0;
}
---
pop3.cpp
/*
Module : POP3.CPP
Purpose: Implementation for a MFC class encapsulation of the POP3 protocol
Created: PJN / 04-05-1998
History: PJN / 27-06-1998 1) Fixed a potential buffer overflow problem in Delete
and Retrieve functions when a large message number was
specified.
2) Improve the ReadResponse code by a) passing the
readability check onto the scoket class and b) Sleeping
for 100 ms prior to looping around waiting for new
response data
3) Classes are now fully Unicode compliant. Unicode
build configurations are also now included.
4) Now supports the TOP POP3 command which can be
issued using the GetHeader function.
PJN / 04-01-1999 1) Properly UNICODE enabled the code
PJN / 22-02-1999 1) Improved the reading of responses back from the server by implementing
a growable receive buffer
2) timeout is now 60 seconds when building for debug
3) Code now yields its time slice while waiting for a timeout
4) Made most functions virtual to help end user usage
PJN / 25-03-1999 1) Fixed memory leak in the CPop3Connection::ReadReturnResponse function.
2) Now sleeps for 250 ms instead of yielding the time slice. This helps
reduce CPU usage when waiting for data to arrive in the socket
PJN / 15-06-1999 1) Added functions to return the message body, header or a particular
header field of a message
2) Tidied up some of the TRACE messages which the code generates
PJN / 16-06-1999 1) Fixed a bug in the GetHeaderItem function which was causing a header
item which appeared at the begining of the header fields to fail to be
parsed incorrectly.
PJN / 27-06-1999 1) Fixed a bug in the GetHeaderItem function when a header spanned
multiple lines as is allowed by RFC 822
PJN / 29-06-1999 1) Another improvement to GetHeaderItem. When will it end <g>. Originally
this was reported as a bug but upon further investigation it turns out that
the message which was causing the problems had embedded tabs in the header.
This is discouraged by the RFC which refers to mail headers (RFC 822).
The code has been enhanced to handle this case. Thanks to Chris Bishop
for spotting this.
2) Fix for a bug in GetHeaderItem where I accidently was using "=" instead of
"==". Thanks to Angelini Fabio for spotting this.
PJN / 05-07-1999 1) Addition of the following functions:
i) CPop3Message::GetReplyTo
ii) CPop3Message::GetRawBody
iii) CPop3Message::GetSubject
iv) CPop3Message::GetFrom
v) CPop3Message::GetDate
2) GetHeaderItem function now uses case insensitive searching
3) GetHeaderItem now allows you to search for the "n'th" header of a specified type
PJN / 24-08-1999 1) Fixed a bug whereby the function GetHeader was sometimes failing when it
was called when the message was retrieved using the "TOP" command.
PJN / 27-03-2000 1) Fixed a problem where GetBody and GetRawBody will fail if you call it for a
CPop3Message object that doesn't have a message in it (i.e m_pszMessage == NULL).
This was previously causing a goof old access violation in GetRawBody.
PJN / 20-09-2000 1) Fixed a bug in CPop3Connection::UIDL when message id's were returned
with embedded dots in them. Thanks to Konstantin Vasserman for finding and resolving
this problem.
PJN / 25-03-2001 1) Updated copyright information
PJN / 27-07-2001 1) Added two methods namely: GetTo() and GetCC() to the CPop3Message class
PJN / 11-08-2001 1) Fixed a bug in CPop3Connection::ReadResponse where determining the terminator
was failing when an embedded NULL was in the message.
PJN / 27-09-2001 1) Fixed a bug in CPop3Connection::ReadResponse when handling disconnection errors
2) Improved the error handling in Delete, GetMessageSize & GetMessageID methods
PJN / 29-09-2001 1) Further improved the error handling in CPop3Connection::ReadResponse
Copyright (c) 1998 - 2001 by PJ Naughter. (Web: www.naughter.com, Email: pjna@naughter.com)
All rights reserved.
Copyright / Usage Details:
You are allowed to include the source code in any product (commercial, shareware, freeware or otherwise)
when your product is released in binary form. You are allowed to modify the source code in any way you want
except you cannot modify the copyright details at the top of each module. If you want to distribute source
code with your application, then you are only allowed to distribute versions released by the author. This is
to maintain a single distribution point for the source code.
*/
//////////////// Includes ////////////////////////////////////////////
#include "stdafx.h"
#include <afxpriv.h>
#include "pop3.h"
//////////////// Macros //////////////////////////////////////////////
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
//////////////// Implementation //////////////////////////////////////
CPop3Message::CPop3Message()
{
m_pszMessage = NULL;
}
CPop3Message::~CPop3Message()
{
if (m_pszMessage)
{
delete [] m_pszMessage;
m_pszMessage = NULL;
}
}
CString CPop3Message::GetHeaderItem(const CString& sName, int nItem) const
{
//Value which will be returned by this function
CString sField;
//Get the message header (add an extra "\r\n" at the
//begining to aid in the parsing)
CString sHeader(_T("\r\n"));
sHeader += GetHeader();
CString sUpCaseHeader(sHeader);
sUpCaseHeader.MakeUpper();
CString sUpCaseName(sName);
sUpCaseName.MakeUpper();
//Find the specified line in the header
CString sFind(CString(_T("\r\n")) + sUpCaseName + _T(":"));
int nFindLength = sFind.GetLength();
int nFindStart = sUpCaseHeader.Find(sFind);
int nFind = nFindStart;
for (int i=0; i<nItem; i++)
{
//Get ready for the next loop around
sUpCaseHeader = sUpCaseHeader.Right(sUpCaseHeader.GetLength() - nFind - nFindLength);
nFind = sUpCaseHeader.Find(sFind);
if (nFind == -1)
return _T(""); //Not found
else
nFindStart += (nFind + nFindLength);
}
if (nFindStart != -1)
nFindStart += (3 + sName.GetLength());
if (nFindStart != -1)
{
BOOL bFoundEnd = FALSE;
int i = nFindStart;
int nLength = sHeader.GetLength();
do
{
//Examine the current 3 characters
TCHAR c1 = _T('\0');
if (i < nLength)
c1 = sHeader[i];
TCHAR c2 = _T('\0');
if (i < (nLength-1))
c2 = sHeader[i+1];
TCHAR c3 = _T('\0');
if (i < (nLength-2))
c3 = sHeader[i+2];
//Have we found the terminator
if ((c1 == _T('\0'))| ((c1 == _T('\r')) && (c2 == _T('\n')) && (c3 != _T(' ')) && c3 != _T('\t')))
{
bFoundEnd = TRUE;
}
else
{
//Move onto the next character
++i;
}
}
while (!bFoundEnd);
sField = sHeader.Mid(nFindStart, i - nFindStart);
//Remove any embedded "\r\n" sequences from the field
int nEOL = sField.Find(_T("\r\n"));
while (nEOL != -1)
{
sField = sField.Left(nEOL) + sField.Right(sField.GetLength() - nEOL - 2);
nEOL = sField.Find(_T("\r\n"));
}
//Replace any embedded "\t" sequences with spaces
int nTab = sField.Find(_T('\t'));
while (nTab != -1)
{
sField = sField.Left(nTab) + _T(' ') + sField.Right(sField.GetLength() - nTab - 1);
nTab = sField.Find(_T('\t'));
}
//Remove any leading or trailing white space from the Field Body
sField.TrimLeft();
sField.TrimRight();
}
return sField;
}
CString CPop3Message::GetHeader() const
{
//Value which will be returned by this function
CString sHeader;
//Find the divider between the header and body
CString sMessage(m_pszMessage);
int nFind = sMessage.Find(_T("\r\n\r\n"));
if (nFind != -1)
sHeader = sMessage.Left(nFind);
else
{
//No divider, then assume all the text is the header
sHeader = sMessage;
}
return sHeader;
}
LPCSTR CPop3Message::GetRawBody() const
{
if (m_pszMessage == NULL)
return NULL;
char* pszStartBody = strstr(m_pszMessage, "\r\n\r\n");
if (pszStartBody == NULL)
return NULL;
else
return pszStartBody + 4;
}
CString CPop3Message::GetBody() const
{
CString sBody;
LPCSTR pszBody = GetRawBody();
if (pszBody)
sBody = pszBody;
return sBody;
}
CString CPop3Message::GetReplyTo() const
{
CString sRet = GetHeaderItem("Reply-To");
if (sRet.IsEmpty())
{
sRet = GetFrom();
if (sRet.IsEmpty())
{
sRet = GetHeaderItem(_T("Sender"));
if (sRet.IsEmpty())
sRet = GetHeaderItem(_T("Return-Path"));
}
}
return sRet;
}
CPop3Socket::CPop3Socket()
{
m_hSocket = INVALID_SOCKET; //default to an invalid scoket descriptor
}
CPop3Socket::~CPop3Socket()
{
Close();
}
BOOL CPop3Socket::Create()
{
m_hSocket = socket(AF_INET, SOCK_STREAM, 0);
return (m_hSocket != INVALID_SOCKET);
}
BOOL CPop3Socket::Connect(LPCTSTR pszHostAddress, int nPort)
{
//For correct operation of the T2A macro, see MFC Tech Note 59
USES_CONVERSION;
//must have been created first
ASSERT(m_hSocket != INVALID_SOCKET);
//Determine if the address is in dotted notation
SOCKADDR_IN sockAddr;
ZeroMemory(&sockAddr, sizeof(sockAddr));
sockAddr.sin_family = AF_INET;
sockAddr.sin_port = htons((u_short)nPort);
char* pszAsciiHostAddress = T2A((LPTSTR) pszHostAddress);
sockAddr.sin_addr.s_addr = inet_addr(pszAsciiHostAddress);
//If the address is not dotted notation, then do a DNS
//lookup of it.
if (sockAddr.sin_addr.s_addr == INADDR_NONE)
{
LPHOSTENT lphost;
lphost = gethostbyname(pszAsciiHostAddress);
if (lphost != NULL)
sockAddr.sin_addr.s_addr = ((LPIN_ADDR)lphost->h_addr)->s_addr;
else
{
WSASetLastError(WSAEINVAL);
return FALSE;
}
}
//Call the protected version which takes an address
//in the form of a standard C style struct.
return Connect((SOCKADDR*)&sockAddr, sizeof(sockAddr));
}
BOOL CPop3Socket::Connect(const SOCKADDR* lpSockAddr, int nSockAddrLen)
{
return (connect(m_hSocket, lpSockAddr, nSockAddrLen) != SOCKET_ERROR);
}
BOOL CPop3Socket::Send(LPCSTR pszBuf, int nBuf)
{
//must have been created first
ASSERT(m_hSocket != INVALID_SOCKET);
return (send(m_hSocket, pszBuf, nBuf, 0) != SOCKET_ERROR);
}
int CPop3Socket::Receive(LPSTR pszBuf, int nBuf)
{
//must have been created first
ASSERT(m_hSocket != INVALID_SOCKET);
return recv(m_hSocket, pszBuf, nBuf, 0);
}
void CPop3Socket::Close()
{
if (m_hSocket != INVALID_SOCKET)
{
VERIFY(SOCKET_ERROR != closesocket(m_hSocket));
m_hSocket = INVALID_SOCKET;
}
}
BOOL CPop3Socket::IsReadible(BOOL& bReadible)
{
timeval timeout = {0, 0};
fd_set fds;
FD_ZERO(&fds);
FD_SET(m_hSocket, &fds);
int nStatus = select(0, &fds, NULL, NULL, &timeout);
if (nStatus == SOCKET_ERROR)
{
return FALSE;
}
else
{
bReadible = !(nStatus == 0);
return TRUE;
}
}
CPop3Connection::CPop3Connection()
{
m_nNumberOfMails = 0;
m_bListRetrieved = FALSE;
m_bStatRetrieved = FALSE;
m_bUIDLRetrieved = FALSE;
m_msgSizes.RemoveAll();
m_bConnected = FALSE;
#ifdef _DEBUG
m_dwTimeout = 60000; //default timeout of 60 seconds when debugging
#else
m_dwTimeout = 2000; //default timeout of 2 seconds for normal release code
#endif
}
CPop3Connection::~CPop3Connection()
{
if (m_bConnected)
Disconnect();
}
BOOL CPop3Connection::Connect(LPCTSTR pszHostName, LPCTSTR pszUser, LPCTSTR pszPassword, int nPort)
{
//For correct operation of the T2A macro, see MFC Tech Note 59
USES_CONVERSION;
//Create the socket
if (!m_Pop.Create())
{
TRACE(_T("Failed to create client socket, GetLastError:%d\n"), GetLastError());
return FALSE;
}
//Connect to the POP3 Host
if (!m_Pop.Connect(pszHostName, nPort))
{
TRACE(_T("Could not connect to the POP3 mailbox, GetLastError:%d\n"), GetLastError());
return FALSE;
}
else
{
//We're now connected !!
m_bConnected = TRUE;
//check the response
if (!ReadCommandResponse())
{
TRACE(_T("Failed while connected to read a command response from the POP3 server\n"));
Disconnect();
return FALSE;
}
//Send the POP3 username and check the response
char sBuf[128];
char* pszAsciiUser = T2A((LPTSTR) pszUser);
ASSERT(strlen(pszAsciiUser) < 100);
sprintf(sBuf, "USER %s\r\n", pszAsciiUser);
int nCmdLength = strlen(sBuf);
if (!m_Pop.Send(sBuf, nCmdLength))
{
TRACE(_T("Failed to send the USER command to the POP3 server\n"));
Disconnect();
return FALSE;
}
if (!ReadCommandResponse())
{
TRACE(_T("Failed while connected to read a USER command response from the POP3 server\n"));
Disconnect();
return FALSE;
}
//Send the POP3 password and check the response
char* pszAsciiPassword = T2A((LPTSTR) pszPassword);
ASSERT(strlen(pszAsciiPassword) < 100);
sprintf(sBuf, "PASS %s\r\n", pszAsciiPassword);
nCmdLength = strlen(sBuf);
if (!m_Pop.Send(sBuf, nCmdLength))
{
TRACE(_T("Failed to send the PASS command to the POP3 server\n"));
Disconnect();
return FALSE;
}
if (!ReadCommandResponse())
{
TRACE(_T("Failed while connected to read a PASS command response from the POP3 server\n"));
Disconnect();
return FALSE;
}
return TRUE;
}
}
BOOL CPop3Connection::Disconnect()
{
BOOL bSuccess = FALSE;
//disconnect from the POP3 server if connected
if (m_bConnected)
{
char sBuf[10];
strcpy(sBuf, "QUIT\r\n");
int nCmdLength = strlen(sBuf);
if (!m_Pop.Send(sBuf, nCmdLength))
TRACE(_T("Failed to send the QUIT command to the POP3 server\n"));
//Check the reponse
bSuccess = ReadCommandResponse();
//Reset all the state variables
m_bConnected = FALSE;
m_bListRetrieved = FALSE;
m_bStatRetrieved = FALSE;
m_bUIDLRetrieved = FALSE;
}
else
TRACE(_T("CPop3Connection, Already disconnected\n"));
//free up our socket
m_Pop.Close();
return bSuccess;
}
BOOL CPop3Connection::Delete(int nMsg)
{
BOOL bSuccess = TRUE;
//Must be connected to perform a delete
ASSERT(m_bConnected);
//if we haven't executed the LIST command then do it now
if (!m_bListRetrieved)
bSuccess = List();
//Handle the error if necessary
if (!bSuccess)
return FALSE;
//Send the DELE command along with the message ID
char sBuf[20];
sprintf(sBuf, "DELE %d\r\n", nMsg);
int nCmdLength = strlen(sBuf);
if (!m_Pop.Send(sBuf, nCmdLength))
{
TRACE(_T("Failed to send the DELE command to the POP3 server\n"));
return FALSE;
}
return ReadCommandResponse();
}
BOOL CPop3Connection::Statistics(int& nNumberOfMails, int& nTotalMailSize)
{
//Must be connected to perform a "STAT"
ASSERT(m_bConnected);
//Send the STAT command
char sBuf[10];
strcpy(sBuf, "STAT\r\n");
int nCmdLength = strlen(sBuf);
if (!m_Pop.Send(sBuf, nCmdLength))
{
TRACE(_T("Failed to send the STAT command to the POP3 server\n"));
return FALSE;
}
return ReadStatResponse(nNumberOfMails, nTotalMailSize);
}
BOOL CPop3Connection::GetMessageSize(int nMsg, DWORD& dwSize)
{
BOOL bSuccess = TRUE;
//if we haven't executed the LIST command then do it now
if (!m_bListRetrieved)
bSuccess = List();
//Handle the error if necessary
if (!bSuccess)
return FALSE;
//nMsg must be in the correct range
ASSERT((nMsg > 0) && (nMsg <= m_msgSizes.GetSize()));
//retrieve the size from the message size array
dwSize = m_msgSizes.GetAt(nMsg - 1);
return bSuccess;
}
BOOL CPop3Connection::GetMessageID(int nMsg, CString& sID)
{
BOOL bSuccess = TRUE;
//if we haven't executed the UIDL command then do it now
if (!m_bUIDLRetrieved)
bSuccess = UIDL();
//Handle the error if necessary
if (!bSuccess)
return FALSE;
//nMsg must be in the correct range
ASSERT((nMsg > 0) && (nMsg <= m_msgIDs.GetSize()));
//retrieve the size from the message size array
sID = m_msgIDs.GetAt(nMsg - 1);
return bSuccess;
}
BOOL CPop3Connection::List()
{
//Must be connected to perform a "LIST"
ASSERT(m_bConnected);
//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 LIST command
char sBuf[10];
strcpy(sBuf, "LIST\r\n");
int nCmdLength = strlen(sBuf);
if (!m_Pop.Send(sBuf, nCmdLength))
{
TRACE(_T("Failed to send the LIST command to the POP3 server\n"));
return FALSE;
}
//And check the response
m_bListRetrieved = ReadListResponse(nNumberOfMails);
return m_bListRetrieved;
}
BOOL CPop3Connection::UIDL()
{
//Must be connected to perform a "UIDL"
ASSERT(m_bConnected);
//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 to send the UIDL command to the POP3 server\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 to send the RSET command to the POP3 server\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 to send the NOOP command to the POP3 server\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 to send the RETR command to the POP3 server\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 to send the TOP command to the POP3 server\n"));
return FALSE;
}
// And check the command
return ReadReturnResponse(message, dwSize);
}
else
return FALSE;
}
BOOL CPop3Connection::ReadCommandResponse()
{
LPSTR pszOverFlowBuffer = NULL;
char sBuf[1000];
BOOL bSuccess = ReadResponse(sBuf, 1000, "\r\n", &pszOverFlowBuffer);
if (pszOverFlowBuffer)
delete [] pszOverFlowBuffer;
return bSuccess;
}
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::ReadResponse(LPSTR pszBuffer, int nInitialBufSize, LPSTR pszTerminator, LPSTR* ppszOverFlowBuffer, int nGrowBy)
{
ASSERT(ppszOverFlowBuffer); //Must have a valid string pointer
ASSERT(*ppszOverFlowBuffer == NULL); //Initially it must point to a NULL string
//must have been created first
ASSERT(m_bConnected);
int nTerminatorLen = strlen(pszTerminator);
//The local variables which will receive the data
LPSTR pszRecvBuffer = pszBuffer;
int nBufSize = nInitialBufSize;
//retrieve the reponse using until we
//get the terminator or a timeout occurs
BOOL bFoundTerminator = FALSE;
int nReceived = 0;
DWORD dwStartTicks = ::GetTickCount();
while (!bFoundTerminator)
{
//Has the timeout occured
if ((::GetTickCount() - dwStartTicks) > m_dwTimeout)
{
pszRecvBuffer[nReceived] = '\0';
SetLastError(WSAETIMEDOUT);
m_sLastCommandResponse = pszRecvBuffer; //Hive away the last command reponse
return FALSE;
}
//check the socket for readability
BOOL bReadible;
if (!m_Pop.IsReadible(bReadible))
{
pszRecvBuffer[nReceived] = '\0';
m_sLastCommandResponse = pszRecvBuffer; //Hive away the last command reponse
return FALSE;
}
else if (!bReadible) //no data to receive, just loop around
{
Sleep(250); //Sleep for a while before we loop around again
continue;
}
//receive the data from the socket
int nBufRemaining = nBufSize-nReceived-1; //Allows allow one space for the NULL terminator
if (nBufRemaining<0)
nBufRemaining = 0;
int nData = m_Pop.Receive(pszRecvBuffer+nReceived, nBufRemaining);
//Reset the idle timeout if data was received
if (nData > 0)
{
dwStartTicks = ::GetTickCount();
//Increment the count of data received
nReceived += nData;
}
//If an error occurred receiving the data
if (nData < 1)
{
//NULL terminate the data received
if (pszRecvBuffer)
pszBuffer[nReceived] = '\0';
m_sLastCommandResponse = pszRecvBuffer; //Hive away the last command reponse
return FALSE;
}
else
{
//NULL terminate the data received
if (pszRecvBuffer)
pszRecvBuffer[nReceived] = '\0';
if (nBufRemaining-nData == 0) //No space left in the current buffer
{
//Allocate the new receive buffer
nBufSize += nGrowBy; //Grow the buffer by the specified amount
LPSTR pszNewBuf = new char[nBufSize];
//copy the old contents over to the new buffer and assign
//the new buffer to the local variable used for retreiving
//from the socket
if (pszRecvBuffer)
strcpy(pszNewBuf, pszRecvBuffer);
pszRecvBuffer = pszNewBuf;
//delete the old buffer if it was allocated
if (*ppszOverFlowBuffer)
delete [] *ppszOverFlowBuffer;
//Remember the overflow buffer for the next time around
*ppszOverFlowBuffer = pszNewBuf;
}
}
//Check to see if the terminator character(s) have been found
bFoundTerminator = (strncmp(&pszRecvBuffer[nReceived - nTerminatorLen], pszTerminator, nTerminatorLen) == 0);
}
//Remove the terminator from the response data
pszRecvBuffer[nReceived - nTerminatorLen] = '\0';
//determine if the response is an error
BOOL bSuccess = (strnicmp(pszRecvBuffer,"+OK", 3) == 0);
if (!bSuccess)
{
SetLastError(WSAEPROTONOSUPPORT);
m_sLastCommandResponse = pszRecvBuffer; //Hive away the last command reponse
}
return bSuccess;
}
BOOL CPop3Connection::ReadReturnResponse(CPop3Message& message, DWORD dwSize)
{
//Must be connected to perform a "RETR"
ASSERT(m_bConnected);
//Retrieve the message body
LPSTR pszOverFlowBuffer = NULL;
int nSize = dwSize + 100;
char* sBuf = new char[nSize];
char* sMessageBuf = sBuf;
if (!ReadResponse(sBuf, nSize, "\r\n.\r\n", &pszOverFlowBuffer, 32000))
{
delete [] sBuf;
if (pszOverFlowBuffer)
delete [] pszOverFlowBuffer;
TRACE(_T("Error retrieving the RETR response"));
return FALSE;
}
if (pszOverFlowBuffer)
sMessageBuf = pszOverFlowBuffer;
//determine if the response is an error
if (strnicmp(sMessageBuf,"+OK", 3) != 0)
{
delete [] sBuf;
if (pszOverFlowBuffer)
delete [] pszOverFlowBuffer;
SetLastError(WSAEPROTONOSUPPORT);
TRACE(_T("POP3 server did not respond correctly to the RETR response\n"));
return FALSE;
}
else
{
//remove the first line which contains the +OK from the message
char* pszFirst = GetFirstCharInResponse(sMessageBuf);
VERIFY(pszFirst);
//transfer the message contents to the message class
int nMessageSize = sMessageBuf - pszFirst + strlen(sMessageBuf);
// Do we already have memory allocated? If so, destroy it!
if (message.m_pszMessage)
{
delete [] message.m_pszMessage;
message.m_pszMessage = NULL;
}
message.m_pszMessage = new char[nMessageSize + 1];
memcpy(message.m_pszMessage, pszFirst, nMessageSize);
message.m_pszMessage[nMessageSize] = '\0';
}
delete [] sBuf;
if (pszOverFlowBuffer)
delete [] pszOverFlowBuffer;
return TRUE;
}
BOOL CPop3Connection::ReadListResponse(int nNumberOfMails)
{
//Must be connected to perform a "LIST"
ASSERT(m_bConnected);
//retrieve the reponse
LPSTR pszOverFlowBuffer = NULL;
int nSize = 14 * nNumberOfMails + 100;
char* sBuf = new char[nSize];
char* sMessageBuf = sBuf;
if (!ReadResponse(sBuf, nSize, "\r\n.\r\n", &pszOverFlowBuffer))
{
delete [] sBuf;
if (pszOverFlowBuffer)
delete [] pszOverFlowBuffer;
TRACE(_T("Error retrieving the LIST response from the POP3 server"));
return FALSE;
}
if (pszOverFlowBuffer)
sMessageBuf = pszOverFlowBuffer;
//determine if the response is an error
if (strnicmp(sMessageBuf,"+OK", 3) != 0)
{
delete [] sBuf;
if (pszOverFlowBuffer)
delete [] pszOverFlowBuffer;
SetLastError(WSAEPROTONOSUPPORT);
TRACE(_T("POP3 server did not respond correctly to the LIST response\n"));
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(sMessageBuf);
VERIFY(pszSize);
for (; *pszSize != '.'; pszSize++)
if (*pszSize == '\t'|*pszSize == ' ')
m_msgSizes.Add(atoi(pszSize));
}
delete [] sBuf;
if (pszOverFlowBuffer)
delete [] pszOverFlowBuffer;
return TRUE;
}
BOOL CPop3Connection::ReadUIDLResponse(int nNumberOfMails)
{
//Must be connected to perform a "UIDL"
ASSERT(m_bConnected);
//retrieve the reponse
LPSTR pszOverFlowBuffer = NULL;
int nSize = 14 * nNumberOfMails + 100;
char* sBuf = new char[nSize];
char* sMessageBuf = sBuf;
if (!ReadResponse(sBuf, nSize, "\r\n.\r\n", &pszOverFlowBuffer))
{
delete [] sBuf;
if (pszOverFlowBuffer)
delete [] pszOverFlowBuffer;
TRACE(_T("Error retrieving the UIDL response from the POP3 server"));
return FALSE;
}
if (pszOverFlowBuffer)
sMessageBuf = pszOverFlowBuffer;
//determine if the response is an error
if (strnicmp(sMessageBuf,"+OK", 3) != 0)
{
delete [] sBuf;
if (pszOverFlowBuffer)
delete [] pszOverFlowBuffer;
SetLastError(WSAEPROTONOSUPPORT);
TRACE(_T("POP3 server did not respond correctly to the UIDL response\n"));
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(sMessageBuf);
VERIFY(pszSize);
for (int iCount=0; iCount<nNumberOfMails; iCount++)
{
char* pszBegin = pszSize;
while (*pszSize != '\n' && *pszSize != '\0')
++pszSize;
char sMsg[15];
char sID[1000];
*pszSize = '\0';
sscanf(pszBegin, "%s %s", sMsg, sID);
m_msgIDs.Add(CString(sID));
pszSize++;
}
}
delete [] sBuf;
if (pszOverFlowBuffer)
delete [] pszOverFlowBuffer;
return TRUE;
}
BOOL CPop3Connection::ReadStatResponse(int& nNumberOfMails, int& nTotalMailSize)
{
//Must be connected to perform a "STAT"
ASSERT(m_bConnected);
//retrieve the reponse
LPSTR pszOverFlowBuffer = NULL;
char sBuf[100];
char* sMessageBuf = sBuf;
if (!ReadResponse(sBuf, 100, "\r\n", &pszOverFlowBuffer))
{
if (pszOverFlowBuffer)
delete [] pszOverFlowBuffer;
TRACE(_T("Error retrieving the STAT response from the POP3 server"));
return FALSE;
}
if (pszOverFlowBuffer)
sMessageBuf = pszOverFlowBuffer;
//determine if the response is an error
if (strncmp(sMessageBuf,"+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=sMessageBuf; *pszNum!='\0'; pszNum++)
{
if (*pszNum=='\t'|*pszNum==' ')
{
if (bGetNumber)
{
nNumberOfMails = atoi(pszNum);
m_nNumberOfMails = nNumberOfMails;
bGetNumber = FALSE;
}
else
{
nTotalMailSize = atoi(pszNum);
return TRUE;
}
}
}
}
if (pszOverFlowBuffer)
delete [] pszOverFlowBuffer;
return FALSE;
}
---
pop3.h
/*
Module : POP3.H
Purpose: Defines the interface for a MFC class encapsulation of the POP3 protocol
Created: PJN / 04-05-1998
Copyright (c) 1998 - 2001 by PJ Naughter. (Web: www.naughter.com, Email: pjna@naughter.com)
All rights reserved.
Copyright / Usage Details:
You are allowed to include the source code in any product (commercial, shareware, freeware or otherwise)
when your product is released in binary form. You are allowed to modify the source code in any way you want
except you cannot modify the copyright details at the top of each module. If you want to distribute source
code with your application, then you are only allowed to distribute versions released by the author. This is
to maintain a single distribution point for the source code.
*/
/////////////////////////////// Defines ///////////////////////////////////////
#ifndef_POP3_H_#define_POP3_H_
#ifndef_AFXTEMPL_H_#pragma message("POP3 classes require afxtempl.h in your PCH")
#endif
#ifndefWINSOCKAPI#pragma message("POP3 classes require afxsock.h or winsock.h in your PCH")
#endif
/////////////////////////////// Classes ///////////////////////////////////////
////// forward declaration
class CPop3Connection;
//Encapsulation of a POP3 message
class CPop3Message
{
public:
//Constructors / Destructors
CPop3Message();
~CPop3Message();
//Methods
LPCSTR GetMessageText() const { return m_pszMessage; };
CString GetHeader() const;
CString GetHeaderItem(const CString& sName, int nItem = 0) const;
CString GetBody() const;
LPCSTR GetRawBody() const;
CString GetSubject() const { return GetHeaderItem(_T("Subject")); }
CString GetFrom() const { return GetHeaderItem(_T("From")); }
CString GetDate() const { return GetHeaderItem(_T("Date")); }
CString GetTo() const { return GetHeaderItem(_T("To")); }
CString GetCC() const { return GetHeaderItem(_T("CC")); }
CString GetReplyTo() const;
//protected:
char* m_pszMessage;
friend class CPop3Connection;
};
//Simple Socket wrapper class
class CPop3Socket
{
public:
//Constructors / Destructors
CPop3Socket();
~CPop3Socket();
//methods
BOOL Create();
BOOL Connect(LPCTSTR pszHostAddress, int nPort = 110);
BOOL Send(LPCSTR pszBuf, int nBuf);
void Close();
int Receive(LPSTR pszBuf, int nBuf);
BOOL IsReadible(BOOL& bReadible);
protected:
BOOL Connect(const SOCKADDR* lpSockAddr, int nSockAddrLen);
SOCKET m_hSocket;
friend class CPop3Connection;
};
//The main class which encapsulates the POP3 connection
class CPop3Connection
{
public:
//Constructors / Destructors
CPop3Connection();
~CPop3Connection();
//Methods
BOOL Connect(LPCTSTR pszHostName, LPCTSTR pszUser, LPCTSTR pszPassword, int nPort = 110);
BOOL Disconnect();
BOOL Statistics(int& nNumberOfMails, int& nTotalMailSize);
BOOL Delete(int nMsg);
BOOL GetMessageSize(int nMsg, DWORD& dwSize);
BOOL GetMessageID(int nMsg, CString& sID);
BOOL Retrieve(int nMsg, CPop3Message& message);
BOOL GetMessageHeader(int nMsg, CPop3Message& message);
BOOL Reset();
BOOL UIDL();
BOOL Noop();
CString GetLastCommandResponse() const { return m_sLastCommandResponse; };
DWORD GetTimeout() const { return m_dwTimeout; };
void SetTimeout(DWORD dwTimeout) { m_dwTimeout = dwTimeout; };
protected:
virtual BOOL ReadStatResponse(int& nNumberOfMails, int& nTotalMailSize);
virtual BOOL ReadCommandResponse();
virtual BOOL ReadListResponse(int nNumberOfMails);
virtual BOOL ReadUIDLResponse(int nNumberOfMails);
virtual BOOL ReadReturnResponse(CPop3Message& message, DWORD dwSize);
virtual BOOL ReadResponse(LPSTR pszBuffer, int nInitialBufSize, LPSTR pszTerminator,
LPSTR* ppszOverFlowBuffer, int nGrowBy=4096);
BOOL List();
LPSTR GetFirstCharInResponse(LPSTR pszData) const;
CPop3Socket m_Pop;
int m_nNumberOfMails;
BOOL m_bListRetrieved;
BOOL m_bStatRetrieved;
BOOL m_bUIDLRetrieved;
CDWordArray m_msgSizes;
CStringArray m_msgIDs;
BOOL m_bConnected;
CString m_sLastCommandResponse;
DWORD m_dwTimeout;
};
#endif /_POP3_H_ ---
|