Sample: Manage lists and send transactional or commercial email

 

Applies To: Dynamics Marketing

This sample code is for Microsoft Dynamics Marketing. The sample code can be found in the following location after you download and install the Microsoft Dynamics Marketing SDK:

Samples\CS\EmailMessageSample

Requirements

Note

This sample works with your live production data. It may create contact objects in your Microsoft Dynamics Marketing and Microsoft Dynamics CRM environments. In addition, it will send emails to the designated recipients.

Tip

  • You should allocate some email addresses that actually exist as a test audience, and then write scenario tests that run against the test audience. Create a marketing list specifically for testing mails and create test contacts with email addresses you control as an audience for testing your email marketing messages and SDK integration.

  • Use email marketing message testing functions to determine if the email messages are formatted correctly before sending the email messages.

Demonstrates

This sample demonstrates how to retrieve and send email marketing emails that are marked “Send Externally”, and send commercial email marketing messages using Dynamics Marketing. Additionally, this sample also demonstrates how to set and retrieve contact permissions for a single or multiple email addresses, retrieve list of email addresses for which contact permissions are missing, and get or set email hard bounces to be processed for a contact.

Example

namespace Microsoft.Dynamics.Marketing.SDK.Samples.EmailMessageSample
{
    using System;
    using System.Collections.Generic;
    using System.Globalization;
    using System.Linq;
    using Microsoft.Dynamics.Marketing.SDK.Common;
    using Microsoft.Dynamics.Marketing.SDK.Messages;
    using Microsoft.Dynamics.Marketing.SDK.Messages.EmailMessage;
    using Microsoft.Dynamics.Marketing.SDK.Model;
    using Microsoft.Dynamics.Marketing.SDK.Samples.SdkClient;
    using Microsoft.Dynamics.Marketing.SDK.Samples.SdkSample;
    using Microsoft.Dynamics.Marketing.SDK.Messages.EmailMarketingResult;

    /// <summary>
    /// Demonstrates how to send and receive transactional and commercial email messages.
    /// </summary>
    /// <remarks>
    /// Depending on which part of the sample you run, some prior set up is required.
    /// For all of the options in this sample you must have the SDK configured with your Microsoft Azure Service Bus queues on the Integration Options page in Microsoft Dynamics Marketing.
    /// You must also have permissions enabled for email messages.
    /// </remarks>
    public class EmailMessageSample : SdkSample
    {
        /// <summary>
        /// Starting point for the sample.
        /// </summary>
        /// <param name="args">Arguments needed for authentication.</param>
        public static void Main(string[] args)
        {
            try
            {
                // This creates the QueueClientProvider that connects to the queues, tests them, and then provides them to the client when needed.
                var queueClientProvider = CreateQueueClientProviderFromArgs(args);

                // This runs the sample that shows a menu of possible requests.
                var sample = new EmailMessageSample(queueClientProvider);
                sample.Run();
            }
            catch (Exception ex)
            {
                EmailMessageSample.WriteException(ex);
                Console.WriteLine("Press enter to exit.");
                Console.ReadLine();
                return;
            }
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="EmailMessageSample"/> class.
        /// </summary>
        /// <param name="queueClientProvider">The <see cref="IQueueClientProvider"/> that’s set up to connect to the SDK queues configured in Microsoft Dynamics Marketing.</param>
        public EmailMessageSample(IQueueClientProvider queueClientProvider)
        {
            var responseHandlerMapping = new Dictionary<Type, Client.ResponseHandler>
            {
                { typeof(RetrieveEmailMessagesResponse), this.ProcessRetrieveEmailMessagesResponse },
                { typeof(RetrieveCommercialEmailMessagesResponse), this.ProcessRetrieveCommercialEmailMessagesResponse },
                { typeof(RetrieveMessageSchemaForEmailMessageResponse), this.ProcessRetrieveMessageSchemaForEmailMessageResponse },
                { typeof(SendEmailMessageByEmailResponse), this.ProcessSendEmailMessageResponse },
                { typeof(SendEmailMessageByIdResponse), this.ProcessSendEmailMessageResponse },
                { typeof(SendCommercialEmailMessageByIdResponse), this.ProcessSendCommercialEmailMessageByIdResponse },
                { typeof(RetrieveEmailMessageSentStatusResponse), this.ProcessRetrieveEmailMessageSentStatusResponse },
                { typeof(SetContactPermissionsResponse), this.ProcessSetContactPermissionsResponse },
                { typeof(SetContactsPermissionsResponse), this.ProcessSetContactsPermissionsResponse },
                { typeof(RetrieveContactPermissionsResponse), this.ProcessRetrieveContactPermissionsResponse },
                { typeof(RetrieveMissingContactPermissionsResponse), this.ProcessRetrieveMissingContactPermissionsResponse },
                { typeof(SetEmailHardBouncesToProcessedForContactResponse), this.ProcessSetEmailHardBouncesToProcessedForContactResponse },
                { typeof(RetrieveUnprocessedEmailHardBouncesResponse), this.ProcessRetrieveUnprocessedEmailHardBouncesResponse },
                { typeof(RetrieveEmailMarketingResultsResponse), this.ProcessRetrieveEmailMarketingResults },
                { typeof(SdkErrorResponse), this.ProcessSdkErrorResponse }
            };

            this.SetupClient(queueClientProvider, responseHandlerMapping);

            this.SampleMenuActions = new Dictionary<string, Tuple<string, Action>>
            {
                { "1", new Tuple<string, Action>("Retrieve transaction email messages", this.RetrieveEmailMessages) },
                { "2", new Tuple<string, Action>("Retrieve commercial email messages", this.RetrieveCommercialEmailMessages) },
                { "3", new Tuple<string, Action>("Retrieve message schema for email message", this.RetrieveMessageSchemaForEmailMessage) },
                { "4", new Tuple<string, Action>("Send email message by email", this.SendEmailMessageByEmail) },
                { "5", new Tuple<string, Action>("Send email message by ID", this.SendEmailMessageById) },
                { "6", new Tuple<string, Action>("Send commercial email message", this.SendCommercialEmailMessageById) },
                { "7", new Tuple<string, Action>("Retrieve email message sent status", this.RetrieveEmailMessageSentStatus) },
                { "8", new Tuple<string, Action>("Set contact permissions for an email address", this.SetContactPermissions) },
                { "9", new Tuple<string, Action>("Set contact permissions for multiple email addresses", this.SetContactsPermissions) },
                { "10", new Tuple<string, Action>("Retrieve contact permissions for an email address", this.RetrieveContactPermissions) },
                { "11", new Tuple<string, Action>("Retrieve list of email addresses for which contact permissions are missing", this.RetrieveMissingContactability) },
                { "12", new Tuple<string, Action>("Set email hard bounces to processed for a contact", this.SetEmailHardBouncesToProcessedForContact) },
                { "13", new Tuple<string, Action>("Retrieve unprocessed email hard bounces", this.RetrieveUnprocessedEmailHardBounces) },
                { "14", new Tuple<string, Action>("Retrieve email marketing results", this.RetrieveEmailMarketingRequest) }
            };
        }

        /// <summary>
        /// Demonstrates RetrieveEmailMessagesRequest and RetrieveEmailMessagesResponse.
        /// </summary>
        /// <remarks>
        /// If you want to see this sample return something other than Count: 0, you need to create some transaction emails in Microsoft Dynamics Marketing where the Send Externally option is checked.
        /// </remarks>
        private void RetrieveEmailMessages()
        {
            Console.WriteLine("This request retrieves all transaction email messages.");

            Console.Write("Enter offset - or empty for the first set of records =>");
            var offset = Console.ReadLine();
            int skipNumberOfRecords;
            int.TryParse(offset, out skipNumberOfRecords);

            var request = new RetrieveEmailMessagesRequest { MaxNumberOfRecordsToGet = 100, SkipNumberOfRecords = skipNumberOfRecords };

            this.Client.ProcessRequest(request);
        }

        /// <summary>
        /// Handles the RetrieveEmailMessagesResponse that is received from the response queue. Displays the count and list of transaction email messages that can be sent using the SDK.
        /// </summary>
        /// <param name="response">The RetrieveEmailMessagesResponse received after sending a RetrieveEmailMessagesRequest.</param>
        private void ProcessRetrieveEmailMessagesResponse(SdkResponse response)
        {
            var retrieveEmailMessagesResponse = (RetrieveEmailMessagesResponse)response;
            Console.WriteLine("Processing RetrieveEmailMessagesResponse.");
            Console.WriteLine("Transaction email message count: {0}", retrieveEmailMessagesResponse.EmailMessages.Count);

            foreach (var emailMessage in retrieveEmailMessagesResponse.EmailMessages)
            {
                Console.WriteLine("ID: {0}  Name: {1} Subject: {2}", emailMessage.Id, emailMessage.Name, emailMessage.Subject);
            }
        }

        /// <summary>
        /// Demonstrates RetrieveCommercialEmailMessagesRequest and RetrieveEmailMessagesResponse.
        /// </summary>
        /// <remarks>
        /// If you want to see this sample return something other than Count: 0, you need to create some commercial emails in Microsoft Dynamics Marketing where the Send Externally option is checked.
        /// </remarks>
        private void RetrieveCommercialEmailMessages()
        {
            Console.WriteLine("This request retrieves all commercial email messages.");

            Console.Write("Enter offset - or empty for the first set of records =>");
            var offset = Console.ReadLine();
            int skipNumberOfRecords;
            int.TryParse(offset, out skipNumberOfRecords);

            var request = new RetrieveCommercialEmailMessagesRequest { MaxNumberOfRecordsToGet = 100, SkipNumberOfRecords = skipNumberOfRecords };

            this.Client.ProcessRequest(request);
        }

        /// <summary>
        /// Handles the RetrieveCommercialEmailMessagesResponse that is received from the response queue. Displays the count and list of email messages that can be sent using the SDK.
        /// </summary>
        /// <param name="response">The RetrieveCommercialEmailMessagesResponse received after sending a RetrieveCommercialEmailMessagesRequest.</param>
        private void ProcessRetrieveCommercialEmailMessagesResponse(SdkResponse response)
        {
            var retrieveCommerciaEmailMessagesResponse = (RetrieveCommercialEmailMessagesResponse)response;
            Console.WriteLine("Processing RetrieveCommercialEmailMessagesResponse.");
            Console.WriteLine("Commercial email message count: {0}", retrieveCommerciaEmailMessagesResponse.EmailMessages.Count);

            foreach (var emailMessage in retrieveCommerciaEmailMessagesResponse.EmailMessages)
            {
                Console.WriteLine("ID: {0}  Name: {1} Subject: {2}", emailMessage.Id, emailMessage.Name, emailMessage.Subject);
            }
        }

        /// <summary>
        /// Demonstrates RetrieveMessageSchemaForEmailMessageRequest and RetrieveMessageSchemaForEmailMessageResponse.
        /// </summary>
        /// <remarks>
        /// In Microsoft Dynamics Marketing, you need an email marketing message marked Send Externally and it must have an external content schema attached. You can get its external ID from the grid of email marketing messages.
        /// </remarks>
        private void RetrieveMessageSchemaForEmailMessage()
        {
            Console.WriteLine("This request retrieves the external content schema for a given email marketing message.");
            Console.Write("Email message ID: ");
            var emailMessageId = Console.ReadLine();

            var request = new RetrieveMessageSchemaForEmailMessageRequest()
            {
                EmailMessageId = new Guid(emailMessageId)
            };

            this.Client.ProcessRequest(request);
        }

        /// <summary>
        /// Handles the RetrieveMessageSchemaForEmailMessageResponse received from the response queue. Displays the schema for the email message.
        /// </summary>
        /// <param name="response">The RetrieveMessageSchemaForEmailMessageResponse received after sending a RetrieveMessageSchemaForEmailMessageRequest.</param>
        private void ProcessRetrieveMessageSchemaForEmailMessageResponse(SdkResponse response)
        {
            var retrieveMessageSchemaForEmailMessageResponse = (RetrieveMessageSchemaForEmailMessageResponse)response;
            Console.WriteLine("Processing RetrieveMessageSchemaForEmailMessageResponse.");

            Console.WriteLine("Schema: {0}", retrieveMessageSchemaForEmailMessageResponse.MessageSchema);
        }

        /// <summary>
        /// Demonstrates SendEmailMessageByEmailRequest and SendEmailMessageByEmailResponse.
        /// </summary>
        /// <remarks>
        /// In Microsoft Dynamics Marketing, you need an email marketing message marked Send Externally. You can get its external ID from the grid of email marketing messages.
        /// If the email address that you provide is connected to a contact in the system, the email will be sent to that contact and results will be associated with the same contact. However, if the email address
        /// doesn’t exist in the system, a new contact will be created. Depending on your Contact Reconciliation settings, this contact may be inactive.
        /// If your email message has an external content schema associated with it, you’ll need to pass an XML blob to the MessageData of the SendEmailMessageByEmailRequest.
        /// As an optional setting, you can override the default Importance of the message by setting it on the SendEmailMessageByEmailRequest.
        /// As an optional setting, you can override the contact that the email will be sent from by setting the SenderId property on the SendEmailMessageByEmailRequest to the external ID of a contact in Microsoft Dynamics Marketing.
        /// </remarks>
        private void SendEmailMessageByEmail()
        {
            Console.WriteLine("This request sends an email message.");
            Console.Write("Recipient email: ");
            var recipientEmail = Console.ReadLine();
            Console.Write("Email message ID: ");
            var emailMessageId = Console.ReadLine();

            var request = new SendEmailMessageByEmailRequest()
            {
                EmailMessageId = new Guid(emailMessageId),
                RecipientEmailAddress = recipientEmail
            };

            this.Client.ProcessRequest(request);
        }

        /// <summary>
        /// Demonstrates SendEmailMessageByIdRequest and SendEmailMessageByIdResponse.
        /// </summary>
        /// <remarks>
        /// In Microsoft Dynamics Marketing, you need an email marketing message marked Send Externally. You can get its external ID from the grid of email marketing messages.
        /// You also need a contact with an email address. You can get its external ID from the grid of contacts.
        /// If your email message has an external content schema associated with it, you’ll need to pass an XML blob to the MessageData of the SendEmailMessageByEmailRequest.
        /// As an optional setting, you can override the default Importance of the message by setting it on the SendEmailMessageByEmailRequest.
        /// As an optional setting, you can override the contact that the email will be sent from by setting the SenderId property on the SendEmailMessageByEmailRequest to the external ID of a contact in Microsoft Dynamics Marketing.
        /// </remarks>
        private void SendEmailMessageById()
        {
            Console.WriteLine("This request sends an email message.");
            Console.Write("Recipient ID: ");
            var recipientId = Console.ReadLine();
            Console.Write("Email message ID: ");
            var emailMessageId = Console.ReadLine();

            var request = new SendEmailMessageByIdRequest()
            {
                EmailMessageId = new Guid(emailMessageId),
                RecipientId = new Guid(recipientId)
            };

            this.Client.ProcessRequest(request);
        }

        /// <summary>
        /// Handles the SendEmailMessageResponse received from the response queue. Displays the queued status and tracking information for the email.
        /// </summary>
        /// <param name="response">The SendEmailMessageResponse received after sending a SendEmailMessageByIdRequest or a SendEmailMessageByEmailRequest.</param>
        private void ProcessSendEmailMessageResponse(SdkResponse response)
        {
            var sendEmailMessageResponse = (SendEmailMessageResponse)response;
            Console.WriteLine("Processing SendEmailMessageResponse.");
            if (sendEmailMessageResponse.QueuedSuccessfully)
            {
                Console.WriteLine(
                    "Successfully queued: {0} Tracking item ID: {1}",
                    sendEmailMessageResponse.QueuedSuccessfully.ToString(CultureInfo.InvariantCulture),
                    sendEmailMessageResponse.TrackingItemId.ToString());
            }
            else
            {
                Console.WriteLine(sendEmailMessageResponse.Message);
            }
        }

        /// <summary>
        /// Demonstrates SendCommercialEmailMessageByIdRequest and SendCommercialEmailMessageByIdResponse.
        /// </summary>
        /// <remarks>
        /// In Microsoft Dynamics Marketing, you need an commercial email marketing message marked Send Externally. You can get its external ID from the grid of email marketing messages.
        /// If your email message has an external content schema associated with it, you’ll need to pass an XML blob to the MessageData of the SendCommercialEmailMessageByIdRequest.
        /// As an optional setting, you can override the default Importance of the message by setting it on the SendCommercialEmailMessageByIdRequest.
        /// As an optional setting, you can override the contact that the email will be sent from by setting the SenderId property on the SendCommercialEmailMessageByIdRequest to the external ID of a contact in Microsoft Dynamics Marketing.
        /// </remarks>
        private void SendCommercialEmailMessageById()
        {
            Console.WriteLine("This request sends a commercial email message.");
            Console.Write("Commercial email message ID: ");
            var emailMessageId = Console.ReadLine();

            var request = new SendCommercialEmailMessageByIdRequest()
            {
                EmailMessageId = new Guid(emailMessageId),
            };

            this.Client.ProcessRequest(request);
        }

        /// <summary>
        /// Handles the SendCommercialEmailMessageByIdResponse received from the response queue. Displays the queued status and tracking information for the commercial email.
        /// </summary>
        /// <param name="response">The SendCommercialEmailMessageByIdResponse received after sending a SendCommercialEmailMessageByIdRequest</param>
        private void ProcessSendCommercialEmailMessageByIdResponse(SdkResponse response)
        {
            var sendEmailMessageResponse = (SendCommercialEmailMessageByIdResponse)response;
            Console.WriteLine("Processing SendCommercialEmailMessageByIdResponse.");
            if (sendEmailMessageResponse.QueuedSuccessfully)
            {
                Console.WriteLine(
                    "Successfully queued: {0} Tracking item ID: {1}",
                    sendEmailMessageResponse.QueuedSuccessfully.ToString(CultureInfo.InvariantCulture),
                    sendEmailMessageResponse.TrackingItemId.ToString());
            }
            else
            {
                Console.WriteLine(sendEmailMessageResponse.Message);
            }
        }

        /// <summary>
        /// Demonstrates RetrieveEmailMessageSentStatusRequest and RetrieveEmailMessageSentStatusResponse.
        /// </summary>
        /// <remarks>
        /// You need to first send an email marketing message via the SDK and get its tracking item's external ID.
        /// </remarks>
        private void RetrieveEmailMessageSentStatus()
        {
            Console.WriteLine("This request gets the sent status for an email message.");
            Console.Write("Tracking ID: ");
            var trackingId = Console.ReadLine();

            var request = new RetrieveEmailMessageSentStatusRequest()
            {
                TrackingId = new Guid(trackingId)
            };

            this.Client.ProcessRequest(request);
        }

        /// <summary>
        /// Handles the RetrieveEmailMessageSentStatusResponse received from the response queue. Displays the sent status of the email.
        /// </summary>
        /// <param name="response">The RetrieveEmailMessageSentStatusResponse received after sending a RetrieveEmailMessageSentStatusRequest.</param>
        private void ProcessRetrieveEmailMessageSentStatusResponse(SdkResponse response)
        {
            var retrieveEmailMessageSentStatusResponse = (RetrieveEmailMessageSentStatusResponse)response;
            Console.WriteLine("Processing RetrieveEmailMessageSentStatusResponse.");
            Console.WriteLine("Sent status: {0}", retrieveEmailMessageSentStatusResponse.SentStatus.ToString());
        }

        /// <summary>
        /// Demonstrates how to set contact permissions for an email address.
        /// </summary>
        /// <remarks>
        /// Contact permission information includes suppress globally flag, encrypted email, do not contact email topics list.
        /// </remarks>
        private void SetContactPermissions()
        {
            Console.WriteLine("This request set contact permissions for an email address.");
            Console.Write("Please type the email address => ");
            string email = Console.ReadLine();

            Console.Write("Please type the suppress globally flag for the email address (true/false) => ");
            bool suppressGlobally = false;
            var supressGloballyValue = Console.ReadLine();
            if (string.IsNullOrEmpty(supressGloballyValue))
            {
                Console.WriteLine("Incorrect suppress globally");
                return;
            }

            var trimSuppressGlobally = supressGloballyValue.Trim();
            if (trimSuppressGlobally.Equals("true", StringComparison.OrdinalIgnoreCase) || trimSuppressGlobally.Equals("t", StringComparison.OrdinalIgnoreCase))
            {
                suppressGlobally = true;
            }
            else if (trimSuppressGlobally.Equals("false", StringComparison.OrdinalIgnoreCase) || trimSuppressGlobally.Equals("f", StringComparison.OrdinalIgnoreCase))
            {
                suppressGlobally = false;
            }
            else
            {
                Console.WriteLine("Incorrect suppress globally");
                return;
            }

            Console.Write("Please type the external email identifier => ");
            var externalEmailIdentifier = Console.ReadLine();
            if (string.IsNullOrEmpty(externalEmailIdentifier))
            {
                Console.WriteLine("Incorrect external email identifier");
                return;
            }

            Console.Write("Please type in the do not contact email topics comma separated. You can ignore this setting if there are no contact permission restrictions. => ");
            var doNotEmailForTopics = new List<string>();
            var topicsString = Console.ReadLine();
            if (!string.IsNullOrEmpty(topicsString))
            {
                doNotEmailForTopics = topicsString.Split(',')
                    .Where(s => !string.IsNullOrWhiteSpace(s))
                    .Select(s => s.Trim())
                    .ToList();
            }

            var contact = new ContactPermissions
            {
                EmailAddress = email,
                SuppressGlobally = suppressGlobally,
                ExternalEmailIdentifier = externalEmailIdentifier,
                DoNotEmailFor = doNotEmailForTopics
            };

            var request = new SetContactPermissionsRequest() { ContactPermissions = contact };
            this.Client.ProcessRequest(request);
        }

        /// <summary>
        /// Demonstrates how to set contact permissions for a batch of email addresses.
        /// </summary>
        /// <remarks>
        /// Contact permissions information includes suppress globally flag, encrypted email, do not contact email topics list.
        /// </remarks>
        private void SetContactsPermissions()
        {
            Console.WriteLine("This request sets contact permissions for multiple email addresses.");

            Console.Write("Please type in the contact emails comma separated. => ");
            var emails = new List<string>();
            var emailString = Console.ReadLine();
            if (!string.IsNullOrEmpty(emailString))
            {
                emails = emailString.Split(',')
                    .Where(s => !string.IsNullOrWhiteSpace(s))
                    .Select(s => s.Trim())
                    .ToList();
            }

            var contactPermissions = new List<ContactPermissions>();
            foreach (var email in emails)
            {
                var contactPermission = new ContactPermissions
                {
                    EmailAddress = email,
                    SuppressGlobally = false,
                    ExternalEmailIdentifier = string.Format(CultureInfo.InvariantCulture, "{0}", Guid.NewGuid()),
                    DoNotEmailFor = new List<string> { "Promotional" }
                };
                contactPermissions.Add(contactPermission);
            }

            var request = new SetContactsPermissionsRequest() { ContactPermissions = contactPermissions };
            this.Client.ProcessRequest(request);
        }

        /// <summary>
        /// Handles the SetContactPermissionsResponse that is received from the response queue.
        /// </summary>
        /// <param name="response">The <see cref="SetContactPermissionsResponse"/> received after sending a <see cref="SetContactPermissionsRequest"/>.</param>
        private void ProcessSetContactPermissionsResponse(SdkResponse response)
        {
            var setContactPermissionsResponse = (SetContactPermissionsResponse)response;
            Console.WriteLine("Processing SetContactPermissionsResponse.");

            if (setContactPermissionsResponse.Succeeded)
            {
                Console.WriteLine("Succeeded to set contact permissions for the specified email address.");
            }
            else
            {
                Console.WriteLine("Failed to set contact permissions for the specified email address.");
                Console.WriteLine(setContactPermissionsResponse.Message);
            }
        }

        /// <summary>
        /// Handles the SetContactsPermissionsResponse that is received from the response queue.
        /// </summary>
        /// <param name="response">The <see cref="SetContactsPermissionsResponse"/> received after sending a <see cref="SetContactsPermissionsRequest"/>.</param>
        private void ProcessSetContactsPermissionsResponse(SdkResponse response)
        {
            var setContactsPermissionsResponse = (SetContactsPermissionsResponse)response;
            Console.WriteLine("Processing SetContactsPermissionsResponse.");

            if (setContactsPermissionsResponse.Succeeded)
            {
                Console.WriteLine("Succeeded to set contact permissions for multiple email addresses.");
            }
            else
            {
                Console.WriteLine("Failed to set contact permissions for multiple email addresses.");
                Console.WriteLine(setContactsPermissionsResponse.Message);
            }
        }

        /// <summary>
        /// Demonstrates how to retrieve contact permissions information for an email address.
        /// </summary>
        private void RetrieveContactPermissions()
        {
            Console.WriteLine("This request retrieve contact permissions for an email address.");
            Console.Write("Please type the email => ");
            var email = Console.ReadLine();

            var request = new RetrieveContactPermissionsRequest() { EmailAddress = email };
            this.Client.ProcessRequest(request);
        }

        /// <summary>
        /// Handles the <see cref="RetrieveContactPermissionsResponse"/> that is received from the response queue.
        /// </summary>
        /// <param name="response">The <see cref="RetrieveContactPermissionsResponse"/> received after sending a <see cref="RetrieveContactPermissionsRequest"/>.</param>
        private void ProcessRetrieveContactPermissionsResponse(SdkResponse response)
        {
            var retrieveContactPermissionsResponse = (RetrieveContactPermissionsResponse)response;
            Console.WriteLine("Processing RetrieveContactPermissionsResponse.");

            if (retrieveContactPermissionsResponse.Succeeded)
            {
                var contactability = retrieveContactPermissionsResponse.ContactPermissions;
                this.PrintContactability(contactability);
            }
            else
            {
                Console.WriteLine("Failed to retrieve contact permissions");
            }
        }

        /// <summary>
        /// Demonstrates how to retrieve a list of email addresses that contact permissions are missing from.
        /// </summary>
        private void RetrieveMissingContactability()
        {
            Console.WriteLine("This request retrieves a list of email addresses that contact permissions are missing from.");

            Console.Write("Enter offset - or empty for the first set of records =>");
            var offset = Console.ReadLine();
            int skipNumberOfRecords;
            int.TryParse(offset, out skipNumberOfRecords);

            var request = new RetrieveMissingContactPermissionsRequest { MaxNumberOfRecordsToGet = 100, SkipNumberOfRecords = skipNumberOfRecords };
            this.Client.ProcessRequest(request);
        }

        /// <summary>
        /// Handles the <see cref="RetrieveMissingContactPermissionsResponse"/> that is received from the response queue.
        /// </summary>
        /// <param name="response">The <see cref="RetrieveMissingContactPermissionsResponse"/> received after sending a <see cref="RetrieveMissingContactPermissionsRequest"/>.</param>
        private void ProcessRetrieveMissingContactPermissionsResponse(SdkResponse response)
        {
            var retrieveMissingContactPermissionsResponse = (RetrieveMissingContactPermissionsResponse)response;
            Console.WriteLine("Processing RetrieveMissingContactPermissionsResponse.");

            Console.WriteLine("List of email addresses for which contact permissions are missing:");
            foreach (var emailAddress in retrieveMissingContactPermissionsResponse.EmailAddresses)
            {
                Console.WriteLine(emailAddress);
            }
        }

        /// <summary>
        /// Print information based on <see cref="ContactPermissions"/>
        /// </summary>
        /// <param name="contactability">An instance of <see cref="ContactPermissions"/>to print to console.</param>
        private void PrintContactability(ContactPermissions contactability)
        {
            Console.WriteLine("EmailAddress:{0}", contactability.EmailAddress);
            Console.WriteLine("SuppressGlobally:{0}", contactability.SuppressGlobally);
            Console.WriteLine("ExternalEmailIdentifier:{0}", contactability.ExternalEmailIdentifier);
            Console.WriteLine("UpdateDate:{0}", contactability.UpdateDate);

            Console.WriteLine("List of do not contact email topics:");
            foreach (var category in contactability.DoNotEmailFor)
            {
                Console.WriteLine(category);
            }
        }

        /// <summary>
        /// Demonstrates how to set email hard bounces to processed for a contact.
        /// </summary>
        private void SetEmailHardBouncesToProcessedForContact()
        {
            Console.WriteLine("This request sets email hard bounces to processed for a contact.");
            Console.Write("Please type the ID (GUID) for the Contact => ");
            Guid id;
            if (!Guid.TryParse(Console.ReadLine(), out id))
            {
                Console.WriteLine("Incorrect ID");
                return;
            }

            var request = new SetEmailHardBouncesToProcessedForContactRequest { ContactId = id };
            this.Client.ProcessRequest(request);
        }

        /// <summary>
        /// Handles the <see cref="SetEmailHardBouncesToProcessedForContactResponse"/> that is received from the response queue.
        /// </summary>
        /// <param name="response">The <see cref="SetEmailHardBouncesToProcessedForContactResponse"/> received after sending a <see cref="SetEmailHardBouncesToProcessedForContactRequest"/>.</param>
        private void ProcessSetEmailHardBouncesToProcessedForContactResponse(SdkResponse response)
        {
            var setEmailHardBouncesToProcessedForContactResponse = (SetEmailHardBouncesToProcessedForContactResponse)response;
            Console.WriteLine("Processing SetEmailHardBouncesToProcessedForContactResponse.");

            if (setEmailHardBouncesToProcessedForContactResponse.Succeeded)
            {
                Console.WriteLine("Succeeded to set email hard bounces to processed for a contact");
            }
            else
            {
                Console.WriteLine("Failed to set email hard bounces to processed for a contact");
            }
        }

        /// <summary>
        /// Demonstrates how to get unprocessed email hard bounces.
        /// </summary>
        private void RetrieveUnprocessedEmailHardBounces()
        {
            Console.WriteLine("This request demonstrates how to retrieve unprocessed email hard bounces");

            Console.Write("Enter token guid offset - or empty for the first set of records =>");
            var recordsOffset = Console.ReadLine();
            var guidOffsetTokenValue = Guid.Empty;

            if (!string.IsNullOrEmpty(recordsOffset))
            {
                if (!Guid.TryParse(recordsOffset, out guidOffsetTokenValue))
                {
                    Console.WriteLine("Invalid email result Guid value");
                    return;
                }
            }

            var request = new RetrieveUnprocessedEmailHardBouncesRequest { MaxNumberOfRecords = 100, NextBatchTokenGuid = guidOffsetTokenValue };

            this.Client.ProcessRequest(request);
        }

        /// <summary>
        /// Demonstrates how to get email marketing results.
        /// </summary>
        private void RetrieveEmailMarketingRequest()
        {
            Console.WriteLine("This request demonstrates how to retrieve email marketing results");

            // This call will retrieve the first batch which contains 10 records
            var request = new RetrieveEmailMarketingResultsRequest()
            {
                MaxNumberOfRecordsToGet = 10,
                NextBatchTokenGuid = Guid.Empty
            };

            /* -----------------------------------------------Important-------------------------------------------------------------
             * The attribute NextBatchTokenGuid is used as paging cookie, Therefore, NextBatchTokenGuid needs to be set in order to get the next back
             * The value that needs to be set in order to retrieve next batch token will be returned with the response of this call.
             */

            this.Client.ProcessRequest(request);
        }

        /// <summary>
        /// Handles the <see cref="RetrieveUnprocessedEmailHardBouncesResponse"/> that is received from the response queue.
        /// </summary>
        /// <param name="response">The <see cref="RetrieveUnprocessedEmailHardBouncesResponse"/> received after sending a <see cref="RetrieveUnprocessedEmailHardBouncesRequest"/>.</param>
        private void ProcessRetrieveUnprocessedEmailHardBouncesResponse(SdkResponse response)
        {
            var retrieveUnprocessedEmailHardBouncesResponse = (RetrieveUnprocessedEmailHardBouncesResponse)response;
            Console.WriteLine("Processing RetrieveUnprocessedEmailHardBouncesResponse.");

            if (retrieveUnprocessedEmailHardBouncesResponse.Succeeded)
            {
                var counter = 1;
                foreach (var emresult in retrieveUnprocessedEmailHardBouncesResponse.EmailResults)
                {
                    Console.WriteLine("\nEmail result #{0}", counter++);
                    if (emresult.Contact != null)
                    {
                        Console.WriteLine("Contact: {0} {1}", emresult.Contact.FirstName, emresult.Contact.LastName);
                    }

                    Console.WriteLine("EmailAddress: {0}", emresult.EmailAddress);
                    Console.WriteLine("ResultDate: {0}", emresult.ResultDate);
                    Console.WriteLine("Type: {0}", emresult.Type);
                }
            }
            else
            {
                Console.WriteLine("Failed to retrieve unprocesssed email hard bounces");
            }
        }

        /// <summary>
        /// Handles the <see cref="RetrieveUnprocessedEmailHardBouncesResponse"/> that is received from the response queue.
        /// </summary>
        /// <param name="response">The <see cref="RetrieveUnprocessedEmailHardBouncesResponse"/> received after sending a <see cref="RetrieveUnprocessedEmailHardBouncesRequest"/>.</param>
        private void ProcessRetrieveEmailMarketingResults(SdkResponse response)
        {
            var retrieveEmailMarketingResults = (RetrieveEmailMarketingResultsResponse)response;
            Console.WriteLine("Processing RetrieveEmailMarketingResultsResponse.");

            if (retrieveEmailMarketingResults.Succeeded)
            {
                var counter = 1;

                // Iterate on all retrieved email results and print them
                foreach (var emresult in retrieveEmailMarketingResults.EmailResults)
                {
                    Console.WriteLine("\nEmail result #{0}", counter++);
                    if (emresult.ContactId != null)
                    {
                        Console.WriteLine("ContactId: {0}", emresult.ContactId);
                    }
                    else
                    {
                        Console.WriteLine("ContactId:");
                    }

                    if (emresult.Program != null)
                    {
                        Console.WriteLine("Program: {0}", emresult.Program.Name);
                    }
                    else
                    {
                        Console.WriteLine("Program:");
                    }

                    if (emresult.Campaign != null)
                    {
                        Console.WriteLine("Campaign: {0}", emresult.Campaign.Name);
                    }
                    else
                    {
                        Console.WriteLine("Campaign:");
                    }

                    Console.WriteLine("Type: {0}", emresult.Type);
                    Console.WriteLine("ResultDate: {0}", emresult.ResultDate);
                    if (emresult.UnsubscribedFromMarketingListId != null)
                    {
                        Console.WriteLine("UnsubscribedFromMarketingListId: {0}", emresult.UnsubscribedFromMarketingListId);
                    }

                    if (emresult.EmailMessage != null)
                    {
                        Console.WriteLine("EmailMessage: {0}", emresult.EmailMessage.Name);
                    }
                    else
                    {
                        Console.WriteLine("EmailMessage:");
                    }

                    if (string.IsNullOrEmpty(emresult.Link))
                    {
                        Console.WriteLine("Link: {0}", emresult.Link);
                    }
                    else
                    {
                        Console.WriteLine("Link:");
                    }

                    if (string.IsNullOrEmpty(emresult.Url))
                    {
                        Console.WriteLine("URL: {0}", emresult.Url);
                    }
                    else
                    {
                        Console.WriteLine("URL:");
                    }
                }

                /* -----------------------------------------------Important-------------------------------------------------------------
                 * The attribute NextBatchTokenGuid is used as paging cookie, Therefore, NextBatchTokenGuid needs to be set in order to get the next back
                 * The value that needs to be set in order to retrieve next batch token will be returned with the response of this call.
                 * To be able to retrieve the second batch
                 *   var request = new RetrieveEmailMarketingResultsRequest()
                 *   {
                 *       MaxNumberOfRecordsToGet = 10,
                 *       NextBatchTokenGuid = retrieveEmailMarketingResults.NextBatchTokenGuid
                 *   };
                 */ 
            }
            else
            {
                Console.WriteLine("Failed to retrieve email marketing results. Error Message: {0}", retrieveEmailMarketingResults.Message);
            }
        }

        /// <summary>
        /// Handles the <see cref="SdkErrorResponse"/> received from the response queue. Displays the error message.
        /// </summary>
        /// <param name="response">The <see cref="SdkErrorResponse"/> received after sending an <see cref="SdkRequest"/>.</param>
        private void ProcessSdkErrorResponse(SdkResponse response)
        {
            var sdkErrorResponse = (SdkErrorResponse)response;
            Console.WriteLine("An SdkErrorResponse was received.");
            Console.WriteLine("Error message: {0}", sdkErrorResponse.Message);
        }
    }
}

Troubleshooting

  • If the response isn’t received in time, you’ll get the following error message:

    “The request has been sent but the response was not received. You may want to wait a few more seconds and try to receive the response again or try increasing the ResponseMessageTimeout in client.cs. “

    Some of the possible reasons why the response isn’t received:

    • The server took longer than expected to process this response. Try selecting Option A, to see the response. If this issue occurs frequently, consider changing the value of the ResponseMessageTimeout constant in your client.cs file.

    • Either your client is looking at the wrong response queue, or Microsoft Dynamics Marketing is unable to write to the response queue due to a configuration error. To learn how to set up your queues correctly, see Getting started with the SDK.

  • If you don’t receive a response immediately, try using the Get all responses for this session option. Sometimes a response may take longer than the default time-out period.

  • If you never receive the response, make sure your request and response queue names and namespace matches the details you provided on Home > Settings > Administrator > Integration Options. More information: Site configuration and integration settings.

  • If you’re not seeing any emails when using RetrieveEmailMessagesRequest, make sure that you are creating emails with the Send Externally option checked.

  • If your email isn’t being sent, debug the ProcessSendEmailMessageResponse response handler and check the Message property. The message will contain the validation error, if any.

  • If you send email to an external mail ID (email message ID) using the command option Send email message by email ID, you get the following error message:

    “Validation of email message failed for Send. Please check input.”

    For the specified email address that you’re using, there is no email created with the Send Externally option checked. You must first create the email with the Send Externally option checked in Microsoft Dynamics Marketing, and then get the external ID for email message either from the Retrieve action or on the Home > Marketing Execution > Email Marketing > Messages by clicking on the Customize column icon and selecting External ID from the list.

See Also

Microsoft.Dynamics.Marketing.SDK.Common
Microsoft.Dynamics.Marketing.SDK.Messages
Microsoft.Dynamics.Marketing.SDK.Messages.EmailMessage
Microsoft.Dynamics.Marketing.SDK.Model
Developer overview of Microsoft Dynamics Marketing
Introduction to marketing entities
Manage lists and send transactional or commercial email
Getting started with the SDK
Quick start with sample code
Sample code
Assembly included in the Microsoft Dynamics Marketing SDK
Programming reference for Microsoft Dynamics Marketing