You can set Microsoft Outlook to process read and delivery receipts on arrival (by selecting the option from Tools, Options, E-mail Options, Tracking Options), but Outlook might not do the processing until your system has been idle for a while. If you're in a hurry, you can open the receipts to cause the responses to appear immediately on the Tracking tab of the original item in the Sent Items folder.
Another way to process receipts is to use Outlook code to simulate what you'd typically do—open a receipt and then close it. You can also apply this method to processing responses to messages that you sent with voting buttons.
How can you distinguish between receipts, responses, email messages, and other items in the Inbox? Each Outlook item has two properties that give you information about the item's type: Class and MessageClass. You can also use the TypeName() function to obtain the object type. The code fragment that Listing 1 shows loops through all the items in the Inbox and displays information about each item in the VBA Immediate window.
Different types of responses can share the same Class and object type but use a different MessageClass. For example, a read receipt and a delivery receipt both have the Class olReport (with constant value 46), and TypeName() returns the type ReportItem for both, but the MessageClass for a read receipt is Report.IPM.Note.IPNRN, and the MessageClass for a delivery receipt is REPORT.IPM.Note.NDR. For an email message, you can check the VotingResponse property to determine whether the item is a response to a voting-button message.
The ProcessResponses() subroutine in Listing 2, page 128, loops through all the items in the Inbox and processes each receipt and response. The DoProcess() subroutine opens each item, sets a value in the BillingInformation property, then closes and saves the item.
The code sets the value of BillingInformation to "Discard" so that the ProcessResponses() subroutine can delete any responses that remain in the Inbox after processing. (The system might already have deleted some of the responses if the user set Outlook to delete receipts after processing.) You can't delete items inside the For Each objItem In colInbox ... Next loop because deleting items within a For Each loop affects the indexes assigned to the items, with the result that the code deletes only every other item. Remembering to not delete items in a For Each loop is important when you're working with collections in Outlook.
Using the Restrict method to filter all the items with BillingInformation set to "Discard" is so easy that you might wonder why I didn't use Restrict to get the items with the specific message classes that I wanted to process. The main reason is that I wanted you to see how to use the Class property to distinguish between item types. The other reason is that the necessary filter isn't as simple as the one I used to obtain the items to discard.
Take a look at Listing 3, page 128, the ProcessResponses2() subroutine. The strWhere = statement uses four separate clauses—each with a property name, operator, and value—to filter for delivery receipts, read receipts, and messages with voting responses. The final two clauses (which callout A in Listing 3 shows) are enclosed in parentheses and connected with an AND operator. This expression will filter for only those messages that also have a voting response. The \[MessageClass\] clause uses the >= operator to test for all types of messages—even those with custom forms—because the MessageClass for an email message always starts with IPM.NOTE. For example, a custom form might have a MessageClass property of IPM.NOTE.MYFORM. (Restrict doesn't support an SQL-style LIKE operator.) Listing 3 produces this rather long strWhere clause for use with the Restrict method:
\[MessageClass\] = "REPORT.IPM.NOTE.DR" OR \[MessageClass\] = "REPORT.IPM.NOTE.IPNRN" OR (\[MessageClass\] >= "IPM.NOTE" AND \[VotingResponse\] <> "")
As you can see in Listing 3, I've left in a Debug.Print strWhere statement and commented it out. Don't even think about building complex Restrict filters like the one in Listing 3 unless you use Debug.Print to show the result in the Immediate window so that you can check the syntax.
You can use the TypeName() function and examine the Class and MessageClass properties to learn more about receipts and responses. You've also seen how to remove a group of items and use the Restrict method to return a collection of items that meet specific criteria. Next time you send out a voting-button message, try using one of these routines to process the responses in one batch.