GMail APIを使用したRESTコンポーネントでのメール送信

# はじめに

ASTERIA WarpのRESTコンポーネントでGMail APIを使ってメール送信する方法を考えてみました。

# 環境

+ OS: Windows10
+ Java:1.8.0.241
+ ASTERIA Warp : 1912

# 事前準備・前提

フローは、AccessToken、RefreshTokenありきでひとまず考えてみています。
クライアントIDやクライアントシークレット、AuthorizationCode含め、AccessToken、RefreshTokenの取得は事前準備として行なっておきます。
scopeはひとまず以下を指定しておきました。

+ `https://www.googleapis.com/auth/gmail.readonly`
+ `https://www.googleapis.com/auth/gmail.send`

# フロー

![GMailSend01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180292/81301ddb-d093-af0c-9832-69e197b1b3ef.png)


## フローの流れ
主な流れは

1. AccessTokenの検証
+ AccessTokenの期限が切れていたらRefreshTokenから生成
+ メール送信データを作成
	1. From、To、Subject、本文などを設定
	+ base64でエンコード
	+ JSONに変換
+ GMail APIでメールを送信

です。それぞれの処理について掘り下げて説明していきます。

## AccessTokenの検証

AccessTokenの検証は

```
https://www.googleapis.com/oauth2/v3/tokeninfo?[アクセストークン]
```
のHTTPステータスをBranchStartで判断してみています。

![GMailSend02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180292/2babf10b-ff7c-a17a-4894-3414e9c6418f.png)

URLパラメーター
![GMailSend03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180292/893ee69e-3a84-c50c-32e9-16d389ef598c.png)

BranchStart
![GMailSend04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180292/af9b5283-38a1-4e1b-5d39-ca2c9b1e67ee.png)


`200 OK` 以外の場合は期限切れとみなしてRefreshTokenを使って再取得しています。



## RefreshTokenからAccessTokenの生成

RefreshTokenからAccessTokenを生成するときは

```
https://accounts.google.com/o/oauth2/token
```
へ以下のフォームデータでPOSTするらしいので

+ client_id
+ client_secret
+ refresh_token
+ grant_type

RESTの入力ストリームをParameterListにしてPOSTするようにしてみました。

![GMailSend05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180292/ad822d1d-a05e-3007-f330-41f2ed11b836.png)


レスポンスはJSONなのでここでは出力ストリームを`XML`にして生成したaccess_tokenをフロー変数に格納しています。

![GMailSend06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180292/526bfda8-82b1-23c9-b3f8-69863dac5011.png)


## メール送信データを作成

###1. From、To、Subject、本文を設定
MIMEEncodeを使って設定しています。
![GMailSend07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180292/e2364314-588e-92fb-1e08-3f5a39bad160.png)


###2. base64でエンコード
Base64Encodeを使って全体をエンコード。
![GMailSend08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180292/5fe67131-75bb-52ca-77bc-45e6293e5b64.png)
改行文字を削除プロパティは`はい`にしています。

###3. JSONに変換
JSONEncodeでJSONに変換。
![GMailSend09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180292/ac6957bf-e8da-b9d3-1def-cc385ffc0ba0.png)
`{raw:[base64文字列]}`としたかったのでParameterListを入力ストリームにしています。
![GMailSend10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180292/25d07483-c9d7-337e-3744-e29a07460578.png)


## GMail APIでメールを送信

```
https://www.googleapis.com/gmail/v1/users/me/messages/send
```
へ作成したJSONをそのまま差し込んでいます。

![GMailSend11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180292/24579403-fced-a3ea-bb32-dba542721f94.png)

送信ヘッダーは以下のように設定しています。

| ヘッダー名 | 値 |
| --- | --- |
| Authorization |Bearer ${flow.AccessToken} |
| Content-Type |application/json |
| Accept |application/json |

![GMailSend12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180292/b21370d0-a1b7-a542-bc04-e3994e52a0e1.png)

以上でフローは完成です。

## フローの実行

![GMailSend13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180292/adcdb37d-3f3d-224a-ae6c-be71506d53ed.png)

無事にメール送信できているようです。

![GMailSend14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180292/bbc758a0-3294-2f72-508b-5ee6cc74b0ec.png)


## 番外編

AuthorizationCodeからAccessTokenとRefreshTokenを取得する部分はRESTコンポーネントで設定すると以下のような感じです。

URL:

```
https://accounts.google.com/o/oauth2/token
```
入力ストリーム:ParameterList

+ client_id
+ client_secret
+ redirect_uri
+ grant_type
+ code

redirect_uriとgrant_typeは固定で`urn:ietf:wg:oauth:2.0:oob`と`authorization_code`を指定しています。
RefreshTokenから生成するときと似たような設定内容です。

<img width="1131" alt="GMailAPI10x.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180292/6a90c74f-3c92-401a-91bf-18bcebb5ce76.png">


# その他雑感

今のままだとほぼ毎回RefreshTokenからAccessTokenを生成することになるのでまだまだ改良の余地はあると思っています。
トークンをAESで暗号化してファイル保存しておいて取り出すときは複合化するといった処理を入れるともっと本格的ですよね。
AuthorizationCodeは一度しか取得しないと思うので最初にブラウザーからアクセスして取得するのが簡単だと思います。
CodeからAccessTokenとRefreshTokenを取得する部分はRESTコンポーネントでもできそうですが、AuthorizationCodeを使って一度取得するとそのCodeは数分くらいで使えなくなってしまうようなので、実質最初にRefreshTokenを取得するために１回実行するくらいかと思います。
curlで実行している例はたくさん見かけましたので、それを参考にRESTコンポーネントで組み立ていくとわかりやすかったです。
Javaのライブラリとしても提供されているのでJavaInterpreterで書いてみるのもよいかもしれません。

# 終わりに

AccessToken、RefreshTokenさえあれば意外と単純なフローになりました。時間があればファイル添付やメール受信もやってみたいなと思っています。