無料の Outlook メールと無料の Azure AD を使って REST API 経由でメール送信してみた

## 背景と目的

Web アプリから開発時の動作検証やテスト目的でメールを送りたいけど、パブリッククラウド上や社内からだと SMTP ポート閉じられていたり、かといって従量課金のPaaSやその他の面倒な構成は嫌なので、無料の Outlook メールと無料の Azure AD を使って REST API 経由でメール送信することにしました。

## 前提条件

この例では python3 を使いますが、localhost:80 にアクセス出来れば何でも良いです。

## 実施内容

### Outlook メールのアカウントを作成

[https://office.live.com/start/Outlook.aspx?omkt=ja%2DJP](https://office.live.com/start/Outlook.aspx?omkt=ja%2DJP)

例えば、「アカウントがない場合 アカウントを作成しましょう」→「または、既にお持ちのメールアドレスを使う」→「新しいメールアドレスを取得」と進みます。

@outlook.jp または @outlook.com または @hotmail.com

の何れかからメールドメインを選択して、メールアカウントを作成します。

### Azure AD を作成

[https://portal.azure.com/#create/Microsoft.AzureActiveDirectory](https://portal.azure.com/#create/Microsoft.AzureActiveDirectory)

「組織名」「初期ドメイン名」「国/リージョン」を入力または選択して作成します。

作成が完了したら「新しいテナントを管理するには、ここをクリックします。」をクリックします。

### Azure AD にアプリを登録

Azure ポータルの一番上にある検索バーで「Azure Active Directory」を検索＆選択し、左にある「管理」メニューから「アプリの登録」を開きます。

「＋新規登録」でアプリを登録します。

* 名前：（例）restapi-test
* サポートされているアカウントの種類：個人用 Microsoft アカウントのみ
* リダイレクトURI：Web [http://localhost/](http://localhost/)

アプリが登録されたら、アプリケーション（クライアント） ID とディレクトリ（テナント） ID をコピーしておきます。

次に、左にある「管理」メニューから「証明書とシークレット」を開きます。

「＋新しいクライアントシークレット」でシークレットを作成します。

* 説明：（例）secret
* 有効期限：（例）なし

「値」列にある、作成されたシークレットをコピーします。

最終的に必要なアプリ情報はこちらです。（注）固有情報の一部は xxxx に置き換えています。

* クライアント ID ：b31c787f-xxxx-45af-9d58-a451916f2bc2
* クライアントシークレット：U24171_xxxxja8V-Zwo6i5~QcU9MrYc9-_

### REST API に必要なトークンを取得

Web サーバーを立ち上げます。

```bash:bash
$ python3 -m http.server 80
```

client_id の値を先ほど作成したアプリのクライアントIDに変更して、ブラウザに貼り付けます。

[https://login.microsoftonline.com/consumers/oauth2/v2.0/authorize?client_id=b31c787f-xxxx-45af-9d58-a451916f2bc2&response_type=code&redirect_uri=http%3A%2F%2Flocalhost%2F&response_mode=query&scope=offline_access%20mail.send&state=12345](https://login.microsoftonline.com/consumers/oauth2/v2.0/authorize?client_id=b31c787f-xxxx-45af-9d58-a451916f2bc2&response_type=code&redirect_uri=http%3A%2F%2Flocalhost%2F&response_mode=query&scope=offline_access%20mail.send&state=12345)

「このアプリがあなたの情報にアクセスすることを許可しますか？」と表示されるので、「はい」を選択します。

画面もしくはアドレスバーに表示された「/?code=M.R3_BAY.f2b65b96-xxxx-9838-aaa1-5d7874c8279c&state=12345」の code の値をコピーします。

python の http.server は停止して、client_id と client_secret の値を先ほど作成したアプリのクライアント ID とクライアントシークレットに変更して、curl を実行します。

```bash:bash
$ curl https://login.microsoftonline.com/consumers/oauth2/v2.0/token \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=authorization_code&code=M.R3_BAY.f2b65b96-xxxx-9838-aaa1-5d7874c8279c&redirect_uri=http%3A%2F%2Flocalhost%2F&client_id=b31c787f-xxxx-45af-9d58-a451916f2bc2&client_secret=U24171_xxxxja8V-Zwo6i5~QcU9MrYc9-_" | jq .
{
  "token_type": "Bearer",
  "scope": "Mail.Send",
  "expires_in": 3600,
  "ext_expires_in": 3600,
  "access_token": "EwBQA8l6BAAU6k7+xxxx+30x5t4B11nRniWUkbAI=",
  "refresh_token": "M.R3_BAY.CQ12c5REY4!xxxxT05Mux3bAbh*s$"
}
```

### REST API 経由でメール送信

取得したアクセストークンを使ってメールを送信します。＜受け取りたいメールアドレス＞は変更します。

```bash:bash
$ curl -v https://graph.microsoft.com/v1.0/me/sendMail \
  -H "Content-type: application/json" \
  -H "Authorization: Bearer EwBQA8l6BAAU6k7+xxxx30x5t4B11nRniWUkbAI=" \
  -d '{"message": {"subject": "テストメール", "body": {"contentType": "Text","content": "これはテストメールです。"}, "toRecipients": [{"emailAddress": {"address": "＜受け取りたいメールアドレス＞"}}]}, "saveToSentItems": "false"}'
```

「HTTP/1.1 202 Accepted」が表示されていれば OK。

メールが届いているか確認します。迷惑メールに入っていないかも確認してください。

### トークンの更新

トークンに有効期限があるので、リフレッシュトークンを使用して、トークンを取得し直します。

```bash:bash
$ curl https://login.microsoftonline.com/consumers/oauth2/v2.0/token \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d 'grant_type=refresh_token&refresh_token=M.R3_BAY.CQ12c5REY4!T05Mux3bAbh*s$&redirect_uri=http%3A%2F%2Flocalhost%2F&client_id=b31c787f-xxxx-45af-9d58-a451916f2bc2&client_secret=U24171_xxxxja8V-Zwo6i5~QcU9MrYc9-_' | jq .
{
  "token_type": "Bearer",
  "scope": "Mail.Send",
  "expires_in": 3600,
  "ext_expires_in": 3600,
  "access_token": "EwBQA8l6BAAU6k7+xxxx/0RKEcW3QYPkpFACbAI=",
  "refresh_token": "M.R3_BAY.CSSkry!aewxxxxPLi0RUfFbbBP!0$"
}
```

### 不要になったら

下記のリストは、メールが不要になった時に削除するものです。

* Azure AD からアプリ削除
* Azure AD テナント削除
* MS アカウント削除（もしくは許可したアプリの削除）

## 参考

[認証トークンを取得する - ユーザーの代わりにアクセスを取得](https://docs.microsoft.com/ja-jp/graph/auth-v2-user)