4

I am using the Exchange Web Services Managed API 2.2 to monitor users inboxes and need to determine if an e-mail is a new item, a reply or a forwarded message.

I have seen various articles on SO such as how to notice if a mail is a forwarded mail? and Is there a way to determine if a email is a reply/response using ews c#? which both help in their specific cases but I still cannot work out how to distinguish between a reply and a forwarded item.

In the first article an extra 5 bytes is added each time (forward or reply) so I don't know what the last action was.

The second article suggests using the InReplyTo however when I examine the property for forwarded e-mails it contains the original senders e-mail address (not null).

I have seen other articles such as this or this that suggest using extended properties to examine the values in PR_ICON_INDEX, PR_LAST_VERB_EXECUTED and PR_LAST_VERB_EXECUTION_TIME.

My code looks as follows but never returns a value for lastVerbExecuted

var lastVerbExecutedProperty = new ExtendedPropertyDefinition(4225, MapiPropertyType.Integer);

var response = service.BindToItems(newMails, new PropertySet(BasePropertySet.IdOnly,  lastVerbExecutedProperty));
var items = response.Select(itemResponse => itemResponse.Item);

foreach (var item in items)
{
    object lastVerb;

    if (item.TryGetProperty(lastVerbExecutedProperty, out lastVerb))
    {
        // do something
    }
}
Community
  • 1
  • 1
Newm
  • 1,313
  • 3
  • 16
  • 29

3 Answers3

1

PR_ICON_INDEX, PR_LAST_VERB_EXECUTED and PR_LAST_VERB_EXECUTION_TIME would only work to tell you if the recipient has acted on a message in their Inbox. Eg if the user had replied or forwarded a message in their inbox then these properties get set on the message in their Inbox. On the message that was responded to or forwarded these properties would not be set. I would suggest you use the In-Reply-To Transport header which should be set on any message that is replied to or forwarded, this should contain the internet messageid of the message that was replied to or forwarded eg.

        FindItemsResults<Item> fiRs = service.FindItems(WellKnownFolderName.Inbox, new ItemView(10));
        PropertySet fiRsPropSet = new PropertySet(BasePropertySet.FirstClassProperties);
        ExtendedPropertyDefinition PR_TRANSPORT_MESSAGE_HEADERS = new ExtendedPropertyDefinition(0x007D, MapiPropertyType.String);
        fiRsPropSet.Add(PR_TRANSPORT_MESSAGE_HEADERS);
        service.LoadPropertiesForItems(fiRs.Items, fiRsPropSet);
        foreach (Item itItem in fiRs)
        {
            Object TransportHeaderValue = null;
            if(itItem.TryGetProperty(PR_TRANSPORT_MESSAGE_HEADERS,out TransportHeaderValue)) {
                string[] stringSeparators = new string[] { "\r\n" };
                String[] taArray = TransportHeaderValue.ToString().Split(stringSeparators, StringSplitOptions.None);
                for (Int32 txCount = 0; txCount < taArray.Length; txCount++)
                {
                    if (taArray[txCount].Length > 12)
                    {
                        if (taArray[txCount].Substring(0, 12).ToLower() == "in-reply-to:")
                        {
                            String OriginalId = taArray[txCount].Substring(13);
                            Console.WriteLine(OriginalId);
                        }
                    }
                }

            }
        }

Apart from the Subject prefix that was discussed in the other link I don't know of any other proprieties that will differentiate between a reply or forward.

Cheers Glen

Glen Scales
  • 20,495
  • 1
  • 20
  • 23
  • Thanks, I didn't realise the properties were only set if the user interacted with the item – Newm Sep 23 '15 at 08:17
  • Thanks for detailed answer. Is it also possible to find out to whom an email was forwarded or replied to ? – bala Feb 11 '19 at 13:43
  • You would need to either check the SendItems for the Message that was forward or replied to or check the Message Tracking logs on the server – Glen Scales Feb 12 '19 at 23:19
0

The best way to rely is on the ResponeCode of Extended properties

Refer below scripts

private static int IsForwardOrReplyMail(ExchangeService service, EmailMessage messageToCheck)
    {
        try
        {
            // Create extended property definitions for PidTagLastVerbExecuted and PidTagLastVerbExecutionTime.
            ExtendedPropertyDefinition PidTagLastVerbExecuted = new ExtendedPropertyDefinition(0x1081, MapiPropertyType.Integer);
            ExtendedPropertyDefinition PidTagLastVerbExecutionTime = new ExtendedPropertyDefinition(0x1082, MapiPropertyType.SystemTime);

            PropertySet propSet = new PropertySet(BasePropertySet.IdOnly, EmailMessageSchema.Subject, PidTagLastVerbExecutionTime, PidTagLastVerbExecuted);
            messageToCheck = EmailMessage.Bind(service, messageToCheck.Id, propSet);

            // Determine the last verb executed on the message and display output.
            object responseType;
            messageToCheck.TryGetProperty(PidTagLastVerbExecuted, out responseType);

            if (responseType != null && ((Int32)responseType) == 104)
            {
                //FORWARD
                return 104;
            }
            else if (responseType != null && ((Int32)responseType) == 102)
            {
                //REPLY
                return 102;
            }


        }
        catch (Exception)
        {
            return 0;

            //throw new NotImplementedException();
        }

    }
user1093452
  • 121
  • 2
  • 3
  • 19
0

To determine if it was a reply to a email, you can use the EmailMessage objects InReplyTo property, e.g:

EmailMessage mail = ((EmailMessage)Item.Bind(service, new ItemId(UniqueId)));

if (mail.InReplyTo == null)
    return;
else
    ..your code
hd84335
  • 8,815
  • 5
  • 34
  • 45
Anish Kutti
  • 337
  • 2
  • 7