Wednesday, 12 April 2017

Move a CRM Processed Email from Inbox to another Folder in Exchange Mailbox

One of our clients uses MS CRM 2013 Online and Exchange Online. The requirement is to convert a received Email into a case and then move that processed email to a specified folder. Though Dynamics CRM 2013 provides an out of the box solution for converting an Email to a Case, this client’s requirement warranted a custom solution.
The picture below shows the flow of events that are involved in achieving this requirement.
EmailToCase
In this article, we will discuss how to move the MS CRM processed emails from inbox to other folder of an exchange mailbox (it may be custom folder or existing folder in exchange server).
This can be achieved by following the steps given below.
We have divided the requirement to 4 parts:
1) Identify when a CRM email is converted into case
2) Communicate with the exchange web service
3) Identify the respective CRM email in exchange mailbox
4) Move the email to respective folder
Step 1
For Email to Case creation, we have coded a Plug-in that triggers when an email is created in CRM and creates a Case for the email based on few conditions (like who is the recipient of the email etc.). Also, identifying when the CRM email is converted into case will be taken care of in the same plugin. Once we identify this, we should get the message ID of this CRM email.
To get the email message ID, we need to fetch the processed email details. Below is the fetch we have used to get the email message ID.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
string strFetch = string.Format(@"<fetch version='1.0' output-format='xml-platform' mapping='logical' distinct='false'> 
                                <entity name='email'>
                                   <all-attributes/>
                                    <filter type='and'>
                                      <condition attribute='activityid' operator='eq' value='{0}' />
                                    </filter>
                                  </entity>
                                </fetch>", strEmailID);//strEmailID is the processed email record guid</pre>
<pre>EntityCollection entEmailCol = ExecuteCRMFetch(strFetch, service);
if (entEmailCol != null &amp;&amp; entEmailCol.Entities.Count &gt; 0)
{
    if (entEmailCol.Entities[0].Attributes.Contains("messageid"))
   {
     strMessageId = entEmailCol.Entities[0].Attributes["messageid"].ToString().ToLower();
   }
}
Note: The message ID will be available only after the record creation. If we register the plugin on pre-stage we cannot find the message ID.
Step 2
The second step is to establish the communication between CRM and Exchange Online. So we have created a custom web service, which references ‘Microsoft.Exchange.WebServices’ DLL and communicates with the exchange online web service.
**As this is an online CRM we have opted for the custom web service instead of moving this logic into a Plug-in.
1
2
3
4
5
6
public void ExchangeConnection()
{
   ExchangeService service = new ExchangeService(ExchangeVersion.Exchange2013);
   service.Credentials = new WebCredentials(ConfigurationManager.AppSettings["ExngUserName"], ConfigurationManager.AppSettings["ExngPassword"]);
   service.AutodiscoverUrl(ConfigurationManager.AppSettings["ExngUserName"], RedirectionUrlValidationCallback);
}
In the above code we can get the exchange credentials from the config file.
Step 3
Next step is to identify the corresponding CRM email in the Exchange mailbox. We found that there is an attribute called ‘messageId’ in CRM Email which stores the ‘InternetMessageId’ of exchange email. We have used the ‘InternetMessageId’ to identify the respective CRM email in exchange mailbox.
We can filter the emails using ‘Created on date’ option and also we can specify the number of mails to be shown in a page. Using this, we can easily get a particular email which we want to move.
1
2
3
4
5
6
7
List lstSearchFilters = new List();
lstSearchFilters.Add(new SearchFilter.IsEqualTo(EmailMessageSchema.DateTimeCreated, DateTime.Now.Date));
SearchFilter sfUnreadEmails = new SearchFilter.SearchFilterCollection(LogicalOperator.And, lstSearchFilters.ToArray());
FindItemsResults findResults = service.FindItems(WellKnownFolderName.Inbox, "", new ItemView(50));
ExtendedPropertyDefinition PR_TRANSPORT_MESSAGE_HEADERS = new ExtendedPropertyDefinition(0x007D, MapiPropertyType.String);
PropertySet psPropSet = new PropertySet(BasePropertySet.FirstClassProperties) { PR_TRANSPORT_MESSAGE_HEADERS, ItemSchema.MimeContent };
Pass the message Id (which we get from plugin) to exchange to get the exact email.
In the above step we have already got the list of emails. We need to find out the particular email.
1
2
3
4
5
6
7
8
9
10
11
12
13
Item selectedItem = null;
foreach (Item itItem in findResults.Items)
{
  if (itItem is EmailMessage)
  {
    EmailMessage msg = itItem as EmailMessage;//Here messageid is passed from plugin.
    if (msg.InternetMessageId.ToLower().ToString() == strMessageId.ToLower())
    {
      selectedItem = itItem;
      break;
    }
  }
}
Step 4
Final step is to move the identified exchange email into another folder.
We need to find out the exchange mailbox folderid to move the messages. If the folder is an existing folder we can get the folder by “WellKnownFolderName.JunkEmail”,  where ‘JunkEmail’ is the folder name.
If the folder is a custom folder, we need to find the folder id by folder name.
Below method can be used to find the custom folder id.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
private static Folder FindFolder(string strFolderName, ExchangeService service)
{
     Folder folderName = null;
     FolderView view = new FolderView(100);
     view.PropertySet = new PropertySet(BasePropertySet.IdOnly);
     view.PropertySet.Add(FolderSchema.DisplayName);
     view.Traversal = FolderTraversal.Deep;
     FindFoldersResults findFolderResults = service.FindFolders(WellKnownFolderName.Root, view);//find specific folder
     foreach (Folder f in findFolderResults)
     {
      //show folderId of the folder "test"
      if (f.DisplayName == strFolderName)
      {
        folderName = f;
        return folderName;
      }
     }
    return folderName;
}
Finally check whether the folder is null. If it is not null, move the email to the new folder. We can read the custom folder name from config file from the below code.
1
2
3
4
5
6
7
8
Folder folderName = FindFolder(ConfigurationManager.AppSettings["FolderName"], service);
if (folderName != null)
{
  if (folderName.Id != null)
  {
    selectedItem.Move(folderName.Id);
  }
}

No comments:

Post a Comment

Voice of the Customer (VOC) – Dynamics 365 CRM

Tags:   Dynamics 365   Dynamics CRM   feedback   survey   VOC   Voice of customer Introduction To Voice of the Customer For any bus...