Modify E-mail Recipients in a Custom Workflow in MSCRM 2011

This bit of code will allow you to specify Team members as e-mail recipients in a workflow in Microsoft CRM 2011. Make sure to visit Creating a Custom Workflow Activity in MS CRM 2011 to understand how to create custom workflow activities!

This bit of code will allow you to specify Team members as e-mail recipients in a workflow in Microsoft CRM 2011. Make sure to visit Creating a Custom Workflow Activity in MS CRM 2011 to understand how to create custom workflow activities!

To implement:

  1. Register your compiled custom workflow activity DLL using the Plugin Registration Tool (see Creating a Custom Workflow Activity in MS CRM 2011).
  2. Create a new workflow process.
  3. Create an e-mail record.
  4. Add the send e-mail to team custom workflow step (I called mine “Send Team Email”):
  5. Click on the step’s Set Properties.
  6. For each send to field (e.g. TO:, CC:, BCC:, etc.), select the appropriate team. Note that setting any of these send to fields won’t overwrite what you currently set in the e-mail, the code will simply append to that field. Also note that you’ll only be able to select one team at a time:
  7. Set the e-mail reference to the e-mail record you created in step #3.
  8. Activate your workflow process.

When your workflow triggers based on the parameters you specified for the workflow process, it will fire off an e-mail to the appropriate team members!

namespace MyWorkflow
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Activities;
    using System.Web.Services.Protocols;
    using System.Diagnostics;
    using Microsoft.Xrm.Sdk;
    using Microsoft.Xrm.Sdk.Messages;
    using Microsoft.Xrm.Sdk.Workflow;
    using Microsoft.Xrm.Sdk.Query;
    using Microsoft.Crm.Sdk.Messages;
    using WorkflowActivities.RSWebReference; // This is the web reference to your CRM web service (e.g. http://<SERVER_NAME>/ReportServer/ReportExecution2005.asmx)
    using Xrm;

    /****************************************************************************************************
     * SendTeamEmail Class implements CodeActivity class
     *      This class creates a custom workflow activity for CRM 2011. It accepts a Team entity and Email
     *      entity.  It pulls the members of the team and adds them as the recipients to the email and then
     *      sends the email.
     ****************************************************************************************************/
    public class SendTeamEmail : CodeActivity
    {
        [Input("TO: Team")]
        [ReferenceTarget(Team.EntityLogicalName)]
        public InArgument<EntityReference> LookupToTeam { get; set; }

        [Input("CC: Team")]
        [ReferenceTarget(Team.EntityLogicalName)]
        public InArgument<EntityReference> LookupCcTeam { get; set; }

        [Input("BCC: Team")]
        [ReferenceTarget(Team.EntityLogicalName)]
        public InArgument<EntityReference> LookupBccTeam { get; set; }

        [Input("E-mail Reference")]
        [ReferenceTarget(Email.EntityLogicalName)]
        public InArgument<EntityReference> LookupEmail { get; set; }

        protected override void Execute(CodeActivityContext executionContext)
        {
            try
            {
                // Create the tracing service
                ITracingService tracingService = executionContext.GetExtension<ITracingService>();

                // Create the context
                IWorkflowContext context = executionContext.GetExtension<IWorkflowContext>();

                IOrganizationServiceFactory serviceFactory = executionContext.GetExtension<IOrganizationServiceFactory>();

                // Create the Organization service
                IOrganizationService service = serviceFactory.CreateOrganizationService(context.UserId);

                // Get the target entity from the context
                Entity target = (Entity)service.Retrieve(Quote.EntityLogicalName, context.PrimaryEntityId, new ColumnSet(true));

                // Set TO:, CC:, BCC: team members
                dynamic[] sendFields = {
                                      new { type = "TO", teamMembers = GetTeamMembers(service, LookupToTeam.Get<EntityReference>(executionContext)) },
                                      new { type = "CC", teamMembers = GetTeamMembers(service, LookupCcTeam.Get<EntityReference>(executionContext)) },
                                      new { type = "BCC", teamMembers = GetTeamMembers(service, LookupBccTeam.Get<EntityReference>(executionContext)) },
                                  };

                // Send email to members of the team
                CreateEmail(service, sendFields, target, context.InitiatingUserId, LookupEmail.Get<EntityReference>(executionContext)/*, LookupAttachQuote.Get<Boolean>(executionContext)*/);

            }
            catch (SoapException ex)
            {
                // Add the SoapException message in event log
                EventLog.WriteEntry("code error", "Error occured in " + ex.Detail.InnerText.ToString(), EventLogEntryType.Error);
            }
            catch (Exception exe)
            {
                // Add the GeneralException message in event log
                EventLog.WriteEntry("code error", "Error occured in " + exe.InnerException.ToString(), EventLogEntryType.Error);
            }
        }

        public static List<TeamMembership> GetTeamMembers(IOrganizationService service, EntityReference teamRef)
        {
            if (teamRef == null) return null;

            // Prepare DataContext by using AutoGenerated cs file:
            // CrmSvcUtil.exe /out:Xrm.cs /url:http<s>://<CRMSERVER>/XRMServices/2011/Organization.svc /domain:<DOMAIN> /username:<USERNAME> /password:<PASSWORD> /namespace:Xrm /serviceContextName:XrmDataContext
            XrmDataContext datacontext = new XrmDataContext(service);

            // Get the Team Name from the Workflow input parameter
            Entity teamEntity = service.Retrieve(Team.EntityLogicalName, teamRef.Id, new ColumnSet(true));

            // Get the Team Id from the Team Name
            var team = (from t in datacontext.TeamSet
                        where t.Name == teamEntity.Attributes["name"]
                        select new { t.TeamId }).First();

            // Get all the members of the team to send email
            return (from t in datacontext.TeamMembershipSet
                                                where t.TeamId == team.TeamId
                                                select t).ToList();
        }

        public static void CreateEmail(IOrganizationService service, dynamic[] sendFields, Entity quoteEntity, Guid loggedinUser, EntityReference emailRef/*, Boolean attachQuote*/)
        {
            // Create Email 
            Email emailInstance = new Email();
            Entity emailEntity = service.Retrieve(Email.EntityLogicalName, emailRef.Id, new ColumnSet(true));
            emailInstance.ActivityId = emailEntity.Id;

            for (int i = 0; i < sendFields.Length; i++)
            {
                if (sendFields[i].teamMembers == null) continue;
                List<ActivityParty> toPartyList = new List<ActivityParty>();
                EntityCollection recipients;

                // Add the Activity party for each member in the team
                foreach (TeamMembership user in sendFields[i].teamMembers)
                {
                    ActivityParty toParty = new ActivityParty();
                    toParty.PartyId = new EntityReference(SystemUser.EntityLogicalName, user.SystemUserId.Value);
                    toPartyList.Add(toParty);
                }
                switch ((string)sendFields[i].type)
                {
                    case "TO":
                        recipients = emailEntity.GetAttributeValue<EntityCollection>("to");
                        foreach (ActivityParty party in recipients.Entities)
                        {
                            toPartyList.Add(party);
                        }

                        // Add To and From users to emailInstance
                        emailInstance.To = toPartyList.ToArray();
                        break;
                    case "CC":
                        recipients = emailEntity.GetAttributeValue<EntityCollection>("cc");
                        foreach (ActivityParty party in recipients.Entities)
                        {
                            toPartyList.Add(party);
                        }

                        // Add To and From users to emailInstance
                        emailInstance.Cc = toPartyList.ToArray();
                        break;
                    case "BCC":
                        recipients = emailEntity.GetAttributeValue<EntityCollection>("bcc");
                        foreach (ActivityParty party in recipients.Entities)
                        {
                            toPartyList.Add(party);
                        }

                        // Add To and From users to emailInstance
                        emailInstance.Bcc = toPartyList.ToArray();
                        break;
                }
            }

            // Set the case regarding
            emailInstance.RegardingObjectId = new EntityReference(Quote.EntityLogicalName, quoteEntity.Id);

            // Send email
            service.Update(emailInstance);
            SendEmailRequest sendRequest = new SendEmailRequest();
            sendRequest.EmailId = emailEntity.Id;
            sendRequest.TrackingToken = string.Empty;
            sendRequest.IssueSend = true;

            // Send the email message.
            service.Execute(sendRequest);

        }
    }

}