none
Retrieving ALL Delivery statuses in MessageTracking - EWS RRS feed

  • Question

  • Hi!

    Using Exchange 2010 SP1 Web Service for tracking sent emails. VS 2010 C#.

    I am trying to retrieve ALL the delivery statuses for a sent email per each recipient. For now, I can only retrieve one status per recipient. (The last status message whether it is delivered or has failed). The picture below shows the two statuses I want to retrieve: Submitted and Failed.

     

     

    I even have messages with three statuses, but i am only able to retrieve the LAST status from EWS MessageTrackingCenter.

    Here is my code:

    In the mail folder "sentitems" i will fetch one mail based on a unique subject "Test 1" and show ALL statuses for this one mail.

        private string FindAllStatusesEWS()
        {
          string sURL = "https://myExchangeServer.com/EWS/Exchange.asmx";
          string sUserName= "myUser";
          string sPassword = "myPassword";
          string sDomain = "myDomain";
          string sEmailFrom = "myUser@myDomain.com";
          string sScope = "Site";
          string sSubject = "Test 1";
    
    
          string sResultat = MessageTrackingDeliveryStatusType.Unknown.ToString();
          List<MessageTrackingEntity> METCollection = new List<MessageTrackingEntity>();
          try
          {
            this._esb = new ExchangeServiceBinding();
            this._esb.Url = sURL;
            this._esb.Credentials = new NetworkCredential(sUserName, sPassword, sDomain);
            this._esb.RequestServerVersionValue = new RequestServerVersion();
            this._esb.RequestServerVersionValue.Version = ExchangeVersionType.Exchange2010_SP1;
    
            Type enumType = typeof(DistinguishedFolderIdNameType);
            string selection = (string)cbFolder.Text;
            DistinguishedFolderIdNameType value = DistinguishedFolderIdNameType.sentitems ;
    
            this._fc = new FolderCache("", this._esb, value);
    
            // FindItem Request Properties
            FindItemType fit = new FindItemType();
            fit.ParentFolderIds = this._fc.EWSSourceFolderId;
            fit.Traversal = ItemQueryTraversalType.Shallow;
    
            // Set Request Shape
            ItemResponseShapeType oShape = new ItemResponseShapeType();
            oShape.BaseShape = DefaultShapeNamesType.AllProperties;
            fit.ItemShape = oShape;
    
            // Create a restriction
            RestrictionType rt = new RestrictionType();
            ContainsExpressionType cet = new ContainsExpressionType();
    
            // Specify how the search expressoin is compared
            cet.ContainmentComparison = ContainmentComparisonType.IgnoreCase;
            cet.ContainmentComparisonSpecified = true;
            cet.ContainmentMode = ContainmentModeType.Substring;
            cet.ContainmentModeSpecified = true;
    
            // Identify the field to identify the item field to examine
            PathToUnindexedFieldType ptuft = new PathToUnindexedFieldType();
            ptuft.FieldURI = UnindexedFieldURIType.itemSubject;
    
            // Add the field to compare to the search expression
            cet.Item = ptuft;
    
            // Identify the value to compare to the examined field (ItemClass)
            ConstantValueType cvt = new ConstantValueType();
            cvt.Value = sSubject;
    
            // Add the value to the search expression
            cet.Constant = cvt;
    
            // Add the search expression to the restriction
            rt.Item = cet;
    
            // Add the restriction to the request
            fit.Restriction = rt;
    
            // Find Items
            FindItemResponseType firt = this._esb.FindItem(fit);
            FindItemResponseMessageType firmt = (FindItemResponseMessageType)firt.ResponseMessages.Items[0];
            ArrayOfRealItemsType aItem = new ArrayOfRealItemsType();
    
            aItem = (ArrayOfRealItemsType)firmt.RootFolder.Item;
    
    
            if (aItem.Items != null)
            {
              if (aItem.Items.Length < 2)
              {
                if (aItem.Items.Length > 0)
                {
                  foreach (ItemType aorit in aItem.Items)
                  {
                    MessageType mt = (MessageType)aorit;
    
                    // Build Message ID Search
                    FindMessageTrackingReportRequestType fmtRequest = new FindMessageTrackingReportRequestType();
                    fmtRequest.Domain = sDomain;
                    fmtRequest.Scope = sScope;
                    fmtRequest.MessageId = mt.InternetMessageId;
                    fmtRequest.Sender = new EmailAddressType();
                    fmtRequest.Sender.EmailAddress = sEmailFrom;
    
                    // Search
                    FindMessageTrackingReportResponseMessageType fmtResponse = this._esb.FindMessageTrackingReport(fmtRequest);
    
                    if (fmtResponse.MessageTrackingSearchResults != null)
                    {
                      GetMessageTrackingReportRequestType gmt = new GetMessageTrackingReportRequestType();
                      gmt.Scope = sScope;
    
                      foreach (FindMessageTrackingSearchResultType mtsResult in fmtResponse.MessageTrackingSearchResults)
                      {
                        gmt.MessageTrackingReportId = mtsResult.MessageTrackingReportId;
                        GetMessageTrackingReportResponseMessageType gmtResponse = this._esb.GetMessageTrackingReport(gmt);
    
                        foreach (RecipientTrackingEventType rte in gmtResponse.MessageTrackingReport.RecipientTrackingEvents)
                        {
                          MessageBox.Show("Mail to: " + rte.Recipient.EmailAddress + ", Status: " + rte.DeliveryStatus);
                        }                    
                      }
                    }
                  }
                }
              }
              else
              {
                lb.Items.Add(String.Format("Subject: {0}: Error: More than one mail found.", sSubject));
              }
            }
            else
            {
              lb.Items.Add(String.Format("Subject: {0}: Error: No mail found.", sSubject));
            }
          }
          catch (Exception ex)
          {
            throw new Exception("Error. ", ex);
          }
          return sResultat;
        }
    
    

    Could anyone please point me in the right direction?

     

    Best Regards

    Gunnarvoy

    Friday, May 20, 2011 2:22 PM

Answers

  • Thanks for trying to help, JoSwa, but I was perhaps a bit unclear.

    By "retrieving all delivery statuses" I meant all the events that was related to a sent mail (statuses like Pending and Transferred) per recipient - just like the report in "Open Delivery Report" menu item when right clicking on a mail in the sentitems folder in the outlook web client.

    I found a solution, and for the sake of completeness I post it here:

    From the code below, replace

             foreach (FindMessageTrackingSearchResultType mtsResult in fmtResponse.MessageTrackingSearchResults)
             {
              gmt.MessageTrackingReportId = mtsResult.MessageTrackingReportId;
              GetMessageTrackingReportResponseMessageType gmtResponse = this._esb.GetMessageTrackingReport(gmt);
    
              foreach (RecipientTrackingEventType rte in gmtResponse.MessageTrackingReport.RecipientTrackingEvents)
              {
               MessageBox.Show("Mail to: " + rte.Recipient.EmailAddress + ", Status: " + rte.DeliveryStatus);
              }          
    

     

    with

     

                      foreach (FindMessageTrackingSearchResultType mtsResult in fmtResponse.MessageTrackingSearchResults)
                      {
                        gmt.MessageTrackingReportId = mtsResult.MessageTrackingReportId;
                        gmt.ReportTemplate = MessageTrackingReportTemplateType.RecipientPath;
                        
                        foreach (EmailAddressType mtsrRecipients in mtsResult.Recipients)
                        {
                          gmt.RecipientFilter = mtsrRecipients;
                          
                          GetMessageTrackingReportResponseMessageType gmtResponse = this._esb.GetMessageTrackingReport(gmt);
                          METCollection.AddRange(MessageTrackingEntityPopulate(gmtResponse));
                        }
                      }
    

     


    where MessageTrackingEntityPopulate is as follows:

     

        /// <summary>
        /// Populate a list of MessageTrackingEntity. Contains delivery status and EventDescription per recipient.
        /// </summary>
        /// <param name="gmtResponse">GetMessageTrackingReportResponseMessageType</param>
        /// <returns>List<MessageTrackingEntity></returns>
        private List<MessageTrackingEntity> MessageTrackingEntityPopulate(GetMessageTrackingReportResponseMessageType gmtResponse)
        {
          List<MessageTrackingEntity> MTEList = new List<MessageTrackingEntity>();
    
          MessageTrackingReportType mtr = gmtResponse.MessageTrackingReport;
    
          //DeliveryStatus
          foreach (RecipientTrackingEventType rte in mtr.RecipientTrackingEvents)
          {    
            MessageTrackingEntity MTE = new MessageTrackingEntity();
    
            //Dont care to track the NOTREAD or READ statuses
            if (rte.EventDescription.ToUpper() == "NOTREAD" || rte.EventDescription.ToUpper() == "READ")
              continue;
    
            //EventDescription
            MTE.EventDescription = rte.EventDescription;
    
            //Submit time
            MTE.SubmitTime = mtr.SubmitTime;
    
            //Tracking date
            MTE.TrackingDate = rte.Date;
    
            //Subject
            MTE.Subject = mtr.Subject;
    
            //DeliveryStatus
            MTE.DeliveryStatus = rte.DeliveryStatus;
    
            //RecipientEmailAddress
            MTE.RecipientsEmailAddress = rte.Recipient.EmailAddress;
    
            //Name
            MTE.Name = rte.Recipient.Name;
            
            //EventData
            if (rte.EventData != null)
            {
              StringBuilder sbEventData = new StringBuilder();
    
              //Append EventData
              foreach (string ed in rte.EventData)
                sbEventData.Append(ed + ", ");
    
              //Remove trailing ', '
              if (sbEventData.Length > 0)
                sbEventData.Remove(sbEventData.Length - 2, 2);
    
            }
            MTEList.Add(MTE);
          }
    
          return MTEList;
        }


    The clue was to assign MessageTrackingReportTemplateType.RecipientPath to gmt.ReportTemplate, and for each recipients in mtsResult.Recipients apply the recipient email address as a filter to gmt.RecipientFilter.

     

    Best Regards

    Gunnarvoy

     

     

     

    • Marked as answer by Gunnarvoy Friday, July 1, 2011 9:47 AM
    Friday, July 1, 2011 9:36 AM

All replies

  • Helo Gunnarvoy..

    In Exchange server 2010 have 25 field and there one field "EventID" only have the Delivery status  value.


    EventID   This search filter uses the event-id field. The value must exactly match one of the possible EventID values. EventID is the event classification that is assigned to each message tracking log entry. The available values are BADMAIL, DEFER, DELIVER, DSN, EXPAND, FAIL, POISONMESSAGE, RECEIVE, REDIRECT, RESOLVE, SEND, SUBMIT, and TRANSFER.

    By
    A PathFinder
    JoSwa..

    Monday, May 23, 2011 5:48 PM
  • Thanks for trying to help, JoSwa, but I was perhaps a bit unclear.

    By "retrieving all delivery statuses" I meant all the events that was related to a sent mail (statuses like Pending and Transferred) per recipient - just like the report in "Open Delivery Report" menu item when right clicking on a mail in the sentitems folder in the outlook web client.

    I found a solution, and for the sake of completeness I post it here:

    From the code below, replace

             foreach (FindMessageTrackingSearchResultType mtsResult in fmtResponse.MessageTrackingSearchResults)
             {
              gmt.MessageTrackingReportId = mtsResult.MessageTrackingReportId;
              GetMessageTrackingReportResponseMessageType gmtResponse = this._esb.GetMessageTrackingReport(gmt);
    
              foreach (RecipientTrackingEventType rte in gmtResponse.MessageTrackingReport.RecipientTrackingEvents)
              {
               MessageBox.Show("Mail to: " + rte.Recipient.EmailAddress + ", Status: " + rte.DeliveryStatus);
              }          
    

     

    with

     

                      foreach (FindMessageTrackingSearchResultType mtsResult in fmtResponse.MessageTrackingSearchResults)
                      {
                        gmt.MessageTrackingReportId = mtsResult.MessageTrackingReportId;
                        gmt.ReportTemplate = MessageTrackingReportTemplateType.RecipientPath;
                        
                        foreach (EmailAddressType mtsrRecipients in mtsResult.Recipients)
                        {
                          gmt.RecipientFilter = mtsrRecipients;
                          
                          GetMessageTrackingReportResponseMessageType gmtResponse = this._esb.GetMessageTrackingReport(gmt);
                          METCollection.AddRange(MessageTrackingEntityPopulate(gmtResponse));
                        }
                      }
    

     


    where MessageTrackingEntityPopulate is as follows:

     

        /// <summary>
        /// Populate a list of MessageTrackingEntity. Contains delivery status and EventDescription per recipient.
        /// </summary>
        /// <param name="gmtResponse">GetMessageTrackingReportResponseMessageType</param>
        /// <returns>List<MessageTrackingEntity></returns>
        private List<MessageTrackingEntity> MessageTrackingEntityPopulate(GetMessageTrackingReportResponseMessageType gmtResponse)
        {
          List<MessageTrackingEntity> MTEList = new List<MessageTrackingEntity>();
    
          MessageTrackingReportType mtr = gmtResponse.MessageTrackingReport;
    
          //DeliveryStatus
          foreach (RecipientTrackingEventType rte in mtr.RecipientTrackingEvents)
          {    
            MessageTrackingEntity MTE = new MessageTrackingEntity();
    
            //Dont care to track the NOTREAD or READ statuses
            if (rte.EventDescription.ToUpper() == "NOTREAD" || rte.EventDescription.ToUpper() == "READ")
              continue;
    
            //EventDescription
            MTE.EventDescription = rte.EventDescription;
    
            //Submit time
            MTE.SubmitTime = mtr.SubmitTime;
    
            //Tracking date
            MTE.TrackingDate = rte.Date;
    
            //Subject
            MTE.Subject = mtr.Subject;
    
            //DeliveryStatus
            MTE.DeliveryStatus = rte.DeliveryStatus;
    
            //RecipientEmailAddress
            MTE.RecipientsEmailAddress = rte.Recipient.EmailAddress;
    
            //Name
            MTE.Name = rte.Recipient.Name;
            
            //EventData
            if (rte.EventData != null)
            {
              StringBuilder sbEventData = new StringBuilder();
    
              //Append EventData
              foreach (string ed in rte.EventData)
                sbEventData.Append(ed + ", ");
    
              //Remove trailing ', '
              if (sbEventData.Length > 0)
                sbEventData.Remove(sbEventData.Length - 2, 2);
    
            }
            MTEList.Add(MTE);
          }
    
          return MTEList;
        }


    The clue was to assign MessageTrackingReportTemplateType.RecipientPath to gmt.ReportTemplate, and for each recipients in mtsResult.Recipients apply the recipient email address as a filter to gmt.RecipientFilter.

     

    Best Regards

    Gunnarvoy

     

     

     

    • Marked as answer by Gunnarvoy Friday, July 1, 2011 9:47 AM
    Friday, July 1, 2011 9:36 AM