Retrieve Email with Event Handler in Visual C++

In previous section, I introduced how to retrieve email from Hotmail/MSN Live account. In this section, I will introduce how to retrieve email with event handler in Visual C++.

Introduction

After Connect method, GetMail method or other methods are invoked, if you want to know the progress of the email receiving, you should use Event Handler. The following sample codes demonstrate how to use Event Handler to monitor the progress of email receiving.

Note

Remarks: All of examples in this section are based on first section: A simple Visual C++ project. To compile and run the following example codes successfully, please click here to learn how to create the test project and add reference to your project.

[Visual C++ Example - Retrieve email with event handler]

The following example codes demonstrate how to use EAGetMail POP3 component to retrieve email with event handler. In order to run it correctly, please change email server, user, password, folder, file name values.

Note

To get the full sample projects, please refer to Samples section.

#include "stdafx.h"
#include <atlbase.h>
#include <atlcom.h>

#include "eagetmailobj.tlh"
using namespace EAGetMailObjLib;

#define IDC_SRCIMAILCLIENT 1

static _ATL_FUNC_INFO OnIdle = {CC_STDCALL, VT_EMPTY, 2,
        {VT_DISPATCH, VT_BOOL|VT_BYREF }};

static _ATL_FUNC_INFO OnConnected = {CC_STDCALL, VT_EMPTY, 2,
        {VT_DISPATCH, VT_BOOL|VT_BYREF }};

static _ATL_FUNC_INFO OnQuit = {CC_STDCALL, VT_EMPTY, 2,
        {VT_DISPATCH, VT_BOOL|VT_BYREF }};

static _ATL_FUNC_INFO OnSendCommand = {CC_STDCALL, VT_EMPTY, 4,
        {VT_DISPATCH, VT_VARIANT, VT_BOOL, VT_BOOL|VT_BYREF }};

static _ATL_FUNC_INFO OnReceiveResponse = {CC_STDCALL, VT_EMPTY, 4,
        {VT_DISPATCH, VT_VARIANT, VT_BOOL, VT_BOOL|VT_BYREF }};

static _ATL_FUNC_INFO OnSecuring = {CC_STDCALL, VT_EMPTY, 2,
        {VT_DISPATCH, VT_BOOL|VT_BYREF }};

static _ATL_FUNC_INFO OnAuthorized = {CC_STDCALL, VT_EMPTY, 2,
        {VT_DISPATCH, VT_BOOL|VT_BYREF }};

static _ATL_FUNC_INFO OnSendingDataStream = {CC_STDCALL, VT_EMPTY, 4,
        {VT_DISPATCH, VT_I4, VT_I4, VT_BOOL|VT_BYREF }};

static _ATL_FUNC_INFO OnReceivingDataStream  = {CC_STDCALL, VT_EMPTY, 5,
        {VT_DISPATCH, VT_DISPATCH, VT_I4, VT_I4, VT_BOOL|VT_BYREF }};

class CMailClientEvents:public IDispEventSimpleImpl<IDC_SRCIMAILCLIENT,
                                            CMailClientEvents,
                                            &__uuidof(_IMailClientEvents)>
{
public:
    CMailClientEvents(){};

BEGIN_SINK_MAP(CMailClientEvents)
    SINK_ENTRY_INFO(IDC_SRCIMAILCLIENT,
        __uuidof(_IMailClientEvents), 1, OnIdleHandler, &OnIdle)
    SINK_ENTRY_INFO(IDC_SRCIMAILCLIENT,
        __uuidof(_IMailClientEvents), 2, OnConnectedHandler, &OnConnected)
    SINK_ENTRY_INFO(IDC_SRCIMAILCLIENT,
        __uuidof(_IMailClientEvents), 3, OnQuitHandler, &OnQuit)
    SINK_ENTRY_INFO(IDC_SRCIMAILCLIENT,
        __uuidof(_IMailClientEvents), 4, OnSendCommandHandler, &OnSendCommand)
    SINK_ENTRY_INFO(IDC_SRCIMAILCLIENT,
        __uuidof(_IMailClientEvents), 5, OnReceiveResponseHandler, &OnReceiveResponse)
    SINK_ENTRY_INFO(IDC_SRCIMAILCLIENT,
        __uuidof(_IMailClientEvents), 6, OnSecuringHandler, &OnSecuring)
    SINK_ENTRY_INFO(IDC_SRCIMAILCLIENT,
        __uuidof(_IMailClientEvents), 7, OnAuthorizedHandler, &OnAuthorized)
    SINK_ENTRY_INFO(IDC_SRCIMAILCLIENT,
        __uuidof(_IMailClientEvents), 8, OnSendingDataStreamHandler, &OnSendingDataStream)
    SINK_ENTRY_INFO(IDC_SRCIMAILCLIENT,
        __uuidof(_IMailClientEvents), 9, OnReceivingDataStreamHandler, &OnReceivingDataStream)

END_SINK_MAP()

protected:
        HRESULT __stdcall OnIdleHandler(
        IDispatch * oSender,
        VARIANT_BOOL * Cancel)
    {
        return S_OK;
    }

    HRESULT __stdcall OnConnectedHandler(
        IDispatch * oSender,
        VARIANT_BOOL * Cancel)
    {
        _tprintf( _T("Connected\r\n"));
        return S_OK;
    }

    HRESULT __stdcall OnQuitHandler(
        IDispatch * oSender,
        VARIANT_BOOL * Cancel)
    {
        _tprintf( _T("Quit\r\n"));
        return S_OK;
    }

    HRESULT __stdcall OnSendCommandHandler(
        IDispatch * oSender,
        VARIANT data,
        VARIANT_BOOL IsDataStream,
        VARIANT_BOOL * Cancel)
    {
        return S_OK;
    }

    HRESULT __stdcall OnReceiveResponseHandler (
        IDispatch * oSender,
        VARIANT data,
        VARIANT_BOOL IsDataStream,
        VARIANT_BOOL * Cancel )
    {
        return S_OK;
    }

    HRESULT __stdcall OnSecuringHandler (
        IDispatch * oSender,
        VARIANT_BOOL * Cancel )
    {
        _tprintf( _T("Securing ...\r\n"));
        return S_OK;
    }

    HRESULT __stdcall OnAuthorizedHandler (
        IDispatch * oSender,
        VARIANT_BOOL * Cancel )
    {
        _tprintf( _T("Authorized\r\n"));
        return S_OK;
    }

    HRESULT __stdcall OnSendingDataStreamHandler (
        IDispatch * oSender,
        long Sent,
        long Total,
        VARIANT_BOOL * Cancel )
    {
        return S_OK;
    }

    HRESULT __stdcall OnReceivingDataStreamHandler (
        IDispatch * oSender,
        IDispatch * oInfo,
        long Received,
        long Total,
        VARIANT_BOOL * Cancel )
    {
        IMailInfoPtr pInfo = NULL;
        oInfo->QueryInterface(__uuidof(IMailInfo), (void**)&pInfo);
        _tprintf( _T("Receiving index:%d, %d/%d\r\n"), pInfo->Index, Received, Total);
        return S_OK;
    }
};

int _tmain(int argc, _TCHAR* argv[])
{
    const int MailServerPop3 = 0;
    const int MailServerImap4 = 1;
    const int MailServerEWS = 2;
    const int MailServerDAV = 3;

    // Initialize COM environment
    ::CoInitialize( NULL );

    // Create a folder named "inbox" under current exe file directory
    // to save the emails retrieved.
    TCHAR szPath[MAX_PATH+1];
    memset( szPath, 0, sizeof(szPath));
    ::GetModuleFileName( NULL, szPath,  MAX_PATH );

    // Change file name to current full path
    LPCTSTR psz = _tcsrchr( szPath, _T('\\'));
    if( psz != NULL )
    {
        szPath[psz-szPath] = _T('\0');
    }
    TCHAR szMailBox[MAX_PATH+1];
    memset( szMailBox, 0, sizeof(szMailBox));
    wsprintf( szMailBox, _T("%s\\inbox"), szPath );

    // Create a folder to store emails
    ::CreateDirectory( szMailBox, NULL );

    try
    {
        IMailServerPtr oServer = NULL;
        oServer.CreateInstance(__uuidof(EAGetMailObjLib::MailServer));
        oServer->Server = _T("pop3.emailarchitect.net");
        oServer->User = _T("test@emailarchitect.net");
        oServer->Password = _T("testpassword");
        oServer->Protocol = MailServerPop3;

        // If your POP3 requires SSL connection
        // Please add the following codes
        // oServer->SSLConnection = VARIANT_TRUE;
        // oServer->Port = 995;

        IMailClientPtr oClient = NULL;
        oClient.CreateInstance(__uuidof(EAGetMailObjLib::MailClient))
        oClient->LicenseCode = _T("TryIt");

        // Attach event handler
        CMailClientEvents oEvents;
        oEvents.DispEventAdvise( oClient.GetInterfacePtr());

        oClient->Connect( oServer );
        _tprintf(_T("Connected\r\n"));

        _variant_t infos = oClient->GetMailInfos();
        SAFEARRAY *psa = infos.parray;
        long LBound = 0, UBound = 0;
        SafeArrayGetLBound( psa, 1, &LBound );
        SafeArrayGetUBound( psa, 1, &UBound );

        INT count = UBound-LBound+1;
        _tprintf(_T("Total %d emails\r\n"), count );

        for( long i = LBound; i <= UBound; i++ )
        {
            _variant_t vtInfo;
            SafeArrayGetElement( psa, &i, &vtInfo );

            IMailInfoPtr pInfo;
            vtInfo.pdispVal->QueryInterface(__uuidof(IMailInfo), (void**)&pInfo);

            TCHAR szFile[MAX_PATH+1];
            memset( szFile, 0, sizeof(szFile));

            // Generate a random file name by current local datetime,
            // You can use your method to generate the filename if you do not like it
            SYSTEMTIME curtm;
            ::GetLocalTime( &curtm );
            ::wsprintf( szFile, _T("%s\\%04d%02d%02d%02d%02d%02d%03d%d.eml"),
                szMailBox,
                curtm.wYear,
                curtm.wMonth,
                curtm.wDay,
                curtm.wHour,
                curtm.wMinute,
                curtm.wSecond,
                curtm.wMilliseconds,
                i );

            // Receive email from POP3 server
            IMailPtr oMail = oClient->GetMail(pInfo);

            // Save email to local disk
            oMail->SaveAs( szFile, VARIANT_TRUE );

            // Mark email as deleted from POP3 server.
            oClient->Delete( pInfo );
        }

        // Delete method just mark the email as deleted,
        // Quit method purge the emails from server exactly.
        infos.Clear();
        oClient->Quit();

        // Detach event handler
        oEvents.DispEventUnadvise(oClient.GetInterfacePtr());
    }
    catch( _com_error &ep )
    {
        _tprintf( _T("Error: %s"), (const TCHAR*)ep.Description());
    }

    return 0;
}

Next Section

At next section I will introduce how to use UIDL function to mark the email has been downloaded.

Appendix

Comments

If you have any comments or questions about above example codes, please click here to add your comments.