Microsoft Dynamics 365 Blog

One of the best attribute of Microsoft Dynamics CRM is its extensibility. You can define workflow rules to automate certain processes and you can also add custom assemblies if the built-in functionality would not fulfill your requirements. I ran into the following problem a few weeks ago: whenever a CRM user receives an e-mail from a person who is represented as a contact in CRM, the owner of the contact should receive a notifying e-mail about this event (if the recipient and the owner are not the same person).


You can achieve the above functionality by following this guide:


1. Create a custom assembly (EmailNotifier).
2. Create a new class in the custom assembly (OwnerNotifier) and add the following method. This method receives the unique identifier of the e-mail activity and sends an e-mail to the contact’s owner if it is necessary.

public void Notify(Guid emailId)
{
  // Create service object.
   CrmService srv = new CrmService();
  srv.Url = “http://localhost:5555/MSCRMServices/2006/CrmService.asmx”;
  srv.Credentials = System.Net.CredentialCache.DefaultCredentials;
  // Retrieve e-mail by its identifier.
  // We need the from and torecipients attributes only.
  ColumnSet cols = new ColumnSet();
  cols.Attributes = new string[] { “from”, “torecipients” };
  email email = (email)srv.Retrieve(EntityName.email.ToString(), emailId, cols);
  if (email.from.Length == 0)
    return;
   // Query the contact by his/her e-mail address.
   QueryExpression query = new QueryExpression();
   // We need the owner’s identifier from contact entity.
   cols = new ColumnSet();
  cols.Attributes = new string[] { “ownerid” };
  query.ColumnSet = cols;
  query.EntityName = EntityName.contact.ToString();
   // Create condition expression for the filter.
  // We are filtering by the e-mail address.
  ConditionExpression condition = new ConditionExpression();
  condition.AttributeName = “emailaddress1”;
  condition.Operator = ConditionOperator.Equal;
  condition.Values = new string[] { email.from[0].addressused };
   // Create filter.
   FilterExpression filter = new FilterExpression();
  filter.FilterOperator = LogicalOperator.And;
  filter.Conditions = new ConditionExpression[] { condition };
   // Set the filter for the query.
   query.Criteria = filter;
   // Execute the query.
   RetrieveMultipleRequest req = new RetrieveMultipleRequest();
  req.Query = query;
  RetrieveMultipleResponse resp = (RetrieveMultipleResponse)srv.Execute(req);
  if (resp.BusinessEntityCollection.BusinessEntities.Length == 0)
    return;
   // We get the first contact from the returned collection.
   contact contact = (contact)resp.BusinessEntityCollection.BusinessEntities[0];
  // Retrieve systemuser by its identifier (contact.ownerid).
  // We need the internalemailaddress attribute only.
   cols = new ColumnSet();
  cols.Attributes = new string[] { “internalemailaddress” };
  systemuser usr = (systemuser)srv.Retrieve(EntityName.systemuser.ToString(),
    contact.ownerid.Value, cols);
  // If the owner is not on the recipients’ list then send e-mail to him/her.
   if (!email.torecipients.Contains(usr.internalemailaddress))
  {
    SmtpClient smtpClnt = new SmtpClient(“localhost”);
    MailMessage msg = new MailMessage(
      email.from[0].addressused,
      usr.internalemailaddress,
      “E-mail notification”,
      “New e-mail activity:” + 
      “<br><br>http://localhost:5555/Activities/email/edit.aspx?id=” +
      emailId.ToString());
    msg.IsBodyHtml = true;
    smtpClnt.Send(msg);
  }
}


3. Modify the URLs in this code according to your system’s setup.
4. Sign the assembly or add allowunsignedassemblies=”true” to the root node of workflow.config.
5. Register the assembly to the workflow service by following the guidelines in the CRM SDK documentation:


mk:@MSITStore:C:\CRMSDK\crmsdk3_0.chm::/htm/v3d0workflowsetup.htm



Add the following method description to the workflow.config file:

<method name=”Notify owner”
  assembly=”EmailNotifier.dll” 
  typename=”EmailNotifier.OwnerNotifier” 
  methodname=”Notify”
  group=”Notification functions”>
  <parameter name=”Email Id” datatype=”lookup” entityname=”email”/>
</method>


6. Create an e-mail workflow rule in Workflow Manager.
7. Add the following condition to the rule: E-mail.Direction = Incoming
8. Call the custom assembly in the action part of the condition.
9. Activate the rule.


Note: Since the workflow rule is triggered by new e-mail activity events, this solution works only if the incoming e-mail has a tracking token or the e-mail’s recipient tracks the e-mail in CRM (either manually or automatically).


Praveen Upadhyay

We're always looking for feedback and would like to hear from you. Please head to the Dynamics 365 Community to start a discussion, ask questions, and tell us what you think!