를 사용한 Amazon SES API v2 예제 AWS SDK for .NET - AWS SDK 코드 예제

AWS Doc SDK ExamplesWord AWS SDK 리포지토리에는 더 많은 GitHub 예제가 있습니다.

기계 번역으로 제공되는 번역입니다. 제공된 번역과 원본 영어의 내용이 상충하는 경우에는 영어 버전이 우선합니다.

를 사용한 Amazon SES API v2 예제 AWS SDK for .NET

다음 코드 예제에서는 Amazon API SES v2와 AWS SDK for .NET 함께를 사용하여 작업을 수행하고 일반적인 시나리오를 구현하는 방법을 보여줍니다.

작업은 대규모 프로그램에서 발췌한 코드이며 컨텍스트에 맞춰 실행해야 합니다. 작업은 개별 서비스 함수를 직접적으로 호출하는 방법을 보여주며 관련 시나리오의 컨텍스트에 맞는 작업을 볼 수 있습니다.

시나리오는 동일한 서비스 내에서 또는 다른 AWS 서비스와 결합된 상태에서 여러 함수를 호출하여 특정 태스크를 수행하는 방법을 보여주는 코드 예제입니다.

각 예제에는 컨텍스트에서 코드를 설정하고 실행하는 방법에 대한 지침을 찾을 수 있는 전체 소스 코드에 대한 링크가 포함되어 있습니다.

작업

다음 코드 예시에서는 CreateContact을 사용하는 방법을 보여 줍니다.

AWS SDK for .NET
참고

더 많은 on GitHub가 있습니다. AWS 코드 예시 리포지토리에서 전체 예시를 찾고 설정 및 실행하는 방법을 배워보세요.

/// <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; }
  • API 세부 정보는 CreateContact AWS SDK for .NET 참조의 API를 참조하세요.

다음 코드 예시에서는 CreateContactList을 사용하는 방법을 보여 줍니다.

AWS SDK for .NET
참고

더 많은 on GitHub가 있습니다. AWS 코드 예시 리포지토리에서 전체 예시를 찾고 설정 및 실행하는 방법을 배워보세요.

/// <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; }
  • API 세부 정보는 CreateContactList AWS SDK for .NET 참조의 API를 참조하세요.

다음 코드 예시에서는 CreateEmailIdentity을 사용하는 방법을 보여 줍니다.

AWS SDK for .NET
참고

더 많은 on GitHub가 있습니다. AWS 코드 예시 리포지토리에서 전체 예시를 찾고 설정 및 실행하는 방법을 배워보세요.

/// <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; } }

다음 코드 예시에서는 CreateEmailTemplate을 사용하는 방법을 보여 줍니다.

AWS SDK for .NET
참고

더 많은 on GitHub가 있습니다. AWS 코드 예시 리포지토리에서 전체 예시를 찾고 설정 및 실행하는 방법을 배워보세요.

/// <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; }

다음 코드 예시에서는 DeleteContactList을 사용하는 방법을 보여 줍니다.

AWS SDK for .NET
참고

더 많은 on GitHub가 있습니다. AWS 코드 예시 리포지토리에서 전체 예시를 찾고 설정 및 실행하는 방법을 배워보세요.

/// <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; }
  • API 세부 정보는 DeleteContactList AWS SDK for .NET 참조의 API를 참조하세요.

다음 코드 예시에서는 DeleteEmailIdentity을 사용하는 방법을 보여 줍니다.

AWS SDK for .NET
참고

더 많은 on GitHub가 있습니다. AWS 코드 예시 리포지토리에서 전체 예시를 찾고 설정 및 실행하는 방법을 배워보세요.

/// <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; }

다음 코드 예시에서는 DeleteEmailTemplate을 사용하는 방법을 보여 줍니다.

AWS SDK for .NET
참고

더 많은 on GitHub가 있습니다. AWS 코드 예시 리포지토리에서 전체 예시를 찾고 설정 및 실행하는 방법을 배워보세요.

/// <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; }

다음 코드 예시에서는 ListContacts을 사용하는 방법을 보여 줍니다.

AWS SDK for .NET
참고

더 많은 on GitHub가 있습니다. AWS 코드 예시 리포지토리에서 전체 예시를 찾고 설정 및 실행하는 방법을 배워보세요.

/// <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>(); }
  • API 세부 정보는 ListContacts AWS SDK for .NET 참조의 API를 참조하세요.

다음 코드 예시에서는 SendEmail을 사용하는 방법을 보여 줍니다.

AWS SDK for .NET
참고

더 많은 on GitHub가 있습니다. AWS 코드 예시 리포지토리에서 전체 예시를 찾고 설정 및 실행하는 방법을 배워보세요.

/// <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; }
  • API 세부 정보는 SendEmail AWS SDK for .NET 참조의 API를 참조하세요.

시나리오

다음 코드 예제에서는 Amazon API SES v2 뉴스레터 워크플로를 실행하는 방법을 보여줍니다.

AWS SDK for .NET
참고

더 많은 on GitHub가 있습니다. AWS 코드 예시 리포지토리에서 전체 예시를 찾고 설정 및 실행하는 방법을 배워보세요.

워크플로를 실행합니다.

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 resources folder. private static string _resourcesFilePathLocation = "../../../../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); } }

서비스 작업을 위한 래퍼입니다.

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; } }