AWS初心者がやってみた。同じドメインで手動・自動の両方からメールを送信する方法。

# はじめに

現在、業務都合でハワイにいます。
ハワイの自由時間、遊ぶ暇を削って、AdventCalenderを書いてます。(自業自得)
役に立ったら「いいね」してってください！

# 結論

はじめに結論。
SESとWorkMailを組み合わせて良い感じにしましょう。
もうちょっと詳しい実装は実装の項目に記載しました。

# 挨拶

皆様こんにちは。フルスタックエンジニア見習いの[tng527](http://qiita.com/tng527)です。
配属4ヶ月でフロントとインフラ(AWS)を学び、着実にフルスタックエンジニアに近づいています。
というわけで、ド素人が数ヶ月でインフラを学んだ結果を共有します。

# 背景

サービスに登録する際に、メールアドレス確認のため、メールを送信する事があると思います。
送信元が、

- `no-reply@example.com`

とかならいいんですが、

- `info@example.com`
- `support@example.com`
- `register@example.com`

などから送信し、**返信を受け取りたい**。
なんなら、**返信に対し手動で返信したい**といった場合があります。
まあ、ユーザもわざわざ`no-replay@example.com`から来たメール内の、別のメールアドレスクリックして自分の名前書きなおして返信〜とかやりたくないですし、有益な気がします。

# 課題

一般的に、サービス登録時に送信されるメールはシステムから自動で送信されることが多いと思います。
AWSゴリゴリだと、Lambdaとかメール整形してSESでメールを送信するわけです。

しかし、メールに返信が来たときにどうするかが課題になります。
捨て置くというのも選択肢ですが、背景で説明したように返信を受け取りたい場合もあります。
この場合、SESで選択可能なイベントは主に4つです。

- Lambdaでなんかする
- S3に置く
- SNSでなんかする
- WorkMailと連携する

あとはヘッダー追加したりなど。
一次ソースはこちらです。
http://docs.aws.amazon.com/ses/latest/DeveloperGuide/receiving-email-action.html

# 解決策

今回は、WorkMailで実装することにしました。
WorkMailは、Gmailのようにブラウザ上でメールの確認や返信が可能なWebAppとして利用可能なサービスです。

採用理由を説明します。現在の要件はこちらでした。

> - `info@example.com`
> - `support@example.com`
> - `register@example.com`

> などから送信し、**返信を受け取りたい**。
> なんなら、**返信に対し手動で返信したい**といった場合があります。

WorkMail採用理由は、返信を受け取るだけならS3で構わないが、手動で返信する際の送信元のアドレスを上記アドレスに統一することが可能か不明であったためです。
ここらへんは詳細を詰めるに至りませんでしたが、SESの裏側で動いてるであろうSMTPサーバにアクセスできれば適当なメーラーから可能な気がします。
~~誰か調べて。。。~~

他に候補として
> - S3に置く

を行い

> - Lambdeでなんとかする

という選択肢もありましたが、S3に置かれたメールがjson等ではなく平文になっており、パースが~~めんど~~大変そうなのでやめました。

というわけで、**SESで送信したメールをWorkMailで受信し、手動で返信する。**を実装します。

# 実装

~~疲れて来たので手を抜きます。~~後日わかりにくいところは追記します。特にわからない所があればコメント欄にお願いします。重点的に追記します。
メール送信実装の過程で、送信元のアドレスでメールを受信する必要があるため、受信部分から実装します。

## メールを受信する

メールを受信出来るようになるまではこちらが詳しいです。
WorkMailでの受信は後ほど説明するので、一旦S3へ保存出来るあたりまで実装して確認しましょう。
http://dev.classmethod.jp/cloud/receiving-email-with-amazon-ses/

## メールの自動送信部分

WorkMailから返信できるようにする前に、送信出来る所まで先に作ってしまいます。
返信環境の実装は後で良いからとにかく送信したい、なんてこともありますよね。
今回の主目的は
> サービスに登録する際に、メールアドレス確認のため、メールを送信する事があると思います。

なのでMVP以外は後回しにしたいですしね。

メール送信部はこちらが詳しいです。
http://dev.classmethod.jp/cloud/aws/amazon-ses-build-and-practice/

## WorkMailで受信する設定

WorkMailで受信を確認するところまでは、こちらが詳しいです。
送信確認は現段階では失敗する想定です。
http://qiita.com/ysKey2/items/2b019337772f8499beec

SESでの受信設定に紐付けるには、上記設定後に、
> WorkMailでの受信は後ほど説明するので、一旦S3へ保存出来るあたりまで実装して確認しましょう。

で実装した、SESのRule SetsでWorkMailのActionを追加しましょう。
設定値は

- Organization ARN: arn:was:workmail:region:account_ID:organization/organization_ID
  - organization_IDはWorkMailのOrganization Settingsから確認可能です。

- SNS Topic: 空白(設定しない想定)

一次ソースはこちらです。
http://docs.aws.amazon.com/ses/latest/DeveloperGuide/receiving-email-action-workmail.html

ここまでで、SESでメールを送信し、それに対する返信を受信してWebApp(WorkMail)で確認するところまで実装出来ました。
残りは、WorkMailから返信する部分です。

## WorkMailで送信する設定
SESより先にWorkMailを使っていた場合、SESにはよしなに権限が設定されますが、同ドメインですでにSESを運用していた場合などは、手動で権限を設定するまでWorkMailからメールを送信することは出来ません。
WorkMailでの送信時に内部的にSESを使用しているため、とのことです。

ここからの手順は民間療法になります。
詳細はAWSに問い合わせ中なので、詳しいことが分かり次第追記予定です。

### 送信エラー時のメール確認
WorkMailからメールを送信しようとすると、エラーが返ってくるはずです。
正常に送信できていれば、これ以降は不要です。

エラーのメール本文を確認すると、こんな感じのメールが返ってきているかと思います。

```
AmazonSESException: Status Code: 403, AWS Service: SES, AWS Request ID: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx, AWS Error Code: AccessDenied, AWS Error Message: User `arn:aws:iam::xxxxxxxxxxxx:user/amazon-workmail-xx-xxxx' is not authorized to perform `ses:SendRawEmail' on resource `arn:aws:ses:xx-xxxx-xx:xxxxxxxxxxxx:identity/example.com'
```

このメールの、`arn:aws:iam::xxxxxxxxxxxx:user/amazon-workmail-xx-xxxx`を`arn:aws:iam::xxxxxxxxxxxx:root`に置き換え、その値をコピっておきます。

### SESに権限設定
SESの送信時の権限をWorkMailに渡します。domain, email addressのどちらに渡しても良いですが、ここではdomain全体で権限設定することにします。
設定場所は以下のとおりです。
SES > Domains > example.com > View Details > Identity Policies > Edit Policy or Create Policy
こちらに、以下の感じで、Policyを設定します。
参考はこちら
http://docs.aws.amazon.com/ses/latest/DeveloperGuide/sending-authorization-policy-examples.html

```
{
  "Id": "ExamplePolicy",	
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "AuthorizeFromAddress",
      "Effect": "Allow",
      "Resource": "arn:aws:ses:[region]::[aws-account]:identity/example.com",
      "Principal": {"AWS": "arn:aws:iam::xxxxxxxxxxxx:root"},
      "Action": ["SES:SendEmail", "SES:SendRawEmail"]
    }
  ]
}
```

Principalの部分はエラーメールからコピーして書き換えた値です。

これで、自動的にメールを送信し、ユーザから返信が来たら、最初に送信したアドレスから返信を行う事ができるようになりました。

# 最後に
AWSは、初心者のうちは大量のインプットが必要ですが、一度慣れてしまえば、コーディングで実装していた部分をAWSのサービスを用いて簡単に実装できると感じました。
今回は、WorkMailに関する日本語の情報が乏しく、実装方法の調査が難航したため、記事にしてみました。
役に立ったら「いいね」をお願いします。

また、修正や実装の代替案など、コメントいただければ、大変嬉しく思います。
すぐに反映していきますのでよろしくお願いします。

本記事は、一部、記述が大雑把であったり、事実関係がはっきりしない部分が残っているため、引き続き追記していく予定です。