Amazon SNS、Amazon SESを使用したAWS Lambdaからのメール送信

Lambdaからメール送信するためにちょっと調べたのでメモ。
ちなみに、最終的にSNSを使用することにしたのでSESはおまけとなっています。

#料金
https://aws.amazon.com/jp/sns/pricing/
https://aws.amazon.com/jp/ses/pricing/

#アジアパシフィック (東京)ありなし
SNS：あり
SES：なし　(米国東部 (バージニア北部)、EU (アイルランド)、米国西部 (オレゴン)　のみ)

#送信元メールアドレスの事前登録
SNS：不要。(`no-reply@sns.amazonaws.com`から送られる)
SES：必要。

#送信先メールアドレスの事前登録
SNS：必要。
SES：不要。

SESについて補足：
　不正使用や悪用を防止などのため、新しいAmazon SES アカウントには一定の制限が適用される。
　そのため、規制緩和のリクエストが必要。

詳しくは以下を参照。
https://docs.aws.amazon.com/ja_jp/ses/latest/DeveloperGuide/request-production-access.html


#添付ファイル
SNS：不可
SES：可

※SESが扱えるEメールメッセージのサイズは最大10MB
　メッセージの一部である画像や添付ファイルも含まれる。

#HTML形式のメール
SNS：不可
SES：可

#Amazon SNSを使用したメール送信

##トピック/サブスクリプション作成

###マネジメントコンソールの場合
Simple Notificationa Serviceのコンソールを開き「今すぐ始める」を押す。
![2019-01-11_10h44_35.png](https://qiita-image-store.s3.amazonaws.com/0/200585/c9920989-335e-9cd9-a52f-926aff8f9d0d.png)

「トピック」を押す。
![2019-01-11_10h44_40.png](https://qiita-image-store.s3.amazonaws.com/0/200585/5674d948-a62e-e378-1f90-63bf44f52e28.png)

「新しいトピックの作成」を押す。
![2019-01-11_10h44_45.png](https://qiita-image-store.s3.amazonaws.com/0/200585/141a4586-3848-737d-2fce-3676ac35f650.png)

以下を入力し、「トピックの作成」を押す。
・「トピック名」
・「表示名」(省略可)
![2019-01-11_10h46_02.png](https://qiita-image-store.s3.amazonaws.com/0/200585/6f4bd815-0eec-9286-0857-be118f1d00f0.png)


作成されたトピックのARNのリンクを押す。
![2019-01-11_10h46_09.png](https://qiita-image-store.s3.amazonaws.com/0/200585/33be38b6-c659-3f0a-d753-c11085585f77.png)

「サブスクリプションの作成」を押す。
![2019-01-11_10h46_16.png](https://qiita-image-store.s3.amazonaws.com/0/200585/f6c57e92-735f-823f-5cee-e054dc1b85bc.png)

以下を入力し、「サブスクリプションの作成」を押す。
・「プロトコル」：Email
・「エンドポイント」：送信先メールアドレス
![2019-01-11_10h50_33.png](https://qiita-image-store.s3.amazonaws.com/0/200585/4af25d25-32bf-bfb3-4ef6-90e261a6d0d2.png)

エンドポイントに指定したメールアドレス宛に確認メールが送信される。
![2019-01-11_10h51_08.png](https://qiita-image-store.s3.amazonaws.com/0/200585/efa72601-8de3-547d-0581-b079a69b98c3.png)

メールを確認し「Confirm subscription」を押す。
![2019-01-11_10h52_41.png](https://qiita-image-store.s3.amazonaws.com/0/200585/7eb7e156-549a-db5c-ffff-adf5d5eb29b2.png)

確認完了画面に遷移する。
![2019-01-25_12h41_24.png](https://qiita-image-store.s3.amazonaws.com/0/200585/d6ccfd09-15d4-4b3e-b93b-6072a7a47976.png)
これでSNSの設定は完了。

マネジメントコンソールからトピックへの送信確認。
「トピックに発行」を押す。
![2019-01-11_11h11_42.png](https://qiita-image-store.s3.amazonaws.com/0/200585/4adb70ed-6cbf-e822-074c-33850d9a9ebf.png)

以下を入力し「メッセージの発行」を押す。
・「件名」
・「メッセージ」
![2019-01-11_11h16_14.png](https://qiita-image-store.s3.amazonaws.com/0/200585/24d2f15f-dd4a-82c8-59ea-14edaa7b9ef5.png)

メールが送信される。
![2019-01-11_11h16_26.png](https://qiita-image-store.s3.amazonaws.com/0/200585/960f7942-e693-15dd-5f6c-a7bb0eec260d.png)

送信されたメール。
![2019-01-11_11h17_26.png](https://qiita-image-store.s3.amazonaws.com/0/200585/7eacbe30-b002-8c6a-2aca-1050cc48be5d.png)

###AWSCLIの場合

AWSCLIを使用した場合、
送信されるメールにある配信停止のリンクを無効化できるので合わせてメモ。

```bash:トピック作成
$ aws sns create-topic --name test-topic --attributes DisplayName="表示名" --profile dev
{
    "TopicArn": "arn:aws:sns:ap-northeast-1:<アカウントID>:test-topic"
}
```

トピック作成で返却されたTopicArnを使用してコマンドを作成し実行する。

```bash:サブスクリプション作成
$ aws sns subscribe --topic-arn arn:aws:sns:ap-northeast-1:<アカウントID>:test-topic --protocol email --notification-endpoint <メールアドレス> --profile dev
{
    "SubscriptionArn": "pending confirmation"
}
```

メールが送信される。
メール内容の確認リンク(赤枠)は押さずに右クリックから「リンクのアドレスをコピー」する。
![2019-01-11_10h52_41.png](https://qiita-image-store.s3.amazonaws.com/0/200585/c4dc505d-3a44-b4da-e758-ae47cf7020a8.png)

↓メールからコピーしたリンク内容。

```bash:リンク内容
https://sns.ap-northeast-1.amazonaws.com/confirmation.html?TopicArn=arn:aws:sns:ap-northeast-1:<アカウントID>:test-topic&Token=<トークン>&Endpoint=<メールアドレス>
```

コピーした内容の「TopicArn」と「Token」を使用してコマンドを作成し実行する。
上記例の場合
　TopicArn：arn:aws:sns:ap-northeast-1:<アカウントID>:test-topic
　Token：<トークン>

```bash:サブスクライブの確認
$ aws sns confirm-subscription --topic-arn arn:aws:sns:ap-northeast-1:<アカウントID>:test-topic --token <トークン> --authenticate-on-unsubscribe true --profile dev
{
    "SubscriptionArn": "arn:aws:sns:ap-northeast-1:<アカウントID>:test-topic:480f6607-f69a-494a-a8aa-cb7b4af54500"
}
```

無効化することで配信停止リンクを押しても、アンサブスクライブ出来なくなる。
(配信停止リンクは残存)
![2019-01-11_11h17_58.png](https://qiita-image-store.s3.amazonaws.com/0/200585/39787a7c-5917-ace2-2098-00b6ddf3972f.png)

##Lambda関数作成
使用するポリシー：AmazonSNSFullAccess、AWSLambdaBasicExecutionRole

```python:AmazonSNSでメール送信
import boto3

def lambda_handler(event, context):
    sns_client = boto3.client('sns')
    sns_client.publish(
        TopicArn='arn:aws:sns:ap-northeast-1:<アカウントID>:test-topic',
        Subject='テストメール',
        Message='メール送信メッセージ',
    )
    return "ok"

```

送信されるメールサンプル。
![2019-01-24_18h48_02.png](https://qiita-image-store.s3.amazonaws.com/0/200585/4d4c28e3-700a-6ca6-8df0-2d3c778851ea.png)

#Amazon SESを使用したメール送信
##Eメールのセットアップ
###マネジメントコンソールの場合
アジアパシフィック (東京)がないのでリージョンを変更する。
![2019-01-11_11h28_27.png](https://qiita-image-store.s3.amazonaws.com/0/200585/323bcb30-6cf3-b363-fb28-0163e415b1c4.png)

「Email Addresses」を押す。
![2019-01-11_11h28_39.png](https://qiita-image-store.s3.amazonaws.com/0/200585/bdb669db-9e92-eab3-d2b7-5fc015784db4.png)

「Verify a New Email Address」を押す。
![2019-01-11_11h35_03.png](https://qiita-image-store.s3.amazonaws.com/0/200585/2e692800-bfc7-470a-dc29-4b3b8ef5aa92.png)

以下を入力し「Verify This Email Address」を押す。
・「EmailAddress」：送信元メールアドレス
![2019-01-11_11h36_12.png](https://qiita-image-store.s3.amazonaws.com/0/200585/398cea53-5ee1-50b7-0d36-fb2a4d09ab6e.png)

指定したメールアドレスに検証のためメールが送信される。
![2019-01-11_11h36_22.png](https://qiita-image-store.s3.amazonaws.com/0/200585/2a309db6-3097-691e-8142-a70f08c24b50.png)

この時点ではpendingの状態。
![2019-01-11_11h37_20.png](https://qiita-image-store.s3.amazonaws.com/0/200585/16518e8e-b819-8af0-3807-475876941967.png)

メールアドレスにあるリンクを押して検証を完了させる。
![2019-01-11_11h38_21.png](https://qiita-image-store.s3.amazonaws.com/0/200585/19437d3d-9747-efd6-ee71-d652b090b666.png)

リンクを押すと検証完了。
![2019-01-11_11h38_42.png](https://qiita-image-store.s3.amazonaws.com/0/200585/281d4bef-ace9-27b2-dcb7-a73e5da07537.png)

コンソール上でもpendingからverifiedになる。
![2019-01-11_11h39_20.png](https://qiita-image-store.s3.amazonaws.com/0/200585/a5a97bee-76c7-67bb-7167-53bc7f93bec8.png)


###AWSCLIの場合
```bash:Eメールのセットアップ
$ aws ses verify-email-identity --email-address <送信元メールアドレス> --profile dev --region us-east-1
```

※返却値は特になし

指定したメールアドレスに検証用のメールが送信されるので、
マネジメントコンソールの場合と同様にリンクを押し検証を完了する。

##Lambda関数作成
使用するポリシー：AmazonSNSFullAccess、AWSLambdaBasicExecutionRole

```python:AmazonSESでメール送信
import boto3
from botocore.exceptions import ClientError

def lambda_handler(event, context):
    SENDER = "Sender Name <test@testtest.jp>"
    RECIPIENT = "test@testtest.jp"
    AWS_REGION = "us-east-1"
    SUBJECT = "テストメール送信"
    
    CHARSET = "UTF-8"
    client = boto3.client('ses',region_name=AWS_REGION)

    BODY_HTML = """<html>
    <head></head>
    <body>
      <h1>Amazon SES Test (SDK for Python)</h1>
      <p>テストメール</p>
    </body>
    </html>
    """

    try:
        response = client.send_email(
            Source=SENDER,
            Destination={
                'ToAddresses': [
                    RECIPIENT,
                ],
            },
            Message={
                'Subject': {
                    'Charset': CHARSET,
                    'Data': SUBJECT
                },
                'Body': {
                    'Html': {
                        'Charset': CHARSET,
                        'Data': BODY_HTML
                    }
                }
            }
        )

    except ClientError as e:
        print(e.response['Error']['Message'])
    else:
        print("Email sent! Message ID:"),
        print(response['MessageId'])
```
![2019-01-29_13h30_58.png](https://qiita-image-store.s3.amazonaws.com/0/200585/8320cea4-f4f3-375e-133d-32793ff74dd1.png)


#おまけ
##AWSCLIの事前準備(設定)
AWSCLIのコマンドで使用している`--profile dev`はAWSCLIで使用する認証情報を指定しています。
IAMユーザに関連付けられているAWS Access Key ID、AWS Secret Access Keyを使用して設定します。
(AWS Access Key ID、AWS Secret Access Keyはマネジメントコンソールから作成可能)

設定例

```bash:AWSCLI認証設定
$ aws configure --profile dev
AWS Access Key ID [None]: <アクセスキー>
AWS Secret Access Key [None]: <シークレットアクセスキー>
Default region name [None]: ap-northeast-1
Default output format [None]: json
```

SESではリージョンが設定した値と違うため、コマンドライン上で以下を指定しています。
・` --region us-east-1`

#SNS参考
https://docs.aws.amazon.com/ja_jp/sns/latest/dg/welcome.html
https://aws.amazon.com/jp/sns/faqs/
https://docs.aws.amazon.com/cli/latest/reference/sns/create-topic.html
https://docs.aws.amazon.com/cli/latest/reference/sns/subscribe.html
https://docs.aws.amazon.com/cli/latest/reference/sns/confirm-subscription.html
https://dev.classmethod.jp/cloud/aws/amazon-sns-disable-unsubscribe-link/

#SES参考
https://docs.aws.amazon.com/ja_jp/ses/latest/DeveloperGuide/Welcome.html
https://docs.aws.amazon.com/ja_jp/ses/latest/DeveloperGuide/send-using-sdk-python.html
https://aws.amazon.com/jp/ses/faqs/
https://dev.classmethod.jp/cloud/aws/lambda-to-ses/
https://docs.aws.amazon.com/ses/latest/DeveloperGuide/verify-email-addresses-procedure.html
https://docs.aws.amazon.com/cli/latest/reference/ses/verify-email-identity.html

#AWSCLI参考
https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/cli-chap-install.html
https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/cli-chap-configure.html