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
}
}
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.
Impersonation in plug-ins is not supported while in offline mode.
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.
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.
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:
Maddening.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With