Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dynamics CRM 2011 - Block Creation of Entity via Plugin

Problem: We use the CRM for Outlook plugin to automatically log our support emails, but internal emails between employees (some of which contain sensitive information) are also being logged.

Ideal Solution: I am attempting to write a pre-event (the "create email" message) plugin to block the automatic logging of internal emails, but (apparently) the only way to stop a message from being executed is to throw an exception in the pre-event phase, but this always results in an error message being shown in outlook (which we obviously can't have). According to the documentation, only the "InvalidPluginExecutionExeception" is supposed to show messages to the user, but this is not the case as all exceptions result in an error message in the user's Outlook application.

Potential Solution: There is also a "CheckPromoteEmail" message that (according to the documentation) determines whether or not an email should be promoted to the CRM (I assume "promoted to CRM" means "make an email entity to store in CRM"), but I couldn't find anything in the context that would let me tell CRM to not promote the email. Is there some flag buried in the context that I can set, or some way to invlaidate the email so the CRM's own logic decides to not store it?

Workaround Solution: The only other solution that I am aware of (mentioned here) to just clear the subject and contents of the email after it has been created, but I would rather stop the email from being created in the first place than editing or deleting it after time and resources have been wasted creating the email.

Is there a clean way to stop an operation from a plugin? Or from anywhere? If there isn't, does anyone know why Microsoft didn't provide this feature? They already have ironclad rollback functionality under the hood in case an operation fails, why don't they just give me a way to call the rollback?

Here's my code in case it's helpful in answering my question:

public class InternalEmailFilter : IPlugin
{
    void IPlugin.Execute(IServiceProvider serviceProvider)
    {
        IPluginExecutionContext _context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
        Entity e = (Entity)_context.InputParameters["Target"];
        bool shouldStore = ShouldStoreInCRM(e);

        if (shouldStore == false)
        {
            throw new Exception(); //attempting to stop the operation without an InvalidPluginExecutionException, but still results in error message to user
        }            
    }

    protected bool ShouldStoreInCRM(Entity e)
    {

           List<Entity> parties = new List<Entity>();

            var atttributes = e.Attributes;
            if (atttributes.ContainsKey("to") == true) parties.AddRange((atttributes["to"] as EntityCollection).Entities);
            if (atttributes.ContainsKey("from") == true) parties.AddRange((atttributes["from"] as EntityCollection).Entities);
            if (atttributes.ContainsKey("cc") == true) parties.AddRange((atttributes["cc"] as EntityCollection).Entities);
            if (atttributes.ContainsKey("bcc") == true) parties.AddRange((atttributes["bcc"] as EntityCollection).Entities);

            foreach (Entity p in parties)
            {
                if (p.LogicalName == "activityparty" && p.Attributes.ContainsKey("addressused") == true && p.Attributes["addressused"] != null)
                {
                    if (p.Attributes["addressused"].ToString().ToLower().Contains("@ourdomain.com") == false)
                    {
                        return true; //someone connected in the email is not an employee, store the email
                    }
                }
            }

            return false;  //everyone was an employee, do not store          
    }
}
like image 314
Richard Avatar asked Feb 04 '13 22:02

Richard


People also ask

What is the difference between plugin context and pre image?

Context contains the entity business information which is being updated currently on CRM Platform. In Plugin, IPluginExecutionContext contains information that describes the run-time environment that the plug-in executes, information related to the execution pipeline, and entity business information.

Does impersonation work for offline plugins?

Impersonation in plug-ins is not supported while in offline mode.

What is secondary entity in plugin?

Secondary entity is used for SetRelated and RemoveRelated messages, otherwise it should be null. Secondary entity is child is the related entity of primary entity. Secondary Entity should used only when you want to trigger plugin for an event requiring two entities like the "SetRelated" message.

What is synchronous and asynchronous plugin?

Synchronous Vs Asynchronous pluginsSynchronous execution means that triggering event will wait until the plugins finishes the execution. Asynchronous plug-ins allow triggering event to finish before plugins code runs. Can only run for 2 minutes.


1 Answers

After much blood, sweat, and tears I finally figured out how to do this:

You have to use an async post-event plugin on the "Create email" message to delete the email from the DB with the CRMService after it has been created. It has to be asynchronous because you need to wait for the CRM finish creating and 'let go' of the entity before you can delete it. Otherwise, the process hangs.

Any of these solutions would have been better, but for reference, you cannot:

  1. Throw an exception in the pre-event to cancel the create/promote email operation without either showing the user an error message or wreaking havoc on their Outlook. Even though only the InvlaidPluginExectuionExecption is supposed to show a message to a user, all exceptions show error messages to users.
  2. Block the promotion of an email to CRM. The CheckPromoteEmail message pre-event (amazingly) gives no information about the message to be potentially promoted (so there's no data to use to decide if the message should be promoted) and there is nothing to use to tell CRM to not promote the message. And, if you use the pre/post-event and try and use the Output params and change the ShouldPromote flag there, it does nothing.
  3. Clear the body content of an email before an Entity is created for it - any changes you make to the body content in the pre-event don't stay with the execution context and are lost when the core operation begins.

Maddening.

like image 185
Richard Avatar answered Oct 11 '22 15:10

Richard