Tuesday, October 23, 2018

Extracting attachments from an incoming email, create case, and add attachments to as notes

Problem

One of my client's using Dynamics CRM Online 2016 Update had a requirements to create Case (renamed to Enquiry) records when an email arrives to their info@*****.com mailbox. Using OOTB Automatic Record Creation and Update Rules feature a Case is created and the email is visible under Activities.
Our client felt that the user experience wasn't great and the original Email was hard to find with all the other activities got created afterwards.

Solution

The solution was to extract the attachments from the email message and create notes against the Case record during the case creation process. Below are the steps used to implement the solution.
  1. Create a custom workflow activity to extract the attachments and create notes
  2. Create a workflow which includes the above custom workflow activity as a Step
  3. Create an Automatic Record Creation and Update Rule
  4. Specify Record Creation and Update Details which calls the workflow created in step 2

Implementation

Create a custom workflow activity to extract the attachments and create notes

Below is the source code of the custom workflow activity.
using System;
using System.Activities;
using System.Linq;

using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Query;
using Microsoft.Xrm.Sdk.Workflow;

namespace Dyn365Apps.CRM.Workflow
{
    public class ExtractAttachmentsFromEmailAndCreateNotes : CodeActivity
    {
        [RequiredArgument]
        [Input("Email")]
        [ReferenceTarget("email")]
        public InArgument<EntityReference> receivedEmail { get; set; }

        [RequiredArgument]
        [Input("Enquiry")]
        [ReferenceTarget("incident")]
        public InArgument<EntityReference> enquiry { get; set; }

        protected override void Execute(CodeActivityContext context)
        {
            var trace = context.GetExtension<ITracingService>();

            try
            {
                var serviceFactory = context.GetExtension<IOrganizationServiceFactory>();
                var service = serviceFactory.CreateOrganizationService(Guid.Empty); //Use current user's IDif (service != null)
                {
                    trace.Trace("Organization Service Created");
                }

                // Get Attachment Count
                trace.Trace("Get Attachment Count");
                var rem = receivedEmail.Get(context);
                Entity email = service.Retrieve(rem.LogicalName, rem.Id, new ColumnSet("attachmentcount"));
                int atc = (int)email["attachmentcount"];
                trace.Trace("Attachment count = " + atc.ToString());

                if (atc > 0)
                {
                    // Get all attachments
                    QueryExpression queryAtt = new QueryExpression("activitymimeattachment");
                    queryAtt.ColumnSet = new ColumnSet(newstring[] { "activityid", "attachmentid", "filename", "body", "mimetype", "subject" });
                    queryAtt.Criteria = new FilterExpression();
                    queryAtt.Criteria.FilterOperator = LogicalOperator.And;
                    queryAtt.Criteria.AddCondition(new ConditionExpression("activityid", ConditionOperator.Equal, email.Id));
                    EntityCollection eatt = service.RetrieveMultiple(queryAtt);
                    var entities = eatt.Entities;

                    trace.Trace("Entities count = " + entities.Count());

                    foreach (var ent in entities)
                    {                        
                        trace.Trace("Inside the for loop");
                        trace.Trace("Attributes count = " + ent.Attributes.Count());

                        // Instantiate an Annotation object.
                        Entity annotation = new Entity("annotation");

                        if (ent.Attributes.Contains("subject"))
                        {
                            trace.Trace("subject = " + ent.Attributes["subject"].ToString());
                            annotation["subject"] = ent.Attributes["subject"].ToString();
                        }
                        else
                        {
                            trace.Trace("subject not found");
                            annotation["subject"] = "Undefined";
                        }
                        
                        if(ent.Attributes.Contains("filename"))
                        {
                            trace.Trace("filename = " + ent.Attributes["filename"].ToString());
                            annotation["filename"] = ent.Attributes["filename"].ToString();
                        }
                        else
                        {
                            trace.Trace("filename not found");
                            annotation["filename"] = "Undefined.txt";
                        }

                        if (ent.Attributes.Contains("mimetype"))
                        {
                            trace.Trace("mimetype = " + ent.Attributes["mimetype"].ToString());
                            annotation["mimetype"] = ent.Attributes["mimetype"].ToString();
                        }
                        else
                        {
                            trace.Trace("mimetype not found");
                            annotation["mimetype"] = "plain/text";
                        }

                        if (ent.Attributes.Contains("body"))
                        {
                            annotation["documentbody"] = ent.Attributes["body"];
                        }
                        
                        trace.Trace("objectid = " + enquiry.Get(context).Id.ToString());
                        
                        annotation["objectid"] = enquiry.Get(context);
                        annotation["objecttypecode"] = 112; // Case// Create a Note with the attachment
                        service.Create(annotation);
                    }
                }
            }
            catch (Exception ex)
            {
                trace.Trace("ex.Message = {0}", ex.Message);
                trace.Trace("ex.StackTrace = {0}", ex.StackTrace);
            }
        }
    }
}

Create a workflow which includes the above custom workflow activity as a Step

  • Create a workflow and name it Extract Attachments from Email - Create Notes - Attach to Enquiry
  • Set the Entity as Email
  • Enable workflow to run as a child process.
  • Add the custom workflow activity ExtractAttachmentsFromEmailAndCreateNotes as a step.
  • Custom workflow activity requires two inputs
  1. Email
  2. Case (Enquiry)
  • Activate the workflow.

Create an Automatic Record Creation and Update Rule

  • Navigate to Settings > Service Management and click on Automatic Record Creation and Update Rules.
  • Create a new Record Creation and Update Rule.

Specify Record Creation and Update Details which calls the workflow created in step 2

  • Create a new Record Creation and Update Details record.
  • Configure the conditions and actions.
  • Under Specify Other Actions, add a new step to Start a Child Workflow.
  • Select the Workflow created in Step 1
That's it (Assumption: The mailbox is configured to receive emails).
Now send an email with attachments to the mailbox.
The attachments in the Email Message are now under Case record's Notes section.

No comments:

Post a Comment

Get files of last hour in Azure Data Factory

  Case I have a Data Factory pipeline that should run each hour and collect all new files added to the data lake since the last run. What is...