A common scenario in Dynamics 365 CRM is that you have a mail queue where the customers can send support requests. When a mail is received in the queue, a Case/Incident is automatically created and the mail attached.
When your support staff replies to that mail, it will be from their personal mail address. So when the customer subsequently sends a reply to the support staff reply, it will go to the person who send the reply in the first place, and not to the common queue.
It is of course possible to change the From mail address in the create email form to that of the queue, but that requires that the support staff remembers to do so.
A common request is that when you create a reply mail, the default From address should be changed to the support queue’s mail. One should think that there would be a way to do that out of the box, but no, that’s not the case.
Here are two ways you can solve the problem:
1) The Javascript Way
If you Google the issue, this is probably the solution you will find:
1.
Navigate to Settings | Customizations and either Customize the system (the default solution) or a solution of your choice.
Click Web resources and add New. Enter Name and Display Name and set type to Script/JScript. The click the Text Editor button:
Enter the code below and click OK to close the text editor:
CrmDeveloperEmailCodeLib = {
ChangeFromAddressToQueue: function () {
debugger;
// Initialize variables to use
var lookup = null;
var direction = false;
var statusCode = 0;
var sla = null;
// Get statusCode of Email
if (Xrm.Page.getAttribute("statuscode") != null && Xrm.Page.getAttribute("statuscode").getValue() != null) {
statusCode = Xrm.Page.getAttribute("statuscode").getValue();
}
// Check if we're creating a new email (statusCode == 1)
if (Xrm.Page.ui.getFormType() == 1 || statusCode == 1) // Created
{
// Get direction of email. Incoming = 0 (False) and Outgoing = 1 (true)
var directionAtt = Xrm.Page.getAttribute("directioncode");
if (directionAtt != null && directionAtt.getValue() != null) {
direction = directionAtt.getValue();
}
// Get the Regarding object and check if it's a support case/incident
var lookupAtt = Xrm.Page.getAttribute("regardingobjectid");
if (lookupAtt != null && lookupAtt.getValue() != null) {
if (lookupAtt.getValue()[0].entityType == "incident") {
lookup = lookupAtt.getValue();
}
}
// Get the SLA if you need that for something...
var slaAtt = Xrm.Page.getAttribute("slaid");
if (slaAtt != null && slaAtt.getValue() != null) {
sla = slaAtt.getValue()[0].name;
}
if (direction != null && direction == true && lookup != null) {
var lookupData = new Array();
var lookupItem = new Object();
lookupItem.id = "{b3e39673-56df-ed11-a7c6-0022489fd8e4}"; //Change this
lookupItem.name = "CRM Support"; //Change this
lookupItem.entityType = "queue";
lookupData[0] = lookupItem;
Xrm.Page.getAttribute("from").setValue(lookupData);
}
}
}
};
Click Save, and the Publish, and when the publish is done, you can close the Web Resource dialog.
2.
Navigate to Entities and click Add Existing.
Select the Email entity and click OK. Observe: If you have an Email entity in the list named msdynmkt_email, it NOT THAT ONE!
Select the Main email form and click Finish. You don’t need to add anything else, and you don’t need to include all metadata.
If it says “Missing Required Components”, you can select “No, do not include required components” and click OK.
3.
Navigate to Entities | Email | Forms and open the Main form you just added.
Click the Form Properties button. The Events tab should already be selected.
Click the Add button under Form Libraries.
Use the Search button to locate the javascript web resource you added in 1). Check it and click Add:
Under Event Handlers, The Form control and the OnLoad event should already be selected. Click the Add button there.
Select your newly added library in the dropdown, enter the name of your function (in the case above, it should be CrmDeveloperEmailCodeLib.ChangeFromAddressToQueue. Check “Pass execution context as first parameter” (It’s not used right now, but always good to have). Finally click OK.
Click OK to close the Form Properties dialog.
Save the Form and publish all changes.
4.
Open a case and test your new functionality. If you click a reply email button, the From address should be the queue you selected. OBSERVE: Because you added a javascript, you may need to refresh the browser cache for it to work.
2) The Plugin Way
1.
You will probably already have created a Visual Studio plugin solution/project, but if not, you need to create a plugin solution in Visual Studio.
Add the following class:
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Client;
using Microsoft.Xrm.Sdk.Query;
using System;
using System.Linq;
using Xrm;
namespace msabPlugins
{
public class PreValidateEmailCreate : IPlugin
{
public void Execute(IServiceProvider serviceProvider)
{
#region Initializion of context etc
// Obtain the tracing service for plugin trace log.
ITracingService tracingService = (ITracingService)serviceProvider.GetService(typeof(ITracingService));
// Obtain the execution context from the service provider.
IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
// Obtain the organization service reference which you will need for
// web service calls.
IOrganizationServiceFactory serviceFactory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
IOrganizationService service = serviceFactory.CreateOrganizationService(context.UserId);
// Obtain the ServiceContext, which you will need for LINQ-queries with generated early bound entities (MsabXRM365-LM.cs)
var ServiceContext = new OrganizationServiceContext(service);
// Get record from form
Entity record = (Entity)context.InputParameters["Target"];
#endregion
// Here goes the custom Plug-in business logic.
if (record == null)
return;
if (record.Attributes.Contains("directioncode") && record.Attributes["directioncode"].Equals(false)) //Incoming email
return;
if (record.Attributes.Contains("statuscode") && ((OptionSetValue)record.Attributes["statuscode"]).Value != 1) //Email created
return;
Queue fromQueue = null;
if (record.Attributes.Contains("regardingobjectid"))
{
EntityReference regardingRef = (EntityReference)record.Attributes["regardingobjectid"];
if (regardingRef != null && regardingRef.LogicalName == "incident")
{
Incident regarding = (Incident)service.Retrieve(regardingRef.LogicalName, regardingRef.Id, new ColumnSet("slaid"));
if (regarding != null)
{
//EntityReference slaRef = regarding.SLAId;
//SLA sla = null;
//if (slaRef != null)
//{
// sla = (SLA)service.Retrieve(SLA.EntityLogicalName, slaRef.Id, new ColumnSet("name"));
//}
string queueId = "CRM Support"; //Change this
Queue queue = (from q in ServiceContext.CreateQuery<Queue>()
where q.Name == queueId
select q).FirstOrDefault();
if (queue != null && queue.QueueId != null && queue.QueueId != Guid.Empty)
{
fromQueue = queue;
}
}
}
}
if (fromQueue != null)
{
Entity fromEntity = new Entity("activityparty");
fromEntity.Attributes["addressused"] = fromQueue.EMailAddress; //Optional
fromEntity.Attributes["partyid"] = new EntityReference(Queue.EntityLogicalName, fromQueue.Id);
record.Attributes["from"] = new Entity[] { fromEntity };
}
}
}
}
You will probably notice that I have used late binding to assign the Queue to the From address property. That is to avoid having to create an early binding object and trigger an update process to assign the property.
2.
Compile the Plugin dll and register it using the Plugin Registration tool.
3.
Add a Plugin Message Step:
4.
Open a case and test your new functionality. If you click a reply email button, the From address should be the queue you selected. OBSERVE: Because you added a plugin, you may need to refresh the browser cache for it to work.
Conclusion
So! Which solution is best? Normally I’d say that there are advantages and disadvantages to every method, but this case is special; I’d say that all evidence suggests that you should use the Plugin method.
Why? Lot’s of reasons:
You are working with a Visual Studio solution with all the advantages that entails: Code writing help, Intellisense, easy catching of compiler errors, easy deployment, source control.
Also, you’ll have all your code in one solution. It’s easy to find and search through. Deployed javascript web resources in CRM is so much harder to maintain and search through.
And one of the most important reasons in my point of view:
The Email entity (draft) is created BEFORE the email dialog is opened. If you use the javascript method, you will see that the From address is correct in the email dialog itself. The javascript works on the dialog control, though, not the Email entity itself.
If you look at the Case/Incident timeline behind the email dialog, you will see the draft, and you will notice that the email address on the draft is different from the one you set in your code. It should normally be your personal user email:
That means that if you close the email dialog without sending, the Email entity remains in the timeline, and you can open it later and send, but then it will be with your personal email – not that of the queue you set.
However, if you use the plugin method, the From email is set on the entity itself, and you can verify that by looking at the Case/Incident timeline, which will show the correct email address: