1

In CRM when emails arrive and have the tracking token in them they automatically set the regarding field to be the incident (or whatever they relate to)

Unfortunately the Record wall isn't updated with this info so even if you are following the case nothing alerts you to the new activity.

I want to write a plugin on email or incident (or both) that updates the record wall and creates a task to follow up on that email with in 3 days.

I'm looking at the SDK and I can't see what the appropriate event in the pipe line would be to work out when an email is/has its regarding field set on arrival in the CRM.

The CRM email creation life-cycle is not well described in the documentation. [shakes fist]

Extra things that are bothering me

I can't seem to include a reference to get a strongly typed Email, Post or Case (driving me crazy)

Testing this is really hard (harder than it should be)

EDIT Here is my current code

namespace Assembly.Plugins
{
using System;
using System.ServiceModel;
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Query;

/// <summary>
/// PostEmailDeliverIncoming Plugin.
/// </summary>    
public class PostEmailDeliverIncoming : Plugin
{
    /// <summary>
    /// Initializes a new instance of the <see cref="PostEmailDeliverIncoming"/> class.
    /// </summary>
    public PostEmailDeliverIncoming()
        : base(typeof(PostEmailDeliverIncoming))
    {
        RegisteredEvents.Add(new Tuple<int, string, string, Action<LocalPluginContext>>(40, "DeliverIncoming", "email", ExecutePostEmailDeliverIncoming));

        // Note : you can register for more events here if this plugin is not specific to an individual entity and message combination.
        // You may also need to update your RegisterFile.crmregister plug-in registration file to reflect any change.
    }


    protected void ExecutePostEmailDeliverIncoming(LocalPluginContext localContext)
    {
        if (localContext == null)
        {
            throw new ArgumentNullException("localContext");
        }

        //Extract the tracing service for use in debugging sandboxed plug-ins.
        ITracingService tracingService = localContext.TracingService;

        // Obtain the execution context from the service provider.
        IPluginExecutionContext context = localContext.PluginExecutionContext;

        // Obtain the organization service reference.
        var service = localContext.OrganizationService;

             // The InputParameters collection contains all the data passed in the message request.
        if (!context.InputParameters.Contains("Target") || !(context.InputParameters["Target"] is Entity)) 
            return;

        // Obtain the target entity from the input parmameters.
        var target = (Entity)context.InputParameters["Target"];

        // Verify that the target entity represents an account.
        // If not, this plug-in was not registered correctly.
        if (target.LogicalName != "email")
            return;

        if((string)target["direction"] != "Incoming")
            return;

        if (target["regardingobjectid"] == null)
            return;

        try
        {
            // if its not a case I don't care
            var incident = service.Retrieve("incident", (Guid)target["regardingobjectid"], new ColumnSet(true));
            if (incident == null) 
                return;

            var post = new Entity("post");

            post["regardingobjectid"] = target["regardingobjectid"];

            post["source"]=new OptionSetValue(0);
            post["text"] = String.Format("a new email has arrived.");

            // Create the task in Microsoft Dynamics CRM.
            tracingService.Trace("FollowupPlugin: Creating the post.");
            service.Create(post);


            // Create a task activity to follow up with the account customer in 7 days. 
            var followup = new Entity("task");

            followup["subject"] = "Follow up incoming email.";
            followup["description"] = "An email arrived that was assigned to a case please follow it up.";
            followup["scheduledstart"] = DateTime.Now.AddDays(3);
            followup["scheduledend"] = DateTime.Now.AddDays(3);
            followup["category"] = context.PrimaryEntityName;

            // Refer to the email in the task activity.
            if (context.OutputParameters.Contains("id"))
            {
                var regardingobjectid = new Guid(context.OutputParameters["id"].ToString());
                followup["regardingobjectid"] = new EntityReference("email", regardingobjectid);
            }

            // Create the task in Microsoft Dynamics CRM.
            tracingService.Trace("FollowupPlugin: Creating the task activity.");
            service.Create(followup);
        }
        catch (FaultException<OrganizationServiceFault> ex)
        {
            throw new InvalidPluginExecutionException("An error occurred in the FollupupPlugin plug-in.", ex);
        }
        catch (Exception ex)
        {
            tracingService.Trace("FollowupPlugin: {0}", ex.ToString());
            throw;
        }
    }
}
}
Peter
  • 7,792
  • 9
  • 63
  • 94

4 Answers4

3

I've just been fighting with this exact same issue and came across this post. I thought I'd post the solution for you (if you still need it) and anyone else who comes across the issue in the future.

Here's the solution I arrived at: - Using the Plugin Registration Tool register a New Image on the appropriate step( Stage = "40", MessageName = "DeliverIncoming") - Set the New Image to be a Post Image - In your plugin fetch the Post Image's entity ID:

Guid emailID = context.PostEntityImages["PostImage"].Id;
Entity emailFromRetrieve = localContext.OrganizationService.Retrieve(
    "email",
    emailID,
    new Microsoft.Xrm.Sdk.Query.ColumnSet(true));
Email email = emailFromRetrieve.ToEntity<Email>();

if (email.RegardingObjectId == null)
{
    return;
}

var regardingObject = email.RegardingObjectId;

Hope this helps!

Casey Margell
  • 224
  • 2
  • 12
  • What is a PostImage? I ended up doing what I wanted with a workflow in the UI. I was pretty simple once I bent my head the right way. – Peter May 31 '13 at 01:36
  • 1
    A Post Image is basically a copy of the Entity after the operation. There are also Pre Images for a snapshot of the entity before the operation. Here is some documentation on them: http://msdn.microsoft.com/en-us/library/gg309673.aspx#bkmk_preandpost And here is how you add one via the plugin registration tool: http://msdn.microsoft.com/en-us/library/hh237515.aspx#bkmk_RegImage Let me know if there's any additional information that I can provide. – Casey Margell May 31 '13 at 15:59
1

I'm actually working on a very similar plugin at the moment. Mine creates a custom entity upon arrival of an email addressed to a certain email address. It also associates the incoming email with that new record via the Regarding field. I've added a Pre-Operation step on Create of Email and it works great, including incoming email from the router.

What I'm not sure of is when CRM fills in the Regarding field. You might look at Post-Operation and see if it is set there?

One interesting caveat regarding the Regarding field (haha!): Unlike single lookup fields, the Regarding object's name is actually stored in the ActivityPointer table, so when you update the Regarding field, be sure to set the Name on the EntityReference. If you don't, the Regarding lookup will still have a clickable icon but there won't be any text. I do it like this:

        email.RegardingObjectId = [yourentity].ToEntityReference();
        email.RegardingObjectId.Name = email.Subject;

Hope that helps!

Josh Painter
  • 4,071
  • 21
  • 26
  • I'll make sure I add this, How are you testing? at the moment I'm deploying and hoping...It's really horrible. – Peter May 14 '13 at 00:49
  • 1
    Yep, deploy and pray! :) Aside from debugging directly on the CRM server, here's another debugging method that I've used: http://stackoverflow.com/questions/8401537/is-it-possible-to-place-an-org-in-its-own-process/8406398#8406398 – Josh Painter May 14 '13 at 01:47
  • I am brand new to CRM 2013 development. You state "Mine creates a custom entity upon arrival of an email addressed to a certain email address" I am looking to fire a plugin when emails arrive in a specific queue. Would that be the same as yours Create Email? – GPGVM Dec 23 '13 at 21:53
1

I ended up doing this in a workflow on the email entity

Steps

  1. Create new workflow, I called it 'incoming email workflow'
  2. Scope is Organisation
  3. Choose Email as the entity and check 'Record field changes'
  4. Add a step that checks Regarding (Case):Case Contains Data

if true:

  1. Add a step that creates a Post
  2. Edit the properties in the Post

    • Text : This case has had {Direction(E-mail)} email activity from {From(E-mail)}
    • Source : Auto Post
    • Regarding : {Regarding(E-mail)}
  3. Add a step that creates a Task

  4. Edit the properties in the Task
    • Subject : Follow up {Subject(E-mail)}
    • Regarding : {Regarding(E-mail)}
Peter
  • 7,792
  • 9
  • 63
  • 94
0

Try to use the following code:

if ((bool)entity["directioncode"] == false)

Instead of your code:

if((string)target["direction"] != "Incoming")
Ryan Endacott
  • 8,772
  • 4
  • 27
  • 39
Nitesh
  • 1
  • There is already an accepted answer on this question. If you are looking for unanswered questions, you can find them here: http://stackoverflow.com/unanswered – valverij Jun 26 '13 at 13:09