Spring-Boot + Heroku でメール送信

# 概要
Spring BootとHerokuを使ってメール送信をします。

# やり方
Herokuの[SendGrid](https://devcenter.heroku.com/articles/sendgrid)というaddonを利用してメールを送信します。

# 事前準備
- heroku CLIのインストール済
- Spring BootのアプリケーションをHerokuにデプロイする
- Herokuのアカウントにクレジットカードを登録する([ここから登録](https://dashboard.heroku.com/account/billing))(addonが利用できるようになります)

# 手順

※herokuのアプリケーション名は、`gosshys-testproject`にしています。

## SendGridのaddonを追加

以下のコマンドでSendGridのaddonを登録します。コマンドは、デプロイ済のSpring Bootのアプリケーションのgitリポジトリで実行してください。

```
heroku addons:create sendgrid:starter
```
### 実行結果
```
$ heroku addons:create sendgrid:starter
Creating sendgrid:starter on ⬢ gosshys-testproject... free
Created sendgrid-convex-82110 as SENDGRID_PASSWORD, SENDGRID_USERNAME
Use heroku addons:docs sendgrid to view documentation
```

成功したら以下のコマンドで、SendGridの環境変数がセットされていることを確認します。自動的にSendGridのユーザー(メールアドレス)とパスワードがセットされます。

```
$ heroku config:get SENDGRID_USERNAME
app99999999@heroku.com
$ heroku config:get SENDGRID_PASSWORD
xxxpasswdxxx
```

###### アカウントのクレジットカード情報を登録していないとが追加できません
`Please verify your account to install this add-on plan`のエラーがでています。

```
$ heroku addons:create sendgrid:starter
Creating sendgrid:starter on ⬢ gosshys-testproject... !
 ▸    Please verify your account to install this add-on plan (please enter a credit card) For more information, see https://devcenter.heroku.com/categories/billing Verify now at https://heroku.com/verify
```

## SendGridのAPIキーを取得する

SendGridのドキュメントの[Obtaining an API key](https://devcenter.heroku.com/articles/sendgrid#obtaining-an-api-key)を参考にSendGridのAPIキーを取得します。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/38174/7dbee504-9821-d3fb-8dba-9f583834f27f.png)

Go [here](https://app.sendgrid.com/settings/api_keys)のhere部分をクリックするとSendGridのAPIキーの取得の画面に遷移します。

最初のアクセス時は、ログイン画面がでてきますが、ここに先程`heroku config:get`で取得したSendGridのユーザーとパスワードを入力します。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/38174/79be9f05-a88c-1bcf-4f3e-003ecec9a9ed.png)

ログインするとこんな画面がでてきます。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/38174/1917fc4a-7e91-9fbc-5b9e-3423f7bd2ac1.png)

画面右上の「Create API Key」ボタンをクリックすると、APIキー生成の画面が現れます。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/38174/732d856d-a6f9-d3fd-fb28-205965ff1489.png)

- 「API Key Name」にAPIキーの説明を入れます。ここは単純にHerokuのアプリケーション名を入れました。
- 「API Key Permissions」は、「Full Access」と「Restricted Access」のどちらかを選択します。「Billing Access」は、主にエンタープライズ向けのようなので選択しません。また「Restricted Access」は細かくメールの機能を制限できますが、今はどの機能を制限すべきか定かでないので「Full Access」を選択します。

「Create & View」ボタンを押してAPIキーを生成します。

### APIキー生成

「Create & View」ボタンをクリックすると以下の画面が現れます。セキュリティの観点からこの画面は１度しか表示されないので、赤字の下にでてくる英数字の羅列をコピーしてどこかにメモしておきます。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/38174/4df51927-23c4-f611-6f3b-28b0743adc59.png)

APIキーをコピーしてメモしたら「Done」ボタンを押します。するとAPIキーの一覧画面に遷移するので、そこで「API Key ID」と*でマスク化された「API KEY」が参照されます。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/38174/4b321f83-4680-a7d4-a901-8d2a08d60f55.png)

## Herokuの環境変数にSendGridのAPIキーIDとAPIキーを設定する

ドキュメントの[Setup API key environment variable](https://devcenter.heroku.com/articles/sendgrid#setup-api-key-environment-variable)の手順に従ってHerokuの環境変数にSendGridのAPIキーIDとAPIキーを設定します。

```
$ heroku config:set SENDGRID_API_KEY=(SendGridのページでメモしたAPIキー、APIキーIDではないので注意)
Setting SENDGRID_API_KEY and restarting ⬢ gosshys-testproject... done, v7
SENDGRID_API_KEY: (SendGridのページでメモしたAPIキーが表示されます)
```

## Spring Bootのアプリケーションでメールを送る

ドキュメントの[java](https://devcenter.heroku.com/articles/sendgrid#java)を参考に、Spring Bootにメール送信のプログラムを追加します。

### pomにSendGridのライブラリを追加

mavenのpom.xmlのdependenciesに以下を追加します。現時点で4.1.2が最新のようなのでそれを追加しました。Gradleの方はドキュメントに例があります。

```
		<dependency>
			<groupId>com.sendgrid</groupId>
			<artifactId>sendgrid-java</artifactId>
			<version>4.1.2</version>
		</dependency>
```

### Spring Bootのコントローラーにメール送信機能を追加

Spring BootのRestControllerにドキュメント内の[サンプル](https://devcenter.heroku.com/articles/sendgrid#java-example-with-mail-helper-class)をベタ貼りします。Kotlinで書いていてしまっていますが、Javaで大丈夫です。

```
package com.koiwaimilk.tsukigaoka.core.controller

import com.sendgrid.*
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RequestParam
import org.springframework.web.bind.annotation.RestController
import java.io.IOException


@RestController
@RequestMapping(value = "/mail")
class MailSendController {
    @RequestMapping(value = "/send")
    fun send(@RequestParam(value = "contents", defaultValue = "Hello, Email!") contents: String): String {
        val from = Email("test@example.com")
        val subject = "Hello World from the SendGrid Java Library!"
        val to = Email("（ここに送信先のメールアドレスを設定します）")
        val content = Content("text/plain", "Hello, Email!")
        val mail = Mail(from, subject, to, content)

        val sg = SendGrid(System.getenv("SENDGRID_API_KEY"))
        val request = Request()
        try {
            request.method = Method.POST
            request.endpoint = "mail/send"
            request.body = mail.build()
            val response = sg.api(request)
            System.out.println(response.statusCode)
            System.out.println(response.body)
            System.out.println(response.headers)
        } catch (ex: IOException) {
            throw ex
        }

        return "OK"
    }
}
```

### ローカル環境の環境変数の設定

ローカルで動作させる場合は、SENDGRID_API_KEYの設定が必要になるのでIDEのアプリケーション起動時の環境変数にSENDGRID_API_KEYを設定します。例はIntelliJです。

「メニュー」ー「Run」ー「Edit Configurations」
![image.png](https://qiita-image-store.s3.amazonaws.com/0/38174/b38267f4-7354-76f7-a7d1-51ec584732d2.png)
「Enviroment variables」の「...」マークをクリック
![image.png](https://qiita-image-store.s3.amazonaws.com/0/38174/228c5684-e26c-d711-82c0-e6a204f09e38.png)
「+」ボタンをクリックして、SendGridの環境変数のキー「SENDGRID_API_KEY」とAPIキー(APIキーIDではない)を入力して「OK」ボタンをクリック
![image.png](https://qiita-image-store.s3.amazonaws.com/0/38174/ab5c205b-40dc-9e0d-5641-83ccceba1fcc.png)
「Enviroment variables」に入力したAPIキーが設定されていることを確認して、「OK」ボタンをクリックして設定を完了します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/38174/e82f1238-28f1-8073-4598-caea6c0b6ab2.png)

### Spring Bootの起動とメール送信

Spring Bootを起動します。

curlを利用して、メール送信コントローラーをコールします。

```
$ curl localhost:8080/mail/send
```

### 数分後

メールボックを確認するとメールが届いています。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/38174/c17ff7af-f1f4-ccff-f3f1-ae23729b9a57.png)