Thursday, January 26, 2017

Sending email to an alternate / secondary email address

Small plugin to send email to an alternate / secondary email address


Those who have worked with Dynamics365:CRM for a while has undoubtedly encounter this issue, which is that whatever address you enter as a recipient the system will resolve the record and substitute the address with the primary email address of the record.
There are several different ways of working around this issue, like creating leads that can be merged into existing contacts, duplicate contacts with links, etc. but I have created a small plugin which allows you to send an email to the address you want.
All you have to do is to compile the following code and register it as a synchronous, pre-operation plugin, and add a pre-entity image with the "to" field included. The secret here is to register it on the "send" message for the email entity.

Just add the microsoft.crmsdk from nuget to your project, and you'll have all the libraries you need to compile this little thing.

public class SendToSafeEmail : IPlugin
{
    public void Execute(IServiceProvider sp)
    {
        var context = (IPluginExecutionContext)sp.GetService(typeof(IPluginExecutionContext));
        var factory = (IOrganizationServiceFactory)sp.GetService(typeof(IOrganizationServiceFactory));
        var service = factory.CreateOrganizationService(context.UserId);

        Entity email = context.PreEntityImages.Values.First();
        var recipient = ((EntityCollection)email.Attributes["to"]).Entities.FirstOrDefault<Entity>();
        var to = (EntityReference)recipient.Attributes["partyid"];
        var contact = service.Retrieve("contact", to.Id, new ColumnSet("emailaddress3"));
        ((EntityCollection)email.Attributes["to"]).Entities[0].Attributes["addressused"] = contact.Attributes["emailaddress3"];
        service.Update(email);
    }
}

As you can see this isn't particularly advanced, and I would like to start with pointing out that I've removed exception handling and tracing for illustration purposes, I'm usually a lot more tidy (it's true!).
First off we retrieve the usual suspects, the execution context and the orgservice factory. Then we generate a new org-service connection based on the user ID of the user which triggered the plugin. Next up we retrieve the email from the pre entity images. This imlies that this is a pre-operation, synchronous plugin, and we need to add a pre-entity image when we register the plugin.

Next up we get the recipient from the "to" list. My code example does not take into account several recipients, it doesn't do any exception handling, and it's hard-coded for contacts. You'll have to make it work for your purpose on your own :)
The contact is retrieved from the system, and finally we do the following:
From the to recipient list, we update the "addressused" field on the first one, to the "emailaddress3" of the contact collected.
Next we update the entity back into the system, and continue the execution context.

That's all it takes, and some of your own logic of course.

A few thought on this solution before I wrap up:
It seems like a small, simple plugin for sending to alternate email addresses, but notice how we're hooking up to the "send" message for the email entity? That means that this plugin will trigger for all emails sent from the system. This doesn't need to have a large impact on your system, because there are a lot of optimizations in place in MSDYN365, but every line of code that has to execute causes a tiny bit of extra load on the system, and then multiply it by the number of emails sent from the system.

1 comment: