//# Send a Bulk E-mail and Monitor the Job
using System;
using CrmSdk;
using Microsoft.Crm.Sdk.Utility;
namespace Microsoft.Crm.Sdk.HowTo.BulkOperation
{
public class SendBulkEmailAndMonitor
{
public SendBulkEmailAndMonitor()
{
}
public static bool Run(string crmServerUrl, string orgName)
{
bool success = false;
try
{
// Set up the CRM Service.
CrmService service = Microsoft.Crm.Sdk.Utility.CrmServiceUtility.GetCrmService(crmServerUrl, orgName);
service.PreAuthenticate = true;
// Create some contacts to send a bulk e-mail to.
// Typically, this would be an existing list of customers, such as a marketing list.
object[] contactIds = new object[2];
contact emailContact1 = new contact();
emailContact1.firstname = "Adam";
emailContact1.lastname = "Carter";
emailContact1.emailaddress1 = "adam.carter@example.com";
// Create the contact.
contactIds[0] = service.Create(emailContact1);
contact emailContact2 = new contact();
emailContact2.firstname = "Adina";
emailContact2.lastname = "Hagege";
emailContact2.emailaddress1 = "adina.hagege@example.com";
// Create the contact.
contactIds[1] = service.Create(emailContact2);
// Create the bulk mail request.
SendBulkMailRequest bulkMailRequest = new SendBulkMailRequest();
// Create a query expression for the bulk operation to use to retrieve
// the contacts in our e-mail list.
ConditionExpression condition = new ConditionExpression();
condition.AttributeName = "contactid";
condition.Operator = ConditionOperator.In;
condition.Values = contactIds;
FilterExpression filterExpression = new FilterExpression();
filterExpression.Conditions = new ConditionExpression[] { condition };
ColumnSet returnColumns = new ColumnSet();
returnColumns.Attributes = new string[] { "contactid" };
QueryExpression queryRequest = new QueryExpression();
queryRequest.ColumnSet = returnColumns;
queryRequest.EntityName = EntityName.contact.ToString();
queryRequest.Criteria = filterExpression;
// Attach the contact query to the bulk e-mail request.
bulkMailRequest.Query = queryRequest;
// Get a system user to use as the sender.
bulkMailRequest.Sender = GetEmailSenderMoniker(service);
// Set the RegardingId to the e-mail sender.
bulkMailRequest.RegardingId = bulkMailRequest.Sender.Id;
bulkMailRequest.RegardingType = EntityName.systemuser.ToString();
// Use a built-in e-mail template.
// NOTE: The e-mail template's 'template type' must match the type of customers
// in the e-mail list. Our list contains contacts, so our template must be for contacts.
bulkMailRequest.TemplateId = new Guid("07B94C1D-C85F-492F-B120-F0A743C540E6");
// Create a tracking ID for the bulk operation to monitor its progress.
RequestIdOptionalParameter trackingId = new RequestIdOptionalParameter();
trackingId.Value = Guid.NewGuid();
// Attach the tracking ID to the bulk e-mail request.
bulkMailRequest.OptionalParameters = new OptionalParameter[] { trackingId };
// Execute the async bulk e-mail request.
service.Execute(bulkMailRequest);
// Now that we have executed the bulk operation, we have to retrieve it using our tracking ID.
ColumnSet asyncColumns = new ColumnSet();
asyncColumns.Attributes = new string[] { "requestid", "statecode" };
QueryByAttribute bulkQuery = new QueryByAttribute();
bulkQuery.ColumnSet = asyncColumns;
bulkQuery.EntityName = EntityName.asyncoperation.ToString();
bulkQuery.Attributes = new string[] { "requestid" };
bulkQuery.Values = new object[1];
bulkQuery.Values[0] = trackingId.Value;
// Retrieve the bulk e-mail async operation.
BusinessEntityCollection aResponse = service.RetrieveMultiple(bulkQuery);
// Monitor the async operation through polling.
const int ARBITRARY_MAX_POLLING_TIME = 60;
int secondsTicker = ARBITRARY_MAX_POLLING_TIME;
asyncoperation createdBulkMailOperation = null;
while (secondsTicker > 0)
{
// Make sure that the async operation was retrieved.
if (aResponse.BusinessEntities.Length > 0)
{
// Grab the one bulk operation that was created.
createdBulkMailOperation = (asyncoperation)aResponse.BusinessEntities[0];
// Check the operation's state.
if (createdBulkMailOperation.statecode.Value != AsyncOperationState.Completed)
{
// The operation has not yet completed. Wait a second for the status to change.
System.Threading.Thread.Sleep(1000);
secondsTicker--;
// Retrieve a fresh version the bulk delete operation.
aResponse = service.RetrieveMultiple(bulkQuery);
}
else
{
// Stop polling because the operation's state is now completed.
secondsTicker = 0;
}
}
else
{
// Wait a second for the async operation to become active.
System.Threading.Thread.Sleep(1000);
secondsTicker--;
// Retrieve the entity again.
aResponse = service.RetrieveMultiple(bulkQuery);
}
}
// When the bulk e-mail operation has finished, all sent e-mail messages will have a status of "Pending Send" and
// will be picked up by your e-mail router. Or, you can then use BackgroundSendEmail to download
// all the e-mail messages that were created by using the SendBulkEmail message. See the BackgroundSendEmail sample for an example.
#region check success
// Validate async operation succeeded.
if (createdBulkMailOperation.statecode.Value == AsyncOperationState.Completed)
{
success = true;
}
#endregion
#region Remove Data Required for this Sample.
// Delete the sent e-mail messages.
ColumnSet sentMailColumns = new ColumnSet();
sentMailColumns.Attributes = new string[] { "statuscode" };
ConditionExpression statusCondition = new ConditionExpression();
statusCondition.AttributeName = "statuscode";
statusCondition.Operator = ConditionOperator.Equal;
statusCondition.Values = new object[] { EmailStatus.PendingSend };
// Create the query filter.
FilterExpression emailFilter = new FilterExpression();
emailFilter.Conditions = new ConditionExpression[] { statusCondition };
emailFilter.FilterOperator = LogicalOperator.And;
// Query for e-mail activity.
QueryExpression emailsQuery = new QueryExpression();
emailsQuery.ColumnSet = sentMailColumns;
emailsQuery.EntityName = EntityName.email.ToString();
emailsQuery.Criteria = emailFilter;
// Retrieve the e-mail activity.
BusinessEntityCollection emails = service.RetrieveMultiple(emailsQuery);
foreach (email sentMail in emails.BusinessEntities)
{
service.Delete(EntityName.email.ToString(), sentMail.activityid.Value);
}
// Delete the contacts created for e-mails.
foreach (Guid createdContactId in contactIds)
{
service.Delete(EntityName.contact.ToString(), createdContactId);
}
#endregion
}
catch (System.Web.Services.Protocols.SoapException)
{
// Perform error handling here.
throw;
}
catch (Exception)
{
throw;
}
return success;
}
///
/// Retrieves a systemuser to use as the sender of an e-mail.
///
/// The CRM service
/// Moniker to use as e-mail sender
public static Moniker GetEmailSenderMoniker(CrmService service)
{
Moniker emailSender = new Moniker();
ColumnSet selectClause = new ColumnSet();
selectClause.Attributes = new string[] { "fullname" };
QueryExpression allSystemUsersQuery = new QueryExpression();
allSystemUsersQuery.EntityName = EntityName.systemuser.ToString();
allSystemUsersQuery.ColumnSet = selectClause;
// Create the query request.
RetrieveMultipleRequest allSystemUsersRequest = new RetrieveMultipleRequest();
allSystemUsersRequest.Query = allSystemUsersQuery;
// Execute the request.
RetrieveMultipleResponse allSystemUsersResponse = (RetrieveMultipleResponse)service.Execute(allSystemUsersRequest);
// Grab a system user for the bulk e-mail.
if (allSystemUsersResponse.BusinessEntityCollection.BusinessEntities.Length > 0)
{
// For demonstration, grab the first system user.
systemuser emailUser = (systemuser)allSystemUsersResponse.BusinessEntityCollection.BusinessEntities[0];
emailSender.Id = emailUser.systemuserid.Value;
emailSender.Name = EntityName.systemuser.ToString();
}
else
{
// If no system user was found, we cannot continue with bulk e-mail.
throw (new Exception("No system user found to send e-mail."));
}
return emailSender;
}
}
}