Are you a world traveler? ZoneTick is a cool utility that'll help you stay in touch over multiple time zones!
 
Sending an E-mail Message  
Nik Okuntseff  MS Exchange Server Programming 

Sending an E-mail Message

You can use CDO and COleDispatchDriver derived classes to create and send an e-mail message. The following fragment (CDO/SendMail) illustrates this:

void CSendMailDlg::OnSend()
{
    try
    {
        // Initialize session object
        Session session;
        BOOL bResult = session.CreateDispatch("MAPI.Session");
        ASSERT(bResult);
 
        // Logon
        VARIANT vResult;
        VariantInit(&vResult);
        session.InvokeHelper(0x77, DISPATCH_METHOD, VT_VARIANT, (void *) &vResult, NULL);
        VariantClear(&vResult);
 
        // Get Outbox
        VARIANT vOutbox = session.GetOutbox();
        Folder Outbox(vOutbox.pdispVal);
        ASSERT(Outbox.m_lpDispatch);

        // Get Messages collection
        VARIANT vMessages = Outbox.GetMessages();
        Messages messages(vMessages.pdispVal);
        ASSERT(messages.m_lpDispatch);
 
        // Add empty message. Use InvokeHelper for simplicity
        VARIANT vMessage;
        VariantInit(&vMessage);
        messages.InvokeHelper(0x64, DISPATCH_METHOD, VT_VARIANT, (void *) &vMessage, NULL);
        Message message(vMessage.pdispVal);
 
        // Initialize subject
        CString strSubject = "My subject";
        VARIANT vSubject;
        VariantInit(&vSubject);
        V_VT(&vSubject) = VT_BSTR;
        V_BSTR(&vSubject) = strSubject.AllocSysString();
        message.SetSubject(vSubject);
        VariantClear(&vSubject);
 
        // Initialize body
        CString strBody = "My message";
        VARIANT vBody;
        VariantInit(&vBody);
        V_VT(&vBody) = VT_BSTR;
        V_BSTR(&vBody) = strBody.AllocSysString();
        message.SetText(vBody);
        VariantClear(&vBody);
 
        // Save properties
        VariantInit(&vResult);
        message.InvokeHelper(0x84, DISPATCH_METHOD, VT_VARIANT, (void *) &vResult, NULL);
        VariantClear(&vResult);

        // Get Recipients
        VARIANT vRecipients;
        VariantInit(&vRecipients);
        vRecipients = message.GetRecipients();
        Recipients recipients(vRecipients.pdispVal);
        ASSERT(recipients.m_lpDispatch);

        // Add myself to the collection
        CString strMe = "Nik Okuntseff"; // You'll need to change this
        VARIANT vMe;
        VariantInit(&vMe);
        V_VT(&vMe) = VT_BSTR;
        V_BSTR(&vMe) = strMe.AllocSysString();
        VARIANT vType;
        VariantInit(&vType);
        V_VT(&vType) = VT_I2;
        V_I2(&vType) = 1;
        recipients.AddMultiple(vMe, vType);
        VariantClear(&vMe);
        VariantClear(&vType);

        // Resolve name to entry ID
        VARIANT vBool;
        VariantInit(&vBool);
        V_VT(&vBool) = VT_BOOL;
        V_BOOL(&vBool) = true;
        recipients.Resolve(vBool);
        VariantClear(&vBool);

        // Save properties
        VariantInit(&vResult);
        message.InvokeHelper(0x84, DISPATCH_METHOD, VT_VARIANT, (void *) &vResult, NULL);
        VariantClear(&vResult);

        // Send the message
        VariantInit(&vResult);
        message.InvokeHelper(0x83, DISPATCH_METHOD, VT_VARIANT, (void *) &vResult, NULL);
        VariantClear(&vResult);
 
        // Cleanup
        recipients.ReleaseDispatch();
        message.ReleaseDispatch();
        messages.ReleaseDispatch();
        Outbox.ReleaseDispatch();
 
        // Display success
        ::MessageBox(NULL, "Successfully sent test message", "Success",
            MB_OK | MB_ICONINFORMATION);
        session.Logoff();
    }
    catch (...)
    {
        ::MessageBox(NULL, "Exception raised...", "Error", MB_OK | MB_ICONINFORMATION);
    }
}

The initial part of this code creates a session objects and calls its Logon method (InvokeHelper(0x77...). Then I use the session object to obtain access to Outbox and to Messages collection in it. I create an empty message, initialize its subject and body and then save its properties. Next step is to properly address it. This is done via creating a recipients collection with one name and then resolving it to entry ID (Recipients::Resolve method). Finally I save the message properties and submit it.

If you have ever sent a message with MAPI you would recognize this algorithm. There is nothing unusual about it because CDO is built on top of MAPI and therefore must follow MAPI rules.

Perhaps you have noticed a number of InvokeHelper calls where I bypass ClassWizard generated functions and use shortcuts. If you plan to experiment with this code don't forget to change recipient's name.
 

[ Contents | Home ]

Send comments and suggestions to niko@wrconsulting.com
Copyright © 1997-1998 by Nik Okuntseff