AWS SES으로 유저에게 이메일 전송하기

인마헷·2023년 11월 28일
2
post-thumbnail

✂️ ... 포스팅 순서문제로 생략된 이야기 ... ✂️
블로그에 전자책 비스무리하게 자료를 올렸는데 카드 결제 요청도 있고, 간편결제 좀 편하게 하려고 삽질하다가 페이앱을 발견. 사업자 등록하고 이래저래 api 연동하려고 했더니만 보증보험(100만원)에 가입해야 정산이 가능한다는 통보를 받음. 이럴 바엔 그냥 보증보험 포함 22만원 가입비 내고 토스 페이먼츠 PG계약이 더 편했을 거라는 생각이.

...일주일 간 진정한 삽질을 경험했다🥲
이 참에 구매자가 송금하고 다운로드 하는 과정을 그냥 자동화 해보기로.

결제 모듈을 붙일 수 없으니, 송금 확인을 수동으로 해야 하고 구매자가 결제 후 다운로드가 가능하기까지 약간의 텀이 발생한다. 돈이 왔다갔다하는 과정이라 유저에게 최대한 친절할 필요가 있고, 이메일이 이 과정에서 제일 효과적인 방법이었다.

이메일 왔다갔다 필요한 부분

  • 나에게 송금확인 요청 이메일이 전송된다.
  • 송금한 유저의 이메일로 다운로드 가능 이메일이 전송된다.

카카오페이 송금 알림에 훅을 걸어볼 수 있는 방법이 있나 api 문서를 확인해봐도 그런 기능은 없어보였다.

나중에 자료 요청 건이 많아지면 그냥 PG 붙여야지.


AWS SES 설정하기

1. 로그인하고 SES로 들어간다.

아래 이미지는 이메일 인증과 도메인 등록을 끝내면 확인할 수 있는 페이지인데 처음 시작할 때 그냥 여기서 시작해도 되는 것 같았다.

처음 생성할 때 이미지가 없는데, 누가 봐도 이메일이랑 도메인 넣어야 할 것 같은 페이지가 등장한다.

설정 시작

이제 하라는 걸 천천히 해보면 된다.
크게 3가지가 있다.

  • 이메일 인증
  • 도메인 인증
  • 프로덕션으로!

만약 처음에 어떻게 해야할지 모르겠다면 구성/확인된 자격증명으로 가서 생성해보자.

자격 증명 생성

2. 이메일 인증하기

유저에게 보낼 이메일 주소를 입력한다. 사업용 이메일이 있다면 해당 이메일이 되겠고, 없다면 테스트 계정을 만들거나 본인 개인 이메일도 상관은 없다.

이 인증은 매우 쉽다. 이메일 입력하고 해당 이메일로 가서 확인 링크 클릭해주면 바로 인증이 된다.

3. 도메인 인증하기

블로그를 많이 찾아봤는데 도메인 인증하기 부분은 어떻게 해야 할지 몰랐다. AWS Route 53으로 해야 하나 싶었지만 나는 이미 DNS서버를 다른 플랫폼으로 두고 있었으니까.

일단 위의 자격증명생성에서 내가 사용하는 웹사이트의 도메인을 입력했다. 그리고 여타 다른 설정의 변경 없이 계속 확인을 눌렀고 그랬더니 아래와 같이 DKIM이 등장했다.

DKIM이미지

왜인지 저 CNAME을 내 도메인 관리 플랫폼에 등록해주어야 할 것만 같은 기분.
CloudFlare에 CNAME을 넣어줬다.

클라우드 플레어

3개 전부 설정해줘야 한다.
오래걸린다더니 1시간도 걸리지 않고 바로 도메인 자격 증명이 되었다. AWS 문서 상에서는 최대 72시간까지 소요된다고 하니 안 되더라도 조금 기다려보자.

4. 샌드박스에서 나가기(한도 해제)

AWS의 SES에는 두가지 환경이 있다.

하나는 샌드박스 환경이고 하나는 프로덕션 환경인데 샌드박스 환경은 테스트 목적으로, 메일도 200개로 제한되어있고 SES에서 확인된 이메일 주소 또는 도메인으로만 이메일을 보낼 수 있다. 즉, SES 콘솔에서 확인되지 않은 여타 다른 이메일 주소로는 이메일을 보낼 수 없음.

따라서 샌드박스 해제를 해주어야 한다.

(0) Request production access 찾기

인증을 마쳐도 아마 계정 대시보드 상단에 알림창이 뜰 것이다.
Your amazon ses account is in the sandbox 블라블라
그럼 해당 알림창 오른쪽 상단의 Request production access를 클릭하고 프로덕션으로 나갈테니 승인 좀! 과정을 거친다.

그렇게 하기 위해서는 어떤 폼을 채워야 하는데 아래 3가지만 입력하면 설정하면 된다.

(1) 용도 선택

  • 대량 이메일 전송, 마케팅 목적이면 Marketing
  • 본인인증, 구매확인 등 고객의 요청에 의해 트리거되면 Transactional

(2) 웹사이트 url 입력

(3) Use case description 작성

어떻게 사용할지 작성하면 될 텐데 나는 "admin testing" 이라고 적어버렸다.

optional 부분은 굳이 작성하지 않았고 제출을 했는데

aws 답장

하루에 5만개 발송할 수 있게 해줬다고 이메일이 날아왔다.

집 떠나는 자식 내보내는 부모 마음..인가 싶었지만 ‘관리자 테스트’라고 보냈는데 5만개 준걸 보면 다 5만개씩 주나 보다.


👆🏻

위의 설명에서 알 수 있듯이 정말 이것저것 만져보면서 무턱대고 SES 설정을 진행했다. 아래는 도움을 받은 포스트들.

참고하기

이젠 너무 수월하게 되면 뭔가 두려움😳


서버 코드 작성하기

서버는 파이썬 플라스크(Flask)로 구성했다.

자료 다운로드 링크를 생성할 일이 있어서 S3버킷을 사용했기 때문에 보안자격증명에서 API KEY는 이미 서버쪽 환경변수로 설정해 주었다. client 생성할 때 필요할 줄 알았는데 AWS에서 제공하는 샘플코드에는 해당하는 내용이 없었다. (알고보니 기본으로 갖고 온다고 한다.)

보안자격 증명

덧붙여 설명하자면 위 이미지에서와 같이 보안자격증명은 로그인 후 본인 계정 클릭하면 확인할 수 있다.

python boto3 사용하기

참고하기

AWS의 boto3 페이지: 바로가기

파이썬에서는 AWS SDK를 쉽게 코드로 프로그래밍할 수 있도록 boto3라는 라이브러리를 제공하고 있다. 이걸로 S3버킷 url생성도 가능하고 파일 업로드도 자유롭게 가능하다.

서버 예시 코드

아래는 aws의 샘플 코드를 가져다가 필요한 부분을 변경했다.

@app.route('/해당하는 엔드포인트', method=['해당하는 메서드'])
def send_mail():
    CHARSET = "UTF-8"
    SENDER = f"블로그명 <{AWS_SES_SENDER}>"
    RECIPIENT = ADMIN_RECIPENT
    AWS_REGION = "ap-northeast-2"
    SUBJECT = "이메일에 표시되는 제목"
    BODY_TEXT = ("이메일 표시 내용"
                 "이메일 표시 내용"
				#...생략...
                )        
    BODY_HTML = """<html>
				<head></head>
				<body>
				<h1>이메일에 표시되는 내용</h1>
				<p>이메일 표시되는 내용
				<a href={ADMIN_URL}>관리자 페이지</a>.
				</p>
				</body>
				</html>
            """            

    client = boto3.client('ses',region_name=AWS_REGION)
    try:
        response = client.send_email(
            Destination={
                'ToAddresses': [
                    RECIPIENT,
                ],
            },
            Message={
                'Body': {
                    'Html': {
                        'Charset': CHARSET,
                        'Data': BODY_HTML,
                    },
                    'Text': {
                        'Charset': CHARSET,
                        'Data': BODY_TEXT,
                    },
                },
                'Subject': {
                    'Charset': CHARSET,
                    'Data': SUBJECT,
                },
            },
            Source=SENDER,
        )
    except ClientError as e:
        print(e.response['Error']['Message'])
        return jsonify({'message': "failed"})
    else:
        print("Email sent! Message ID:"),
        print(response['MessageId'])
        return jsonify({'message': "sent"})

해당 코드 내의 html은 당연히 커스텀이 가능하다. 원하는 템플릿으로 변경해서 원하는 내용을 전달할 수 있다.

예시: @app.route(’/email’, method=[’GET’])

flask run으로 서버 실행하고 서버 url로 들어가서 url뒤에 /email 엔터치면 이메일이 발송된다.

화면에 { message : “sent” } 가 뜨면 성공.

전송받은 유저에게는 다음 이미지와 같이 가게 된다. 유저가 메일앱 알림을 설정해두면 너무 좋겠지만…(나는 스파크라는 메일앱을 사용한다)

유저가 받는 이메일

이걸로, 유저가 확인을 누르면 관리자에게 이메일이 가도록 엔드 포인트를 하나 더 만들어서 사용했다.

향후 회원가입 시 이메일 인증, 비밀번호 찾기 등도 AWS SES로 쉽게 구현가능 할 것 같아 서비스가 커지고 로그인이 붙으면 마찬가지 방식을 통해서 구현해볼 예정.


돈 많이 벌면 PG 가입해야지🤑
탈세 아님. 세금내고픔

profile
비공개 글이 너무 많다...My code may sink, but at least I can swim🤿

0개의 댓글