를 SES 사용하여 Amazon으로 이메일 ID 확인 및 메시지 전송 AWS SDK - Amazon Simple Email Service

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

를 SES 사용하여 Amazon으로 이메일 ID 확인 및 메시지 전송 AWS SDK

다음 코드 예시는 다음과 같은 작업을 수행하는 방법을 보여줍니다.

  • Amazon 을 사용하여 이메일 주소를 추가하고 확인합니다SES.

  • 표준 이메일 메시지를 보냅니다.

  • 템플릿을 생성하고 템플릿 이메일 메시지를 보냅니다.

  • Amazon SES SMTP 서버를 사용하여 메시지를 보냅니다.

Python
SDK Python용(Boto3)
참고

에 대한 자세한 내용은 를 참조하세요 GitHub. AWS 코드 예시 리포지토리에서 전체 예시를 찾고 설정 및 실행하는 방법을 배워보세요.

Amazon에서 이메일 주소를 확인하고 메시지를 SES 보냅니다.

def usage_demo(): print("-" * 88) print("Welcome to the Amazon Simple Email Service (Amazon SES) email demo!") print("-" * 88) logging.basicConfig(level=logging.INFO, format="%(levelname)s: %(message)s") ses_client = boto3.client("ses") ses_identity = SesIdentity(ses_client) ses_mail_sender = SesMailSender(ses_client) ses_template = SesTemplate(ses_client) email = input("Enter an email address to send mail with Amazon SES: ") status = ses_identity.get_identity_status(email) verified = status == "Success" if not verified: answer = input( f"The address '{email}' is not verified with Amazon SES. Unless your " f"Amazon SES account is out of sandbox, you can send mail only from " f"and to verified accounts. Do you want to verify this account for use " f"with Amazon SES? If yes, the address will receive a verification " f"email (y/n): " ) if answer.lower() == "y": ses_identity.verify_email_identity(email) print(f"Follow the steps in the email to {email} to complete verification.") print("Waiting for verification...") try: ses_identity.wait_until_identity_exists(email) print(f"Identity verified for {email}.") verified = True except WaiterError: print( f"Verification timeout exceeded. You must complete the " f"steps in the email sent to {email} to verify the address." ) if verified: test_message_text = "Hello from the Amazon SES mail demo!" test_message_html = "<p>Hello!</p><p>From the <b>Amazon SES</b> mail demo!</p>" print(f"Sending mail from {email} to {email}.") ses_mail_sender.send_email( email, SesDestination([email]), "Amazon SES demo", test_message_text, test_message_html, ) input("Mail sent. Check your inbox and press Enter to continue.") template = { "name": "doc-example-template", "subject": "Example of an email template.", "text": "This is what {{name}} will {{action}} if {{name}} can't display " "HTML.", "html": "<p><i>This</i> is what {{name}} will {{action}} if {{name}} " "<b>can</b> display HTML.</p>", } print("Creating a template and sending a templated email.") ses_template.create_template(**template) template_data = {"name": email.split("@")[0], "action": "read"} if ses_template.verify_tags(template_data): ses_mail_sender.send_templated_email( email, SesDestination([email]), ses_template.name(), template_data ) input("Mail sent. Check your inbox and press Enter to continue.") print("Sending mail through the Amazon SES SMTP server.") boto3_session = boto3.Session() region = boto3_session.region_name credentials = boto3_session.get_credentials() port = 587 smtp_server = f"email-smtp.{region}.amazonaws.com" password = calculate_key(credentials.secret_key, region) message = """ Subject: Hi there This message is sent from the Amazon SES SMTP mail demo.""" context = ssl.create_default_context() with smtplib.SMTP(smtp_server, port) as server: server.starttls(context=context) server.login(credentials.access_key, password) server.sendmail(email, email, message) print("Mail sent. Check your inbox!") if ses_template.template is not None: print("Deleting demo template.") ses_template.delete_template() if verified: answer = input(f"Do you want to remove {email} from Amazon SES (y/n)? ") if answer.lower() == "y": ses_identity.delete_identity(email) print("Thanks for watching!") print("-" * 88)

Amazon SES 자격 증명 작업을 래핑하는 함수를 생성합니다.

class SesIdentity: """Encapsulates Amazon SES identity functions.""" def __init__(self, ses_client): """ :param ses_client: A Boto3 Amazon SES client. """ self.ses_client = ses_client def verify_domain_identity(self, domain_name): """ Starts verification of a domain identity. To complete verification, you must create a TXT record with a specific format through your DNS provider. For more information, see *Verifying a domain with Amazon SES* in the Amazon SES documentation: https://docs.aws.amazon.com/ses/latest/DeveloperGuide/verify-domain-procedure.html :param domain_name: The name of the domain to verify. :return: The token to include in the TXT record with your DNS provider. """ try: response = self.ses_client.verify_domain_identity(Domain=domain_name) token = response["VerificationToken"] logger.info("Got domain verification token for %s.", domain_name) except ClientError: logger.exception("Couldn't verify domain %s.", domain_name) raise else: return token def verify_email_identity(self, email_address): """ Starts verification of an email identity. This function causes an email to be sent to the specified email address from Amazon SES. To complete verification, follow the instructions in the email. :param email_address: The email address to verify. """ try: self.ses_client.verify_email_identity(EmailAddress=email_address) logger.info("Started verification of %s.", email_address) except ClientError: logger.exception("Couldn't start verification of %s.", email_address) raise def wait_until_identity_exists(self, identity): """ Waits until an identity exists. The waiter polls Amazon SES until the identity has been successfully verified or until it exceeds its maximum time. :param identity: The identity to wait for. """ try: waiter = self.ses_client.get_waiter("identity_exists") logger.info("Waiting until %s exists.", identity) waiter.wait(Identities=[identity]) except WaiterError: logger.error("Waiting for identity %s failed or timed out.", identity) raise def get_identity_status(self, identity): """ Gets the status of an identity. This can be used to discover whether an identity has been successfully verified. :param identity: The identity to query. :return: The status of the identity. """ try: response = self.ses_client.get_identity_verification_attributes( Identities=[identity] ) status = response["VerificationAttributes"].get( identity, {"VerificationStatus": "NotFound"} )["VerificationStatus"] logger.info("Got status of %s for %s.", status, identity) except ClientError: logger.exception("Couldn't get status for %s.", identity) raise else: return status def delete_identity(self, identity): """ Deletes an identity. :param identity: The identity to remove. """ try: self.ses_client.delete_identity(Identity=identity) logger.info("Deleted identity %s.", identity) except ClientError: logger.exception("Couldn't delete identity %s.", identity) raise def list_identities(self, identity_type, max_items): """ Gets the identities of the specified type for the current account. :param identity_type: The type of identity to retrieve, such as EmailAddress. :param max_items: The maximum number of identities to retrieve. :return: The list of retrieved identities. """ try: response = self.ses_client.list_identities( IdentityType=identity_type, MaxItems=max_items ) identities = response["Identities"] logger.info("Got %s identities for the current account.", len(identities)) except ClientError: logger.exception("Couldn't list identities for the current account.") raise else: return identities

Amazon SES 템플릿 작업을 래핑하는 함수를 생성합니다.

class SesTemplate: """Encapsulates Amazon SES template functions.""" def __init__(self, ses_client): """ :param ses_client: A Boto3 Amazon SES client. """ self.ses_client = ses_client self.template = None self.template_tags = set() def _extract_tags(self, subject, text, html): """ Extracts tags from a template as a set of unique values. :param subject: The subject of the email. :param text: The text version of the email. :param html: The html version of the email. """ self.template_tags = set(re.findall(TEMPLATE_REGEX, subject + text + html)) logger.info("Extracted template tags: %s", self.template_tags) def create_template(self, name, subject, text, html): """ Creates an email template. :param name: The name of the template. :param subject: The subject of the email. :param text: The plain text version of the email. :param html: The HTML version of the email. """ try: template = { "TemplateName": name, "SubjectPart": subject, "TextPart": text, "HtmlPart": html, } self.ses_client.create_template(Template=template) logger.info("Created template %s.", name) self.template = template self._extract_tags(subject, text, html) except ClientError: logger.exception("Couldn't create template %s.", name) raise def delete_template(self): """ Deletes an email template. """ try: self.ses_client.delete_template(TemplateName=self.template["TemplateName"]) logger.info("Deleted template %s.", self.template["TemplateName"]) self.template = None self.template_tags = None except ClientError: logger.exception( "Couldn't delete template %s.", self.template["TemplateName"] ) raise def get_template(self, name): """ Gets a previously created email template. :param name: The name of the template to retrieve. :return: The retrieved email template. """ try: response = self.ses_client.get_template(TemplateName=name) self.template = response["Template"] logger.info("Got template %s.", name) self._extract_tags( self.template["SubjectPart"], self.template["TextPart"], self.template["HtmlPart"], ) except ClientError: logger.exception("Couldn't get template %s.", name) raise else: return self.template def list_templates(self): """ Gets a list of all email templates for the current account. :return: The list of retrieved email templates. """ try: response = self.ses_client.list_templates() templates = response["TemplatesMetadata"] logger.info("Got %s templates.", len(templates)) except ClientError: logger.exception("Couldn't get templates.") raise else: return templates def update_template(self, name, subject, text, html): """ Updates a previously created email template. :param name: The name of the template. :param subject: The subject of the email. :param text: The plain text version of the email. :param html: The HTML version of the email. """ try: template = { "TemplateName": name, "SubjectPart": subject, "TextPart": text, "HtmlPart": html, } self.ses_client.update_template(Template=template) logger.info("Updated template %s.", name) self.template = template self._extract_tags(subject, text, html) except ClientError: logger.exception("Couldn't update template %s.", name) raise

Amazon SES 이메일 작업을 래핑하는 함수를 생성합니다.

class SesDestination: """Contains data about an email destination.""" def __init__(self, tos, ccs=None, bccs=None): """ :param tos: The list of recipients on the 'To:' line. :param ccs: The list of recipients on the 'CC:' line. :param bccs: The list of recipients on the 'BCC:' line. """ self.tos = tos self.ccs = ccs self.bccs = bccs def to_service_format(self): """ :return: The destination data in the format expected by Amazon SES. """ svc_format = {"ToAddresses": self.tos} if self.ccs is not None: svc_format["CcAddresses"] = self.ccs if self.bccs is not None: svc_format["BccAddresses"] = self.bccs return svc_format class SesMailSender: """Encapsulates functions to send emails with Amazon SES.""" def __init__(self, ses_client): """ :param ses_client: A Boto3 Amazon SES client. """ self.ses_client = ses_client def send_email(self, source, destination, subject, text, html, reply_tos=None): """ Sends an email. Note: If your account is in the Amazon SES sandbox, the source and destination email accounts must both be verified. :param source: The source email account. :param destination: The destination email account. :param subject: The subject of the email. :param text: The plain text version of the body of the email. :param html: The HTML version of the body of the email. :param reply_tos: Email accounts that will receive a reply if the recipient replies to the message. :return: The ID of the message, assigned by Amazon SES. """ send_args = { "Source": source, "Destination": destination.to_service_format(), "Message": { "Subject": {"Data": subject}, "Body": {"Text": {"Data": text}, "Html": {"Data": html}}, }, } if reply_tos is not None: send_args["ReplyToAddresses"] = reply_tos try: response = self.ses_client.send_email(**send_args) message_id = response["MessageId"] logger.info( "Sent mail %s from %s to %s.", message_id, source, destination.tos ) except ClientError: logger.exception( "Couldn't send mail from %s to %s.", source, destination.tos ) raise else: return message_id def send_templated_email( self, source, destination, template_name, template_data, reply_tos=None ): """ Sends an email based on a template. A template contains replaceable tags each enclosed in two curly braces, such as {{name}}. The template data passed in this function contains key-value pairs that define the values to insert in place of the template tags. Note: If your account is in the Amazon SES sandbox, the source and destination email accounts must both be verified. :param source: The source email account. :param destination: The destination email account. :param template_name: The name of a previously created template. :param template_data: JSON-formatted key-value pairs of replacement values that are inserted in the template before it is sent. :return: The ID of the message, assigned by Amazon SES. """ send_args = { "Source": source, "Destination": destination.to_service_format(), "Template": template_name, "TemplateData": json.dumps(template_data), } if reply_tos is not None: send_args["ReplyToAddresses"] = reply_tos try: response = self.ses_client.send_templated_email(**send_args) message_id = response["MessageId"] logger.info( "Sent templated mail %s from %s to %s.", message_id, source, destination.tos, ) except ClientError: logger.exception( "Couldn't send templated mail from %s to %s.", source, destination.tos ) raise else: return message_id

개발자 안내서 및 코드 예제의 AWS SDK 전체 목록은 섹션을 참조하세요SES 에서 Amazon 사용 AWS SDK. 이 주제에는 시작하기에 대한 정보와 이전 SDK 버전에 대한 세부 정보도 포함되어 있습니다.