Sending Messages by Using a Transport Provider

Sending Messages by Using a Transport Provider

Before you can send messages by using a transport provider, you must initialize the transport provider to establish a connection between MAPI and the transport provider. You must also set up the transport provider so that MAPI knows what types of addresses the transport provider accepts. For more information, see Initializing a Transport Provider and Setting Up a Transport Provider.

Once the transport provider is ready to transmit messages, you must implement the IXPLogon::SubmitMessage function to send messages. This function notifies MAPI when messages are waiting to be sent, verifies the recipient addresses, and sends the message to the recipient's file share.

In this topic, the IXPLogon::SubmitMessage function is demonstrated by using a code example from the MRXP Sample Transport Provider. The MRXP Sample Transport Provider implements a shared network file system transport provider using a UNC share or a local folder. For more information about downloading and installing the MRXP Sample Transport Provider, see Installing the Sample Transport Provider.

While you are sending messages by using the transport provider, you can also receive messages by using the transport provider. For more information, see Receiving Messages by Using a Transport Provider.

If you stop using the transport provider, you must follow the proper procedures for shutting down and logging off the transport provider. For more information, see Shutting Down a Transport Provider.

Submit Message Routine

MAPI calls the IXPLogon::SubmitMessage function to indicate that is has a message for the transport provider to deliver. The function calls GetRecipientsToProcess to validate that all the recipients are in the MRXP format. The message is sent by calling the SaveToMSG method that saves the message to the recipient's file share.

CXPLogon::SubmitMessage() Example

  STDMETHODIMP CXPLogon::SubmitMessage(
    ULONG /*ulFlags*/,
    LPMESSAGE lpMessage,
    ULONG FAR * lpulMsgRef,
    ULONG FAR * lpulReturnParm)
{
    Log(true, _T("CXPLogon::SubmitMessage function called\n"));
if (!lpMessage || !lpulMsgRef || !lpulReturnParm)
    return MAPI_E_INVALID_PARAMETER;
if (m_ulStatusBits & STATUS_OUTBOUND_ACTIVE)
{
    Log(true, _T("CXPLogon::SubmitMessage: called while already processing."
        + " Returning MAPI_E_BUSY\n"));
    return MAPI_E_BUSY;
}
HRESULT hRes = S_OK;

AddStatusBits(STATUS_OUTBOUND_ACTIVE);
hRes = UpdateStatusRow();
if (FAILED(hRes))
{
    Log(true, _T("CXPLogon::SubmitMessage: UpdateStatusRow returned an error: "
        + "0x%08X\n"), hRes);
    RemoveStatusBits(STATUS_OUTBOUND_ACTIVE);
    return hRes;
}
LPADRLIST lpMyRecips = NULL;
hRes = GetRecipientsToProcess(lpMessage, &lpMyRecips);

if (SUCCEEDED(hRes) && lpMyRecips)
{
    // Stamp Sender Props
    hRes = StampSender(lpMessage);
    if (FAILED(hRes))
    {
        Log(true, _T("CXPLogon::SubmitMessage: StampSender returned an error: "
            + "0x%08X\n"), hRes);
    }
    // Get current system time to make the file name unique to prevent conflicts
    SYSTEMTIME CurrentTime = {0};
    GetSystemTime(&CurrentTime);
    LPTSTR pszFileName = NULL;
    TCHAR szFileName[MAX_PATH] = {0};

    hRes = StringCchPrintf(szFileName, CCH(szFileName), 
        _T("%02d%02d%4d%02d%02d%02d%03d%s"),
        CurrentTime.wMonth, CurrentTime.wDay, CurrentTime.wYear, 
        CurrentTime.wHour, CurrentTime.wMinute, CurrentTime.wSecond, 
        CurrentTime.wMilliseconds, MSG_EXT);
    if (SUCCEEDED(hRes))
    {
        pszFileName = szFileName;
    }
    else
    {
        pszFileName = DEFAULT_FILENAME;
    }

    for (ULONG i = 0; i < lpMyRecips->cEntries; i++)
    {
        	// Do the submit
        if (lpMyRecips->aEntries[i].rgPropVals[RECIP_EMAIL_ADDRESS].ulPropTag 
            == PR_EMAIL_ADDRESS)
        {
            LPTSTR pszSaveToDir = NULL;
            pszSaveToDir = lpMyRecips->
                aEntries[i].rgPropVals[RECIP_EMAIL_ADDRESS].Value.LPSZ;
            TCHAR szFullFilePath[MAX_PATH] = {0};
            hRes = StringCchPrintf(szFullFilePath, CCH(szFullFilePath), _T("%s\\%s"), 
                pszSaveToDir, pszFileName);

            if (SUCCEEDED(hRes))
            {
                Log(true, _T("CXPLogon::SubmitMessage: Delivering message to %s\n"), 
                    szFullFilePath);
                hRes = SaveToMSG(lpMessage, szFullFilePath);
                if (FAILED(hRes))
                {
                    Log(true, _T("CXPLogon::SubmitMessage: SaveToMSG returned an "
                        + "error: 0x%08X\n"), hRes);
                    // Do non-delivery report (NDR)
                    hRes = SetNDRText(lpMyRecips->aEntries[i], hRes, 
                        (LPVOID)lpMyRecips);
                    if (FAILED(hRes))
                    {
                        Log(true, _T("CXPLogon::SubmitMessage: SetNDRText returned an "
                            + "error: 0x%08X\n"), hRes);
                    }
                    hRes = S_OK;
                }
            }	
            else
            {
                // NDR
                Log(true, _T("CXPLogon::SubmitMessage: StringCchPrintf returned an "
                    + "error: 0x%08X\n"), hRes);
            }
        }
        else
        {
            // Error getting the e-mail address -  NDR
            Log(true, _T("CXPLogon::SubmitMessage: PR_EMAIL_ADDRESS on a "
                + "recipient was bad\n"));
        }
        // Signal that this message was handled
        lpMyRecips->aEntries[i].rgPropVals[RECIP_RESPONSBILITY].Value.b = TRUE;
    }
    LPADRLIST lpBadRecips = NULL;
    hRes = GenerateBadRecipList(lpMyRecips, &lpBadRecips);
    if (SUCCEEDED(hRes) && lpBadRecips)
    {
        hRes = m_pMAPISup->StatusRecips(lpMessage, lpBadRecips);
        if (FAILED(hRes))
        {
            Log(true, _T("CXPLogon::SubmitMessage: StatusRecips returned an error: "
                + "0x%08X\n"), hRes);
        }
    }
    else if (FAILED(hRes))
    {
        Log(true, _T("CXPLogon::SubmitMessage: GenerateBadRecipList returned an "
            + "error: 0x%08X\n"), hRes);
    }
    FreePadrlist(lpBadRecips);
    hRes = lpMessage->ModifyRecipients(MODRECIP_MODIFY, lpMyRecips);
    if (SUCCEEDED(hRes))
    {
        hRes = lpMessage->SaveChanges(0);
        if (FAILED(hRes))
            Log(true, _T("CXPLogon::SubmitMessage: SaveChanges returned an error: "
                + "0x%08X\n"), hRes);
    }
    else
    {
        Log(true, _T("CXPLogon::SubmitMessage: ModifyRecipients returned an error: "
            + "0x%08X\n"), hRes);
    }
}
else
{
    Log(true, _T("CXPLogon::SubmitMessage: GetRecipientsToProcess returned an "
        + "error: 0x%08X\n"), hRes);
}
FreePadrlist(lpMyRecips);
RemoveStatusBits(STATUS_OUTBOUND_ACTIVE);
HRESULT hResTemp = S_OK;
hResTemp = UpdateStatusRow();
if (FAILED(hResTemp))
{
    Log(true, _T("CXPLogon::SubmitMessage: UpdateStatusRow returned an error: "
        + "0x%08X\n"), hResTemp);
}
if (FAILED(hRes))
{
    m_pMAPISup->SpoolerNotify(NOTIFY_CRITICAL_ERROR, NULL);
}
return hRes;

}

See Also

About the Sample Transport Provider

Installing the Sample Transport Provider

Initializing a Transport Provider

Setting Up a Transport Provider

Receiving Messages by Using a Transport Provider

Shutting Down a Transport Provider