Gmail + AWSで独自ドメインのメールを受信する

この記事では独自ドメインのメールを、GmailとAWSを使って受信できるようにすることを目的としています。Gmailで **送信** できるようにしたい場合はもっと簡単にできるので、以下の記事を参照にしてください。

[お名前.comで取得したドメインでGmailからメール送信する](https://qiita.com/komakomako/items/d7bac6d24104c3d3ce06)
※ 上の記事では、レジストラとしてお名前.comを想定しているが、他のレジストラであってもやり方は基本的には同じ。

# 0. メール受信方式の概要
 - 独自ドメインのネームサーバをRoute53にする
 - Route53でMXレコードを設定する
 - SESで独自ドメインメールを受信できるように設定する
 - 受信したメールをS3に保存するよう設定する
 - S3にメールが保存されたときにGmailに転送するLambdaスクリプトを作成する

# 1. 独自ドメインのネームサーバをRoute53にする

AWSコンソールでRoute53を開き、「Create Hosted Zone」をクリック

<img width="600" alt="ss 2018-07-01 18.19.05.png" src="https://qiita-image-store.s3.amazonaws.com/0/80357/28db3946-ab66-c19d-cfc1-5aeebc5b4d4f.png">

ドメイン名を入力する。例えばメールアドレスsupport@example.comのようのメールアドレスを運用したい場合、example.comと入力すればOK。
コメントは任意。TypeはPublic Hosted Zone。

<img width="600" alt="ss 2018-07-0118.19.20.png" src="https://qiita-image-store.s3.amazonaws.com/0/80357/66d05a26-861b-92d7-fe24-680de14d9338.png">

以下のような画面になるはず。この画面で「NSレコード」の欄に表示されている4つのネームサーバの名前をメモっておく。

<img width="600" alt="ss 2018-07-01 18.24.50.png" src="https://qiita-image-store.s3.amazonaws.com/0/80357/f621300c-48e5-c61c-02a6-d90c17fcd0d7.png">

[お名前.comのドメインNavi](https://www.onamae.com/domain/navi/menu/domain)にアクセスし、「ネームサーバの変更」をクリック

<img width="600" alt="ss 2018-07-01 18.36.29.png" src="https://qiita-image-store.s3.amazonaws.com/0/80357/cf3ca402-40e5-3110-4a9e-775554cd8de8.png">

対象のドメインを選択し、画面中段のタブ「他のネームサーバを利用」をクリック。画面下部に表示される「ネームサーバー情報を入力」の入力欄に、さきほどメモったRoute53の4つのネームサーバを入力

<img width="600" alt="ss 2018-07-01 18.37.09.png" src="https://qiita-image-store.s3.amazonaws.com/0/80357/d1297723-87f5-2cd4-4fcf-83c9857730d1.png">

しばらく待つ(最大でも72時間)と、ドメインのネームサーバがDNS全体に反映される。

# 2. Amazon S3でメールを受け取れるようにする

AWSのサービス群の中からSESを選択
<img width="600" alt="ss 2018-07-01 20.09.53.png" src="https://qiita-image-store.s3.amazonaws.com/0/80357/6b80c84d-0863-f3b2-4c46-dccf81d5d232.png">

画面右上のリージョンが「バージニア北部」になっていることを確認し、左のメニューの中からDomainsを選択
<img width="600" alt="ss 2018-07-01 18.50.03.png" src="https://qiita-image-store.s3.amazonaws.com/0/80357/2c592a1b-65dd-2f7b-7134-44598a37ee23.png">

「Verify a New Domain」をクリック
<img width="600" alt="ss 2018-07-01 18.50.14.png" src="https://qiita-image-store.s3.amazonaws.com/0/80357/a6067b27-de4c-f81a-9915-c2451f5fb322.png">

ドメイン名を入力。「Generate DKIM Setting」にチェック。
<img width="600" alt="ss 2018-07-01 18.50.49.png" src="https://qiita-image-store.s3.amazonaws.com/0/80357/4b5a3d26-72a6-9b13-b5a5-7ab0809c3f4c.png">

そのまま「Use Route 53」をクリック
<img width="600" alt="ss 2018-07-01 18.51.01.png" src="https://qiita-image-store.s3.amazonaws.com/0/80357/a4c1ad6a-9310-f23d-0ca7-714c1c01b91c.png">

「Domain Verification Record」「DKIM Record Set」「Email Receiving Record」「Hosted Zones」にチェックを入れ、「Create Record Sets」をクリック
<img width="600" alt="ss 2018-07-01 18.51.21.png" src="https://qiita-image-store.s3.amazonaws.com/0/80357/ee483ae3-6b0f-e71b-711c-a294a6e2985c.png">

しばらく待ち、有効化されることを確認する。以下のようになればOK
<img width="600" alt="ss 2018-07-01 20.44.03.png" src="https://qiita-image-store.s3.amazonaws.com/0/80357/0cc944dc-8575-1a8b-dab7-fa36d56f2eb1.png">

次に、メールを受け取るGmailを有効化しておく。左のメニューから「Email Addresses」をクリック。画面上部の「Verify a New Email Address」をクリック。
<img width="600" alt="ss 2018-07-01 18.52.19.png" src="https://qiita-image-store.s3.amazonaws.com/0/80357/966b82fb-da76-f22b-3fd6-7c85fe681f59.png">

この画面で、独自ドメインのメールを受け取るGmailアカウント(メールアドレス)を入力。Gmailに確認メールが届いているのでURLをクリックして有効化する。
<img width="600" alt="ss 2018-07-01 18.52.25.png" src="https://qiita-image-store.s3.amazonaws.com/0/80357/35f206e3-1f77-66f5-768f-af7683fac75e.png">

これでSESからGmailにメールが送れるようになった。
次に、独自ドメインのメールをS3に保存できるようにする。

AWSのサービス群の中から「S3」を選択する。

<img width="600" alt="ss 2018-07-01 21.34.25.png" src="https://qiita-image-store.s3.amazonaws.com/0/80357/a819dda4-537b-bf9a-1e2d-a3a60122272a.png">

「バケットを作成する」をクリック
<img width="600" alt="ss 2018-07-01 22.30.24.png" src="https://qiita-image-store.s3.amazonaws.com/0/80357/c6598fea-8820-7a1f-a0f8-8d0073235631.png">

バケット名（任意）を入力。ここでは「_ドメイン名_-mailbox」というバケット名にする。リージョンは「東京」を選択。「作成」ボタンをクリック。
<img width="600" alt="ss 2018-07-01 22.31.00.png" src="https://qiita-image-store.s3.amazonaws.com/0/80357/a94ad1e6-4980-940c-bf9f-1148bcaa0424.png">

作成されたバケットを編集する。「アクセス制限」のタブから「バケットポリシー」をクリック。
<img width="600" alt="ss 2018-07-01 22.33.03.png" src="https://qiita-image-store.s3.amazonaws.com/0/80357/eff57fc0-224b-9657-7301-4d3638d7a372.png">

エディターには以下のポリシーを貼り付ける。`YOUR_BUCKET_NAME`と`YOUR_AWS_ID`はそれぞれ、さきほど作ったバケット名、自身のAWSアカウントIDを表している。適宜読み替えてほしい。

```text
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "AllowSESPuts",
            "Effect": "Allow",
            "Principal": {
                "Service": "ses.amazonaws.com"
            },
            "Action": "s3:PutObject",
            "Resource": "arn:aws:s3:::[YOUR_BUCKET_NAME]/*",
            "Condition": {
                "StringEquals": {
                    "aws:Referer": "[YOUR_AWS_ID]"
                }
            }
        }
    ]
}
```

再びSESの画面に戻り、左側の「Rule Sets」をクリック。画面上部の「View Active Rule Set」をクリック。

<img width="600" alt="ss 2018-07-01 22.34.00.png" src="https://qiita-image-store.s3.amazonaws.com/0/80357/b46d923d-0c0c-7200-b8ed-f6d30c52bd31.png">

「Create Rule」をクリック。
<img width="600" alt="ss 2018-07-01 22.34.53.png" src="https://qiita-image-store.s3.amazonaws.com/0/80357/a65bc080-dcb6-8fde-bbf8-117c620b2217.png">

入力ボックスにドメインを入力。「Add Recipient」をクリック。「Next Step」をクリック。
<img width="600" alt="ss 2018-07-01 22.35.30.png" src="https://qiita-image-store.s3.amazonaws.com/0/80357/ec1e5f34-88b0-9f72-f61e-09502ee8b6d1.png">

「Add Action」でS3を選択。「S3 bucket」で先程作成したバケットを選択。「Next Step」をクリック。
<img width="600" alt="ss 2018-07-01 22.35.55.png" src="https://qiita-image-store.s3.amazonaws.com/0/80357/09b55798-5b19-b63d-6bdf-43261e352945.png">

「Rule name」にルール名（任意）を入力。ここでは、「_ドメイン名_-mailbox-rule」とする。「Next Step」をクリック。

<img width="600" alt="ss 2018-07-01 22.39.36.png" src="https://qiita-image-store.s3.amazonaws.com/0/80357/e23ee297-1e5e-9b8a-5296-5d5129a76c1f.png">

「Create Rule」をクリック。
<img width="600" alt="ss 2018-07-01 22.39.50.png" src="https://qiita-image-store.s3.amazonaws.com/0/80357/c68388c6-f932-f222-a132-1833108d2377.png">

以上で、S3にメールを保存するルールファイルが出来上がった。試しにsupport@_独自ドメイン_でメールを送ってみて、S3にメールが保存されているか確認しよう。

# 3. S3に保存されたメールをGmailに送る

AWSのサービス群の中から「IAM」を選択する。

<img width="600" alt="ss 2018-07-01 23.35.06.png" src="https://qiita-image-store.s3.amazonaws.com/0/80357/478b54c2-2511-1118-dbae-654191c5e0f3.png">

左のメニューの中から「ロール」をクリック。画面中央の「ロールの作成」をクリック。
<img width="600" alt="ss 2018-07-01 23.35.31.png" src="https://qiita-image-store.s3.amazonaws.com/0/80357/727afae8-c950-5282-c2e8-58f48c71547f.png">

「Lambda」を選択し「次のステップ」をクリック。
<img width="600" alt="ss 2018-07-01 23.35.45.png" src="https://qiita-image-store.s3.amazonaws.com/0/80357/198e9789-f450-6a3c-6490-71be29469cb2.png">

「AmazonSESFullAccess」と「AmazonS3FullAccess」を選択し、「次のステップ」をクリック
<img width="300" alt="ss 2018-07-01 23.36.22.png" src="https://qiita-image-store.s3.amazonaws.com/0/80357/448f4b99-183c-5ec7-1f77-23ab2358f884.png">
<img width="300" alt="ss 2018-07-01 23.36.10.png" src="https://qiita-image-store.s3.amazonaws.com/0/80357/7b97b4d2-a8e1-2e1d-d2e6-26e3651730e2.png">

任意の「ロール名」および「ロールの説明」を記入して「ロールの作成」をクリック。
<img width="600" alt="ss 2018-07-01 23.36.38.png" src="https://qiita-image-store.s3.amazonaws.com/0/80357/55a201aa-687e-1c56-99c9-8bfe293dc3bd.png">

これでロールは完成。

次に、AWSのサービス群の中から「Lambda」を選択。

<img width="600" alt="ss 2018-07-01 23.45.26.png" src="https://qiita-image-store.s3.amazonaws.com/0/80357/78a5f088-c208-69fd-2bb3-3ad73c42a8de.png">

リージョンを「東京」にし、「関数の作成」を選択。
<img width="600" alt="ss 2018-07-01 23.45.51.png" src="https://qiita-image-store.s3.amazonaws.com/0/80357/5153b4b6-adf1-255d-8a4e-22dc19899d70.png">

「名前」に任意の関数名を入力。ここでは「_xxxxxxx_-email-transportation」とした。「ランタイム」は「Python2.7」を選択。「ロール」は「既存のロールを選択」を選択。「既存のロール」には、先程作成した、S3とSESの権限が含まれているロールを選択。以上ができたら「関数の作成」をクリック。
<img width="600" alt="ss 2018-07-01 23.46.58.png" src="https://qiita-image-store.s3.amazonaws.com/0/80357/a9ea036f-9fec-6228-afb8-4d1ae9d79a25.png">

左上部のリストの中からS3を選択。画面下部のトリガーの設定画面で、先程作ったメール保存用のバケットを選択。以上ができたら右下の「追加」をクリック。
<img width="600" alt="ss 2018-07-01 23.48.14.png" src="https://qiita-image-store.s3.amazonaws.com/0/80357/5b0017be-207e-9be9-6042-32a0dd507d32.png">

画面中央の「xxxxxxx-email-transportation」をクリック。
<img width="600" alt="ss 2018-07-01 23.50.28.png" src="https://qiita-image-store.s3.amazonaws.com/0/80357/22358ebb-a9ac-db2e-6cb1-f919756869ae.png">

画面下部のエディタの欄に以下のコードを貼り付け。ただし、

```
ORIGIN_TO  = "support@[YOUR_DOMAIN]"
FORWARD_TO = "[YOUR_GMAIL]@gmail.com"
SES_REGION = "us-east-1"
S3_BUCKET  = "[YOUR_BUCKET_NAME]"
```
の部分は適宜読み替えてほしい。

```python
import boto3
import email
import re

ORIGIN_TO  = "support@[YOUR_DOMAIN]"
FORWARD_TO = "[YOUR_GMAIL]@gmail.com"
SES_REGION = "us-east-1"
S3_BUCKET  = "[YOUR_BUCKET_NAME]"

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(ORIGIN_TO, FORWARD_TO)
    replaced_message = re.sub(r'^From:\s*.+?$', r'From: "%s" <%s>' % (from_name, ORIGIN_TO), replaced_message, flags=re.MULTILINE)
    replaced_message = re.sub(r'^Return-Path:\s*.+?$', r'Return-Path: "%s" <%s>' % (from_name, ORIGIN_TO), 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_TO,
        Destinations=[
            FORWARD_TO
        ],
        RawMessage={
            'Data': message
        }
    )

def lambda_handler(event, context):
    try:
        s3_key = event['Records'][0]['s3']['object']['key']

        s3 = boto3.client('s3')
        response = s3.get_object(
            Bucket = S3_BUCKET,
            Key    = s3_key
        )
        raw_message = response['Body'].read()
        message = parse_mail(raw_message)

        send_mail(message)

    except Exception as e:
        print(e)
```

以上ができたら、「保存」をクリック。

これで、独自ドメインに送ったメールをGmailで受信できるようになる。