Platform SDK: MAPI

Receiving a Message: Simple MAPI Sample

The following example shows how you can receive a message with Simple MAPI. For simplicity, this example assumes that a character interface is being used.

First, the client application defines needed variables and logs on to get a session handle. Unlike when sending a message, the Simple MAPI functions for reading messages can't log on implicitly and require an explicit session handle.

ULONG ReadNextUnreadMsg()
{
ULONG err;
LHANDLE lhSession;      // Need a session for MAPIFindNext.
CHAR rgchMsgID[513];    // Message IDs should be >= 512 CHARs + a null.
MapiMessage *lpMessage; // Used to get a message back from MAPIReadMail.
int i,                  // Ubiquitous loop counter.
    totalLength;        // Number of characters printed on a line.
err = MAPILogon(0L,               // ulUIParam; 0 always valid.
               "c:\\pst\\myprofil.pro",// Shouldn't hardcode this.
               NULL,              // No password needed.
               0L,                // Use shared session.
               0L,                // Reserved; must be 0.
               &lhSession);       // Session handle.
if (err != SUCCESS_SUCCESS)       // Make sure MAPILogon succeeded.
{
    printf("Error: could not log on\r\n");
    return(err);
}
 

Next, the client searches for the first unread message in the default folder in the store — probably the user's Inbox. Since there might not be any unread messages in the folder, the client first tests the return value from the MAPIFindNext function against MAPI_E_NO_MESSAGES before checking against SUCCESS_SUCCESS. If the call is successful, the client will have a valid message identifier to use to retrieve the first unread message.

// find the first unread message
err = MAPIFindNext(lhSession, // explicit session required
                   0L,        // always valid ulUIParam
                   NULL,      // NULL specifies interpersonal messages
                   NULL,      // seed message ID; NULL=get first message
                   MAPI_LONG_MSGID | // needed for 512 byte rgchMsgID.
                   MAPI_UNREAD_ONLY, // only get unread messages.
                   0L,        // reserved; must be 0
                   rgchMsgID);// buffer to get back a message ID.

if (err == MAPI_E_NO_MESSAGES) // make sure a message was found
{
    printf("No unread messages.\r\n");
    return(err);
}
if (err != SUCCESS_SUCCESS)    // make sure MAPIFindNext didn't fail 
{
    printf("Error while searching for messages\r\n");
    return(err);
}
 

The client can now be sure it is safe to retrieve the message. However, it is still a good idea to check the return value from the MAPIReadMail function. If the call fails, the memory pointed to by the client's lpMessage pointer will not be accessible by the client. The client should not try to display a message at that location. Note that this example sets the MAPI_SUPPRESS_ATTACH flag so the returned message will not have any attachments in it and Simple MAPI will not create any temporary files for them.

// retrieve the message
err = MAPIReadMail(lhSession,   // Explicit session required.
                   0L,          // Always valid ulUIParam.
                   rgchMsgID,   // The message found by MAPIFindNext.
                   MAPI_SUPPRESS_ATTACH, // TO DO: handle attachments.
                   0L,          // Reserved; must be 0.
                   &lpMessage); // Location of the returned message.
if(err != SUCCESS_SUCCESS)      // Make sure MAPIReadMail succeeded.
{
    printf("Error retrieving message %s\r\n",rgchMsgID);
    return(err);
}
 

Now, the client can display the message. As expected, it begins by displaying the addressing information attached to the message before displaying the subject line and message text. When displaying the addressing information, it is best if you can display friendly names. However, since friendly names are not always available, you must verify that each recipient structure's lpszName member points to a valid string, and that the string is not a null string.

// Display the sender's name or address; use the friendly name
// if it is present.
if((lpMessage->lpOriginator->lpszName != NULL) &&
   lpMessage->lpOriginator->lpszName[0] != '\0')
    printf("From: %s\r\n",lpMessage->lpOriginator->lpszName);
else
    printf("From: %s\r\n",lpMessage->lpOriginator->lpszAddress);
 

Displaying the recipients' addresses is complicated by the need to avoid breaking a recipient's name or address across two lines. This code can be further improved by differentiating between recipients based on their ulRecipClass members so that they can be properly displayed as To, CC, or BCC recipients. As this code shows, handling recipient data can be the most complex part of reading a message.

// Display the recipients' names or addresses.  To Do: enhance
// this code to separate the recipients into lists of MAPI_TO, 
// MAPI_CC, and MAPI_BCC recipients for separate display.
if(lpMessage->nRecipCount == 0)
    printf("Warning: no recipients present for this message\r\n");
else
    for(i = 0; i < lpMessage->nRecipCount; i++) // For each recipient...
    {
        // This code uses lstrlen to calculate the length of strings and
        // to validate that the strings have some content, since the
        // length is needed anyway. This avoids the more verbose checks
        // as were done for lpMessage->lpOriginator->lpszName earlier.

        // lpszT references a name or address; simplifies later code.
        // length is the length of the name or address.
        LPSTR lpszT = lpMessage->lpRecips[i]->lpszName;
        int length = lstrlen(lpszT);

        if(i == 0) // First recipient; need to do some initialization.
        {
            printf("Recipients:");
            totalLength = 11;      // since strlen("Recipients:") = 11.
        }

        // Decide whether to use the friendly name or the address.
        if(length == 0)
            length = lstrlen(lpszT=lpMessage->lpRecips[i]->lpszAddress);

        // Verify that the line has room for this name or address. If
        // not, print a CR LF pair to go to the next line.
        if(totalLength + length + 1 > LINE_WIDTH)
        {
            printf("\r\n");
            totalLength = 0;
        }

        printf(" %s",lpszT);      // Finally, print the name or address.
        totalLength += length + 1;// Maintain the line length.

        // If there are more addresses, separate them with semicolons.
        if(i < (lpMessage->nRecipCount - 1))
        {
            printf(";");
            totalLength++;
        }
    }
 

Now, the client displays the subject line and message text if they are present. Note that the message text can be printed with a simple call to the C library function printf. Since the message was read with the MAPI_SUPPRESS_ATTACH flag set, there will be no attachments in it.

// Display the subject and message body. Not printing anything for the
// subject is fine, but something should always be printed for the
// message body since it is the last thing that this function displays.
if(lpMessage->lpszSubject    != NULL &&   // Standard validity check
   lpMessage->lpszSubject[0] != '\0')
    printf("Subject: %s\r\n",lpMessage->lpszSubject);
if(lpMessage->lpszNoteText    != NULL &&  // Standard validity check
   lpMessage->lpszNoteText[0] != '\0')
    printf("Message Text:\r\n%s",lpMessage->lpszNoteText;
else
    printf("No message text.\r\n");
 

Finally, the client releases the memory that the MAPIReadMail function allocated for the message, closes the session, and returns a successful return value.

MAPIFreeBuffer(lpMessage);
MAPILogoff(lhSession,    // The session.
           0L,           // 0 always valid for ulUIParam.
           0L,           // No logoff flags.
           0L);          // Reserved; must be 0.
return SUCCESS_SUCCESS;  // Inform the caller of our success.
} // End of ReadNextUnreadMsg.