Amazon SESを使って独自ドメインのメールをGmailで受け取る

やってみた

 Amazon Route53に登録した独自ドメインのメールをGmailで受け取りたくなったので、SESのアクションにLambdaを仕込んでGmailに飛ばすようにしてみた。

3行でまとめると

  • Amazon SESでMXレコードの準備とDNSの登録をする
  • メール格納先S3と転送用のLamda関数を作成する
  • SESにアクション登録する

以上。転送先はGmailなくても何でもよい。

Amazon SESの設定

独自ドメインのMXレコード登録

 SES > Domains > Verify a New Domainを選んでドメイン名を入力する。DKIMは必須ではないが入れておいたほうがよいと思う。なお、SESは東京リージョンではサービスを展開していないのでバージニア北部などにしておくこと。

各種DNSの設定内容が表示されるので、独自ドメインを管理しているレジストラのDNSに設定を追加する。Route 53で管理している人は右下の「Use Route 53」から簡単に登録できる。

「Use Route 53」から登録するとき、登録済のMXレコードがあるときは「Email receiving Record」にチェックをいれないこと。注意文にも書いてあるが既存のものが消えてしまう。

DNSレコードの登録が完了してdnsに反映されればVarification Statusなどがverifiedになる。dnsの伝搬にやや時間がかかるが、ステータスがpendingのまま変わらないときは登録内容を再度確認する。

通知メールの受信先登録

 DNSの伝搬を待っている間にSESの各種通知を受け取るメールを登録する。
SES > Email Addresses > Verify New Email Addressで受け取る可能なメールアドレスを登録する。しばらくするとメールアドレスが存在しているか確認するためのメールが届くので、メール内のリンクを踏んで確認する。

ステータスがpendingからverifiedになればOK。

Rule Setの登録

 Rule set > View Active Rule Set > Create Ruleでメールを受信したときのアクションを登録する。ここで受信したメールの格納先(s3のバケット)やGmailへの転送のためのLambdaスクリプトが登録できる。

 まず、使いたい独自ドメインのメールアドレスを入力する。

次にアクションとしてメールをS3に格納する設定を行う。S3のバケットは既存のものを選んでもよいが、新規に作成したほうが楽だと思う。次にLambdaをactionとして登録するところだが、まだLambdaを準備していないので、いったんS3だけで登録しておく。

最後にルール名をつけたらアクションの登録が完了する。

Lambdaの設定

関数作成

 Lambda > 関数 > 関数の作成から行う。今回はpythonを使用するのでランタイムはpythonを選ぶこと。関数名は何でもよい。

関数の内容は以下の通り。S3からメールを取り出し、送り先を書き換えて送信する。

import os
import boto3
import email

import re
import logging

s3_client = boto3.client('s3')
ses_client = boto3.client('ses')

logger = logging.getLogger()
logger.setLevel(logging.INFO)

ORIGINAL_ADDRESS = os.environ.get('originalAddress', '')
FORWARD_ADDRESS = os.environ.get('forwardAdresses', '')
S3_BUCKET_NAME = os.environ.get('s3BucketName', '')
SES_REGION = 'us-east-1'

def parse_mail(raw_message):

    from_name = 'No Name'

    pattern = re.compile(r'^From:\s*(.+?)$', re.MULTILINE)
    m = re.search(pattern, raw_message)
    if m:
        from_name = m.group(1)[:-1]
        
    replaced_message = raw_message.replace(ORIGINAL_ADDRESS, FORWARD_ADDRESS)
    replaced_message = re.sub(r'^From:\s*.+?$', r'From: "%s" <%s>' % (from_name, ORIGINAL_ADDRESS), replaced_message, flags=re.MULTILINE)
    replaced_message = re.sub(r'^Return-Path:\s*.+?$', r'Return-Path: "%s" <%s>' % (from_name, ORIGINAL_ADDRESS), replaced_message, flags=re.MULTILINE)
    replaced_message = re.sub(r'^Sender:\s*.+?$', r'Sender: "%s" <%s>' % (from_name, ORIGINAL_ADDRESS), replaced_message, flags=re.MULTILINE)

    return replaced_message

def send_mail(message):

    ses = boto3.client('ses', region_name=SES_REGION)

    ses.send_raw_email(
        Source = FORWARD_ADDRESS,
        Destinations=[
            FORWARD_ADDRESS
        ],
        RawMessage={
            'Data': message
        }
    )

def lambda_handler(event, context):
    try:
        s3_object = s3_client.get_object(
            Bucket = S3_BUCKET_NAME,
            Key = event['Records'][0]['ses']['mail']['messageId'])

        raw_message = s3_object["Body"].read().decode('utf-8')
        message = parse_mail(raw_message)
        send_mail(message)

        logger.info('SUCCESS')
        
    except Exception:
        logger.critical(
            'Execution failed. Exception encountered',
            exc_info=True)
    
    logger.info('FAILED')

環境変数設定

環境変数として独自ドメインのメールアドレス(ORIGINAL_ADDRESS)、転送先のメールアドレス(FORWARD_ADDRESS)、SESのアクション設定で作瀬下メールを格納するS3バケット名が必要になるので、環境変数の欄から登録しておくこと。

権限設定

 この関数はS3とSESを利用する権限が必要になるので、実行ロールの欄にあるIAMコンソールへのリンクを踏んでIAMの管理画面に飛んで権限を追加する。

SESはses:SendRawEmailがあればよい。fullが気になる場合は絞ろう。

Amazon SESでLambdaをアクションに追加&送信テスト

 SES > RuleSetで先ほど登録したルールセットを選び、アクションとして先ほど登録したLambdaを登録する。登録できたら、Domainのverificationが終わっているか確認して、
終わっていたら SES > Email Address > Send a Test Email でメールが転送されるか確認する。
普通にGmailでから送信してGmailに帰ってくるか確認してもよい。

うまくいかなかったときは、cloudwatch logsでログを確認して問題個所を修正しよう。

(2019/06/28追記:Lambda関数を改良しました。 Amazon SESを使って独自ドメインのメールをGmailで受け取る

タイトルとURLをコピーしました