/************************************************************************************************************
Methods:
1. Delete()			delete specified message(s) from the mailbox using their sequence numbers
2. GetAll()			retrieves the data associated with messages using message sequence numbers
3. GetHeaderOnly()	retrieves the headers data associated with messages using message sequence numbers
4. Status()			requests the current status

Properties:
1. PutAttachmentPath()				the physical path where attachments will be saved
2. GetAttachmentPathError()			returns 1 if any error occur in AttachmentPath otherwise 0
3. GetAttachmentPathErrorReason()	reports any error that occur due to AttchmentPath
4. PutAttachmentPathHTTP()			URL for the AttachmentPath where attachments are saved
5. PutDownloadedUIDs()				this attribute is optional. the UIDs of messages previously downloaded 
									from server. Used to determine which messages are new. we can also write
									it as 3:8 means do not download messages with UIDs starts from 3 and ends
									at 8. also 3,8 (comma separated list) can be given which means do not
									download messages with sequence number 3 and 8 only
6. GetErrorReason()					reports any errors that occur during the request
7. GetIsError()						returns 1 if any error occur during the request otherwise 0
8. PutMessageNumber()				required for Delete, GetHeaderOnly(optional, default is all message numbers)
									and GetAll(optional, default is all message numbers). message sequence
									numbers of messages, for performing action. We can also write it as 3:8
									means messages with sequence number starts from 3 and ends at 8. Also 3,8
									(comma separated list) can be given which means messages with sequence
									number 3 and 8 only  
9. PutOrderBy()						required for GetHeaderOnly(optional), GetAll(optional). required for sorting
									of mails. if not specified then no sorting is performed and mail messages
									are returned in order as returned by POP3 server. valid sorting criteria are
									Subject_ASC
									Subject_DESC
									From_ASC
									From_DESC
									To_ASC
									To_DESC
									Date_ASC
									Date_DESC
									Size_ASC
									Size_DESC
									Attachment_ASC(without attachment mails first)
									Attachment_DESC(with attachment mails first)
10. PutPassword()					required for connection to server in all methods
11. PutPort()						optional. if not specified then default port 110 is used
12. PutServerName()					required. host name or IP address of the POP3 server
13. PutSortFirst()					required for GetHeaderOnly(optional), required for sorting mail messages first
									and then return required mail messages. this parameter is only valid for
									GetHeaderOnly and ignored in case of GetAll. if parameter MessageNumber
									contains 1:5 and this parameter is set as TRUE then the component will fetch
									all messages first and will sort on given sorting criteria and then will
									return mail messages that come in sequence from 1 to 5, and if this parameter
									is set as FALSE then the component will fetch messages from 1 to 5 and will
									sort on given sorting criteria and then will return mail messages. valid
									sorting criteria are
									TRUE
									FALSE (default)
14. PutUserName()					required for connection to server in all method
************************************************************************************************************/

/***********************************/
/*include all required header files*/
/***********************************/
#include <stdio.h>
#include <conio.h>

/************************************************************************/
/*import AdvDirectory COM library here to get its methods and properties*/
/************************************************************************/
#import "C:\AdvPOP3.dll" no_namespace

/*************************/
/*prototype for functions*/
/*************************/
void Delete();//Delete function
void GetAll();//GetAll function
void GetHeaderOnly();//GetHeaderOnly function
void Status();//Status function

/**************/
/*main program*/
/**************/
void main(void)
{
	char Ch;
	do
	{
		printf("\r\nDelete		[D]");
		printf("\r\nGetAll		[A]");
		printf("\r\nGetHeaderOnly	[H]");
		printf("\r\nStatus		[S]");
		printf("\r\nQuit		[Q]");
		printf("\r\n\r\nEnter Choice = ");
		scanf("%c", &Ch);
		getchar();
		Ch = toupper(Ch);
		switch (Ch)
		{
			case 'D':Delete();break;//call Delete function
			case 'A':GetAll();break;//call GetAll function
			case 'H':GetHeaderOnly();break;//call GetHeaderOnly function
			case 'S':Status();break;//call Status function
			case 'Q':printf("\r\nGood Bye\r\n");break;
			default: printf("\r\nError: Please enter valid choice\r\n");
		}
	}
	while (Ch != 'Q');
}

/************************************************************************************/
/*Delete function: The function is used to delete mail messages from any POP3 server*/
/************************************************************************************/
void Delete()
{
	char m_Server[256], m_User[256], m_Password[256], m_MessageNo[256];//define charecter buffer of 256 to read server name, user name, password and message numbers to be deleted
	printf("\r\nEnter Server Name = ");
	gets(m_Server);//read server name
	printf("\r\nEnter User Name = ");
	gets(m_User);//read user name
	printf("\r\nEnter Password = ");
	gets(m_Password);//read password name
	printf("\r\nEnter Message Number = ");
	gets(m_MessageNo);//read message numbers
	try//for COM library call, try...catch is used to handle exceptions
	{
		IPOP3Ptr obj;//take smart pointer object obj for COM library
		CoInitialize(NULL);//Initializes the COM library on the current thread
		obj = IPOP3Ptr("AdvPOP3.POP3");
		obj->PutServerName(m_Server);//set server name property
		obj->PutUserName(m_User);//set user name property
		obj->PutPassword(m_Password);//set password property
		obj->PutMessageNumber(m_MessageNo);//set message number property
		HRESULT hr = obj->Delete();//call Delete method of COM library
		if (!SUCCEEDED(hr))//if COM call is not successfull then display error message and return
		{
			printf("\r\nError: %s\r\n", (char*)obj->GetErrorReason());//display error message
			return;
		}
		//call GetIsError() property of COM library and check its value, if its value is 1, then
		//GetErrorReason() property of COM will contain error message, for which this error occured
		if (obj->GetIsError() == 1)
			printf("\r\nError: %s\r\n", (char*)obj->GetErrorReason());//display error message
		else
			printf("\r\nSuccessfully Deleted\r\n");//display successfull message
	}
	catch (_com_error &error)//catch exception here
	{
		printf(TEXT("%S[%X]"), error.ErrorMessage(), error.Error());//display error message
	}
}

/***************************************************************************/
/*Status function: The function is used to get current status about mailbox*/
/***************************************************************************/
void Status()
{
	char m_Server[256], m_User[256], m_Password[256];//define charecter buffer of 256 to read server name, user name and password
	printf("\r\nEnter Server Name = ");
	gets(m_Server);//read server name
	printf("\r\nEnter User Name = ");
	gets(m_User);//read user name
	printf("\r\nEnter Password = ");
	gets(m_Password);//read password name
	try//for COM library call, try...catch is used to handle exceptions
	{
		IPOP3Ptr obj;//take smart pointer object obj for COM library
		CoInitialize(NULL);//Initializes the COM library on the current thread
		obj = IPOP3Ptr("AdvPOP3.POP3");
		obj->PutServerName(m_Server);//set server name property
		obj->PutUserName(m_User);//set user name property
		obj->PutPassword(m_Password);//set password property
		IDispatch *p = obj->Status();//call Status method of COM library
		//call GetIsError() property of COM library and check its value, if its value is 1, then
		//GetErrorReason() property of COM will contain error message, for which this error occured
		if (obj->GetIsError() == 1)
			printf("\r\nError: %s\r\n", (char*)obj->GetErrorReason());//display error message
		else
		{
			printf("\r\nSuccessfully Status\r\n");//display successfull message
			IStatusPtr statusobj;
			p->QueryInterface(IID_IDispatch,(void**)&statusobj);//call query interface
			printf("\r\nCount = %d\r\nSize = %d\r\n", statusobj->GetCount(), statusobj->GetSize());
		}
	}
	catch (_com_error &error)//catch exception here
	{
		printf(TEXT("%S[%X]"), error.ErrorMessage(), error.Error());//display error message
	}
}

/*****************************************************************************/
/*GetHeaderOnly function: The function is used to get headers of mail message*/
/*****************************************************************************/
void GetHeaderOnly()
{
	char m_Server[256], m_User[256], m_Password[256], m_MessageNo[256], m_DownloadUIDs[256], m_OrderBy[256];//define charecter buffer of 256 to read server name, user name, password, message numbers, dowmload uids and sorting criteria
	long l_SortFirst;//sort first
	printf("\r\nEnter Server Name = ");
	gets(m_Server);//read server name
	printf("\r\nEnter User Name = ");
	gets(m_User);//read user name
	printf("\r\nEnter Password = ");
	gets(m_Password);//read password name
	printf("\r\nEnter Message Number = ");
	gets(m_MessageNo);//read message numbers
	printf("\r\nEnter Downloaded UIDs = ");
	gets(m_DownloadUIDs);//read downloaded uids
	printf("\r\nEnter Sorting Criteria = ");
	gets(m_OrderBy);//read sorting criteria
	printf("\r\nEnter Sort First Flag [0/1] = ");
	scanf("%d", &l_SortFirst);//read sort first
	getchar();
	try//for COM library call, try...catch is used to handle exceptions
	{
		IPOP3Ptr obj;//take smart pointer object obj for COM library
		CoInitialize(NULL);//Initializes the COM library on the current thread
		obj = IPOP3Ptr("AdvPOP3.POP3");
		obj->PutServerName(m_Server);//set server name property
		obj->PutUserName(m_User);//set user name property
		obj->PutPassword(m_Password);//set password property
		obj->PutMessageNumber(m_MessageNo);//set message number property
		obj->PutDownloadedUIDs(m_DownloadUIDs);//set download uids property
		obj->PutOrderBy(m_OrderBy);//set sorting criteria property
		obj->PutSortFirst(l_SortFirst);//set sort first flag property
		_variant_t pVal = obj->GetHeaderOnly();//call GetHeaderOnly method of COM library
		//call GetIsError() property of COM library and check its value, if its value is 1, then
		//GetErrorReason() property of COM will contain error message, for which this error occured
		if (obj->GetIsError() == 1)
			printf("\r\nError: %s\r\n", (char*)obj->GetErrorReason());//display error message
		else
		{
			printf("\r\nSuccessfully GetHeaderOnly\r\n");//display successfull message
			IDispatch* p = pVal.pdispVal;//IDispatch object is assigned VARIANT object
			IFetchPtr fetchobj;//take Fetch interface object
			p->QueryInterface(IID_IDispatch,(void**)&fetchobj);//call query interface
			long count = fetchobj->GetCount();//get number of nodes
			for (int j = 1; j <= count; j++)//loop over each node
			{
				_variant_t retVal = fetchobj->GetItem(j);//get node item
				IDispatch* pp = retVal.pdispVal;//IDispatch object is assigned VARIANT object
				IFetchEntriesPtr fetchentriesobj;//take FetchEntries interface object
				pp->QueryInterface(IID_IDispatch,(void**)&fetchentriesobj);//call query interface
				printf("\r\nMessage No = %s\r\nPriority = %s\r\nDate = %s\r\nMessage Id = %s\r\nMime Version = %s\r\nContent Type = %s\r\nFrom = %s\r\nReply To = %s\r\nTo = %s\r\nSubject = %s\r\nX-Mailer = %s\r\nUID = %s\r\nStatus = %s\r\nSize = %d\r\nCC = %s\r\n",
					(char*)fetchentriesobj->GetMessageNo(), (char*)fetchentriesobj->GetPriority(),
					(char*)fetchentriesobj->GetDate(), (char*)fetchentriesobj->GetMessageId(),
					(char*)fetchentriesobj->GetMimeVersion(), (char*)fetchentriesobj->GetContentType(),
					(char*)fetchentriesobj->GetFrom(), (char*)fetchentriesobj->GetReplyTo(),
					(char*)fetchentriesobj->GetTo(), (char*)fetchentriesobj->GetSubject(),
					(char*)fetchentriesobj->GetXMailer(), (char*)fetchentriesobj->GetUID(),
					(char*)fetchentriesobj->GetStatus(), fetchentriesobj->GetSize(),
					(char*)fetchentriesobj->GetCC());//format data
				_variant_t subpVal = fetchentriesobj->ExtraHeaders();//call ExtraHeaders method
				IDispatch* ppp = subpVal.pdispVal;//IDispatch object is assigned VARIANT object
				IExtraHeadersPtr extraheadersobj;//take ExtraHeaders interface object
				ppp->QueryInterface(IID_IDispatch,(void**)&extraheadersobj);//call query interface
				long subcount = extraheadersobj->GetCount();//get number of nodes
				for (int i = 1; i <= subcount; i++)
				{
					_variant_t subretVal = extraheadersobj->GetItem(i);//get node item
					IDispatch* pppp = subretVal.pdispVal;//IDispatch object is assigned VARIANT object
					IExtraHeadersEntriesPtr extraheadersentriesobj;//take ExtraHeadersEntries interface object
					pppp->QueryInterface(IID_IDispatch,(void**)&extraheadersentriesobj);//call query interface
					printf("\r\n%s = %s", (char*)extraheadersentriesobj->GetName(), (char*)extraheadersentriesobj->GetValue());
				}
			}
			printf("\r\n");
		}
	}
	catch (_com_error &error)//catch exception here
	{
		printf(TEXT("%S[%X]"), error.ErrorMessage(), error.Error());//display error message
	}
}

/********************************************************************/
/*GetAll function: The function is used to get complete mail message*/
/********************************************************************/
void GetAll()
{
	char m_Server[256], m_User[256], m_Password[256], m_MessageNo[256], m_DownloadUIDs[256], m_OrderBy[256], m_Path[256], m_HTTPPath[256];//define charecter buffer of 256 to read server name, user name, password, message numbers, dowmload uids, sorting criteria, attachment path and its http path
	long l_SortFirst;//sort first
	printf("\r\nEnter Server Name = ");
	gets(m_Server);//read server name
	printf("\r\nEnter User Name = ");
	gets(m_User);//read user name
	printf("\r\nEnter Password = ");
	gets(m_Password);//read password name
	printf("\r\nEnter Message Number = ");
	gets(m_MessageNo);//read message numbers
	printf("\r\nEnter Downloaded UIDs = ");
	gets(m_DownloadUIDs);//read downloaded uids
	printf("\r\nEnter Sorting Criteria = ");
	gets(m_OrderBy);//read sorting criteria
	printf("\r\nEnter Sort First Flag [0/1] = ");
	scanf("%d", &l_SortFirst);//read sort first
	getchar();
	printf("\r\nEnter Attachment Path = ");
	gets(m_Path);//read attachment path
	printf("\r\nEnter HTTP Attachment Path = ");
	gets(m_HTTPPath);//read http attachment path
	try//for COM library call, try...catch is used to handle exceptions
	{
		IPOP3Ptr obj;//take smart pointer object obj for COM library
		CoInitialize(NULL);//Initializes the COM library on the current thread
		obj = IPOP3Ptr("AdvPOP3.POP3");
		obj->PutServerName(m_Server);//set server name property
		obj->PutUserName(m_User);//set user name property
		obj->PutPassword(m_Password);//set password property
		obj->PutMessageNumber(m_MessageNo);//set message number property
		obj->PutDownloadedUIDs(m_DownloadUIDs);//set download uids property
		obj->PutOrderBy(m_OrderBy);//set sorting criteria property
		obj->PutSortFirst(l_SortFirst);//set sort first flag property
		_variant_t pVal = obj->GetAll();//call GetAll method of COM library
		//call GetIsError() property of COM library and check its value, if its value is 1, then
		//GetErrorReason() property of COM will contain error message, for which this error occured
		if (obj->GetIsError() == 1)
			printf("\r\nError: %s\r\n", (char*)obj->GetErrorReason());//display error message
		else
		{
			printf("\r\nSuccessfully GetHeaderOnly\r\n");//display successfull message
			IDispatch* p = pVal.pdispVal;//IDispatch object is assigned VARIANT object
			IFetchPtr fetchobj;//take Fetch interface object
			p->QueryInterface(IID_IDispatch,(void**)&fetchobj);//call query interface
			long count = fetchobj->GetCount();//get number of nodes
			for (int j = 1; j <= count; j++)//loop over each node
			{
				_variant_t retVal = fetchobj->GetItem(j);//get node item
				IDispatch* pp = retVal.pdispVal;//IDispatch object is assigned VARIANT object
				IFetchEntriesPtr fetchentriesobj;//take FetchEntries interface object
				pp->QueryInterface(IID_IDispatch,(void**)&fetchentriesobj);//call query interface
				printf("\r\nMessage No = %s\r\nPriority = %s\r\nDate = %s\r\nMessage Id = %s\r\nMime Version = %s\r\nContent Type = %s\r\nFrom = %s\r\nReply To = %s\r\nTo = %s\r\nSubject = %s\r\nX-Mailer = %s\r\nUID = %s\r\nStatus = %s\r\nSize = %d\r\nCC = %s\r\nAttachment Sent = %s\r\nAttachment Saved = %s\r\nAttachment Files = %s\r\nBody = %s\r\nHTML Body = %s\r\n",
					(char*)fetchentriesobj->GetMessageNo(), (char*)fetchentriesobj->GetPriority(),
					(char*)fetchentriesobj->GetDate(), (char*)fetchentriesobj->GetMessageId(),
					(char*)fetchentriesobj->GetMimeVersion(), (char*)fetchentriesobj->GetContentType(),
					(char*)fetchentriesobj->GetFrom(), (char*)fetchentriesobj->GetReplyTo(),
					(char*)fetchentriesobj->GetTo(), (char*)fetchentriesobj->GetSubject(),
					(char*)fetchentriesobj->GetXMailer(), (char*)fetchentriesobj->GetUID(),
					(char*)fetchentriesobj->GetStatus(), fetchentriesobj->GetSize(),
					(char*)fetchentriesobj->GetCC(), (char*)fetchentriesobj->GetAttachmentSent(),
					(char*)fetchentriesobj->GetAttachmentSaved(), (char*)fetchentriesobj->GetAttachmentFiles(),
					(char*)fetchentriesobj->GetBody(), (char*)fetchentriesobj->GetHTMLBody());//format data
				_variant_t subpVal = fetchentriesobj->ExtraHeaders();//call ExtraHeaders method
				IDispatch* ppp = subpVal.pdispVal;//IDispatch object is assigned VARIANT object
				IExtraHeadersPtr extraheadersobj;//take ExtraHeaders interface object
				ppp->QueryInterface(IID_IDispatch,(void**)&extraheadersobj);//call query interface
				long subcount = extraheadersobj->GetCount();//get number of nodes
				for (int i = 1; i <= subcount; i++)
				{
					_variant_t subretVal = extraheadersobj->GetItem(i);//get node item
					IDispatch* pppp = subretVal.pdispVal;//IDispatch object is assigned VARIANT object
					IExtraHeadersEntriesPtr extraheadersentriesobj;//take ExtraHeadersEntries interface object
					pppp->QueryInterface(IID_IDispatch,(void**)&extraheadersentriesobj);//call query interface
					printf("\r\n%s = %s", (char*)extraheadersentriesobj->GetName(), (char*)extraheadersentriesobj->GetValue());
				}
			}
			printf("\r\n");
		}
	}
	catch (_com_error &error)//catch exception here
	{
		printf(TEXT("%S[%X]"), error.ErrorMessage(), error.Error());//display error message
	}
}
