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の管理画面に飛んで権限を追加する。
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で受け取る)