If you are automatically process emails in an Exchange Mailbox, you might also need to process non delivery reports (NDRs) and correlate these NDRs to their original values. Luckily, Exchange does most of the heavy lifting, as long as the NDR conforms to the RFC 3461, which defines the proper structure for an NDR that can be automatically parsed. Not all MTAs (Mail transfer agents) do generate these types of NDRs.
First of all, you need to check whether the mail item in question is actually a non delivery report. This is done by examining the Item Class of the mail. An NDR has an item class of REPORT.IPM.Note.NDR. Next, you need to retrieve the property PidTagParentKey from the item. This property contains the PidTagSearchKey of the original mail.
Unfortunately, the PidTagSearchKey cannot be used to bind to the item directly. Instead, you have to issue a FindItem operation to get it. Normally, sent items are all stored in the SentItems folder, so this narrows the search down.
Here is a sample method which describes the process:
1: class Program
2: {
3: private static readonly ExtendedPropertyDefinition PidTagParentKeyProperty = new ExtendedPropertyDefinition(0x25, MapiPropertyType.Binary);
4: private static readonly ExtendedPropertyDefinition PidTagSeachKeyProperty = new ExtendedPropertyDefinition(0x300B, MapiPropertyType.Binary);
5:
6:
7: private static bool TryGetOriginalMail(string ndrId, ExchangeService service, out Item originalItem)
8: {
9: byte[] value;
10:
11: var item = service.BindToItems(new[] {new ItemId(ndrId)},
12: new PropertySet(BasePropertySet.IdOnly,
13: PidTagParentKeyProperty, ItemSchema.Subject)).First().Item;
14:
15: if (!item.TryGetProperty(PidTagParentKeyProperty, out value))
16: {
17: Console.Out.WriteLine("Correlationtoken not found.");
18: originalItem = null;
19: return false;
20: }
21:
22: originalItem = service
23: .FindItems(WellKnownFolderName.SentItems,
24: new SearchFilter.IsEqualTo(PidTagSeachKeyProperty, Convert.ToBase64String(value)),
25: new ItemView(1) {PropertySet = PropertySet.FirstClassProperties})
26: .FirstOrDefault();
27:
28: return true;
29: }
30: }