Share via


Create an E-Mail Activity Using Workflow

 

Microsoft Corporation

January 2004

Applies to:
    Microsoft® Customer Relationship Management (CRM) version 1.2

Requires:
    Microsoft Business Solutions CRM version 1.2
    Microsoft Visual Studio® .NET
    .NET Framework 1.1
    Microsoft Windows® 2000 Server

Summary: This example application demonstrates a workflow customization for Microsoft Customer Relationship Management (CRM). The application sends an e-mail notification to a designated list of recipients whenever a new contact is added to the system. The flow of activity is controlled by a workflow rule set up with a PostURL action. The Web service is coded in C# and created with Microsoft Visual Studio .NET 2003 using the .NET Framework version 1.1. (17 printed pages)

Download the example application for this article: CreateEmailActivity

Contents

Overview
Deploy the Solution in Visual Studio .NET
Create the Custom Fields in Microsoft CRM
Create and Activate a PostURL Workflow Rule
Test the Customization
Conclusion
Additional Information

Overview

This example application illustrates customizing Microsoft® Customer Relationship Management (CRM) using a workflow rule. The application uses the e-mail address in a custom field to send an e-mail through a custom Web service whenever a new contact is added to Microsoft CRM. The program flow is controlled by a workflow rule set up with a PostURL action. The following list describes the sequence of events:

  1. A new contact is created in Microsoft CRM, triggering a workflow rule.
  2. The workflow rule executes a PostURL action.
  3. The Web service receives the post method from the PostURL workflow action.
  4. The PostURL passes the value of a custom drop-down list (picklist) field that contains the e-mail address of a user that exists in Microsoft CRM.
  5. An e-mail activity is created and associated with the new contact.
  6. The e-mail is sent to the person selected in the custom drop-down list (picklist) field Notify E-mail on the contact form.
  7. A text file on the local drive is created for testing purposes.

Deploy the Solution in Visual Studio .NET

We have provided a complete solution for this article: CreateEmailActivity.

Once you have downloaded the example application to your Microsoft CRM server (running Windows 2000), unzip the CreateEMailActivity.exe file to C:\inetpub\wwwroot\. This creates the CreateEMailActivity folder.

Map a virtual directory in IIS to the CreateEMailActivity folder

  1. From the Start menu, point to Programs, point to Administrative Tools, and click Internet Services Manager.
  2. Expand the tree view for your server.
  3. Right-click Microsoft CRM Version 1.2 or Default Web Site, click New, and then click Virtual Directory.
  4. The Virtual Directory Creation Wizard opens. Click Next.
  5. On the Virtual Directory Alias page, enter an alias of CreateEMailActivity. Click Next.
  6. On the Web Site Content Directory page, browse to the CreateEMailActivity folder in C:\inetpub\wwwroot\. Click Next.
  7. On the Access Permissions page, make sure that Read and Run scripts are checked. Click Next, and then click Finish.
  8. Right-click the new virtual directory in Internet Information Services (IIS), click Properties.
  9. On the Directory Security tab, in the Anonymous access and authentication control section, click Edit.
  10. Make sure the Anonymous access option is not selected and the Integrated Windows authentication is selected. Click OK twice to close the dialog boxes.

You should now be able to open the project in Microsoft Visual Studio® .NET to view the code by performing the following steps. You can also open the files in Notepad or an alternative text editor.

  1. Open the CreateEmailActivity.asmx.cs file. Find the _strCRMURL string and change the value to the URL of your Microsoft CRM installation.
  2. Save the project and rebuild it in Visual Studio .NET. On the Build menu, click Rebuild Solution.

Note   If the references to the Microsoft.Crm.Platform.Proxy.dll or Microsoft.Crm.Platform.Types.dll are unresolved, simply remove and re-add the references. In Solution Explorer, expand References and right-click the assembly and select Remove. Then right-click References and choose Add Reference to re-add the reference. The Microsoft.Crm.Platform.Proxy.dll and the Microsoft.Crm.Platform.Types.dll are located on the Microsoft CRM server in the inetpub\wwwroot\bin folder.

If you run this application on a computer other than your Microsoft CRM platform server, you must add the registry key "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\MSCRM\mailserverurl", and assign it a string value of the same name as the server with the Microsoft CRM-Exchange E-Mail Router installed (for example, CRMExchangeServer) and a data field that is the URL to the ICrmEmailDispatch.SRF file on that server (for example, https://CRMExchangeServer/MSCRMConnector/ICrmEmailDispatch.SRF).

Caution   Incorrectly editing the registry may severely damage your system. Using the registry editors to modify the registry bypasses the standard safeguards that are provided by administrative tools, allowing settings that could degrade performance, damage your system, or even require you to reinstall the Microsoft Windows® operating system. If you must edit the registry directly, first back it up. See Registry Editor Help or "Backing Up the Windows 2000 Registry" in the Microsoft Windows 2000 Server Resource Kit for more information.

About the Create E-Mail Activity Web Service

In the CreateEmailActivity example, a workflow rule executes a PostURL action and a Web service receives the post method. This Web service performs four steps:

  1. Retrieves the ID of the user given the drop-down list (picklist) entry chosen by the user.
  2. Constructs the e-mail body.
  3. Sends the e-mail.
  4. Writes to a log file.

The following code shows the primary method in the Web service, CreateAndSendEmailActivity. The _strCRMURL variable contains the path of your Microsoft CRM server. The details of these four steps will be discussed after this code.

private static string _strCRMURL = "https://MyServerName/MSCRMServices/";

[WebMethod]
public void CreateAndSendEmailActivity(string CFPContactEmailAddress, string contactid)
{
   // Get the custom recipient, and then send the e-mail.
   try 
   {
      string strCustomRecipientID = RetrieveCustomRecipient(_strCRMURL,
                                               CFPContactEmailAddress);
      string strMessageBody = CreateMessageBody(_strCRMURL, contactid);
      string strEmailId = SendEmail(_strCRMURL, strCustomRecipientID,
                                          contactid, strMessageBody);
      WriteToLog(strEmailId);
   }
   catch (System.Web.Services.Protocols.SoapException e)
   {
      StringBuilder strError = new StringBuilder("Error Message: ");
      strError.AppendFormat("Message: {0} \r\n", e.Message);
      strError.AppendFormat("Stack Trace: {0} \r\n", e.StackTrace);
      strError.AppendFormat("Detail: {0} \r\n", e.Detail.OuterXml);
      WriteToLog(strError.ToString());
   }
   catch (Exception e)
   {
      WriteToLog("ErrorMessage: " + e.Message + " " + e.StackTrace);
   }
}

Step 1: Retrieve the ID of the user

Search for an e-mail address corresponding to a given drop-down list (picklist) value. The RetrieveCustomRecipient method uses a helper function to parse the XML returned from the Microsoft CRM database. This helper function is described later in this article.

private string RetrieveCustomRecipient(string strCRMURL,
                    string strOrdinalPositionInPicklist)
{
   // Create BizUser proxy object.
   BizUser bizUser   = new BizUser();
   bizUser.Url   = strCRMURL + "BizUser.srf";
   bizUser.Credentials   = System.Net.CredentialCache.DefaultCredentials;

   // Create CRMCustomization proxy object.
   CRMCustomization picklist = new CRMCustomization();
   picklist.Url = strCRMURL + "CRMCustomization.srf";
   picklist.Credentials = bizUser.Credentials;

   // Create CRMQuery proxy object.
   CRMQuery query = new CRMQuery();
   query.Url = strCRMURL + "CRMQuery.srf";
   query.Credentials = bizUser.Credentials;

   // Authenticate the Microsoft CRM user.
   CUserAuth userAuth = bizUser.WhoAmI();

   // Retrieve a list consisting of the CFPContactEmailAddress 
   // codes and values.
   string strPicklistValues = picklist.RetrievePicklist(userAuth,
               Microsoft.Crm.Platform.Types.ObjectType.otContact,
               "CFPcontactemailaddress");

   // Create XML parsing objects.
   NameTable nt = new NameTable();
   XmlNamespaceManager nsmgr = new XmlNamespaceManager(nt);
   nsmgr.AddNamespace("ms", "urn:microsoft.com");
   XmlParserContext context = new XmlParserContext(null, nsmgr, null,
                                                   XmlSpace.None);
   XmlTextReader tr = new XmlTextReader(strPicklistValues,
                                        XmlNodeType.Element, context);

   // Retrieve the e-mail address in the picklist 
   // corresponding to the specified code.
   XMLTextReaderSample.ParseXMLString objParseXMLString 
                           = new XMLTextReaderSample.ParseXMLString();
   string strCustomEmailAddress 
                   = objParseXMLString.ParseXML(strPicklistValues,
                                         strOrdinalPositionInPicklist);

   // Create a fetch specification to retrieve IDs 
   // for all users matching this e-mail address. 
   StringBuilder strQuery = new StringBuilder();
   strQuery.Append("<fetch mapping='logical'><entity name='systemuser'>");
   strQuery.Append("<attribute name = 'systemuserid'/>");
   strQuery.Append("<filter type='and'>");
   strQuery.Append("<condition attribute = 'internalemailaddress' ");
   strQuery.Append("operator='eq' value='");
   strQuery.Append(strCustomEmailAddress);
   strQuery.Append("'/>");
   strQuery.Append("</filter>");
   strQuery.Append("</entity></fetch>");

   // Execute the query.
   string strContactXml = query.ExecuteQuery(userAuth, strQuery.ToString());

   // Get the user from the query results.
   XmlDocument xmlDoc = new XmlDocument();
   xmlDoc.LoadXml(strContactXml);
   XmlNodeList xmlNodes = xmlDoc.GetElementsByTagName("systemuserid");

   if (xmlNodes != null && xmlNodes.Count != 0)
   {
      return xmlNodes.Item(0).InnerText;
   }

   string strError = "No matching user found for this e-mail address: ";
   throw new Exception(strError + strCustomEmailAddress);}

Step 2: Construct the e-mail body

The following code is used to build a message body consisting of the new contact's name and telephone number.

private string CreateMessageBody(string strCRMURL, string strContactID)
{
   // Create BizUser proxy object.
   BizUser bizUser = new BizUser();
   bizUser.Url = strCRMURL + "BizUser.srf";
   bizUser.Credentials = System.Net.CredentialCache.DefaultCredentials;

   // Create CRMCustomization proxy object.
   CRMCustomization picklist = new CRMCustomization();
   picklist.Url = strCRMURL + "CRMCustomization.srf";
   picklist.Credentials = bizUser.Credentials;

   // Create CRMContact proxy object.
   CRMContact contact = new CRMContact();
   contact.Url = strCRMURL + "CRMContact.srf";
   contact.Credentials = bizUser.Credentials;

   // Authenticate the Microsoft CRM user.
   CUserAuth userAuth = bizUser.WhoAmI();

   // Create a columset specification to retrieve
   // the contact's name and telephone number.
   string strColumnSet = 
      @"<columnset>
         <column>fullname</column>
         <column>telephone1</column>
      </columnset>";

   // Retrieve the information for this contact.
   string strContactXml = contact.Retrieve(userAuth, strContactID,
                                           strColumnSet);

   // Parse the values from the resultset.
   string strContactName = "";
   string strPhoneNumber = "";

   XmlDocument xmlDoc = new XmlDocument();
   xmlDoc.LoadXml(strContactXml);

   XmlNodeList xmlNodes = xmlDoc.GetElementsByTagName("fullname");
   if (xmlNodes != null && xmlNodes.Count != 0)
   {
      strContactName = xmlNodes.Item(0).InnerText;
   }
   else 
   {
      string strError = "No contact was found.";
      throw new Exception(strError);
   }

   xmlNodes = xmlDoc.GetElementsByTagName("telephone1");
   if (xmlNodes != null && xmlNodes.Count != 0)
   {
      strPhoneNumber = xmlNodes.Item(0).InnerText;
   } 

   // Build the e-mail message body.
   StringBuilder strMessage = new StringBuilder("The following new contact ");
   strMessage.AppendFormat("Contact Name: {0} &lt;br&gt;");
   strMessage.AppendFormat(strContactName);
   strMessage.AppendFormat("Phone Number: {0} &lt;br&gt;");
   strMessage.AppendFormat(strPhoneNumber);
   return strMessage.ToString();
}

Step 3: Send the e-mail

The following code is used to send the e-mail.

private string SendEmail(string strCRMURL, string strCustomRecipientID,
                         string strContactID, string strBody)
{
   // Create BizUser proxy object.
   BizUser bizUser = new BizUser();
   bizUser.Credentials = System.Net.CredentialCache.DefaultCredentials;
   bizUser.Url = strCRMURL + "BizUser.srf";

   // Create CRMActivity proxy object.
   CRMActivity activity = new CRMActivity();
   activity.Credentials = bizUser.Credentials;
   activity.Url = strCRMURL + "CRMActivity.srf";

   // Create CRMEmail proxy object.
   CRMEmail email = new CRMEmail();
   email.Credentials = bizUser.Credentials;
   email.Url = strCRMURL + "CRMEmail.srf";

   // Authenticate the Microsoft CRM user.
   CUserAuth userAuth = bizUser.WhoAmI();

   StringBuilder strActivityXml = new StringBuilder();
   strActivityXml.Append("<emailactivity>");
   strActivityXml.Append("<messagesubject>");
   strActivityXml.Append("A new contact has been created.");
   strActivityXml.Append("</messagesubject>");
   strActivityXml.Append("<messagebody>");
   strActivityXml.Append(strBody);
   strActivityXml.Append("</messagebody>");
   strActivityXml.Append("<objectid>");
   strActivityXml.Append(strContactID);
   strActivityXml.Append("</objectid>");
   strActivityXml.Append("<objecttypecode>");
   strActivityXml.Append(Microsoft.Crm.Platform.Types.ObjectType.otContact);
   strActivityXml.Append("</objecttypecode>");
   strActivityXml.Append("<ownerid type='");
   strActivityXml.Append(Microsoft.Crm.Platform.Types.ObjectType.otSystemUser);
   strActivityXml.Append("'>");
   strActivityXml.Append(userAuth.UserId);
   strActivityXml.Append("</ownerid>");
   strActivityXml.Append("</emailactivity>");

   StringBuilder strPartiesXml =  new StringBuilder();
   strPartiesXml.Append("<activityparties>");

   // Add the recipient.
   strPartiesXml.Append("<activityparty>");
   strPartiesXml.Append("<partyobjecttypecode>");
   strPartiesXml.Append(Microsoft.Crm.Platform.Types.ObjectType.otSystemUser);
   strPartiesXml.Append("</partyobjecttypecode>"); 
   strPartiesXml.Append("<partyid>");
   strPartiesXml.Append(strCustomRecipientID);
   strPartiesXml.Append("</partyid>");
   strPartiesXml.Append("<participationtypemask>2</participationtypemask>");
   strPartiesXml.Append("</activityparty>");

   // Add the logged on user as the sender.
   strPartiesXml.Append("<activityparty>"); 
   strPartiesXml.Append("<partyobjecttypecode>");
   strPartiesXml.Append(Microsoft.Crm.Platform.Types.ObjectType.otSystemUser);
   strPartiesXml.Append("</partyobjecttypecode>"); 
   strPartiesXml.Append("<partyid>");
   strPartiesXml.Append(userAuth.UserId);
   strPartiesXml.Append("</partyid>");
   strPartiesXml.Append("<participationtypemask>1</participationtypemask>");
   strPartiesXml.Append("</activityparty>");

   strPartiesXml.Append("</activityparties>");

   string strActivityEmailId = email.Create(userAuth,
                    strActivityXml.ToString(), strPartiesXml.ToString());
   string strEmailResult = email.Send(userAuth, strActivityXml.ToString(),
                    strPartiesXml.ToString());

   return strActivityEmailId + " : " + strEmailResult;
}

Step 4: Write to the log file

The following code creates a simple log file.

private void WriteToLog(string strLog)
{
   FileStream fs 
      = new FileStream(@"C:\inetpub\wwwroot\createemailactivity\MyLog.txt",
           FileMode.Append, FileAccess.Write);
   StreamWriter sr = new StreamWriter(fs);
   sr.WriteLine(strLog);
   sr.Flush();
   sr.Close();
}

About the XML Helper Class

This helper class was created specifically to retrieve Value attributes from Microsoft CRM drop-down lists (picklists).

namespace XMLTextReaderSample
{
   /// <summary>
   /// A helper function that is used to retrive "value" attributes from 
   /// Microsoft CRM picklists.
   /// </summary>
   public class ParseXMLString
   {
      public string ParseXML(string strXMLStringToParse, 
         string strCodeToMatch)
      {
         NameTable nt = new NameTable();
         XmlNamespaceManager nsmgr = new XmlNamespaceManager(nt);
         XmlParserContext context = new XmlParserContext(null, nsmgr,
                                            null, XmlSpace.None);
         XmlTextReader tr = new XmlTextReader(strXMLStringToParse, 
                                        XmlNodeType.Element, context);

         while(!tr.EOF)
         {
            if(tr.MoveToContent()== XmlNodeType.Element && tr.Name=="Code")
            {
               string strCode=tr.ReadElementString();
               if (strCode == strCodeToMatch)
               {
                  while(tr.Name != "Value" && !tr.EOF)
                  {
                     tr.Read();
                  }
                  return tr.ReadElementString();
               }
            }
            else
            {
               tr.Read();
            }
         }
         return "No match found";
      }
   }
}

Create the Custom Fields in Microsoft CRM

Now that you have the sample code installed on you computer, you need to customize Microsoft CRM by adding the custom fields needed by the application. Also, you must create a user for each applicable e-mail recipient.

Create the custom drop-down list (picklist) field

  1. From the Start menu, click Programs, point to Microsoft CRM, and then click Deployment Manager.
  2. Expand Schema Manager. Scroll to Contacts and click it to expand this entity.
  3. Right-click Attributes, select New and click Schema Field.
  4. For the field name, enter contactemailaddress and set the type to Picklist. Enter CFPcontactEmailAddress as the Display name. Enter a short description for this field.
  5. Click OK.

The Schema Manager will add the CFP prefix to identify it as a custom field. The resulting field name will be CFPcontactemailaddress, as shown in figure 1.

Figure 1. Add the custom drop-down list (picklist) field to the contact form and add values to the field

  1. Open Microsoft CRM, click Settings and then click System Customization.

  2. Select Contacts from the list and in the Common Tasks area, click Customize Form.

  3. On the contact form, click the Administration tab, click the Internal Information section, and then click Add Fields in the Common Tasks area, which is on the right side of the window.

  4. In the Add Fields dialog box, scroll to find the new field CFPcontactEmailAddress, add it to the form, and click OK, as shown in figure 2.

    Click here to see larger image

    Figure 2. Click picture to see larger image

  5. Once the custom drop-down list (picklist) field is on the contact form, double-click it to access the properties. Change the Name and the Label to Notify E-Mail, as shown in figure 3.

    Click here to see larger image

    Figure 3. Click picture to see larger image

  6. Click the Values tab of the Properties window and enter the e-mail addresses of the recipients of the e-mail notification, as shown in the following figure. These e-mail addresses must match the e-mail addresses of users in the Microsoft CRM database.

    Click here to see larger image

    Figure 4. Click picture to see larger image

  7. Click OK to close the Properties window and then click the Save and Close button on the contact form.

Publish customizations in Deployment Manager and reset IIS

  1. In Deployment Manager, right-click Deployment Manager, select All Tasks and click Publish Customization.
  2. In the Publish Objects dialog box, select Contact and click Next.
  3. In the Publish to Web Servers dialog box, click the Add button, select your Microsoft CRM server, click Add and then click Finish.
  4. When the Status dialog box is displayed, click OK.
  5. To reset IIS, from the Start menu click Run. Type iisreset in the Open box and click OK.

Create users in Microsoft CRM for the e-mail recipients

If the users in your drop-down list (picklist) do not already exist, add them to Microsoft CRM. Remember that these users must be created in Active Directory® before they can be added to Microsoft CRM.

  1. Open Microsoft CRM, click Settings and then click Business Unit Settings.
  2. Click Users.
  3. In the upper-right corner, click the New User button.
  4. Populate at least the First Name, Last Name, and Primary E-mail fields.

Repeat these steps for each e-mail recipient listed in the Notify E-mail drop-down list (picklist).

Create and Activate a PostURL Workflow Rule

The following steps describe creating the workflow rule using the Workflow Manager:

  1. From the Start menu, select Programs, navigate to Microsoft CRM and click Workflow Manager to open it.
  2. Select Contact from the Object list, click File and then click New.
  3. Name the new rule, type a description, and set the event to Create.
  4. Click Next.
  5. In the Select Behavior dialog box, click the Insert Action link and choose Post URL.
  6. In the Post URL dialog box, specify the URL that you want to send the information to and make sure to include the method that will be consuming the data. For this example, set the URL to https://MyServerName/CreateEMailActivity/CreateEmailActivity.asmx/CreateAndSendEmailActivity.
  7. Insert the fields you want to send to the URL in the Selected list box. For this example, insert the contactid and CFPcontactEmailAddress fields.
  8. Click OK to close the Post URL dialog box.
  9. Click Save to save and close the workflow rule.
  10. To activate the rule, right-click the rule in Workflow Manager and select Activate.
  11. Close Workflow Manager.

Test the Customization

The following steps describe how to test the example application:

  1. Start Microsoft CRM.
  2. Create a new contact, fill in the required information and at least the first name, last name, and phone number. Select a value in the Notify E-mail field you added to the contact form, and then click Save, as shown in figure 5.

Click here to see larger image

Figure 5. Click picture to see larger image

The workflow rule will be executed, resulting in an e-mail similar to the one in figure 6.

Click here to see larger image

Figure 6. Click picture to see larger image

Conclusion

The steps discussed in the previous sections result in a post to the custom Web service, passing the Notify E-mail field value and the contactid. The Web service then executes a query back into the Microsoft CRM platform to get the actual value of the custom drop-down list (picklist) field because the PostURL passes only the ordinal position of the selected value. Once the e-mail address and its associated user are retrieved, an e-mail activity is created and sent. A text file is created on the local C:\ drive for debugging purposes.

Note   This solution is provided as is. Any customizations performed against it are at your own risk. This solution has been tested; however, that does not guarantee it will work in your environment without modification to the actual code.

Additional Information

For more information about customizing the Microsoft CRM application, see the Microsoft CRM Software Development Kit (SDK).