today key : SES, simple, email, service, lambda, amazon, 이메일, sandbox, production, 메일, 람다
Amazon SES Production 전환 요청
Amazon SES의 경우, 기본적으로 리전 별로 모두 Sandbox 상태로 되어 있습니다.
Sandbox 형태인 경우에는 ~~~ 제한 사항이 있습니다.
본 포스팅에서는 Sandbox인 경우에도 실습이 가능하도록 구성하였지만,
먼저 Sandbox 상태를 Production으로 전환하는 것을 알아 보겠습니다.
바로 실습을 위한 것이라면 이 단계를 넘어가도 무방합니다.
SES 대시보드에서 현재 서울 리전이 Sandbox 상태임을 확인 할 수 있습니다.

하단의 Open Tasks에서 'Request production access' 를 선택하여,
서울 리전의 SES를 Production으로 변경하기 위한 요청을 진행합니다.

Production으로 전환 요청을 위해서 작성해야 하는 내용은 몇 개 없습니다.
Mail type과 Website URL이 필수 항목입니다.
아래 항목을 작성하고, Submit request를 하면 됩니다.

이제 서울 리전의 상태가 기존의 'Sandbox' → 'Under review'로 변경된 것을 볼 수 있습니다.

review가 완료되면 아래와 같이 상태 값이
'Production access granted'로 변경된 것을 볼 수 있습니다.
Production 상태가 되면, 메일을 발송할 수 있는 일일 쿼터와 초당 발송 가능한 메일 수가 늘어납니다.

메일 발신자(from)의 Identity 생성 및 검증
Amazon SES로 메일을 발송하기 위해서는
메일 발신자(Source)가 검증된(verified) 이메일 혹은 도메인이어야 합니다.
본 포스팅에서는 이메일 검증과 도메인 검증을 각각 진행하여,
발신자는 도메인 검증으로 검증 받은 도메인을 이용하고,
수신자는 이메일 검증을 받은 이메일을 사용 할 것입니다. (현재 Sandbox 상태이기 때문에 검증 필요)
Amazon SES > Configuration > Identities 메뉴에서, 'Create identities' 을 선택합니다.
Identity Type은 앞서 얘기한 것처럼 도메인 방식과 Email 주소 검증을 사용 할 수 있습니다.
먼저 Email 주소 검증을 선택하고, 하단에 Email 주소를 입력합니다.
나머지는 기본 값으로 두고, Create identity를 클릭하여, Email 주소 identity를 생성합니다.

생성 직후에는 Verification pending 상태인 것을 볼 수 있습니다.

이제 등록한 메일 주소의 메일함으로 가면 아래와 같이 Email 주소 검증을 위한 메일이 온 것을 볼 수 있습니다.
메일 중간에 있는 링크 클릭하면 검증을 할 수 있습니다.

이제 다시 Amazon SES에 생성한 Email 주소 Identity를 보면, 'Verfied' 상태가 된 것을 볼 수 있습니다.

Email 인증의 경우, aws cli로 현재 계정의 리전에 인증된 이메일 주소를 확인 할 수도 있습니다.

이어서 도메인 검증을 시작하겠습니다.
생성 방식은 거의 동일합니다.
Identity Type을 Domain으로 선택하고, Domain 주소를 입력합니다.
하단의 Identity type은 Easy DKIM, DKIM signing key length는 RSA_2048_BIT로 선택하였습니다.
나머지는 기본 값으로 두고, 하단의 Create identity를 클릭하여 생성합니다.


생성하고 나서 보면, 도메인 Identity 값 하단에 'Publish DNS records'에 3개의 CNAME 레코드 정보가 있습니다.
해당 CNAME 레코드를 등록한 도메인에 생성해주면,
해당 레코드를 통해서 인증을 하게 됩니다.

이메일 인증과 달리 도메인 인증의 경우,
레코드 등록 이후 확인 과정이 필요하여 인증까지 최대 72시간 이내 정도가 소요 될 수 있지만,
실제 인증까지는 몇 시간 이내면 보통 완료되는 것 같습니다.

메일 발송을 위한 Lambda 구성
Lambda에서 Amazon SES를 통해서 메일을 발송하기 위한 Role을 먼저 생성합니다.
IAM > Roles 메뉴에서 Create role을 선택하여 Role을 신규로 만듭니다.
Trusted entity type을 AWS service로 하고, Service or use case에서 Lambda를 선택합니다.

Permision을 다음과 같이 설정합니다.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowSendEmailFromSpecificIdentity",
"Effect": "Allow",
"Action": [
"ses:SendEmail",
"ses:SendRawEmail"
],
"Resource": [
"arn:aws:ses:ap-northeast-2:계정:identity/plmingzigi@gmail.com",
"arn:aws:ses:ap-northeast-2:계정:identity/zigispace.net"
]
}
]
}
이제 Lambda 함수를 신규로 만듭니다.
zigi-ses라는 이름으로 만들고, Runtime을 Python을 사용합니다.

Lambda에서 사용할 Role을 앞서 만든 Role로 설정합니다

Lambda의 코드를 아래와 같이 작성합니다.
여기에서는 SES의 리전을 서울로 지정하고,
보내는 주소 메일을 도메인으로 인증 받은 것으로 발신자 메일을 선택했습니다.
수신자는 Email 주소 인증을 받은 주소로 선택했습니다.
메일 제목과 본문은 Lambda에서 Test 할 때 사용하는 event JSON으로 받을 수 있게 했습니다.
import boto3
from botocore.exceptions import ClientError
# ✅ 여기서 발신/수신 주소를 코드에 직접 지정하세요.
SES_REGION = "ap-northeast-2"
FROM_EMAIL = "noreply@zigispace.net" # SES에서 Verified 필요
TO_EMAILS = ["plmingzigi@gmail.com"] # 샌드박스면 SES에서 Verified 필요 (여러 명이면 리스트에 추가)
ses = boto3.client("ses", region_name=SES_REGION)
def lambda_handler(event, context):
if not isinstance(event, dict):
raise ValueError("Event must be a JSON object (dict).")
subject = str(event.get("subject", "")).strip()
if not subject:
raise ValueError("event.subject is required")
text_body = str(event.get("text", "") or "").strip()
html_body = str(event.get("html", "") or "").strip()
if not (text_body or html_body):
raise ValueError("event.text or event.html is required")
body = {}
if text_body:
body["Text"] = {"Data": text_body, "Charset": "UTF-8"}
if html_body:
body["Html"] = {"Data": html_body, "Charset": "UTF-8"}
try:
resp = ses.send_email(
Source=FROM_EMAIL,
Destination={"ToAddresses": TO_EMAILS},
Message={
"Subject": {"Data": subject, "Charset": "UTF-8"},
"Body": body,
},
)
return {
"ok": True,
"messageId": resp.get("MessageId"),
"from": FROM_EMAIL,
"to": TO_EMAILS,
"subject": subject,
}
except ClientError as e:
return {"ok": False, "error": str(e), "sesRegion": SES_REGION}
코드를 작성하고 나서, Deploy 후에 Test를 진행합니다.
테스트 시에, event JSON은 아래와 같이 작성했습니다.
여기에서는 'html'로만 작성했지만, 'text' 값으로도 작성 가능합니다. (코드에 반영된 상태)
{
"subject": "SES Sandbox Test - HTML Body",
"html": "<p><b>안녕하세요.</b><br/>Lambda에서 SES API로 메일 발송 테스트입니다.</p>"
}
Lambda Test를 수행하고 나면 아래와 같이
Amazon SES를 통해서 정상적으로 메일이 발송되어서, 메일함에 수신 된 것을 확인할 수 있습니다.
