Cognitoから送信される検証メールが文字化けするってときは…

# はじめに

AWSにはAmazonCognitoという認証サービスがあります。
[Amazon Cognito](https://docs.aws.amazon.com/ja_jp/cognito/latest/developerguide/what-is-amazon-cognito.html)

Cognitoを利用することで面倒だった認証周りの実装が、マネージドでかつサーバレスで利用することができるので、かなり重宝しています。
( Experess.jsでアプリケーション構築してときはpassportというプラグインを使ってかなりしんどかった… )
しかもCognitoは、ユーザーの検証(Verify)メールを送信させることができます。
ユーザー登録時にメールアドレスを登録させるようにして、そのアドレスに検証リンクや検証コードを送信して、リンクを踏んだり、コードを入力することでユーザーを有効化することができます。
私が構築しているアプリケーションでも、ユーザー登録時に検証メールを送信して、検証リンクを踏むまでユーザーが有効化しようとしていました。

## 化ける日本語たち

```text
これはアカウント有効化メールです。
下記リンクをクリックしアカウントを有効化してください。
Verify Email
```

こんな文面のメールを送信すべくCognitoのコンソール画面から設定しました。
さぁ、検証メールよ送信されよ！と意気揚々に送信してみましたが……

```text
?????????????????
???????????????????????????
Verify Email
```

と、このようにきれいに日本語は文字化けしました。

## 原因はなんだ

悩んでいると頼れる後輩くんが
「メールのソースを見ましょう」
とよくわからないことを言ってきたので、とりあえずソースを確認してみると、下記のようなテキストでした。

```text
Subject: =?UTF-8?B?SW9ULmt5b3RvIFZJUyDjgqI=?=
 =?UTF-8?B?44Kr44Km44Oz44OI55m76Yyy44GC44KK?=
 =?UTF-8?B?44GM44Go44GG44GU44GW44GE44G+44GZ?=
MIME-Version: 1.0
Content-Type: multipart/mixed; 
	boundary="----=_Part_554_2126041111.1535085176849"
user_pool_name: xxxxxxxxxxx
region: ap-northeast-1
Date: Fri, 24 Aug 2018 04:32:57 +0000
X-SES-Outgoing: 2018.08.24-54.240.27.61
Feedback-ID: 1.us-west-2.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=:AmazonSES

------=_Part_554_2126041111.1535085176849
Content-Type: text/html; charset=us-ascii
Content-Transfer-Encoding: 7bit

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
    </head>
    <body>
        <div>?????????????????</div>
        <div>???????????????????????????</div>
        <div> <a href=https://confirm-xxxxxx.auth.ap-northeast-1.amazoncognito.com/confirmUser?client_id=5dvt2i0dkqm50626f2ug9poto1&user_name=xxxxxxxx&confirmation_code=123456>Verify Email</a> </div>
    </body>
</html>
------=_Part_554_2126041111.1535085176849--
```

※一部抜粋。一部マスクしています。


ここで？となったのはまずMINEが `Content-Type: multipart/mixed` になっていること。
そしてどうやら2つめのPartにメールの本文が書かれているようなのですが、 `charset=us-ascii` になっているではありませんか…
そりゃ日本語が見事に化けるわけですよ。

Cognitoの検証メールはSESで送信してきているみたいなので、SESの仕様をあさっていると、

```text
フォーマットされた E メールを送信する場合、送信元アドレス、宛先アドレス、メッセージの件名、およびメッセージ本文を指定する必要があります。
Amazon SES では、E メールクライアントソフトウェアでの表示に最適化された、適切にフォーマットされたマルチパート MIME メールメッセージを
自動的にアセンブルします。
```

という一文を見つけました。
おそらくCognitoで登録している本文の1文字目を見て、文字コードをよしなに解釈したり、マルチパートにしたりしてくれているんだろうなーとぼんやり思いました。SESすげぇ…

## で、なにしたのか

結論から言うと、改行コードを打ち込んでやりました。
そうすると1文字目が改行コードになるので、変にマルチパートで送信されることなくメールが送信されました。
やったね！！

```text
これはアカウント有効化メールです。
下記リンクをクリックしアカウントを有効化してください。
Verify Email
```

メールのソースはこんな感じ

```text
Subject: =?UTF-8?B?SW9ULmt5b3RvIFZJUyDjgqI=?=
 =?UTF-8?B?44Kr44Km44Oz44OI55m76Yyy44GC44KK?=
 =?UTF-8?B?44GM44Go44GG44GU44GW44GE44G+44GZ?=
MIME-Version: 1.0
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable
Message-ID: <010101656a38fce0-ecd85a66-c586-43a6-8e47-30b64a4776f9-000000@us-west-2.amazonses.com>
Date: Fri, 24 Aug 2018 04:37:24 +0000
X-SES-Outgoing: 2018.08.24-54.240.27.62
Feedback-ID: 1.us-west-2.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=:AmazonSES


<!DOCTYPE html>
<html>
    <head>
        <meta charset=3D"utf-8">
    </head>
    <body>
        <div>=E3=81=93=E3=82=8C=E3=81=AF=E3=82=A2=E3=82=AB=E3=82=A6=E3=83=
=B3=E3=83=88=E6=9C=89=E5=8A=B9=E5=8C=96=E3=83=A1=E3=83=BC=E3=83=AB=E3=81=A7=
=E3=81=99=E3=80=82</div>
        <div>=E4=B8=8B=E8=A8=98=E3=83=AA=E3=83=B3=E3=82=AF=E3=82=92=E3=82=
=AF=E3=83=AA=E3=83=83=E3=82=AF=E3=81=97=E3=82=A2=E3=82=AB=E3=82=A6=E3=83=B3=
=E3=83=88=E3=82=92=E6=9C=89=E5=8A=B9=E5=8C=96=E3=81=97=E3=81=A6=E3=81=8F=E3=
=81=A0=E3=81=95=E3=81=84=E3=80=82</div>
        <div> <a href=https://confirm-xxxxxx.auth.ap-northeast-1.amazoncognito.com/confirmUser?client_id=5dvt2i0dkqm50626f2ug9poto1&user_name=xxxxxxxx&confirmation_code=123456>Verify Email</a> </div>
    </body>
</html>
```

# さいごに

こうして日本語が化けることなく検証メールを送信することができました。
根本的な解決に至ったわけではないので、時間があればもっと掘り下げていきたいなと思います。

またメール本文にHTMLが書けるので、ある程度メール本文をデコレーションすることができるのでいい感じの検証メールを作れるなと感じました。
何はともあれ、Cognitoを利用すると、ユーザー用のDBを持つ必要もなくなるし、Cognitoで発行したトークンを使ってその他サービスのアクセスをコントロールすることができたりするのでとても便利なサービスですね！

一緒に調べてくれた後輩くんありがとう！
ではまた！