Dynamics CRM 2011 - 通过插件阻止实体创建

时间:2013-02-04 22:00:25

标签: c# plugins dynamics-crm-2011

问题:我们使用CRM for Outlook插件自动记录我们的支持电子邮件,但员工之间的内部电子邮件(其中一些包含敏感信息)也会被记录。

理想的解决方案:我正在尝试编写一个事件前的“创建电子邮件”消息插件来阻止内部电子邮件的自动记录,但(显然)是阻止内部电子邮件的唯一方法正在执行的消息是在事件前阶段抛出异常,但这总是导致在outlook中显示错误消息(我们显然不能拥有)。根据文档,只有“InvalidPluginExecutionExeception”应该向用户显示消息,但事实并非如此,因为所有异常都会导致用户的Outlook应用程序中出现错误消息。

潜在解决方案还有一条“CheckPromoteEmail”消息(根据文档)确定是否应将电子邮件提升为CRM(我假设“提升为CRM”意味着“制作一个电子邮件实体存储在CRM“)中,但我在上下文中找不到任何可以让我告诉CRM不推广电子邮件的内容。在我可以设置的上下文中是否有一些标记,或者某种方式来放置电子邮件以便CRM自己的逻辑决定不存储它?

解决方法解决方案:我知道的唯一其他解决方案(提及here),以便在创建电子邮件后清除主题和内容,但我宁愿在浪费时间和资源创建电子邮件之后,首先停止创建电子邮件,而不是编辑或删除电子邮件。

是否有一种干净的方法可以阻止插件中的操作?或者来自任何地方?如果没有,有谁知道为什么微软不提供此功能?如果操作失败,他们已经具备了强大的回滚功能,他们为什么不给我一种方法来调用回滚呢?

这是我的代码,以防它回答我的问题:

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          
    }
}

3 个答案:

答案 0 :(得分:8)

经过大量的血,汗和泪,我终于想出了如何做到这一点:

您必须在“创建电子邮件”消息上使用异步事件后插件,以便在创建CRMService后从数据库中删除该电子邮件。它必须是异步的,因为您需要等待CRM完成创建并“释放”实体才能删除它。否则,该过程会挂起。

任何这些解决方案都会更好,但作为参考,你不能:

  1. 在事件前抛出异常以取消创建/提升电子邮件操作,而不会向用户显示错误消息或对其Outlook造成严重破坏。即使只有InvlaidPluginExectuionExecption应该向用户显示消息,所有异常都会向用户显示错误消息。
  2. 阻止向CRM发送电子邮件的促销。 CheckPromoteEmail消息事件前(令人惊讶地)没有提供有关可能被提升的消息的信息(因此没有数据可用于决定是否应该提升消息)并且没有任何可用来告诉CRM不提升消息。并且,如果您使用事件前/后事件并尝试使用输出参数并在那里更改ShouldPromote标志,则它什么都不做。
  3. 在为其创建实体之前清除电子邮件的正文内容 - 您在事件前对正文内容所做的任何更改都不会保留在执行上下文中,并且在执行上下文时会丢失核心业务开始了。
  4. 郁闷了。

答案 1 :(得分:2)

抱歉,解决方法是您唯一的选择。通过插件停止操作的唯一方法是抛出异常。为什么微软这样做?我假设他们不希望插件无声地失败。

至于解决方法,您应该在进入数据库之前清除主题和正文,方法是在事件前插件中清除它们,然后在事后异步中清理记录本身插入。这样,敏感信息也不会进入任何审核日志。

最后,请查看DeliverPromoteEmail而不是CreateEmailDeliverPromoteEmail是Outlook用于创建跟踪的电子邮件的内容。这样,您仍然可以在CRM UI中创建不会触发此插件的电子邮件(如果需要)。

编辑 CheckPromoteEmail仅查看主题中的跟踪令牌(和/或电子邮件标头中的MessageID),以决定是否应跟踪电子邮件,因此不会也很有用。

答案 2 :(得分:0)

您可以选择在个人设置中选择跟踪所有电子邮件,电子邮件回复CRM电子邮件(已跟踪的电子邮件),来自记录(帐户等)的电子邮件以及已启用电子邮件的记录中的电子邮件。