Thursday, October 01, 2009

Custom workflow action, team members and 'to' field of email record for Microsoft Dynamics CRM 4.0

There was interesting question and I decided to help author of question and create such functionality.



Here's the code of this custom workflow action:

using System;
using System.Collections.Generic;
using System.Text;
using System.Workflow.Activities;
using Microsoft.Crm.Workflow;
using System.Workflow.ComponentModel;
using Microsoft.Crm.Sdk;
using Microsoft.Crm.Sdk.Query;
using Microsoft.Crm.SdkTypeProxy;

namespace FillEmailWithTeamMembers
{
[CrmWorkflowActivity("Fill email with team members")]
public class EmailToFiller : SequenceActivity
{
protected override ActivityExecutionStatus Execute(ActivityExecutionContext executionContext)
{
if (Team != null && Email != null)
{
IContextService contextService = (IContextService)executionContext.GetService(typeof(IContextService));
IWorkflowContext workflowContext = contextService.Context;
ICrmService crmservice = workflowContext.CreateCrmService();

//Retrieve System Users based on Team

QueryExpression query = new QueryExpression(EntityName.systemuser.ToString());
query.ColumnSet = new ColumnSet(new string[] { "systemuserid" });
LinkEntity link = query.AddLink("teammembership", "systemuserid", "systemuserid");
link.LinkCriteria.AddCondition(new ConditionExpression("teamid", ConditionOperator.Equal, Team.Value));

List<BusinessEntity> users = crmservice.RetrieveMultiple(query).BusinessEntities;

email emailInstance = new email();
emailInstance.activityid = new Key(Email.Value);

List<activityparty> receivers = new List<activityparty>();

foreach (systemuser user in users)
{
activityparty toparty = new activityparty();
toparty.partyid = new Lookup();
toparty.partyid.type = EntityName.systemuser.ToString();
toparty.partyid.Value = user.systemuserid.Value;

receivers.Add(toparty);
}

emailInstance.to = receivers.ToArray();

crmservice.Update(emailInstance);

SendEmailRequest request = new SendEmailRequest();
request.EmailId = Email.Value;
request.IssueSend = true;
request.TrackingToken = "";
crmservice.Execute(request);
}

return ActivityExecutionStatus.Closed;
}

public static DependencyProperty TeamProperty = DependencyProperty.Register("Team", typeof(Lookup), typeof(EmailToFiller));

[CrmInput("Team")]
[CrmReferenceTarget("team")]
public Lookup Team
{
get
{
return (Lookup)base.GetValue(TeamProperty);
}
set
{
base.SetValue(TeamProperty, value);
}
}

public static DependencyProperty EmailProperty = DependencyProperty.Register("Email", typeof(Lookup), typeof(EmailToFiller));

[CrmInput("Email")]
[CrmReferenceTarget("email")]
public Lookup Email
{
get
{
return (Lookup)base.GetValue(EmailProperty);
}
set
{
base.SetValue(EmailProperty, value);
}
}

}
}


I've tested this code and it works.

15 comments:

  1. Andriy,
    Thank you so much for this code! It literally saved me on a client requirement and yours was the only code out there that worked (sort of). A few things to note, running the SendEmailRequest() function is unsupported in a CRM Workflow Activity... or atleast it was the cause of my errors. Aside from that, this code provided me with an easy way of modifying the "to" recipients of an email via a CRM workflow activity.. thank you so much for building this code as an example!
    Paul Reitmeyer
    www.mscrmdirectory.com

    ReplyDelete
  2. Hi, Paul.
    SendEmail definitely works in custom workflow activities. I've used this code in several projects... You should investigate the exception which is risen with SendEmailRequest...

    ReplyDelete
  3. привет,
    а снимки workflow есть? не могу разобраться как задать свойство Email

    ReplyDelete
  4. На данный момент - нет. Насколько я помню, то имейл там появляется в инпут свойствах. Практически так, как показано на следующей картинке:
    http://2.bp.blogspot.com/_73OmG38HHME/Snl-0E1OcoI/AAAAAAAAAO8/cwXIMM4rfv0/s1600-h/9.jpg
    MailRecipient

    ReplyDelete
  5. Я этот код понимаю так.
    Имеется ворфло, которой можно задать параметр EMail. То есть емайлом будет какое-то письмо, существующее на момент выполнения воркфло. И это письмо будет переотправлено нескольким получателям.
    Вот что я хочу.
    Чтобы на одном шаге воркфло определялся список получателей (из группы / роли / прочей лабуды) а на другом шаге создавалось сообщение эл почты. И ему указать полученных получателей. Сообщение эл почты не существует до запуска воркфло.
    Как это сделать?

    ReplyDelete
  6. Могу предложить сделать так, как было сделано у меня:
    1. Создание email (именно создание сущности типа email), а не отправка email.
    2. Этот кастомный шаг, в который через CrmInput типа lookup передаётся email, созданный в 1.

    ReplyDelete
  7. спасибо, получилось

    ReplyDelete
  8. Hello Andriy,

    Great post, The workflow is working fine for me however the email created is not sent, even after i changed the status to 'Pending Send'.

    Any idea what could be happening?

    thanks
    DM

    ReplyDelete
  9. Several questions:
    1. How does email integration configured (Outlook or email router)?
    2. Does 'from' user has possibility to send emails?

    ReplyDelete
  10. 1.Email integration for the seding user is configured as follows:
    Incoming: Email-router
    Outgoing: Email-router

    2. Yes when creating a normal Send Email workflow, the email is sent. In this case after changing the status to 'Pending Send', the email says "This message has not yet been submitted for delivery".

    Thanks

    ReplyDelete
  11. This message actually means that you have some issues in email integration configuration. I have used this Workflow Activity several times and it worked fine for me.

    ReplyDelete
  12. oops! you're right. I had my service switched off ..

    Great Work Andriy. Your posts are very helpful.
    Thanks

    ReplyDelete
  13. Hi Andriy,
    I am working with CRM 2011, do you have this code updated to be used with 2011?

    ReplyDelete
  14. hi andriy pls share the code for 2011 for same requirement.

    ReplyDelete
  15. hi andriy pls share the code for 2011 for same requirement.

    ReplyDelete