POP3 Protocol wrapper class

.

On the Internet, electronic mail (e-mail) is the most widely used application. According to experts, of all TCP connections that Internet users establish, about one-half are for sending and receiving e-mail messages. So it is impossible for any Internet programmer to leave this area.

Usually e-mail systems use SMTP as a mail sending Protocol and POP3 as a mail receiving Protocol. For details about these Protocols you can refere to RCF 821 (for SMTP) and RFC 1225 (for POP3). Since in Windows environment we have MAPI for e-mail handling but it do not provide enough power to commuincate with e-mail server directly.

Here I developed a class for POP 3 protocol. In this class I used CSocket as class member (surperise not inherent it), so that I can used it in Threads. POP Class has methods which are resembled with POP 3 protocol commands. Following is code of the class with comments.

/*--------------------------------------------------------------------
     Pop.h : main header file for the POP application
-----------------------------------------------------------------------*/

#if !defined(AFX_POP_H__A44B38B6_697C_11D1_881E_00001C302581__INCLUDED_)
#define AFX_POP_H__A44B38B6_697C_11D1_881E_00001C302581__INCLUDED_

#define CONNECTION_CHECK 0
#define USER_CHECK  1
#define PASSWORD_CHECK 2
#define QUIT_CHECK  3
#define DELETE_CHECK 4
#define RSET_CHECK  5
#define STAT_CHECK  6
#define NOOP_CHECK  7
#define LIST_CHECK  8
#define RETR_CHECK  9

/////////////////////////////////////////////////////////////////////////////
class CPop
{
public:
 BOOL List();
 CWordArray m_SizeOfMsg;
 CString GetErrorMessage();    // If there is any error this will return it method
 CString GetPassword();           // Getting Password stored in class
 void SetPassword(CString& Password);    // Setting Password in class
 CString GetUser();                   // Getting user name stored in class
 void SetUser(CString& User);  // Setting user name in class
 CString GetHost();                    // Getting Host name (email server name) stored in class
 void SetHost(CString& Host);    // Setting Host name (email server name) in class
 BOOL Connect();                    // Connecting to email server
 int GetTotalMailSize();                // it returns the Total Mail Size
 int GetNumberOfMails();            // It return the number of mails
 CString GetMsgContents();        
 BOOL Statistics();                    // issue the STAT command on email server
 BOOL Retrieve(int MsgNumber);    // Getting any particular mail message
 BOOL Reset();                        // issue the reset command on email server
 int  GetMessageSize(int MsgNumber);    // Return a size of any particular mail
 BOOL Noop();                     // issue the NOOP command on email server
 BOOL Disconnect();            // issue the QUIT command on email server
 BOOL Delete(int& MsgNumber); // Deleteing a particular message from email server
 BOOL Connect(CString& Host, CString& User, CString& Password);
 CPop();
 virtual ~CPop();

private:
 CString m_ErrorMessage;
 BOOL CheckResponse(int ResponseType);
 CString m_Password;
 CString m_User;
 CString m_Host;
 CString m_MsgContents;
 int m_TotalSize;
 int m_NumberMail;
 CSocket m_PopServer;
};
/#endif // !defined(AFX_POP_H__A44B38B6_697C_11D1_881E_00001C302581__INCLUDED_)
 

/*-----------------------------------------------------------------------------------------------
// Pop.cpp : Defines the class behaviors for the application.
---------------------------------------------------------------------------------------------------*/

#include "stdafx.h"
#include "Pop.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

////////////////////////////////////////////////////////////////////
// CPop Class
//////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CPop::CPop()
{
 m_PopServer.Create();
}
//{4EEC1C91-6BE1-11d1-8824-00001C302581}

CPop::~CPop()
{
 m_PopServer.Close();
}

BOOL CPop::Connect(CString & Host, CString & User, CString & Password)
{
 char buf [512];

 if (!m_PopServer.Connect(Host,110)) // 110 Pop3 Port
 {
  m_ErrorMessage = _T("Server cannot be connected");
  return FALSE;
 }
 else
 {
  if(CheckResponse(CONNECTION_CHECK)==FALSE)
   return FALSE;

  wsprintf (buf, "USER %s\r\n", (LPCSTR) User);
  m_PopServer.Send(buf, strlen (buf));
  if(CheckResponse(USER_CHECK)==FALSE)
   return FALSE;

  wsprintf (buf, "PASS %s\r\n", (LPCSTR) Password);
  m_PopServer.Send(buf, strlen (buf));
  if (CheckResponse(PASSWORD_CHECK)==FALSE)
   return FALSE;

  return TRUE;
 }

}

BOOL CPop::Delete(int & MsgNumber)
{
 char buf [512];

 wsprintf (buf, "DELE %d\r\n",MsgNumber );
 m_PopServer.Send(buf, strlen (buf));
 if (CheckResponse(DELETE_CHECK)==FALSE)
  return FALSE;
 else
  return TRUE;
}

BOOL CPop::Disconnect()
{
 char buf [512];

 wsprintf (buf, "QUIT \r\n");
 m_PopServer.Send(buf, strlen (buf));
 if (CheckResponse(QUIT_CHECK)==FALSE)
  return FALSE;
 else
  return TRUE;
}

BOOL CPop::Noop()
{
 char buf [512];

 wsprintf (buf, "NOOP  \r\n");
 m_PopServer.Send(buf, strlen (buf));
 if (CheckResponse(NOOP_CHECK)==FALSE)
  return FALSE;
 else
  return TRUE;
}

// Return the Msg Size for given msg number
int CPop::GetMessageSize(int MsgNumber)
{
 if(m_SizeOfMsg.GetSize() < MsgNumber+1)
  return 0;
 else
  return m_SizeOfMsg[MsgNumber+1];
}

BOOL CPop::Reset()
{
 char buf [512];

 wsprintf (buf, "RSET \r\n");
 m_PopServer.Send(buf, strlen (buf));
 if (CheckResponse(RSET_CHECK)==FALSE)
  return FALSE;
 else
  return TRUE;
}

// MsgContents will hold the msg body
BOOL CPop::Retrieve(int  MsgNumber)
{
 char buf [512];

 wsprintf (buf, "RETR %d\r\n",MsgNumber );
 m_PopServer.Send(buf, strlen (buf));
 if (CheckResponse(RETR_CHECK)==FALSE)
  return FALSE;
 else
  return TRUE;
}

BOOL CPop::Statistics()
{
 char buf [512];

 wsprintf (buf, "STAT \r\n");
 m_PopServer.Send(buf, strlen (buf));
 if (CheckResponse(STAT_CHECK)==FALSE)
  return FALSE;
 else
  return TRUE;
}

CString CPop::GetMsgContents()
{
 return m_MsgContents;
}

int CPop::GetNumberOfMails()
{
 return m_NumberMail;
}

int CPop::GetTotalMailSize()
{
 return m_TotalSize;
}

BOOL CPop::Connect()
{
 Connect(m_Host, m_User, m_Password);
 return TRUE;
}

void CPop::SetHost(CString & Host)
{
 m_Host = Host;
}

CString CPop::GetHost()
{
 return m_Host;
}

void CPop::SetUser(CString & User)
{
 m_User = User;
}

CString CPop::GetUser()
{
 return m_User;
}

void CPop::SetPassword(CString & Password)
{
 m_Password = Password;
}

CString CPop::GetPassword()
{
 return m_Password;
}

BOOL CPop::CheckResponse(int ResponseType)
{
 char buf [1000];

 for (int i=0;i<512;i++)
  buf[i]='\0';

 m_PopServer.Receive(buf, sizeof(buf));

 switch (ResponseType)
 {
  case CONNECTION_CHECK:
   if (strnicmp(buf,"-ERR", 4) == 0)
   {
    m_ErrorMessage = _T("Bad Connection");
    return FALSE;
   }
   break;

  case USER_CHECK:
   if (strnicmp(buf,"-ERR", 4) == 0)
   {
    m_ErrorMessage = _T("Bad User Name");
    return FALSE;
   }
   break;
  case PASSWORD_CHECK:
   if (strnicmp(buf,"-ERR", 4) == 0)
   {
    m_ErrorMessage = _T("Bad Password Name");
    return FALSE;
   }
   break;
  case QUIT_CHECK:
   if (strnicmp(buf,"-ERR", 4) == 0)
   {
    m_ErrorMessage = _T("Error occured during QUIT");
    return FALSE;
   }
   break;
  case DELETE_CHECK:
   if (strnicmp(buf,"-ERR", 4) == 0)
   {
    m_ErrorMessage = _T("Error occured during DELE");
    return FALSE;
   }
   break;
  case RSET_CHECK:
   if (strnicmp(buf,"-ERR", 4) == 0)
   {
    m_ErrorMessage = _T("Error occured during RSET");
    return FALSE;
   }
   break;
  case STAT_CHECK:
   if (strnicmp(buf,"-ERR", 4) == 0)
   {
    m_ErrorMessage = _T("Error occured during STAT");
    return FALSE;
   }
   else
   {
    BOOL EmailNumber = TRUE;
    for (char *p = buf; *p != '\0'; p++)
    {
     if (*p == '\t' || *p == ' ')
     {
      if(EmailNumber == TRUE)
      {
       m_NumberMail = atoi(p);
       EmailNumber = FALSE;
      }
      else
      {
       m_TotalSize = atoi(p);
       return TRUE;
      }
     }
    }

   }
   break;
  case NOOP_CHECK:
   if (strnicmp(buf,"-ERR", 4) == 0)
   {
    m_ErrorMessage = _T("Error occured during NOOP");
    return FALSE;
   }
   break;

  case LIST_CHECK:
   if (strnicmp(buf,"-ERR", 4) == 0)
   {
    m_ErrorMessage = _T("Error occured during LIST");
    return FALSE;
   }
   else
   {
    m_PopServer.Receive(buf, sizeof(buf));

    for (char *p = buf; *p != '.'; p++)
     if (*p == '\t' || *p == ' ')
      m_SizeOfMsg.Add(atoi(p));
   }
   break;
  case RETR_CHECK:
   if (strnicmp(buf,"-ERR", 4) == 0)
   {
    m_ErrorMessage = _T("Error occured during RETR");
    return FALSE;
   }
   else
   {
    char temp[9000];
    m_PopServer.Receive(temp, sizeof(temp));
    m_MsgContents = temp;
   }
   break;
 }
 return TRUE;
}

CString CPop::GetErrorMessage()
{
 return m_ErrorMessage;
}

BOOL CPop::List()
{
 char buf [512];

 wsprintf (buf, "LIST  \r\n");
 m_PopServer.Send(buf, strlen (buf));
 if (CheckResponse(LIST_CHECK)==FALSE)
  return FALSE;
 else
  return TRUE;
}
 
 
 



Comments

  • 我是朱大牛呀我是朱大牛

    Posted by Legacy on 10/16/2003 12:00am

    Originally posted by: 朱大牛

    我是朱大牛呀我是朱大牛

    Reply
  • CheckResponse()...memory allocation?

    Posted by Legacy on 07/18/2003 12:00am

    Originally posted by: Bob Bonham

    
    

    in the checkResponse() routine in the case of RETR_CHECK

    this code:
    char temp[9000];
    m_PopServer.Receive(temp, sizeof(temp));
    m_MsgContents = temp;

    does not create memory for temp...It worked for me like this on win 95-2000 platforms however.

    Now it crashes on XP. Now if you allocate memory for temp then it works fine.

    I suggest this change:


    char *temp = new char[9000];
    m_PopServer.Receive(temp, sizeof(temp));

    m_MsgContents = temp;
    delete temp;


    Thanks for the great class, I use it all the time.

    Bob

    Reply
  • problem with some commands

    Posted by Legacy on 03/11/2003 12:00am

    Originally posted by: bob

    commands with no arguments (QUIT, LIST, STAT etc) should not have a space character after them.

    I was working with a pop3 server that returned -ERR to the string "QUIT \r\n"

    causing none of the messages to be removed from the server.

    Bob

    Reply
  • details about information messenger system

    Posted by Legacy on 01/07/2003 12:00am

    Originally posted by: kumararaja

    How can I sending the message using mail server to the clients of the organization .What are the main physical and technical requirements(like which type mail server,web server and main VC++ codings) for implementing this IMS?

    Reply
  • details about information messenger system

    Posted by Legacy on 01/07/2003 12:00am

    Originally posted by: kumararaja

    How can I sending the message using mail server to the clients of the organization .What are the main physical and technical requirements(like which type mail server,web server and main VC++ codings) for implementing this IMS?

    Reply
  • Compile error on VC6

    Posted by Legacy on 12/06/2002 12:00am

    Originally posted by: PM

    when i was trying to compile the above codes in VC6, i got the following errors, can any one tell me how to solve it?

    --------------------Configuration: pop - Win32 Debug--------------------
    Linking...
    nafxcwd.lib(afxmem.obj) : error LNK2005: "void __cdecl operator delete(void *)" (??3@YAXPAX@Z) already defined in LIBCD.lib(dbgdel.obj)
    LIBCD.lib(crt0.obj) : error LNK2001: unresolved external symbol _main
    nafxcwd.lib(thrdcore.obj) : error LNK2001: unresolved external symbol __endthreadex
    nafxcwd.lib(thrdcore.obj) : error LNK2001: unresolved external symbol __beginthreadex
    Debug/pop.exe : fatal error LNK1120: 3 unresolved externals
    Error executing link.exe.

    pop.exe - 5 error(s), 0 warning(s)

    Reply
  • Thanx, Nice class. What abt proxy

    Posted by Legacy on 11/19/2002 12:00am

    Originally posted by: Harry Chillboy


    It won't work with proxy...
    Can u help me..to use proxy

    Reply
  • RETR command failing

    Posted by Legacy on 08/29/2002 12:00am

    Originally posted by: steven

    ive found in a program that ive written that the RETR command is failing and returning FALSE. what could be the possible reasons for this? what causes the RETR command to fail as im not sure whether its code error or maybe something i have to look at with the exchange server.
    thanks

    Reply
  • Attachments?

    Posted by Legacy on 10/12/2001 12:00am

    Originally posted by: tinydemo

    How does this manage attachments in BASE64,Can you send me a demo project about it?

    Reply
  • SMTP With COM

    Posted by Legacy on 06/15/2001 12:00am

    Originally posted by: Vu Van Bao

    Please Help Me !!!

    I Need Code SMTP With COM or ATL

    Thank !!!

    Reply
  • Loading, Please Wait ...

Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • On-demand Event Event Date: September 10, 2014 Modern mobile applications connect systems-of-engagement (mobile apps) with systems-of-record (traditional IT) to deliver new and innovative business value. But the lifecycle for development of mobile apps is also new and different. Emerging trends in mobile development call for faster delivery of incremental features, coupled with feedback from the users of the app "in the wild." This loop of continuous delivery and continuous feedback is how the best mobile …

  • QA teams don't have time to test everything yet they can't afford to ship buggy code. Learn how Coverity can help organizations shrink their testing cycles and reduce regression risk by focusing their manual and automated testing based on the impact of change.

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds