title: Dynamics CRM 2011 - Block Creation of Entity via Plugin
body: <p><strong>Problem:</strong> 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. </p>
  
  <p><strong>Ideal Solution:</strong> 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.</p>
  
  <p><strong>Potential Solution:</strong> 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?</p>
  
  <p><strong>Workaround Solution:</strong> The only other solution that I am aware of (mentioned <a href="https://stackoverflow.com/questions/13365153/prevent-create-in-plugin">here</a>) 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.</p>
  
  <p><strong>Is there a clean way to stop an operation from a plugin?</strong> 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?</p>
  
  <p>Here's my code in case it's helpful in answering my question: </p>
  
  <pre><code>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&lt;Entity&gt; parties = new List&lt;Entity&gt;();
  
              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" &amp;&amp; p.Attributes.ContainsKey("addressused") == true &amp;&amp; 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          
      }
  }
  </code></pre>