Monday, August 29, 2011

CRM 4.0 - detach answered email from queue

One of my customers requested following functionality - detach email from queue when email is answered.

Solution consists of 2 parts - customization of email (addition of source email field and JavaScipt which will extract id of source email) and Plugin which will handle Send message.

Add custom nvarchar attribute to email as it shown on the screenshot:



Place this field to the form (this field will be hidden later with JavaScript):


Add following script to OnLoad event handler of email form:

if (crmForm.FormType == 1 || 

(crmForm.FormType == 2 &&
window.location.search != null &&
window.location.search.indexOf('_InReplyToId') != -1))
{
var query = window.location.search;
if (query != null)
{
query = query.substring(1, query.length - 1);
var queryparts = query.split("&");
for(var i = 0; i < queryparts.length; i++)
{
var params = queryparts[i].split("=");
if (params[0] == "_InReplyToId")
{
crmForm.all.dc_sourceemailid.DataValue = params[1].replace("%7b","").replace("%7d","");
break;
}
}
}
}

crmForm.all.dc_sourceemailid_c.style.display = "none";
crmForm.all.dc_sourceemailid_d.style.display = "none";


Save and publish email entity. Plugin part:

using System;

using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Crm.Sdk;
using Microsoft.Crm.SdkTypeProxy;
using Microsoft.Crm.Sdk.Query;
using System.Text.RegularExpressions;
using System.Web.Services.Protocols;
using System.Xml;

namespace Plugins
{
public class SendHandler : IPlugin
{
#region IPlugin Members

public void Execute(IPluginExecutionContext context)
{
if (context.MessageName == MessageName.Send)
{
Guid emailId = (Guid)context.InputParameters["EmailId"];
ICrmService crmservice = context.CreateCrmService(false);

TargetRetrieveDynamic target = new TargetRetrieveDynamic();
target.EntityId = emailId;
target.EntityName = EntityName.email.ToString();

RetrieveRequest request = new RetrieveRequest();
request.ColumnSet = new ColumnSet(new string[] { dc_sourceemailid" });
request.ReturnDynamicEntities = true;
request.Target = target;

RetrieveResponse retrieveresponse = null;
try
{
retrieveresponse = (RetrieveResponse)crmservice.Execute(request);
}
catch(SoapException sexc)
{
throw new Exception(sexc.Detail.InnerText);
}

DynamicEntity _email = (DynamicEntity)retrieveresponse.BusinessEntity;


if (_email.Properties.Contains("dc_sourceemailid"))
{
Guid sourceemailid = new Guid((string)_email.Properties["dc_sourceemailid"]);
string fetchRequest = string.Format(@"<fetch mapping='logical'>
<entity name='queueitem'>
<attribute name='queueid'/>
<filter type='and'>
<condition attribute='objectid' operator='eq' value='{0}'/>
</filter>
</entity>
</fetch>", sourceemailid);

string fetchResponce = string.Empty;

try
{
fetchResponce = crmservice.Fetch(fetchRequest);
}
catch (SoapException sexc)
{
throw new Exception(sexc.Detail.InnerText);
}

XmlDocument doc = new XmlDocument();
doc.LoadXml(fetchResponce);

XmlNode queueidnode = doc.SelectSingleNode("//resultset/result/queueid");
if (queueidnode == null)
return;

DetachFromQueueEmailRequest detachrequest = new DetachFromQueueEmailRequest();
detachrequest.EmailId = sourceemailid;
detachrequest.QueueId = new Guid(queueidnode.InnerText);

try
{
crmservice.Execute(detachrequest);
}
catch (SoapException sexc)
{
throw new Exception(sexc.Detail.InnerText);
}
}
}
}

#endregion IPlugin Members
}
}


Build assembly and register plugin's step as it shown at screenshot:


That's it, have fun!