Vue.js＋CloudFunctions＋SendGridで自動でメール送信をする

## 概要
- Vue.jsとFirebaseを使ってメール通知機能を実装しましたので、備忘録を残します。

## 環境
Windows10
Visual Studio Code(1.73.0)
firebase-tools 11.16.0
vue 3.2.41

## 前提条件
- 以下項目がインストール済み、環境構築済みの前提です。まだの方は先にそれらを実施してください。

- [Node.js](https://nodejs.org/ja/)のダウンロード・インストール済み
- [Vue CLI](https://cli.vuejs.org/) のインストール済み  
```terminal
npm install -g @vue/cli
```

- Vue.jsのプロジェクトを作成
```terminal
vue create my-project
※my-project には好きな名称を設定すればOK
```
- Vue.jsプロジェクトに[CloudFunctions](https://firebase.google.com/docs/functions/get-started?hl=ja)を導入する。

## SendGridのAPI KEYを発行する。

- 以前投稿した記事([SendGridのAPIを作成する](https://qiita.com/zono345/items/25740d8875d893492840))を参照してください  


## SendGridをnpm install
- Node.js向けのSendGridヘルパーライブラリをインストールします
- ルートディレクトリではなく、functionsディレクトリにインストールが必要です。
```terminal:my-project/functions
npm install @sendgrid/mail
```
  
  
  
  
## 実装例(サンプルコード)
- [公式ブログ(twilio)](https://www.twilio.com/blog/how-to-send-emails-in-javascript-with-sendgrid)　や　[公式ブログ(構造計画研究所)](https://sendgrid.kke.co.jp/blog/?p=12390)　も参考になります。
```javascript:my-project/functions/index.js
const sgMail = require('@sendgrid/mail');
sgMail.setApiKey(process.env.SENDGRID_API_KEY);
const msg = {
  to: test@example.com',
  from: 'test@example.com',
  subject: 'Sending with SendGrid is Fun',
  text: 'and easy to do anywhere, even with Node.js',
  html: '<strong>and easy to do anywhere, even with Node.js</strong>',
};
sgMail.send(msg);

```

  
## より具体的な実装例
- Cloud Firestore にドキュメントが作成されたらメール送信するサンプルコードです
    - セキュリティの観点から、API KEYはコードに直接記載するのではなく、SECRETを活用するのが望ましいです。
    - `.runWith({ secrets: ["API_KEY_SENDGRID"] })` の部分はAPI KEYをSECRETに登録が必要です。([SECRETに関する公式ドキュメント](https://firebase.google.com/docs/functions/config-env?hl=ja&authuser=0#secret-manager))
  
  
```javascript:my-project/functions/index.js
const functions = require("firebase-functions");
const admin = require('firebase-admin');
admin.initializeApp()
const sgMail = require('@sendgrid/mail');
const { region } = require("firebase-functions");

exports.sendMailCreateDocument = functions.region('asia-northeast1')
    .runWith({ secrets: ["API_KEY_SENDGRID"] })
    .firestore.document("user/{user_id}")
    .onCreate(async (snap, context) => {
        // createされたドキュメントを取得
        const newDoc = snap.data()

        // 必要なフィールドを取得
        const name = newDoc.name
        const age = newDoc.age
        const address = newDoc.address
        const uid = newDoc.uid

        // email宛先
        let emailTo = ""
        await admin.auth().getUser(uid).then((userRecord) => {
            emailTo = userRecord.email
        })
        .catch((error) => {
            console.log(error)
            return
        });

        // 送信メール内容
        const emailFrom = "info@hoge.co.jp"
        const emailSubject = "【ホゲホゲサービス】ユーザー登録完了のお知らせ"
        const emailText = "ユーザー登録完了しました。\n\n氏名: "+name+"\n年齢: "+age+"\n住所: "+address
        const msg = {
            to: emailTo,
            from: emailFrom,
            subject: emailSubject,
            text: emailText,
        }

        // sendgridのメール送信APIキーをセット
        sgMail.setApiKey(process.env.API_KEY_SENDGRID)

        // メール送信
        await sgMail.send(msg)
            .then(() => {
                console.log("メール送信成功")
            })
            .catch((error) => {
                console.log("メール送信失敗 -> error :", error)
            })
    });
        
```

## デプロイ
- 最後にfunctionsをデプロイして完了です。([デプロイの公式ドキュメント](https://firebase.google.com/docs/functions/get-started?hl=ja&authuser=0#deploy-functions-to-a-production-environment))
  
```terminal:my-project
firebase deploy --only functions
```