Send Email with Asynchronous Mode in Visual C++

In previous section, I introduced how to encrypt email with digital certificate. In this section, I will introduce how to use event handler and asynchronous mode.

Introduction

Asynchronous mode

In synchronous mode, once SendMail method is called, it returns to application after the method is complete. Therefore, if the runtime (it depends on the networking connection and the email size) is long, your application cannot do anything before this method ends, which results “my application is blocked or halted”. In contrast, in asynchronous mode, as SendMail method works in background, this methods return to application immediately no matter the running method is complete or not.

Event handler

In previous examples, after SendMail method is invoked, if you want to know the progress of the email sending, you should use Event Handler to monitor the progress of email sending.

Note

Remarks: All of samples 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 of EASendMail to your project.

[Visual C++ Example - Send email with event handler in asynchronous mode]

To demonstrate how to use asynchronous mode and event handler, let’s add a Label control in the form at first, the name of the label is “Label1”.

The following example codes demonstrate how to send email with event handler in asynchronous mode.

Note

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

#include "stdafx.h"
#include <tchar.h>
#include <Windows.h>

#include "EASendMailObj.tlh"
using namespace EASendMailObjLib;

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

const int ConnectNormal = 0;
const int ConnectSSLAuto = 1;
const int ConnectSTARTTLS = 2;
const int ConnectDirectSSL = 3;
const int ConnectTryTLS = 4;

#define IDC_SRCIMAIL 1
static _ATL_FUNC_INFO OnClosed = {CC_STDCALL, VT_EMPTY, 0};
static _ATL_FUNC_INFO OnSending = {CC_STDCALL, VT_EMPTY, 2, {VT_I4, VT_I4}};
static _ATL_FUNC_INFO OnError = {CC_STDCALL, VT_EMPTY, 2, {VT_I4, VT_BSTR}};
static _ATL_FUNC_INFO OnConnected = {CC_STDCALL, VT_EMPTY, 0};
static _ATL_FUNC_INFO OnAuthenticated = {CC_STDCALL, VT_EMPTY, 0};
class CMailEvents:public IDispEventSimpleImpl<IDC_SRCIMAIL,
                                            CMailEvents,
                                            &__uuidof(_IMailEvents)>
{
public:
    CMailEvents(){};
BEGIN_SINK_MAP(CMailEvents)
    SINK_ENTRY_INFO(IDC_SRCIMAIL, __uuidof(_IMailEvents), 1,
                    &CMailEvents::OnClosedHandler, &OnClosed)
    SINK_ENTRY_INFO(IDC_SRCIMAIL, __uuidof(_IMailEvents), 2,
                    &CMailEvents::OnSendingHandler, &OnSending)
    SINK_ENTRY_INFO(IDC_SRCIMAIL, __uuidof(_IMailEvents), 3,
                    &CMailEvents::OnErrorHandler, &OnError)
    SINK_ENTRY_INFO(IDC_SRCIMAIL, __uuidof(_IMailEvents), 4,
                    &CMailEvents::OnConnectedHandler, &OnConnected)
    SINK_ENTRY_INFO(IDC_SRCIMAIL, __uuidof(_IMailEvents), 5,
                    &CMailEvents::OnAuthenticatedHandler, &OnAuthenticated)
END_SINK_MAP()
public:
    BOOL    m_bError;
    BOOL    m_bFinished;
    _bstr_t m_lastError;
protected:
    HRESULT __stdcall OnClosedHandler()
    {
        m_bFinished = TRUE;
        return S_OK;
    }
    HRESULT __stdcall OnSendingHandler(long nSent, long nTotalSize)
    {
        _tprintf(_T("Sending %d/%d ...\r\n"), nSent, nTotalSize);
        return S_OK;
    }
    HRESULT __stdcall OnErrorHandler(long nErrorCode, BSTR ErrorMessage)
    {
        m_bFinished = TRUE;
        m_bError = TRUE;
        m_lastError = ErrorMessage;
        return S_OK;
    }
    HRESULT __stdcall OnConnectedHandler()
    {
        _tprintf(_T("Connected\r\n"));
        return S_OK;
    }
    HRESULT __stdcall OnAuthenticatedHandler()
    {
        _tprintf(_T("Authenticated\r\n"));
        return S_OK;
    }
};

int _tmain(int argc, _TCHAR* argv[])
{
    ::CoInitialize(NULL);
    IMailPtr oSmtp = NULL;
    oSmtp.CreateInstance(__uuidof(EASendMailObjLib::Mail));
    oSmtp->LicenseCode = _T("TryIt");

    // Set your sender email address
    oSmtp->FromAddr = _T("test@emailarchitect.net");
    // Add recipient email address
    oSmtp->AddRecipientEx(_T("support@emailarchitect.net"), 0);

    // Set email subject
    oSmtp->Subject = _T("email from Visual C++ project in asynchronous mode ");
    // Set email body
    oSmtp->BodyText = _T("this is a test email sent from Visual C++ asynchronously");

    // Your SMTP server address
    oSmtp->ServerAddr = _T("smtp.emailarchitect.net");

    // User and password for ESMTP authentication, if your server doesn't
    // require User authentication, please remove the following codes.
    oSmtp->UserName = _T("test@emailarchitect.net");
    oSmtp->Password = _T("testpassword");

    // Most mordern SMTP servers require SSL/TLS connection now.
    // ConnectTryTLS means if server supports SSL/TLS, SSL/TLS will be used automatically.
    oSmtp->ConnectType = ConnectTryTLS;

    // If your SMTP server uses 587 port
    // oSmtp->ServerPort = 587;

    // If your SMTP server requires SSL/TLS connection on 25/587/465 port
    // oSmtp->ServerPort = 25; // 25 or 587 or 465
    // oSmtp->ConnectType = ConnectSSLAuto;

    _tprintf(_T("Start to send email ...\r\n"));

    // Attach event connection pointer
    CMailEvents oEvents;
    oEvents.DispEventAdvise(oSmtp.GetInterfacePtr());
    oEvents.m_bFinished = FALSE;
    oEvents.m_bError = FALSE;
    // Set asynchronous mode
    oSmtp->Asynchronous = 1;
    oSmtp->SendMail();

    // Waiting for email sending ...
    while(!oEvents.m_bFinished)
    {
        MSG msg;
        while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
        {
            if(msg.message == WM_QUIT)
                return 0;
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }

        // You can do other thing here
        ::Sleep(10);
    }

    // Detach event connection pointer
    oEvents.DispEventUnadvise(oSmtp.GetInterfacePtr());
    if(!oEvents.m_bError)
    {
        _tprintf(_T("email was sent successfully!\r\n"));
    }
    else
    {
        _tprintf(_T("failed to send email with the following error: %s\r\n"),
            (const TCHAR*)oEvents.m_lastError);
    }

    return 0;
}

Next Section

At next section I will introduce how to send mass email with multiple threads.

Appendix

Comments

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