Are you a world traveler? ZoneTick is a cool utility that'll help you stay in touch over multiple time zones!
 
Writing MSMQ Client for MS Exchange Connector  
Nik Okuntseff  MS Exchange Server Programming 

Writing MSMQ Client for MS Exchange Connector

I have written before that it is easier to write code for MSMQ than for MAPI. Now I am going to demonstrate it by providing a few very simple sample applications. There will be four of them in total: a client for MS Exchange connector, a server for MS Exchange connector, a client for MSMQ MAPI transport provider and a server for it. Let me start from the Exchange connector client.

I am going to create a very simple MSMQ client which should be able to send an e-mail message to a MS Exchange mailbox. Here is the implementation:

#include <windows.h>
#include "mq.h"

int main(void)
{
    /*
     * Algorithm:
     *  1. Open Exchange Connector inbound queue.
     *  2. Prepare MQMSGPROPS struct.
     *  3. Send a message to the queue.
     */

    // I assume this queue pathname. Replace this as necessary.
    #define MY_IN_QUEUE_PATHNAME L"mig\\myinbound_mqgw"
 
    // Determine format name of the incoming queue
    LPCWSTR lpwcsPathName = MY_IN_QUEUE_PATHNAME;
    wchar_t wcsQueueFormatName[MAX_PATH];
    DWORD dwSize = MAX_PATH;
    HRESULT hRes = ::MQPathNameToFormatName(lpwcsPathName,
           wcsQueueFormatName,
           &dwSize);
    if (FAILED(hRes))
        throw (-1);

    // Open it.
    QUEUEHANDLE hInQueue = NULL;
    hRes = ::MQOpenQueue(wcsQueueFormatName,
       MQ_SEND_ACCESS,
       MQ_DENY_NONE,
       &hInQueue);
 
    if (FAILED(hRes))
        throw (-1);

    // Prepare MQMSGPROPS struct.
    MQMSGPROPS MsgProps;

    // We'll send message body only. Arrays of size 1 are enough.
    MQPROPVARIANT aVariant[1];
    MSGPROPID aPropId[1];
 
    // Define simple message in MSMQ mail format
    char * pszMessage = "Mime-Version: 1.0\r\n"
      "Date: 9 Apr 1998 17:58:44 +0700\r\n"
      "From: Nik Okuntseff<NikO@myinbound>\r\n"
      "Subject: Hello, world!\r\n"
      "X-Delivery-Report-Requested: False\r\n"
      "X-Non-Delivery-Report-Requested: True\r\n"
      "Content-Transfer-Encoding: binary\r\n"
      "To: Nik Okuntseff<NikO@myinbound>\r\n"  // Change it to your Alias@InboundQueueLabel
      "\r\n"          // Empty line separates message body
      "Hello, world!\r\n";      // Message body
    DWORD dwMessageSize = strlen(pszMessage);

    // Set the PROPID_M_BODY property.
    aPropId[0] = PROPID_M_BODY;        // PropId
    aVariant[0].vt = VT_VECTOR | VT_UI1;     // Type
    aVariant[0].caub.cElems = dwMessageSize;    // Size.
    aVariant[0].caub.pElems = (unsigned char *) pszMessage; // Message itself

    // Set the MQMSGPROPS structure
    MsgProps.cProp = 1;    // Number of properties.
    MsgProps.aPropID = aPropId;  // Ids of properties.
    MsgProps.aPropVar = aVariant; // Values of properties.
    MsgProps.aStatus = NULL;  // No error report.

    hRes = ::MQSendMessage(hInQueue,
       &MsgProps,
       NULL);
    if (FAILED(hRes))
        throw (-1);

    // Close the queue
    hRes = ::MQCloseQueue(hInQueue);
    if (FAILED(hRes))
        throw (-1);

    return 0;
}

Some comments about the above program.

It relies on a certain inbound queue name: mig\myinbound_mqgw. "Mig" is the computer here and "myinbound_mqgw" is the queue that MSMQ Exchange Connector uses for incoming messages. You'll need to rename it to reflect your local data. The "L" in front of the string specifies Unicode compilation. The queue pathname is thus presented as a Unicode string.

The message (pszMessage) constructed in the program is very simple. You'll need to modify the "To:" string to make your Exchange server deliver it to your mailbox. The format is Alias@InboundQueueLabel. Notice that inbound queue label is used here instead of pathname, which we used while opening the queue.

 
Dealing with Errors:
 
Two places are particularly important when tracing errors with MSMQ Exchange Connector: its "Error" subdirectory and the Event Log. The event log message would normally tell what went wrong. For example, when conversion to MAPI fails you would see something like this:

mqgwcnvi.dll conversion DLL convert function failed:  point = MSMQMIME.INBOUND, class = ENVELOPE.IPM, error code = 80004005.

The error code 0x80004005 is E_FAIL. It means an "unspecified error", or an error in general. But in this particular case it is likely to indicate that the message was constructed badly. Either some attributes are missing, the format is wrong, or something of this kind. I had a lot of them when I used only new line ("\n") characters instead of combinations of carriage returns with new lines ("\r\n").

The "Error" subdirectory of MSMQ Exchange connector stores messages having trouble with delivery. Taking a look at them may help you also.
 

[ Contents | Home ]

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