Amazon SES API v2 examples using AWS SDK for .NET - AWS SDK Code Examples

There are more AWS SDK examples available in the AWS Doc SDK Examples GitHub repo.

Amazon SES API v2 examples using AWS SDK for .NET

The following code examples show you how to perform actions and implement common scenarios by using the AWS SDK for .NET with Amazon SES API v2.

Actions are code excerpts from larger programs and must be run in context. While actions show you how to call individual service functions, you can see actions in context in their related scenarios and cross-service examples.

Scenarios are code examples that show you how to accomplish a specific task by calling multiple functions within the same service.

Each example includes a link to GitHub, where you can find instructions on how to set up and run the code in context.

Actions

The following code example shows how to use CreateContact.

AWS SDK for .NET
Note

There's more on GitHub. Find the complete example and learn how to set up and run in the AWS Code Examples Repository.

/// <summary> /// Creates a contact and adds it to the specified contact list. /// </summary> /// <param name="emailAddress">The email address of the contact.</param> /// <param name="contactListName">The name of the contact list.</param> /// <returns>The response from the CreateContact operation.</returns> public async Task<bool> CreateContactAsync(string emailAddress, string contactListName) { var request = new CreateContactRequest { EmailAddress = emailAddress, ContactListName = contactListName }; try { var response = await _sesClient.CreateContactAsync(request); return response.HttpStatusCode == HttpStatusCode.OK; } catch (AlreadyExistsException ex) { Console.WriteLine($"Contact with email address {emailAddress} already exists in the contact list {contactListName}."); Console.WriteLine(ex.Message); return true; } catch (NotFoundException ex) { Console.WriteLine($"The contact list {contactListName} does not exist."); Console.WriteLine(ex.Message); } catch (TooManyRequestsException ex) { Console.WriteLine("Too many requests were made. Please try again later."); Console.WriteLine(ex.Message); } catch (Exception ex) { Console.WriteLine($"An error occurred while creating the contact: {ex.Message}"); } return false; }
  • For API details, see CreateContact in AWS SDK for .NET API Reference.

The following code example shows how to use CreateContactList.

AWS SDK for .NET
Note

There's more on GitHub. Find the complete example and learn how to set up and run in the AWS Code Examples Repository.

/// <summary> /// Creates a contact list with the specified name. /// </summary> /// <param name="contactListName">The name of the contact list.</param> /// <returns>True if successful.</returns> public async Task<bool> CreateContactListAsync(string contactListName) { var request = new CreateContactListRequest { ContactListName = contactListName }; try { var response = await _sesClient.CreateContactListAsync(request); return response.HttpStatusCode == HttpStatusCode.OK; } catch (AlreadyExistsException ex) { Console.WriteLine($"Contact list with name {contactListName} already exists."); Console.WriteLine(ex.Message); return true; } catch (LimitExceededException ex) { Console.WriteLine("The limit for contact lists has been exceeded."); Console.WriteLine(ex.Message); } catch (TooManyRequestsException ex) { Console.WriteLine("Too many requests were made. Please try again later."); Console.WriteLine(ex.Message); } catch (Exception ex) { Console.WriteLine($"An error occurred while creating the contact list: {ex.Message}"); } return false; }

The following code example shows how to use CreateEmailIdentity.

AWS SDK for .NET
Note

There's more on GitHub. Find the complete example and learn how to set up and run in the AWS Code Examples Repository.

/// <summary> /// Creates an email identity (email address or domain) and starts the verification process. /// </summary> /// <param name="emailIdentity">The email address or domain to create and verify.</param> /// <returns>The response from the CreateEmailIdentity operation.</returns> public async Task<CreateEmailIdentityResponse> CreateEmailIdentityAsync(string emailIdentity) { var request = new CreateEmailIdentityRequest { EmailIdentity = emailIdentity }; try { var response = await _sesClient.CreateEmailIdentityAsync(request); return response; } catch (AlreadyExistsException ex) { Console.WriteLine($"Email identity {emailIdentity} already exists."); Console.WriteLine(ex.Message); throw; } catch (ConcurrentModificationException ex) { Console.WriteLine($"The email identity {emailIdentity} is being modified by another operation or thread."); Console.WriteLine(ex.Message); throw; } catch (LimitExceededException ex) { Console.WriteLine("The limit for email identities has been exceeded."); Console.WriteLine(ex.Message); throw; } catch (NotFoundException ex) { Console.WriteLine($"The email identity {emailIdentity} does not exist."); Console.WriteLine(ex.Message); throw; } catch (TooManyRequestsException ex) { Console.WriteLine("Too many requests were made. Please try again later."); Console.WriteLine(ex.Message); throw; } catch (Exception ex) { Console.WriteLine($"An error occurred while creating the email identity: {ex.Message}"); throw; } }

The following code example shows how to use CreateEmailTemplate.

AWS SDK for .NET
Note

There's more on GitHub. Find the complete example and learn how to set up and run in the AWS Code Examples Repository.

/// <summary> /// Creates an email template with the specified content. /// </summary> /// <param name="templateName">The name of the email template.</param> /// <param name="subject">The subject of the email template.</param> /// <param name="htmlContent">The HTML content of the email template.</param> /// <param name="textContent">The text content of the email template.</param> /// <returns>True if successful.</returns> public async Task<bool> CreateEmailTemplateAsync(string templateName, string subject, string htmlContent, string textContent) { var request = new CreateEmailTemplateRequest { TemplateName = templateName, TemplateContent = new EmailTemplateContent { Subject = subject, Html = htmlContent, Text = textContent } }; try { var response = await _sesClient.CreateEmailTemplateAsync(request); return response.HttpStatusCode == HttpStatusCode.OK; } catch (AlreadyExistsException ex) { Console.WriteLine($"Email template with name {templateName} already exists."); Console.WriteLine(ex.Message); } catch (LimitExceededException ex) { Console.WriteLine("The limit for email templates has been exceeded."); Console.WriteLine(ex.Message); } catch (TooManyRequestsException ex) { Console.WriteLine("Too many requests were made. Please try again later."); Console.WriteLine(ex.Message); } catch (Exception ex) { Console.WriteLine($"An error occurred while creating the email template: {ex.Message}"); } return false; }

The following code example shows how to use DeleteContactList.

AWS SDK for .NET
Note

There's more on GitHub. Find the complete example and learn how to set up and run in the AWS Code Examples Repository.

/// <summary> /// Deletes a contact list and all contacts within it. /// </summary> /// <param name="contactListName">The name of the contact list to delete.</param> /// <returns>True if successful.</returns> public async Task<bool> DeleteContactListAsync(string contactListName) { var request = new DeleteContactListRequest { ContactListName = contactListName }; try { var response = await _sesClient.DeleteContactListAsync(request); return response.HttpStatusCode == HttpStatusCode.OK; } catch (ConcurrentModificationException ex) { Console.WriteLine($"The contact list {contactListName} is being modified by another operation or thread."); Console.WriteLine(ex.Message); } catch (NotFoundException ex) { Console.WriteLine($"The contact list {contactListName} does not exist."); Console.WriteLine(ex.Message); } catch (TooManyRequestsException ex) { Console.WriteLine("Too many requests were made. Please try again later."); Console.WriteLine(ex.Message); } catch (Exception ex) { Console.WriteLine($"An error occurred while deleting the contact list: {ex.Message}"); } return false; }

The following code example shows how to use DeleteEmailIdentity.

AWS SDK for .NET
Note

There's more on GitHub. Find the complete example and learn how to set up and run in the AWS Code Examples Repository.

/// <summary> /// Deletes an email identity (email address or domain). /// </summary> /// <param name="emailIdentity">The email address or domain to delete.</param> /// <returns>True if successful.</returns> public async Task<bool> DeleteEmailIdentityAsync(string emailIdentity) { var request = new DeleteEmailIdentityRequest { EmailIdentity = emailIdentity }; try { var response = await _sesClient.DeleteEmailIdentityAsync(request); return response.HttpStatusCode == HttpStatusCode.OK; } catch (ConcurrentModificationException ex) { Console.WriteLine($"The email identity {emailIdentity} is being modified by another operation or thread."); Console.WriteLine(ex.Message); } catch (NotFoundException ex) { Console.WriteLine($"The email identity {emailIdentity} does not exist."); Console.WriteLine(ex.Message); } catch (TooManyRequestsException ex) { Console.WriteLine("Too many requests were made. Please try again later."); Console.WriteLine(ex.Message); } catch (Exception ex) { Console.WriteLine($"An error occurred while deleting the email identity: {ex.Message}"); } return false; }

The following code example shows how to use DeleteEmailTemplate.

AWS SDK for .NET
Note

There's more on GitHub. Find the complete example and learn how to set up and run in the AWS Code Examples Repository.

/// <summary> /// Deletes an email template. /// </summary> /// <param name="templateName">The name of the email template to delete.</param> /// <returns>True if successful.</returns> public async Task<bool> DeleteEmailTemplateAsync(string templateName) { var request = new DeleteEmailTemplateRequest { TemplateName = templateName }; try { var response = await _sesClient.DeleteEmailTemplateAsync(request); return response.HttpStatusCode == HttpStatusCode.OK; } catch (NotFoundException ex) { Console.WriteLine($"The email template {templateName} does not exist."); Console.WriteLine(ex.Message); } catch (TooManyRequestsException ex) { Console.WriteLine("Too many requests were made. Please try again later."); Console.WriteLine(ex.Message); } catch (Exception ex) { Console.WriteLine($"An error occurred while deleting the email template: {ex.Message}"); } return false; }

The following code example shows how to use ListContacts.

AWS SDK for .NET
Note

There's more on GitHub. Find the complete example and learn how to set up and run in the AWS Code Examples Repository.

/// <summary> /// Lists the contacts in the specified contact list. /// </summary> /// <param name="contactListName">The name of the contact list.</param> /// <returns>The list of contacts response from the ListContacts operation.</returns> public async Task<List<Contact>> ListContactsAsync(string contactListName) { var request = new ListContactsRequest { ContactListName = contactListName }; try { var response = await _sesClient.ListContactsAsync(request); return response.Contacts; } catch (NotFoundException ex) { Console.WriteLine($"The contact list {contactListName} does not exist."); Console.WriteLine(ex.Message); } catch (TooManyRequestsException ex) { Console.WriteLine("Too many requests were made. Please try again later."); Console.WriteLine(ex.Message); } catch (Exception ex) { Console.WriteLine($"An error occurred while listing the contacts: {ex.Message}"); } return new List<Contact>(); }
  • For API details, see ListContacts in AWS SDK for .NET API Reference.

The following code example shows how to use SendEmail.

AWS SDK for .NET
Note

There's more on GitHub. Find the complete example and learn how to set up and run in the AWS Code Examples Repository.

/// <summary> /// Sends an email with the specified content and options. /// </summary> /// <param name="fromEmailAddress">The email address to send the email from.</param> /// <param name="toEmailAddresses">The email addresses to send the email to.</param> /// <param name="subject">The subject of the email.</param> /// <param name="htmlContent">The HTML content of the email.</param> /// <param name="textContent">The text content of the email.</param> /// <param name="templateName">The name of the email template to use (optional).</param> /// <param name="templateData">The data to replace placeholders in the email template (optional).</param> /// <param name="contactListName">The name of the contact list for unsubscribe functionality (optional).</param> /// <returns>The MessageId response from the SendEmail operation.</returns> public async Task<string> SendEmailAsync(string fromEmailAddress, List<string> toEmailAddresses, string? subject, string? htmlContent, string? textContent, string? templateName = null, string? templateData = null, string? contactListName = null) { var request = new SendEmailRequest { FromEmailAddress = fromEmailAddress }; if (toEmailAddresses.Any()) { request.Destination = new Destination { ToAddresses = toEmailAddresses }; } if (!string.IsNullOrEmpty(templateName)) { request.Content = new EmailContent() { Template = new Template { TemplateName = templateName, TemplateData = templateData } }; } else { request.Content = new EmailContent { Simple = new Message { Subject = new Content { Data = subject }, Body = new Body { Html = new Content { Data = htmlContent }, Text = new Content { Data = textContent } } } }; } if (!string.IsNullOrEmpty(contactListName)) { request.ListManagementOptions = new ListManagementOptions { ContactListName = contactListName }; } try { var response = await _sesClient.SendEmailAsync(request); return response.MessageId; } catch (AccountSuspendedException ex) { Console.WriteLine("The account's ability to send email has been permanently restricted."); Console.WriteLine(ex.Message); } catch (MailFromDomainNotVerifiedException ex) { Console.WriteLine("The sending domain is not verified."); Console.WriteLine(ex.Message); } catch (MessageRejectedException ex) { Console.WriteLine("The message content is invalid."); Console.WriteLine(ex.Message); } catch (SendingPausedException ex) { Console.WriteLine("The account's ability to send email is currently paused."); Console.WriteLine(ex.Message); } catch (TooManyRequestsException ex) { Console.WriteLine("Too many requests were made. Please try again later."); Console.WriteLine(ex.Message); } catch (Exception ex) { Console.WriteLine($"An error occurred while sending the email: {ex.Message}"); } return string.Empty; }
  • For API details, see SendEmail in AWS SDK for .NET API Reference.

Scenarios

The following code example shows how to run the Amazon SES API v2 newsletter workflow.

AWS SDK for .NET
Note

There's more on GitHub. Find the complete example and learn how to set up and run in the AWS Code Examples Repository.

Run the workflow.

using System.Diagnostics; using System.Text.RegularExpressions; using Amazon.SimpleEmailV2; using Amazon.SimpleEmailV2.Model; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Console; using Microsoft.Extensions.Logging.Debug; namespace Sesv2Scenario; public static class NewsletterWorkflow { /* This workflow demonstrates how to use the Amazon Simple Email Service (SES) v2 to send a coupon newsletter to a list of subscribers. The workflow performs the following tasks: 1. Prepare the application: - Create a verified email identity for sending and replying to emails. - Create a contact list to store the subscribers' email addresses. - Create an email template for the coupon newsletter. 2. Gather subscriber email addresses: - Prompt the user for a base email address. - Create 3 variants of the email address using subaddress extensions (e.g., user+ses-weekly-newsletter-1@example.com). - Add each variant as a contact to the contact list. - Send a welcome email to each new contact. 3. Send the coupon newsletter: - Retrieve the list of contacts from the contact list. - Send the coupon newsletter using the email template to each contact. 4. Monitor and review: - Provide instructions for the user to review the sending activity and metrics in the AWS console. 5. Clean up resources: - Delete the contact list (which also deletes all contacts within it). - Delete the email template. - Optionally delete the verified email identity. */ public static SESv2Wrapper _sesv2Wrapper; public static string? _baseEmailAddress = null; public static string? _verifiedEmail = null; private static string _contactListName = "weekly-coupons-newsletter"; private static string _templateName = "weekly-coupons"; private static string _subject = "Weekly Coupons Newsletter"; private static string _htmlContentFile = "coupon-newsletter.html"; private static string _textContentFile = "coupon-newsletter.txt"; private static string _htmlWelcomeFile = "welcome.html"; private static string _textWelcomeFile = "welcome.txt"; private static string _couponsDataFile = "sample_coupons.json"; // Relative location of the shared workflow resources folder. private static string _resourcesFilePathLocation = "../../../../../../../workflows/sesv2_weekly_mailer/resources/"; public static async Task Main(string[] args) { // Set up dependency injection for the Amazon service. using var host = Host.CreateDefaultBuilder(args) .ConfigureLogging(logging => logging.AddFilter("System", LogLevel.Debug) .AddFilter<DebugLoggerProvider>("Microsoft", LogLevel.Information) .AddFilter<ConsoleLoggerProvider>("Microsoft", LogLevel.Trace)) .ConfigureServices((_, services) => services.AddAWSService<IAmazonSimpleEmailServiceV2>() .AddTransient<SESv2Wrapper>() ) .Build(); ServicesSetup(host); try { Console.WriteLine(new string('-', 80)); Console.WriteLine(new string('-', 80)); Console.WriteLine("Welcome to the Amazon SES v2 Coupon Newsletter Workflow."); Console.WriteLine("This workflow demonstrates how to use the Amazon Simple Email Service (SES) v2 " + "\r\nto send a coupon newsletter to a list of subscribers."); // Prepare the application. var emailIdentity = await PrepareApplication(); // Gather subscriber email addresses. await GatherSubscriberEmailAddresses(emailIdentity); // Send the coupon newsletter. await SendCouponNewsletter(emailIdentity); // Monitor and review. MonitorAndReview(true); // Clean up resources. await Cleanup(emailIdentity, true); Console.WriteLine(new string('-', 80)); Console.WriteLine("Amazon SES v2 Coupon Newsletter Workflow is complete."); Console.WriteLine(new string('-', 80)); Console.WriteLine(new string('-', 80)); } catch (Exception ex) { Console.WriteLine($"An error occurred: {ex.Message}"); } } /// <summary> /// Populate the services for use within the console application. /// </summary> /// <param name="host">The services host.</param> private static void ServicesSetup(IHost host) { _sesv2Wrapper = host.Services.GetRequiredService<SESv2Wrapper>(); } /// <summary> /// Set up the resources for the workflow. /// </summary> /// <returns>The email address of the verified identity.</returns> public static async Task<string?> PrepareApplication() { var htmlContent = await File.ReadAllTextAsync(_resourcesFilePathLocation + _htmlContentFile); var textContent = await File.ReadAllTextAsync(_resourcesFilePathLocation + _textContentFile); Console.WriteLine(new string('-', 80)); Console.WriteLine("1. In this step, we will prepare the application:" + "\r\n - Create a verified email identity for sending and replying to emails." + "\r\n - Create a contact list to store the subscribers' email addresses." + "\r\n - Create an email template for the coupon newsletter.\r\n"); // Prompt the user for a verified email address. while (!IsEmail(_verifiedEmail)) { Console.Write("Enter a verified email address or an email to verify: "); _verifiedEmail = Console.ReadLine(); } try { // Create an email identity and start the verification process. await _sesv2Wrapper.CreateEmailIdentityAsync(_verifiedEmail); Console.WriteLine($"Identity {_verifiedEmail} created."); } catch (AlreadyExistsException) { Console.WriteLine($"Identity {_verifiedEmail} already exists."); } catch (Exception ex) { Console.WriteLine($"Error creating email identity: {ex.Message}"); } // Create a contact list. try { await _sesv2Wrapper.CreateContactListAsync(_contactListName); Console.WriteLine($"Contact list {_contactListName} created."); } catch (AlreadyExistsException) { Console.WriteLine($"Contact list {_contactListName} already exists."); } catch (Exception ex) { Console.WriteLine($"Error creating contact list: {ex.Message}"); } // Create an email template. try { await _sesv2Wrapper.CreateEmailTemplateAsync(_templateName, _subject, htmlContent, textContent); Console.WriteLine($"Email template {_templateName} created."); } catch (AlreadyExistsException) { Console.WriteLine($"Email template {_templateName} already exists."); } catch (Exception ex) { Console.WriteLine($"Error creating email template: {ex.Message}"); } return _verifiedEmail; } /// <summary> /// Generate subscriber addresses and send welcome emails. /// </summary> /// <param name="fromEmailAddress">The verified email address from PrepareApplication.</param> /// <returns>True if successful.</returns> public static async Task<bool> GatherSubscriberEmailAddresses(string fromEmailAddress) { Console.WriteLine(new string('-', 80)); Console.WriteLine("2. In Step 2, we will gather subscriber email addresses:" + "\r\n - Prompt the user for a base email address." + "\r\n - Create 3 variants of the email address using subaddress extensions (e.g., user+ses-weekly-newsletter-1@example.com)." + "\r\n - Add each variant as a contact to the contact list." + "\r\n - Send a welcome email to each new contact.\r\n"); // Prompt the user for a base email address. while (!IsEmail(_baseEmailAddress)) { Console.Write("Enter a base email address (e.g., user@example.com): "); _baseEmailAddress = Console.ReadLine(); } // Create 3 variants of the email address using +ses-weekly-newsletter-1, +ses-weekly-newsletter-2, etc. var baseEmailAddressParts = _baseEmailAddress!.Split("@"); for (int i = 1; i <= 3; i++) { string emailAddress = $"{baseEmailAddressParts[0]}+ses-weekly-newsletter-{i}@{baseEmailAddressParts[1]}"; try { // Create a contact with the email address in the contact list. await _sesv2Wrapper.CreateContactAsync(emailAddress, _contactListName); Console.WriteLine($"Contact {emailAddress} added to the {_contactListName} contact list."); } catch (AlreadyExistsException) { Console.WriteLine($"Contact {emailAddress} already exists in the {_contactListName} contact list."); } catch (Exception ex) { Console.WriteLine($"Error creating contact {emailAddress}: {ex.Message}"); return false; } // Send a welcome email to the new contact. try { string subject = "Welcome to the Weekly Coupons Newsletter"; string htmlContent = await File.ReadAllTextAsync(_resourcesFilePathLocation + _htmlWelcomeFile); string textContent = await File.ReadAllTextAsync(_resourcesFilePathLocation + _textWelcomeFile); await _sesv2Wrapper.SendEmailAsync(fromEmailAddress, new List<string> { emailAddress }, subject, htmlContent, textContent); Console.WriteLine($"Welcome email sent to {emailAddress}."); } catch (Exception ex) { Console.WriteLine($"Error sending welcome email to {emailAddress}: {ex.Message}"); return false; } // Wait 2 seconds before sending the next email (if the account is in the SES Sandbox). await Task.Delay(2000); } return true; } /// <summary> /// Send the coupon newsletter to the subscribers in the contact list. /// </summary> /// <param name="fromEmailAddress">The verified email address from PrepareApplication.</param> /// <returns>True if successful.</returns> public static async Task<bool> SendCouponNewsletter(string fromEmailAddress) { Console.WriteLine(new string('-', 80)); Console.WriteLine("3. In this step, we will send the coupon newsletter:" + "\r\n - Retrieve the list of contacts from the contact list." + "\r\n - Send the coupon newsletter using the email template to each contact.\r\n"); // Retrieve the list of contacts from the contact list. var contacts = await _sesv2Wrapper.ListContactsAsync(_contactListName); if (!contacts.Any()) { Console.WriteLine($"No contacts found in the {_contactListName} contact list."); return false; } // Load the coupon data from the sample_coupons.json file. string couponsData = await File.ReadAllTextAsync(_resourcesFilePathLocation + _couponsDataFile); // Send the coupon newsletter to each contact using the email template. try { foreach (var contact in contacts) { // To use the Contact List for list management, send to only one address at a time. await _sesv2Wrapper.SendEmailAsync(fromEmailAddress, new List<string> { contact.EmailAddress }, null, null, null, _templateName, couponsData, _contactListName); } Console.WriteLine($"Coupon newsletter sent to contact list {_contactListName}."); } catch (Exception ex) { Console.WriteLine($"Error sending coupon newsletter to contact list {_contactListName}: {ex.Message}"); return false; } return true; } /// <summary> /// Provide instructions for monitoring sending activity and metrics. /// </summary> /// <param name="interactive">True to run in interactive mode.</param> /// <returns>True if successful.</returns> public static bool MonitorAndReview(bool interactive) { Console.WriteLine(new string('-', 80)); Console.WriteLine("4. In step 4, we will monitor and review:" + "\r\n - Provide instructions for the user to review the sending activity and metrics in the AWS console.\r\n"); Console.WriteLine("Review your sending activity using the SES Homepage in the AWS console."); Console.WriteLine("Press Enter to open the SES Homepage in your default browser..."); if (interactive) { Console.ReadLine(); try { // Open the SES Homepage in the default browser. Process.Start(new ProcessStartInfo { FileName = "https://console.aws.amazon.com/ses/home", UseShellExecute = true }); } catch (Exception ex) { Console.WriteLine($"Error opening the SES Homepage: {ex.Message}"); return false; } } Console.WriteLine("Review the sending activity and email metrics, then press Enter to continue..."); if (interactive) Console.ReadLine(); return true; } /// <summary> /// Clean up the resources used in the workflow. /// </summary> /// <param name="verifiedEmailAddress">The verified email address from PrepareApplication.</param> /// <param name="interactive">True if interactive.</param> /// <returns>Async task.</returns> public static async Task<bool> Cleanup(string verifiedEmailAddress, bool interactive) { Console.WriteLine(new string('-', 80)); Console.WriteLine("5. Finally, we clean up resources:" + "\r\n - Delete the contact list (which also deletes all contacts within it)." + "\r\n - Delete the email template." + "\r\n - Optionally delete the verified email identity.\r\n"); Console.WriteLine("Cleaning up resources..."); // Delete the contact list (this also deletes all contacts in the list). try { await _sesv2Wrapper.DeleteContactListAsync(_contactListName); Console.WriteLine($"Contact list {_contactListName} deleted."); } catch (NotFoundException) { Console.WriteLine($"Contact list {_contactListName} not found."); } catch (Exception ex) { Console.WriteLine($"Error deleting contact list {_contactListName}: {ex.Message}"); return false; } // Delete the email template. try { await _sesv2Wrapper.DeleteEmailTemplateAsync(_templateName); Console.WriteLine($"Email template {_templateName} deleted."); } catch (NotFoundException) { Console.WriteLine($"Email template {_templateName} not found."); } catch (Exception ex) { Console.WriteLine($"Error deleting email template {_templateName}: {ex.Message}"); return false; } // Ask the user if they want to delete the email identity. var deleteIdentity = !interactive || GetYesNoResponse( $"Do you want to delete the email identity {verifiedEmailAddress}? (y/n) "); if (deleteIdentity) { try { await _sesv2Wrapper.DeleteEmailIdentityAsync(verifiedEmailAddress); Console.WriteLine($"Email identity {verifiedEmailAddress} deleted."); } catch (NotFoundException) { Console.WriteLine( $"Email identity {verifiedEmailAddress} not found."); } catch (Exception ex) { Console.WriteLine( $"Error deleting email identity {verifiedEmailAddress}: {ex.Message}"); return false; } } else { Console.WriteLine( $"Skipping deletion of email identity {verifiedEmailAddress}."); } return true; } /// <summary> /// Helper method to get a yes or no response from the user. /// </summary> /// <param name="question">The question string to print on the console.</param> /// <returns>True if the user responds with a yes.</returns> private static bool GetYesNoResponse(string question) { Console.WriteLine(question); var ynResponse = Console.ReadLine(); var response = ynResponse != null && ynResponse.Equals("y", StringComparison.InvariantCultureIgnoreCase); return response; } /// <summary> /// Simple check to verify a string is an email address. /// </summary> /// <param name="email">The string to verify.</param> /// <returns>True if a valid email.</returns> private static bool IsEmail(string? email) { if (string.IsNullOrEmpty(email)) return false; return Regex.IsMatch(email, @"^[^@\s]+@[^@\s]+\.[^@\s]+$", RegexOptions.IgnoreCase); } }

Wrapper for service operations.

using System.Net; using Amazon.SimpleEmailV2; using Amazon.SimpleEmailV2.Model; namespace Sesv2Scenario; /// <summary> /// Wrapper class for Amazon Simple Email Service (SES) v2 operations. /// </summary> public class SESv2Wrapper { private readonly IAmazonSimpleEmailServiceV2 _sesClient; /// <summary> /// Constructor for the SESv2Wrapper. /// </summary> /// <param name="sesClient">The injected SES v2 client.</param> public SESv2Wrapper(IAmazonSimpleEmailServiceV2 sesClient) { _sesClient = sesClient; } /// <summary> /// Creates a contact and adds it to the specified contact list. /// </summary> /// <param name="emailAddress">The email address of the contact.</param> /// <param name="contactListName">The name of the contact list.</param> /// <returns>The response from the CreateContact operation.</returns> public async Task<bool> CreateContactAsync(string emailAddress, string contactListName) { var request = new CreateContactRequest { EmailAddress = emailAddress, ContactListName = contactListName }; try { var response = await _sesClient.CreateContactAsync(request); return response.HttpStatusCode == HttpStatusCode.OK; } catch (AlreadyExistsException ex) { Console.WriteLine($"Contact with email address {emailAddress} already exists in the contact list {contactListName}."); Console.WriteLine(ex.Message); return true; } catch (NotFoundException ex) { Console.WriteLine($"The contact list {contactListName} does not exist."); Console.WriteLine(ex.Message); } catch (TooManyRequestsException ex) { Console.WriteLine("Too many requests were made. Please try again later."); Console.WriteLine(ex.Message); } catch (Exception ex) { Console.WriteLine($"An error occurred while creating the contact: {ex.Message}"); } return false; } /// <summary> /// Creates a contact list with the specified name. /// </summary> /// <param name="contactListName">The name of the contact list.</param> /// <returns>True if successful.</returns> public async Task<bool> CreateContactListAsync(string contactListName) { var request = new CreateContactListRequest { ContactListName = contactListName }; try { var response = await _sesClient.CreateContactListAsync(request); return response.HttpStatusCode == HttpStatusCode.OK; } catch (AlreadyExistsException ex) { Console.WriteLine($"Contact list with name {contactListName} already exists."); Console.WriteLine(ex.Message); return true; } catch (LimitExceededException ex) { Console.WriteLine("The limit for contact lists has been exceeded."); Console.WriteLine(ex.Message); } catch (TooManyRequestsException ex) { Console.WriteLine("Too many requests were made. Please try again later."); Console.WriteLine(ex.Message); } catch (Exception ex) { Console.WriteLine($"An error occurred while creating the contact list: {ex.Message}"); } return false; } /// <summary> /// Creates an email identity (email address or domain) and starts the verification process. /// </summary> /// <param name="emailIdentity">The email address or domain to create and verify.</param> /// <returns>The response from the CreateEmailIdentity operation.</returns> public async Task<CreateEmailIdentityResponse> CreateEmailIdentityAsync(string emailIdentity) { var request = new CreateEmailIdentityRequest { EmailIdentity = emailIdentity }; try { var response = await _sesClient.CreateEmailIdentityAsync(request); return response; } catch (AlreadyExistsException ex) { Console.WriteLine($"Email identity {emailIdentity} already exists."); Console.WriteLine(ex.Message); throw; } catch (ConcurrentModificationException ex) { Console.WriteLine($"The email identity {emailIdentity} is being modified by another operation or thread."); Console.WriteLine(ex.Message); throw; } catch (LimitExceededException ex) { Console.WriteLine("The limit for email identities has been exceeded."); Console.WriteLine(ex.Message); throw; } catch (NotFoundException ex) { Console.WriteLine($"The email identity {emailIdentity} does not exist."); Console.WriteLine(ex.Message); throw; } catch (TooManyRequestsException ex) { Console.WriteLine("Too many requests were made. Please try again later."); Console.WriteLine(ex.Message); throw; } catch (Exception ex) { Console.WriteLine($"An error occurred while creating the email identity: {ex.Message}"); throw; } } /// <summary> /// Creates an email template with the specified content. /// </summary> /// <param name="templateName">The name of the email template.</param> /// <param name="subject">The subject of the email template.</param> /// <param name="htmlContent">The HTML content of the email template.</param> /// <param name="textContent">The text content of the email template.</param> /// <returns>True if successful.</returns> public async Task<bool> CreateEmailTemplateAsync(string templateName, string subject, string htmlContent, string textContent) { var request = new CreateEmailTemplateRequest { TemplateName = templateName, TemplateContent = new EmailTemplateContent { Subject = subject, Html = htmlContent, Text = textContent } }; try { var response = await _sesClient.CreateEmailTemplateAsync(request); return response.HttpStatusCode == HttpStatusCode.OK; } catch (AlreadyExistsException ex) { Console.WriteLine($"Email template with name {templateName} already exists."); Console.WriteLine(ex.Message); } catch (LimitExceededException ex) { Console.WriteLine("The limit for email templates has been exceeded."); Console.WriteLine(ex.Message); } catch (TooManyRequestsException ex) { Console.WriteLine("Too many requests were made. Please try again later."); Console.WriteLine(ex.Message); } catch (Exception ex) { Console.WriteLine($"An error occurred while creating the email template: {ex.Message}"); } return false; } /// <summary> /// Deletes a contact list and all contacts within it. /// </summary> /// <param name="contactListName">The name of the contact list to delete.</param> /// <returns>True if successful.</returns> public async Task<bool> DeleteContactListAsync(string contactListName) { var request = new DeleteContactListRequest { ContactListName = contactListName }; try { var response = await _sesClient.DeleteContactListAsync(request); return response.HttpStatusCode == HttpStatusCode.OK; } catch (ConcurrentModificationException ex) { Console.WriteLine($"The contact list {contactListName} is being modified by another operation or thread."); Console.WriteLine(ex.Message); } catch (NotFoundException ex) { Console.WriteLine($"The contact list {contactListName} does not exist."); Console.WriteLine(ex.Message); } catch (TooManyRequestsException ex) { Console.WriteLine("Too many requests were made. Please try again later."); Console.WriteLine(ex.Message); } catch (Exception ex) { Console.WriteLine($"An error occurred while deleting the contact list: {ex.Message}"); } return false; } /// <summary> /// Deletes an email identity (email address or domain). /// </summary> /// <param name="emailIdentity">The email address or domain to delete.</param> /// <returns>True if successful.</returns> public async Task<bool> DeleteEmailIdentityAsync(string emailIdentity) { var request = new DeleteEmailIdentityRequest { EmailIdentity = emailIdentity }; try { var response = await _sesClient.DeleteEmailIdentityAsync(request); return response.HttpStatusCode == HttpStatusCode.OK; } catch (ConcurrentModificationException ex) { Console.WriteLine($"The email identity {emailIdentity} is being modified by another operation or thread."); Console.WriteLine(ex.Message); } catch (NotFoundException ex) { Console.WriteLine($"The email identity {emailIdentity} does not exist."); Console.WriteLine(ex.Message); } catch (TooManyRequestsException ex) { Console.WriteLine("Too many requests were made. Please try again later."); Console.WriteLine(ex.Message); } catch (Exception ex) { Console.WriteLine($"An error occurred while deleting the email identity: {ex.Message}"); } return false; } /// <summary> /// Deletes an email template. /// </summary> /// <param name="templateName">The name of the email template to delete.</param> /// <returns>True if successful.</returns> public async Task<bool> DeleteEmailTemplateAsync(string templateName) { var request = new DeleteEmailTemplateRequest { TemplateName = templateName }; try { var response = await _sesClient.DeleteEmailTemplateAsync(request); return response.HttpStatusCode == HttpStatusCode.OK; } catch (NotFoundException ex) { Console.WriteLine($"The email template {templateName} does not exist."); Console.WriteLine(ex.Message); } catch (TooManyRequestsException ex) { Console.WriteLine("Too many requests were made. Please try again later."); Console.WriteLine(ex.Message); } catch (Exception ex) { Console.WriteLine($"An error occurred while deleting the email template: {ex.Message}"); } return false; } /// <summary> /// Lists the contacts in the specified contact list. /// </summary> /// <param name="contactListName">The name of the contact list.</param> /// <returns>The list of contacts response from the ListContacts operation.</returns> public async Task<List<Contact>> ListContactsAsync(string contactListName) { var request = new ListContactsRequest { ContactListName = contactListName }; try { var response = await _sesClient.ListContactsAsync(request); return response.Contacts; } catch (NotFoundException ex) { Console.WriteLine($"The contact list {contactListName} does not exist."); Console.WriteLine(ex.Message); } catch (TooManyRequestsException ex) { Console.WriteLine("Too many requests were made. Please try again later."); Console.WriteLine(ex.Message); } catch (Exception ex) { Console.WriteLine($"An error occurred while listing the contacts: {ex.Message}"); } return new List<Contact>(); } /// <summary> /// Sends an email with the specified content and options. /// </summary> /// <param name="fromEmailAddress">The email address to send the email from.</param> /// <param name="toEmailAddresses">The email addresses to send the email to.</param> /// <param name="subject">The subject of the email.</param> /// <param name="htmlContent">The HTML content of the email.</param> /// <param name="textContent">The text content of the email.</param> /// <param name="templateName">The name of the email template to use (optional).</param> /// <param name="templateData">The data to replace placeholders in the email template (optional).</param> /// <param name="contactListName">The name of the contact list for unsubscribe functionality (optional).</param> /// <returns>The MessageId response from the SendEmail operation.</returns> public async Task<string> SendEmailAsync(string fromEmailAddress, List<string> toEmailAddresses, string? subject, string? htmlContent, string? textContent, string? templateName = null, string? templateData = null, string? contactListName = null) { var request = new SendEmailRequest { FromEmailAddress = fromEmailAddress }; if (toEmailAddresses.Any()) { request.Destination = new Destination { ToAddresses = toEmailAddresses }; } if (!string.IsNullOrEmpty(templateName)) { request.Content = new EmailContent() { Template = new Template { TemplateName = templateName, TemplateData = templateData } }; } else { request.Content = new EmailContent { Simple = new Message { Subject = new Content { Data = subject }, Body = new Body { Html = new Content { Data = htmlContent }, Text = new Content { Data = textContent } } } }; } if (!string.IsNullOrEmpty(contactListName)) { request.ListManagementOptions = new ListManagementOptions { ContactListName = contactListName }; } try { var response = await _sesClient.SendEmailAsync(request); return response.MessageId; } catch (AccountSuspendedException ex) { Console.WriteLine("The account's ability to send email has been permanently restricted."); Console.WriteLine(ex.Message); } catch (MailFromDomainNotVerifiedException ex) { Console.WriteLine("The sending domain is not verified."); Console.WriteLine(ex.Message); } catch (MessageRejectedException ex) { Console.WriteLine("The message content is invalid."); Console.WriteLine(ex.Message); } catch (SendingPausedException ex) { Console.WriteLine("The account's ability to send email is currently paused."); Console.WriteLine(ex.Message); } catch (TooManyRequestsException ex) { Console.WriteLine("Too many requests were made. Please try again later."); Console.WriteLine(ex.Message); } catch (Exception ex) { Console.WriteLine($"An error occurred while sending the email: {ex.Message}"); } return string.Empty; } }