Click here to Skip to main content
15,867,453 members
Articles / Desktop Programming / MFC

Email checking program with support for multiple POP accounts

Rate me:
Please Sign up or sign in to vote.
4.60/5 (4 votes)
18 Apr 2011CPOL3 min read 28.1K   2K   29   3
A program to check for email messages with multiple POP accounts.

Introduction

This application initially was based on an Open Source sample NetManager V1.1 by Petr Stejskal. I used it to explore both MFC and Internet/Networking (email in particular). Email clients nowadays are mostly replaced by Web based email services, but I think this code sample can be useful for programmers studying Internet protocols. This is a relatively simple MFC program to check for email messages on multiple POP accounts. The application was upgraded from Visual C++ 6.0 to VC++ 2008.

Background

To send email, the SMTP (Simple Mail Transfer Protocol) protocol is used. An email message consists of two parts: header and body (+ optional attachment). For ASCII based alphabets, the body (text) is sent non encoded (7-bit ASCII). For non-ASCII data (languages outside the Latin alphabet), encoding is used: the MIME specification lists two binary-to-text encoding schemes quoted-printable for text and base64 for binary attachments. Two protocols are mostly used to retrieve email from a remote server over a TCP/IP connection:

  • Internet message access protocol (IMAP);
  • Post Office Protocol (POP).

Email clients and mail servers usually support both protocols.

Using the code

By writing this code, I got some practice in MFC, but mostly explored the coding of Internet protocols. Thus, the code is a mix of MFC and C++ classes with some C and Win32 API functions. Every time, I simply used what I thought was best applicable for a task to be solved. For implementation of the POP3 protocol, I adapted the CPop class by Robert E. Peters that is an update from the POP3 protocol wrapper class written by Asif Rasheed. The code is well commented and should be clear to people with an MFC and Win32 background.

May be of some interest is a function to receive email. On a slow internet connection (such as dial-up), the transmission can get stuck with the program hanging. So, I added a bit of multithreading to the implementation to be able to interrupt the transmission (to close the socket) from the worker thread in such situations. Every time the transmission begins, you can stop it from the message box window shown. Here is the corresponding code (with some omissions):

C++
//Function to receive mail and write it in the file:
void CMailPop3::OnReceive() 
{
    //1. To have the new socket, create the instance of CThreadInfo class 
    //   (structure/union) where we have a member of CPop3Comm class.
    //   It is done to be able to pass a pointer to the socket in worker thread:
    CThreadInfo m_CThreadInfo;

    //2.Connect the POP3 server:
    int nItem = -1;
    while((nItem = m_Servers.GetNextItem(nItem, LVNI_SELECTED)) != -1)
    {
        //1. Autorization state:////////////////////////////////////////////
        m_CThreadInfo.m_Pop3Comm.SetHost(m_aAccounts[nItem].sServer);
        csMailAccount =m_aAccounts[nItem].sServer;
        m_CThreadInfo.m_Pop3Comm.SetPort(m_aAccounts[nItem].nPort);
        m_CThreadInfo.m_Pop3Comm.SetUser(m_aAccounts[nItem].sUsername);
        userName = m_aAccounts[nItem].sUsername;
        m_CThreadInfo.m_Pop3Comm.SetPassword(m_aAccounts[nItem].sPassword);
   
        if(!m_CThreadInfo.m_Pop3Comm.Connect())
        {
            AfxMessageBox(m_CThreadInfo.m_Pop3Comm.GetErrorMessage());
            return;
        }
        //Restore the condition variable if communication was interrupted by the user
        //(it is used later in this function when output message parameters):
        nSocketClosed=0;

        //Pass the pointer to the CThreadInfo class
        //(structure/union) to the worker thread:
        AfxBeginThread(ThreadProc, &m_CThreadInfo);
   
        //2.Transaction state:
        //2.1 Get number of mails (STAT)
        if(!m_CThreadInfo.m_Pop3Comm.Statistics())
        {
            AfxMessageBox(m_CThreadInfo.m_Pop3Comm.GetErrorMessage());
            return;
        }
        m_Mails.DeleteAllItems();//clear the Mails list
        //get the number of mails
        nMailNum = m_CThreadInfo.m_Pop3Comm.GetNumberOfMails();

        int nMsgSize;//variable to calculate the size of single message

        // Open file to write the received messages
        // (output and append data).
    
        //Get the name of server selected and create an output file:
        csFileName =csMailAccount + (".dat");
        ofstream outfile(csFileName,ios::out, ios::app);

        //Get the mails:
        for(nItem = 0; nItem <nMailNum;  nItem++)
        {
            //2.2.Get information regarding the size of a single message
            //or all the messages in a mail drop (LIST):
            m_CThreadInfo.m_Pop3Comm.List();

            if ((nMailNum % 2) == 0)//if even number of messages 
            {
                nMsgSize=m_CThreadInfo.m_Pop3Comm.GetMessageSize(nItem);
            }
            else//if odd number of messages 
                nMsgSize=m_CThreadInfo.m_Pop3Comm.GetMessageSize(nItem+1);

            //2.3 Display a given message's header (TOP).
            //List box is 0-based, but message's numbering is 1-based,
            //thus, add 1 to the list view first line:
            m_CThreadInfo.m_Pop3Comm.GetTop(nItem+1,nMsgSize); 

            //Output the server's name:
            m_Mails.InsertItem(nItem, csMailAccount);
            //Output mail fields (Attachment, From, Subject, Date):
            if (m_CThreadInfo.m_Pop3Comm.t_Attachment == "text/plain;")
            {
                m_CThreadInfo.m_Pop3Comm.t_Attachment = "";
            }
      
            if (nSocketClosed ==0)
            {
                m_Mails.SetItemText(nItem, 1, m_CThreadInfo.m_Pop3Comm.t_Attachment);
                m_Mails.SetItemText(nItem, 2, m_CThreadInfo.m_Pop3Comm.t_From);
                m_Mails.SetItemText(nItem, 3, m_CThreadInfo.m_Pop3Comm.t_Subject);
                m_Mails.SetItemText(nItem, 4, m_CThreadInfo.m_Pop3Comm.t_Date);
            }
            else//if communication is interrupted by the user
            {
                m_Mails.DeleteAllItems();//clear the Mails list box
            }

            //2.4 Retrieve a message from the host(RETR):
            m_CThreadInfo.m_Pop3Comm.Retrieve(nItem+1);

            //some code here...

            //Disconnect from the server:
            m_CThreadInfo.m_Pop3Comm.Disconnect();

            //If mail is received successfully, post message to the worker thread to close 
            //the socket controlling message box (for explanation on the following code 
            //see "Remarks" section in MSDN article on PostThreadMessage API):
            PostThreadMessage(nThreadID, WM_QUIT, 0, 0);
            //to create a message queue needed to handle PostThreadMessage:
            Sleep(0);
            PostThreadMessage(nThreadID, WM_QUIT, 0, 0);
        }//end of "while" loop
    }

The application

The application has a very simple user friendly interface:

Image 1

The features of the email check program are limited by the purpose of the code sample:

  • It can read only ASCII (Latin alphabet) email messages from multiple POP accounts.
  • The messages are simply output in an Edit Control and a file.

Image 2

  • It can receive attachments but they have to be cut out of the message and decoded by an external base64 decoding application or using an online service.
  • Text in languages outside ASCII have to be cut out of the message and decoded by an external quoted printable decoding application or using an online service.

References

History

  • 04.2009 - Built in Visual C++ 6.0.
  • 04.2011 - Upgraded to Visual C++ 2008.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Russian Federation Russian Federation
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
QuestionFailed for gmail alone, NEED info of SSL and TLS usage with this Pin
Member 471758928-Apr-18 6:51
Member 471758928-Apr-18 6:51 
QuestionOne file is missing in your rar file! Pin
Hadi Dayvary26-Feb-12 20:02
professionalHadi Dayvary26-Feb-12 20:02 
AnswerRe: One file is missing in your rar file! Pin
Sergey Chepurin26-Feb-12 23:23
Sergey Chepurin26-Feb-12 23:23 
This is just email checking sample code, and this is not a whole application, but rather an illustration of raw usage of Internet protocols in C/C++/MFC without .NET or other kind of support. You may get some problems connecting to Web SMTP servers this way, except for your ISP provider, probably. But if you want to see how it can be done, then, in the References list there is a link to the code of NetManager V1.1 by Petr Stejskal (which i used as a sample for this application). You can download it and use SMTP.cpp file with implementation of SMTP protocol for sending email.
P.S. It was so long ago. Just checked again - POP3 wrapper class is written by Asif Rasheed and updated by Robert E. Peters: Updated POP3 Wrapper Clas[^] (without explicit license attached). SMTP protocol implementation is copyrighted by PJ Naughter[^] (see Codepoject.com profile). Here is the link to his own sample of SMTP CSMTPConnection v1.36[^]

modified 27-Feb-12 6:22am.

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.