Firebaseのユーザーにメールを配信する仕組み

# 実装するもの
今回は、Firebaseに登録してくれたUserにメール（登録認証メールではありません）を送る実装をしていきたいと思います。
仕組みは以下の画像に記載しております。
<img width="1173" alt="スクリーンショット 2019-11-21 17.19.40.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/302458/bd072647-ef82-9bbe-db40-84b40a80f474.png">

①CloudFunctionsからFirestoreの情報を取得してレスポンスするAPIを作成
②GASでAPIを叩き、スプレッドシートに記入
③スプレッドシートからユーザー情報を取得し、GASからメールを送信する。


※CloudFunctionsから直接送る方法もあるのですが、今回はスプレッドシートにユーザー情報を保存することも踏まえたかったのでこちらの仕組みにました。

# 前提

- Firebaseの基本的な操作がわかっている前提で說明していきます。
- GASの使い方もわかっているものとしてます。

#では、開発Start
## ① CloudFunctionsからFirestoreの情報を取得してレスポンスするAPIを作成
まずは、Firestoreは以下の画像のような仕組みにしてください。

<img width="1270" alt="スクリーンショット 2019-11-21 17.32.40.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/302458/501410bd-3707-93bc-f556-73bf7aec5770.png">


次に、CloudFunctionsの環境を整えていきます。
ターミナルやiTermを開いて、ディレクトリーに移動し、初期化コマンドを実行します。

```
mkdir ディレクトリ名
cd ディレクトリ名
firebase init
```

そうすると使用する機能を聞かれるのでFunctionsを選択し、他はEnterで進んで下さい。
完了すると以下のファイルが生成されているので確認してください。

```
functions
firebase.json
```
生成されていれば、functionsディレクトリに移動して下さい。

次に、cloudFunctionからFirestoreを操作する場合に必用なFirebaseAdminSDKをインストールしておきます。

```
npm install firebase-admin --save
```

完了したら、functions内にある、index.jsをエディターで開きます。
→index.jsでAPIを作成していきます。

コーディングする前に、Adminとして操作するために、プロジェクトの秘密鍵を生成します。

Firebaseでプロジェクトを開き→プロジェクトの設定→サービスアカウントを開きます。
<img width="1659" alt="スクリーンショット 2019-11-21 17.50.19.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/302458/cffdbd2c-1e4b-cda5-824d-076f980ba168.png">

新しい秘密鍵を生成したらファイルができるのでそのファイルをfunctions内のindex.jsと同じ階層に配置します。
これで、Firestoreを操作できるようになります。

では、index.js内でFirestoreにからデータを取得してJSONを返すAPIを作成します。
全体像を貼っておきます。

```index.js
const functions = require('firebase-functions');
const admin = require('firebase-admin');

var serviceAccount = require('./秘密鍵のファイル');
admin.initializeApp({
    credential: admin.credential.cert(serviceAccount),
    databaseURL: "https://プロジェクト名.firebaseio.com"
  });

 admin.credential.applicationDefault()
var db = admin.firestore();
var userDatas = {"users":[]};

exports.GetUserData = functions.https.onRequest((req, res) => {
  db.collection("user").get().then(function(querySnapshot) {
    userDatas = {"users":[]};
    querySnapshot.forEach(function(doc) {
        userDatas.users.push({"email":doc.data().email,"name":doc.data().name});
    });
    var json = JSON.stringify(userDatas);
    res.send(json);
  });
})

```

特にcodeの解説はないのですが、databaseURLのURlの部分は、秘密鍵を生成したサービスアカウントのページで確認できるので、そちらに沿って同じものを記入してください。

```
admin.initializeApp({
    credential: admin.credential.cert(serviceAccount),
    databaseURL: "https://プロジェクト名.firebaseio.com"
  });
```


これでFirestoreのデータを取得して、JSONとして返すものができたのでデプロイしていきます。
デプロイに関してもFirebase Deployという機能があるのでそちらを使用していきたいと思います。
ターミナル上で以下のコマンドを実行！

```
firebase deploy
```

デプロイが完了しましたら、URLが発行されるので（もしでてこなかったらFirebaseのページにいき、Functionsを確認して下さい。）
URLを控えて置きます。
これにて、Firebase側の処理は終了です👍

## ②GASでAPIを叩き、スプレッドシートに記入

では、GAS側の処理をしていきたいと思います。
まずは、emailとnameを取得して、スプレッドシートに記載するようにコーディングします。

```
function fetchUserInfo() {
　var response = UrlFetchApp.fetch("デプロイで発行されたURL"); 
 
  var json=JSON.parse(response.getContentText());
  var jsonCount = json["users"].length;
  
  var emails = [];
  var userNames = [];
  
  for (var i = 0; i < jsonCount; i++) {
    
    emails.push(json["users"][i]["email"]);
    userNames.push(json["users"][i]["name"]);
  };
 
  var sheet = SpreadsheetApp.getActiveSheet();

  /*emailをスプレッドシートに書き込む*/
  for(var i = 0; i <= jsonCount-1; i++) {
    if(!sheet.getRange(i+1, 1).getValue()){ 
      sheet.getRange(i+1, 1).setValue(emails[i]);
    }
  }
  
  /*userNameをスプレッドシートに書き込む*/
  for(var i = 0; i <= jsonCount-1; i++) {
    if(!sheet.getRange(i+1, 2).getValue()){ 
      sheet.getRange(i+1, 2).setValue(userNames[i]);
    }
  }
  
}
```

こちらを実行すると、スプレッドシートにemailとnameが記載されていると思うので確認して下さい。
<img width="368" alt="スクリーンショット 2019-11-21 18.13.05.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/302458/80864e28-a70b-8e4d-38cc-b710f2eb0228.png">


## ③スプレッドシートからユーザー情報を取得し、GASからメールを送信する。

最後に、GAS側でメールを送信していきます。

```
function sendEmail() {
  
  var sheet = SpreadsheetApp.getActiveSheet();
  
  var emails = [];
  var userNames = [];
  
  
  for(var i = 1; i <= 10; i++) {
    if(sheet.getRange(i, 1).getValue()){ 
      emails.push(sheet.getRange(i, 1).getValue())
    }
  }
  
  for(var i = 1; i <= 10; i++) {
    if(sheet.getRange(i, 2).getValue()){ 
      userNames.push(sheet.getRange(i, 2).getValue())
    }
  }
  
  
  for(var i = 0; i <= emails.length-1; i++) {
      var toEmail = emails[i]
      var toName = userNames[i]
      MailApp.sendEmail(toEmail, 'テスト', toName+"様");
  }
  
}
```

これにて完了です！！！！
こちらを実行すると、メールが配信されると思いますのでご確認下さい。


また、メール送信で色々カスタマイズしたいのであればこちらをご参考ください。
[GASでのメール送信についてまとめてみる](https://qiita.com/mistolteen/items/404c10657b1b27007a3c)


## 最後に
今回はGASを経由したメール送信の仕組みを実装したのですが、こちらの方法ではデバックがしずらいなどの問題があったり、GAS側で処理でいる件数に制限があるので、ちょっと工夫しないいけない問題があります。
筆者もまだまだ駆け出しのものなので、この記事に誤りがあったり、他のよい方法があるなら教えていただきたい所存です。
宜しくお願いします。