티스토리 뷰

반응형

지메일 API

앱 내의 비밀번호 찾기를 구현하기 위해 웹서버에서 자동으로 이메일 보내는 방법을 찾아봤다. 역시나 Gmail API라는게 있었다. 

 

 

Sending Email  |  Gmail API  |  Google Developers

There are two ways to send email using the Gmail API: Emails are sent as base64url encoded strings within the raw property of a message resource. The high-level workflow to send an email is to: Create the email content in some convenient way and encode it

developers.google.com

 

문서에서 시키는대로 일단 크레덴셜을 발급받으려 했는데 집 데스크탑으로 진행하는게 아니라서인지 구글 계정의 로그인 시도가 막혔다. 그래서 집에가서 다시 해보기로 하고 지금 당장 크레덴셜 없이 진행할 수 있는 방법은 없을까? 서치해보던중 찾은 방법

 

 

Flask_mail을 사용해 이메일 보내기

from flask import Flask
from flask_mail import Mail, Message

app = Flask(__name__)
mail = Mail(app)

app.config['MAIL_SERVER'] = 'smtp.gmail.com'
app.config['MAIL_PORT'] = 465
app.config['MAIL_USERNAME'] = ''
app.config['MAIL_PASSWORD'] = ''
app.config['MAIL_USE_TLS'] = False
app.config['MAIL_USE_SSL'] = True
mail = Mail(app)

@app.route('/')
def index():
    msg = Message('STMP test', sender='', recipients=['', ''])
    msg.body = '안뇽 난 자동메시지'
    mail.send(msg)
    return 'Sent'

if __name__ == '__main__':
    app.run(debug=True)

 

MAIL_USERNAME와 MAIL_PASSWORD에 내 계정정보, sender와 recipients에 각각 보내는사람, 받는사람 이메일 주소를 넣어주고 돌리면 된다. 일단 로컬에 돌렸으니 127.0.0.1:5000/ 으로 들어가면

 

 

리턴값으로 설정해둔 Sent가 뜨고

짠 이렇게 메일이 잘 온다

 

 

 

 

에러1: Username and Password not accepted. Learn more at

구글 계정관리 > 보안 탭 > 보안 수준이 낮은 앱의 액세스로 들어가서 보안 수준이 낮은 앱의 허용을 켜주면 된다.

 

에러2: Please log in via your web browser and then try again

이 코드를 짤때 회사 컴퓨터로 진행했는데, 위에서 말했듯 그 컴퓨터에는 메일 보내는 계정이 로그인이 되어있지 않아서 생기는 에러인듯 했다. 집에 와서 데스크탑으로 진행하니 생기지 않았다.

그 후, AWS에서 사용하고 있는 EC2서버에도 올렸는데 분명 같은 코드로 로컬에서는 잘 돌았지만 웹서버에 올리니 역시나 똑같은 에러가 떴다. AuthenticationError인만큼 인증문제인듯해서 아예 인증 토큰을 발급해주는 Gmail API를 사용해서 정석대로 짜볼 예정이다. 

 

 

 

 

Amazon SES

찾아보니 구글이메일이 AWS EC2에서 오는 SMTP 요청을 막아뒀다고 한다. 따라서 다른 방법을 찾던 중 아마존에 SES(Simple Email Service)라는것이 있는데 이걸 활용하면 더 쉽게 할 수 있겠다는 생각이 들었다. 

 

개발자 가이드가 친절한 편이라 시키는대로 코드를 금방짜고 테스트를 돌려봤다. 

credential, configure 등 넘어야 할 산이 여러개 있지만 크게 어렵지는 않다.

 

Configuration basics - AWS Command Line Interface

AWS requires that all incoming requests are cryptographically signed. The AWS CLI does this for you. The "signature" includes a date/time stamp. Therefore, you must ensure that your computer's date and time are set correctly. If you don't, and the date/tim

docs.aws.amazon.com

전송 코드 

# Replace sender@example.com with your "From" address.
# This address must be verified with Amazon SES.
SENDER = "Sender Name <xxxx@gmail.com>"

# Replace recipient@example.com with a "To" address. If your account
# is still in the sandbox, this address must be verified.
RECIPIENT = email

# Specify a configuration set. If you do not want to use a configuration
# set, comment the following variable, and the
# ConfigurationSetName=CONFIGURATION_SET argument below.
CONFIGURATION_SET = "configset"

# If necessary, replace us-west-2 with the AWS Region you're using for Amazon SES.
AWS_REGION = "ap-northeast-2"

# The subject line for the email.
SUBJECT = "메일 제목"

# The email body for recipients with non-HTML email clients.
BODY_TEXT = ("메일 내용 (html 형식이 아닌 클라이언트들에게 보여질 텍스트)")

# The HTML body of the email.
BODY_HTML = """<html>
<head></head>
<body>
  <h1>제목</h1>
  <p>내용</p>
</body>
</html>
            """

# The character encoding for the email.
CHARSET = "UTF-8"

# Create a new SES resource and specify a region.
client = boto3.client('ses', region_name=AWS_REGION)

# Try to send the email.
try:
    # Provide the contents of the email.
    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,
        # If you are not using a configuration set, comment or delete the
        # following line
        ConfigurationSetName=CONFIGURATION_SET,
    )
# Display an error if something goes wrong.
except ClientError as e:
    print(e.response['Error']['Message'])
else:
    print("Email sent! Message ID:"),
    print(response['MessageId'])

 

verified된 주소로부터 verified된 주소로 보낸 자동 이메일

그 후, 성공적으로 메일이 오는걸 확인했는데 보내는 이메일(sender)과 받는 이메일(recipient)이 모두 aws에 등록된(verified) 이메일이어야만 정상적으로 작동한다. 그 외의 주소로 메일을 보내고 싶다면 sandbox 밖으로 나가야한다. 

 

 

 

SES 샌드박스 밖으로 나가기

 

Moving out of the Amazon SES sandbox - Amazon Simple Email Service

Once you submit a review of your account details, you can’t edit your details until the review is complete.

docs.aws.amazon.com

 

아마존은 이메일 어뷰징을 막기 위해 SES에 가입한 유저들을 모두 샌드박스에 넣어둔다고 한다. 샌드박스 안에 있을때는 보낼 수 있는 메일의 수와 범위가 한정되어있으며 보내는 사람도, 받는 사람도 모두 등록된 (verified 된) 경우에만 전송이 가능하다. 따라서 실 유저에게 서비스를 하기 위해서는 샌드박스 밖으로 나가야한다. 

 

그러기 위해서는 간단한 폼을 작성해서 아마존 측으로 보내고, 24시간 내로 답변이 온다고 하는데 문서에 보면 캡쳐까지 친절하게 나와있어서 어렵지 않다. 다만 내가 하려는 서비스는 앱서비스에서 유저가 비밀번호 찾기를 요청하면 웹서버에서 유저의 메일로 정보를 보내주는 것인데, 작성해야하는 폼에는 Website URL을 적게 되어있다. 웹 url이 없어서 다운로드 가능한 플레이스토어 앱 정보 링크를 적어봤지만 유효하지 않다고 뜨고, 웹서버 주소도 안된다고 한다. 

 

어떻게 해야할지 몰라서 일단 문의 메일을 보냈더니, 답장으로 세부 정보를 알려주면 바로 해결해준다고 답변이 왔다. 

 

 

저 항목들에 맞춰 답장을 보내니 바로 승인이 됐고, 지금은 잘 쓰고있는중이다!

 

 

 

 

 

 

 

에러: ImportError: cannot import name 'docevents' release

원인 모를 에러가 나서 찾아봤는데 

pip3 install --upgrade awscli를 해주면 바로 해결된다. 

 

 

 

 

 

 

 

 

 

반응형