サーバーレスアーキテクチャで静的サイトをホスティングしたいけど、お問い合わせのメールは送りたい、というときに読む記事です。
技術的には、
- Google Cloud Functions(Firebase のプラットフォームとして提供されているサーバーレス関数:AWS Lambda と同じような機能の GCP版)、
- Mailgun(メールを API を叩くことで送信してくれるサービス:AWS SES みたいなもの)
の 2つを使います。
動機
なんでこんなことをしたいかと言うと、Angular や React.js で SPA的に静的サイトを作る際に、メールだけは送りたいとか、この情報だけはユーザーの見えるところに置いておけないという要望があるためです。
この場合、通常であれば別途アプリケーションサーバーを用意して独自の処理を書いたりするのですが、それすら面倒くさい最小のサーバーでさえコストが合わない、オートスケールさせたいという状況に出くわしたので、従量課金かつオートスケールする Cloud Functions を使用します。
この記事を書いた動機は、至極単純に日本語の記事がなかったので、です。
書いてないこと
基本的に Cloud Functions や Mailgun がなにか、という説明は書きません(括弧書きの中で少し書いていますが)。
僕自身がこういった数行のまとめを読んで、「このサービス、完璧に理解した!」という経験が無いので、実例を通してなんとなくこういうものかな?という推測を積み重ねていった後に説明を読めば良いと思います。
想定読者
-
gcloud
コマンドラインツールを用いて GCP の設定や運用がある程度できる。
Cloud Functions概要
Cloud Functions は、node.js の形式でファイルをデプロイするといい感じにエントリーポイントを作って機能を提供してくれるサービスです。
まずは雛形を作ります。
- 例えば適当に
sample
というディレクトリを作って、その直下にindex.js
というファイルを置きます。 - 次に、
sample
ディレクトリの中でnpm init
を実行して、package.json
を作ります。 -
npm install
を実行しておきます(何も追加してないのであまり面白いことは起きません)。 -
index.js
を次のように変更します。
'use strict';
exports.sampleAction = (req, res) => {
res.send(`you said ${req.body}`);
}
- GCP のプロジェクトを設定します。
# このプロジェクトは firebase console に載っているものの方が良い気がします。
# https://console.firebase.google.com/u/0/?hl=ja
#
# ...が、GCP上だけで作ったプロジェクトで試してないので真偽はわかりません。
# 試してみてわかった方がいらっしゃいましたら教えてください。
$ gcloud config set project プロジェクトID
- 以下のコマンドでデプロイします。
$ gcloud beta functions deploy sampleAction --trigger-http --region asia-northeast1
おめでとう!これで初めての cloud functions が完成だ!
というわけで、デプロイした後に表示された httpsTrigger:
の後の URL に curl
とかでなにか送ると、リクエストをオウム返しする機能が完成しました。
Mailgun を Cloud Functions で使うために
Mailgun を node.js上で走らせるためには、(自分で API を叩くライブラリを作ってももちろん良いですが)mailgun公式のライブラリを使用します。
https://github.com/mailgun/mailgun-js
使い方は github を見てもらえば分かると思います。
どこかのページを見たら API が古かったので、公式を参照するほうが良いです。
Mailgun でどうやってメール送信の設定するの?ということに関しては、「mailgun 設定」とかでググるといっぱい記事が出てくるので割愛します。
昔はクレジットカード登録しなくても月1,000件くらいまで遅れた気がしますが、現在は無料の範囲でもクレカ登録必須になりました。
さて、先程作成した sample というプロジェクトを修正していくことにしましょう。
まず、sample
ディレクトリの直下で
$ npm i --save mailgun.js
を実行します。
次に、index.js
を次のように書き換えます。
'use strict';
const API_KEY = 'YOUR_MAILGUN_API_KEY';
const DOMAIN = 'YOUR_DOMAIN';
const mailgun = require('mailgun.js');
// mailgun client
const client = mailgun.client({
username: 'api',
key: API_KEY,
})
exports.sampleAction = (req, res) => {
client.messages.create(DOMAIN, data)
.then(msg => console.log(msg))
.catch(err => console.error(err));
}
YOUR_...
のところは適宜書き換えてください。
はい、これでオウム返しをメール経由でできるようになりました。
あとはこのエントリーポイントをフロント側から叩けばメール送信機能の完成です。
本番運用に向けて
簡単のため、いくつか本番環境では好ましくないところを残しています。
-
API_KEY
とDOMAIN
はソースコードから分離して、例えば環境変数などで管理するべき - CORS対応(ドメイン制限含む)
- データの永続化(firebase realtime DB などに接続する)
- 許可しない HTTP Method への対応
本記事ではこれらの設定は特に書きません。
まとめ
正直、メール送信くらいの機能であれば、別途アプリケーションサーバーを用意するよりも全然楽です。
とりあえずサクッと作ってコスト最小で出したい!ってときには良い選択肢なのではないでしょうか?