Sending an Outgoing Message Requesting a Read Receipt With MAPI


[This is now documented here: http://msdn.microsoft.com/en-us/library/cc979231.aspx ]

This is the third part of a three part series documenting the MFCMAPI sample add-in CreateOutlookItemsAddin. We’re in the process of updating the MAPI documentation and these articles are a preview of some of the new content. This article assumes you have downloaded the add-in from the above link and are running it inside the current version of MFCMAPI. Feedback on the article and on the code is especially welcome.

Part 1: Creating a Recurring Appointment With MAPI

Part 2: Creating a Recurring Task With MAPI

Sending an Outgoing Message Requesting a Read Receipt

When a read receipt is requested, the messaging system will generate a read report when the recipient has read the message.

To create and send an message requesting a read receipt

  1. Create an outgoing message. See Handling an Outgoing Message.
  2. Add the PR_READ_RECEIPT_REQUESTED property and set it to true.
  3. Add the PR_CONVERSATION_INDEX property.
  4. Add the PR_REPORT_TAG property.
  5. Submit the message by calling IMessage::SubmitMessage.

MFCMAPI demonstrates these steps with the AddMail function. AddMail takes numerous parameters from the Add Mail dialog box that is displayed when the user selects Add Mail on the Addins menu in MFCMAPI. The DisplayAddMailDialog method in Mail.cpp displays the dialog box and passes values from the dialog box to the AddMail method. The DisplayAddMailDialog method does not relate directly to creating a mail item using MAPI, so it is not listed here. The AddMail method is listed below. Note that the first parameter passed to the AddMail method is a pointer to an IMAPIFolder interface. Given lpFolder that represents an IMAPIFolder interface, the code calls IMAPIFolder::CreateMessage. The CreateMessage method returns a success code and a pointer to a pointer to an IMessage interface. Most of the AddMail function code handles the work of property setting in preparation for IMAPIProp::SetProps. If the SetProps call succeeds, IMAPIProp::SaveChanges commits the changes to the store and creates a new mail item. Then, if requested, IMessage::SubmitMessage is called to send the message.

AddMail uses two helper functions to build values for the PR_CONVERSATION_INDEX and PR_REPORT_TAG properties. These functions are named BuildConversationIndex and AddReportTag, respectively. BuildConversationIndex, located in CreateOutlookItemsAddin.cpp, does the same work that the built in MAPI function ScCreateConversationIndex when a parent isn’t passed. The format of the conversation index buffer which it generates is documented in [MS-OXOMSG].pdf, section 2.2.1.2, PidTagConversationIndex. AddReportTag, located in Mails.cpp, in turn calls BuildReportTag to build a structure for PR_REPORT_TAG. This structure is documented in [MS-OXOMSG].pdf, section 2.2.2.1.19, PidTagReportTag.

Code Snippet


HRESULT AddMail(LPMAPISESSION lpMAPISession,
                LPMAPIFOLDER lpFolder,
                LPWSTR szSubject,
                LPWSTR szBody,
                LPWSTR szRecipientName,
                BOOL bHighImportance,
                BOOL bReadReceipt,
                BOOL bSubmit,
                BOOL bDeleteAfterSubmit)
{
	if (!lpFolder) return MAPI_E_INVALID_PARAMETER;
	HRESULT hRes = S_OK;
	LPMESSAGE lpMessage = 0;
	// create a message and set its properties
	hRes = lpFolder->CreateMessage(0,
		0,
		&lpMessage);
	if (SUCCEEDED(hRes))
	{
		// Since we know in advance which props
		// we'll be setting, we can statically
		// declare most of the structures involved
		// and save expensive MAPIAllocateBuffer calls
		// For brevity, code to set most spvProps
		// has been removed. For the complete listing, see
		// AddMail in Mails.cpp

		spvProps[p_PR_MESSAGE_CLASS_W].Value.lpszW = L"IPM.Note";
		spvProps[p_PR_ICON_INDEX].Value.l = 0x103; // Unsent Mail
		spvProps[p_PR_SUBJECT_W].Value.lpszW = szSubject;
		spvProps[p_PR_CONVERSATION_TOPIC_W].Value.lpszW = szSubject;
		spvProps[p_PR_BODY_W].Value.lpszW = szBody;
		spvProps[p_PR_IMPORTANCE].Value.l = bHighImportance?IMPORTANCE_HIGH:IMPORTANCE_NORMAL;
		spvProps[p_PR_READ_RECEIPT_REQUESTED].Value.b = bReadReceipt?true:false;
		spvProps[p_PR_MESSAGE_FLAGS].Value.l = MSGFLAG_UNSENT;
		spvProps[p_PR_MSG_EDITOR_FORMAT].Value.l = EDITOR_FORMAT_PLAINTEXT;
		spvProps[p_PR_MESSAGE_LOCALE_ID].Value.l = 1033; // (en-us)
		spvProps[p_PR_INETMAIL_OVERRIDE_FORMAT].Value.l = NULL; // Mail system chooses default encoding scheme
		spvProps[p_PR_DELETE_AFTER_SUBMIT].Value.b = bDeleteAfterSubmit?true:false;
		spvProps[p_PR_INTERNET_CPID].Value.l = cpidASCII;

		hRes = BuildConversationIndex(
			&spvProps[p_PR_CONVERSATION_INDEX].Value.bin.cb,
			&spvProps[p_PR_CONVERSATION_INDEX].Value.bin.lpb);

		if (SUCCEEDED(hRes))
		{
			hRes = lpMessage->SetProps(NUM_PROPS, spvProps, NULL);
			if (SUCCEEDED(hRes))
			{
				hRes = AddRecipient(lpMAPISession,
					lpMessage,
					MAPI_TO,
					szRecipientName);
				AddInLog(true,L"CallMenu: AddRecipient - returned hRes = 0x%08X\n",hRes);
				if (SUCCEEDED(hRes))
				{
					if (bReadReceipt)
					{
						hRes = AddReportTag(lpMessage);
					}

					if (SUCCEEDED(hRes))
					{
						hRes = lpMessage->SaveChanges(KEEP_OPEN_READWRITE);
						if (SUCCEEDED(hRes) && bSubmit)
						{
							hRes = lpMessage->SubmitMessage(NULL);
						}
					}
				}
			}
		}
		if (spvProps[p_PR_CONVERSATION_INDEX].Value.bin.lpb) 
			delete[] spvProps[p_PR_CONVERSATION_INDEX].Value.bin.lpb;
	}
	if (lpMessage) lpMessage->Release();
	return hRes;
}
Comments (5)

  1. Hai says:

    With the release of the Exchange documentation, apparently there is now much less dirty guess work for us Outlook/Exchange developers 🙂 Thanks for sharing with us this great series, and I am expecting more of these in the new MAPI documentation that you mentioned will be put out soon. Please let us know when it is released.

    While I was wandering through the large amount of Exchange documents, I found out that now the Server-side Rules binary format is documented. However, the Client-side Rules is NOT documented. It is only mentioned that the binary blob is saved in the PigTagRWRulesStream property in the FAI message, but there is no information about this blob. Does Microsoft has any plan to document this (PigTagRWRulesStream), or we have to keep scratching our heads without much hope to try to decipher it?

  2. Stephen Griffin says:

    If the property is mentioned in the protocol documentation, you can ask about it in the protocol forum (linked at the beginning of each document). AFAIK, if it’s not in there we probably weren’t planning on documenting it, but it wouldn’t hurt to ask.

  3. Hai says:

    Steve, thanks for the information.

    In case it is useful for someone else who has questions for Exchange documents, this is the link I used to post the question: http://forums.msdn.microsoft.com/en-US/os_exchangeprotocols/threads/

  4. Nitin says:

    Hi Steve,

    I’d like to apologize in advance if it’s inappropriate to post about a technical problem that I’m facing on your blog. That said, it would be great if you could help me out with the following issue.

    In a nutshell, all I’m trying to do is set the PR_CONVERSATION_INDEX of an email item before it leaves my application. The problem is that I’m using Java and the Apache slide framework. I’ve been able to successfully set other properties that are of type string such as PR_CONVERSATION_TOPIC and I’ve been able to verify this using mfcmapi. The problem is that Jakarta Slide’s proppatch method signature only allows for string values to be set so any MAPI property that is not of type string (possibly) cannot be set.

    I was wondering if there is any way around this that you might know of. Also, I was wondering if the same goal could be met by using EWS. Is is possible to set item specific MAPI attributes using EWS?

    Any help on this front would be appreciated.

    Thanks,

    Nitin

  5. Stephen Griffin says:

    Nitin – I’ve never heard of this Slide thing before, but the term proppatch shows up in WebDav, so you should look for information on WebDav. I know non-string property types can be set with WebDav.

    EWS can certainly be used to set a wide variety of MAPI properties on messages.