Firebaseの技術情報サイト

Firebaseの技術情報サイト

Firebase活用の為の技術情報サイトです

FirebaseとSendGridを使って送信者の登録を行うには?

FirebaseとSendGridを使って送信者の登録を行うには?

FirebaseとSendGridを利用してメルマガ(ニュースレター)のサービスを実装する場合には、単にメッセージを送信するだけではなく、SendGridといろいろな情報を取得する必要があります。

今日は、メッセージの送信者の登録を中心にお届けします。

前回、SendGridに登録されているメッセージ配信先の取得についてお届けしました。

SendGridのAPIの定義の仕方を見るとわかりますが、SendGridとのやり取りの操作の内容は大きく分けると:

  • データの追加
  • データの取得(読み出し)
  • データの更新
  • データの削除

になります。例外もありますが、これをHTTPのメソッドで分類して区別しています。

操作 HTTP method 送信データ 備考
データの追加 POST 登録データ
データの取得 GET なし 一括取得
個別取得
データの更新 PATCH 更新データ
データの削除 DELETE データのID

前回の例では、SendGridに登録されている送付先の一括取得の詳細をお伝えしました。

基本的なバックエンドの処理は同じ!

データの操作方法や対象とするデータによって詳細のコードは変わってきます。 しかし基本的な処理の「枠組み」は同じです。

app.post(URL,(req:express.Request, res:express.Response) => {
    // 登録の処理
})
app.get(URL,(req:express.Request, res:express.Response) => {
    // データ取得の処理
})
app.patch(URL,(req:express.Request, res:express.Response) => {
    // データ更新の処理
})
app.delete(URL,(req:express.Request, res:express.Response) => {
    // データ削除の処理
})

のように、expressのフレームワークでバックエンドのリクエストに使われるHTTPのメソッドにより同じURLでも処理の中身を変えることができます。

さらに各処理の流れは、

  • フロントエンドからのデータを受け取る
  • SendGridサーバーへのリクエストの送信(転送)
  • SendGridサーバーからの応答の受信
  • フロントエンドへの応答の送信

という流れでこれも基本的には共通です。

フロントエンドからのデータはデータはURLの一部として、クエリーパラメータで送る場合もありますが、ほとんどはURLにはデータを含めずに送る場合が殆どです。SendGridのAPIでは、基本的にHTTPのGETメソッドの場合は、認証のための情報以外は送る必要がありません。それ以外のメソッドでは、メッセージのボディ(body)として送られてきます。 送信者を登録する場合は、送信者の情報がフロントエンドからバックエンドに送られます。これを取得する例です。


const sender: Sender = req.body.sender;

送信者(sender)の型の定義は以下の様に別のファイル(constants.ts)で行っています。

interface Sender {
    nickname:string;
    email:string;
    name: string;
    address: string;
    address_2:string;
    city:string;
    state:string;
    zip:string;
    country:string;
}

データがない場合は、「undefined」を使うことができますが、今回の実装では、データがない場合は「""」を入れて文字列(string)として処理する方法を選びました。

これを取得して、SendGridのサーバーに送るデータを作成してSendGridのサーバーに必要なデータを含めた含めたリクエストを送ります。あとは、SendGridからの応答を処理すれば管理用です。SendGridとのやり取りもHTTPで行わえるので、npmのモジュール「axios」を使うと簡単に実装できます。

    // フロントエンドからのデータを取得
    const sender: TYPE.Sender = req.body.sender;
    // SendGrid のURLとAPI
    const url:string = SENDGRID_API + CONSTANTS.SG_API_SENDERS;
    // SendGridに送信するデータの準備
    const options:any {
        method: "POST", // 処理によって指定するHTTPのメソッドを変える
        url: url,
        headers: {
            // SendGridサーバーにアクセスするための認証情報
            Authorization: "Bearer " + SG_API_KEY
        },
        // 送信するデータ(SendGridのドキュメントを参照して必要なデータを準備)
        data: {
            nickname: sender.nickname,
            from:{
                email: sender.email,
                name: sender.name
            },
            reply_to: {
                email: sender.email,
                name: sender.name
            },
            address: sender.address,
            address_2: sender.address_2,
            city: sender.city,
            state: sender.state,
            zip: sender.zip,
            country: sender.country
        },
        json:true
    };
    // SendGridサーバーにリクエストを送信
    axios(options).then((response:AxiosResponse) => {
        // 正常終了の場合の処理
        // GetでデータをSendGridサーバから取得する場合、取得したデータをフロントエンドに転送
        // それ以外は結果のみを返送
        res.end(JSON.stringify({success:true}))
    }).catch((error: any) => {
        // エラーが発生した場合
        res.end(JSON.stringify({success:false}))
    })

以上がバックエンド処理の基本フローです。必要に応じて、HTTPのメソッド、送信先のURL(API)、送信するデータを変えるだけです。データの取得や削除(DELETE)をする場合は送付するデータは不要で、必要なのはHTTPのメソッドとURL(API)と認証情報です。個別の取得や削除の場合は送信先のURL(API)に選択されたデータのIDを埋め込むようなインターフェースになっています。

フロントエンドの処理も基本は同じ!

フロントエンドでバックエンドとのデータをやり取りする部分はバックエンドのSendGridとデータをやり取りする部分とほぼ同じ作り方になります。フロントエンドでデータを準備する段階でSendGridに送付するデータに近い形のデータが作れると、実装も楽になります。

必要なデータをユーザーインターフェースから受け取って、バックエンドに転送する処理になるためほぼ同じ実装で実現できます。

addSender(sender: TYPE.Sender): Promise<boolean> {
    return new Promise((resolve): void => {
      // バックエンドの送付先URL(API)
      const url: string = this.url + CONSTANT.API_SENDERS;
      // バックエンドに送信するデータ
      const options: any = {
        url: url,
        method: "POST",
        data: sender,
      };
      // バックエンドに送信
      axios(options)
        .then((response: AxiosResponse): void => {
          // 正常終了の場合
          resolve(response.data.success);
        })
        .catch((error: any): void => {
          // エラーが発生した場合
          resolve(false);
        });
    });
  }
}

あとは、ユーザーインターフェースの実装です。送信者を追加する場合は送信者の情報を入力するフォームを作成して送信すればよいことになります。更新の場合も似たようなフォームを作って更新データを送信します。

データを取得する場合は、データを一括取得して一覧を表示するようにします。更新、削除といった処理を実装する場合は、データの一覧から処理する対象のデータ(送信登録者の一覧の場合は特定の送信登録者)を選択してIDを取得するような実装が必要です。

render() {
    return (
      <form
        className="sender_form"
        action={CONSTANT.HOST_URL + CONSTANT.API_SENDERS}
        method="post"
      >
        <div className="form-group">
          <label>表示名</label>
          <input
            className="form-control"
            type="text"
            name="nickname"
            value={this.state.nickname}
            onChange={(e: React.ChangeEvent<HTMLInputElement>) =>
              this.updateNickname(e)
            }
          />
        </div>
        <div className="form-group">
          <label>E-Mail</label>
          <input
            className="form-control"
            type="text"
            name="email"
            value={this.state.email}
            onChange={(e: React.ChangeEvent<HTMLInputElement>) =>
              this.updateEmail(e)
            }
          />
        </div>
        <div className="form-group">
          <label>名前</label>
          <input
            className="form-control"
            type="text"
            name="name"
            value={this.state.name}
            onChange={(e: React.ChangeEvent<HTMLInputElement>) =>
              this.updateName(e)
            }
          />
        </div>
        <div className="form-group">
          <label>郵便番号</label>
          <input
            className="form-control"
            type="text"
            name="zip"
            value={this.state.zip}
            onChange={(e: React.ChangeEvent<HTMLInputElement>) =>
              this.updateZip(e)
            }
          />
        </div>
        <div className="form-group">
          <label>国</label>
          <input
            className="form-control"
            type="text"
            name="country"
            value={this.state.country}
            onChange={(e: React.ChangeEvent<HTMLInputElement>) =>
              this.updateCountry(e)
            }
          />
        </div>
        <div className="form-group">
          <label>県</label>
          <input
            className="form-control"
            type="text"
            name="state"
            value={this.state.state}
            onChange={(e: React.ChangeEvent<HTMLInputElement>) =>
              this.updateState(e)
            }
          />
        </div>
        <div className="form-group">
          <label>市町村</label>
          <input
            className="form-control"
            type="text"
            name="city"
            value={this.state.city}
            onChange={(e: React.ChangeEvent<HTMLInputElement>) =>
              this.updateCity(e)
            }
          />
        </div>
        <div className="form-group">
          <label>住所</label>
          <input
            className="form-control"
            type="text"
            name="address"
            value={this.state.address}
            onChange={(e: React.ChangeEvent<HTMLInputElement>) =>
              this.updateAddress(e)
            }
          />
        </div>
        <div className="form-group">
          <label>住所2</label>
          <input
            className="form-control"
            type="text"
            name="address_2"
            value={this.state.address_2}
            onChange={(e: React.ChangeEvent<HTMLInputElement>) =>
              this.updateAddress2(e)
            }
          />
        </div>
        <button
          className="btn btn-primary"
          type="button"
          onClick={() => this.submit()}
        >
          登録
        </button>
      </form>
    );
  }

フォームの記述の例を挙げておきました。 フォームの送信はHTMLからも可能ですが、今回はReactを使うことが前提でJavascriptが有効になっていない場合はReactのフレームワーク自体が使えないので、Javascriptでデータをバックエンドで送っても問題ではありません。 フロントエンドで入力データを処理できると事前に入力の不備などもチェックできるので便利です。

まとめ

前回のSendGridに登録されている送信先の一括取得と同じ要領で、SendGridにメッセージの送信者を登録する場合の実装について例を挙げなら解説してきました。

データの違いよりは処理の違い(GETとPOST)による違いが判れば、この記事で解説していることは良いかと思います。処理の流れ自体は同じです。

ユーザーインターフェースから処理が始まって、バックエンドにデータを渡して返答を受け取るという流れは共通です。