Google Cloud上のSPAに問い合わせフォームを作る!SendGridによるメール送信

Google Cloud上のSPAに問い合わせフォームを作る!SendGridによるメール送信

Cloud StorageやApp EngineにデプロイしたSPA(Single Page Application)に問い合わせフォームを作りたいという方は多いはずです。

また、問い合わせページを作成したけど、どのようにメールを送信するべきか迷う方もいらっしゃると思います。

そういった方を対象に、Google Cloudの公式ドキュメントで推奨している方法を利用して、問い合わせフォームからメールを送信する方法を紹介します!

完成物のイメージです。

  • Cloud Functionsにメール送信用のAPIを公開(python)
  • SendGridのWebAPIを利用したメール送信
  • 1ヶ月12,000通のメールまで無料

概要

この記事で紹介する方法では、Cloud FunctionsにSendGridを利用したメール送信機能を持つアプリケーションをデプロイし、デプロイしたアプリケーションに対してSPAからリクエストを送信することで問い合わせ機能を実現します。

まず、SendGridやCloudFunctionsnを利用する理由や利点について説明します。

実装方法だけ知りたいという方はこの章は飛ばしてください。

SendGridとは

SendGridは、クラウドベースのSMTPプロバイダで、メール送信が可能なwebサービスです(公式サイト:https://sendgrid.kke.co.jp/)。

2021年6月では、Google CloudにはAWSのAmazon SESのようなサービスはありません(ないよね…?)。

そのため、メール送信方法として、公式ドキュメントにおいてもSendGrid, Mailgun, Mailjetといったサードパーティのメールサービスを利用した方法を紹介しています(例:SendGrid でのメールの送信)。

これらの中でも、下記の利点があるので、個人的にはSendGridの利用がおすすめです。

SendGridのgithubには、python, PHP, java, nodejsなどの言語ごとにリポジトリが作成されており、READMEに簡単なサンプルプログラムが公開されています。

READMEを読むだけで公式の推奨利用方法がわかるので、非常に助かりますね。

また、毎月12,000通まで無料で利用できるというのも非常に嬉しいです。

Cloud Functionsの利用理由

GCPの公式ドキュメントではCompute Engine(CE)を利用した方法を紹介していますが、CEではゼロスケーリングができないのでお金がかかってしまいます。

従量課金性+ゼロスケーリング可能+メール送信機能のみという特徴を考慮して、Cloud Functionsにメール送信アプリケーションをデプロイすることにしました。

ただ、CEやCloudFunctionsの他にAppEngineでも利用可能なはずなので、好きなプラットフォームで良いと思います。

メール送信機能の実装

それでは作成していきます、全体の流れは下記になります。

  1. SendGridのアカウント作成
  2. SendGridのAPIキーの取得
  3. プログラムの作成
  4. Cloud Functionsへのデプロイ

SendGridのアカウント作成

公式サイトからアカウントの作成を行います(https://sendgrid.kke.co.jp/)。

気をつけるべきポイントとして、アカウントの作成に約1営業日かかります

アカウントは早めに作成しましょう。

SendGridのAPIキーの取得

SendGridでアカウント登録後、アカウント名が送られてくるので、そのアカウントでログインします。

ログイン後、”Settings”タブから”API Keys”をクリックします。API Key Nameを入力して、Full Access権限でキーを作成します。

1. 左タブの”Settings”から”API Keys”を選択して、右上のボタンから作成
2. API keyの名前を入力して、”Full Access”でキーを作成

プログラムの作成

Cloud Functions上で動作するプログラムを作成します。

まず、プログラムはこちらです。リクエストのバリデーションなどは自分で追加してください。

from flask import Flask, request, make_response
import os
import sendgrid
from sendgrid.helpers.mail import Email, To, Content, Mail


def sample(request):
    # 取得したAPIKeyを環境変数SENDGRID_API_KEYにいれる
    SENDGRID_API_KEY = os.environ.get('SENDGRID_API_KEY')
    TO_EMAIL = os.environ.get('TO_EMAIL')
    FROM_EMAIL = os.environ.get('FROM_EMAIL')

    req_args = request.args
    sg = sendgrid.SendGridAPIClient(api_key=SENDGRID_API_KEY)
    message = (
        'from: {}\n'
        'Email: {}\n'
        'msg:\n{}'.format(
            req_args["name"],
            req_args["email"],
            req_args["msg"])
    )

    mail = Mail(
        Email(FROM_EMAIL),
        To(TO_EMAIL),
        "Email from Cloud Functions",
        Content("text/plain", message)
    )

    _ = sg.client.mail.send.post(request_body=mail.get())
    return make_response('', 200)


if __name__ == '__main__':
    app = Flask(__name__)

    @app.route('/sample', methods=['GET'])
    def call_function():
        return sample(request)

    app.run(debug=True, host='0.0.0.0', port=5000)

Cloud Functionsへのデプロイで必要なrequirements.txtは下記です。

blinker==1.4
click==8.0.1
Flask==1.0.2
itsdangerous==2.0.1
Jinja2==3.0.1
MarkupSafe==2.0.1
mccabe==0.6.1
pycodestyle==2.7.0
pyflakes==2.3.1
python-http-client==3.3.2
sendgrid==6.7.0
starkbank-ecdsa==1.1.1
toml==0.10.2
Werkzeug==2.0.1

あとは、ローカル環境で動作確認後、Cloud Functionsにデプロイしましょう。

下記では.env.yamlを利用してAPIキーを環境変数に代入していますが、SecretManagerを利用するほうがセキュリティ的には正しいと思います。

# ローカル環境でのテストリクエスト例
$ curl -v "http://localhost:5000/sample?email=test@gmail.com&msg=hoge&name=huga"

# 問題がなければ、Cloud Functionsへデプロイ
# デプロイコマンドの例
$ gcloud functions deploy sample_for_sendgrid \
    --runtime python38 \
    --trigger-http \
    --allow-unauthenticated \
    --region=us-central1 \
    --env-vars-file .env.yaml

# Cloud Functionsに対して、動作確認
$ curl -v "https://.../sample?..."

SPAとの連携

連携というほどのものではありませんが、、、

SPAの問い合わせフォームのボタンを押したときに、上記で作成したCloud FunctionsのエンドポイントへGETリクエストを送信するように変更しましょう。

上記では、クエリパラメータとしてemail, msg, nameを適当に使いましたが、このあたりは各自適当に変更してください。

まとめ

この記事では、Cloud Functions + SendGridを利用してメール送信機能を持つAPIを作成しました。

SPAから作成したエンドポイントに対してリクエストを送ることで、問い合わせフォームからメールを送信することが可能になります。

Google検索でGCP上のメール送信方法を調べると、Firebase+gmailを利用した方法が多く見られます。ただ、Google Cloudで完結可能なので、わざわざFirebaseを利用する必要はないです(実際にはFirebaseもGoogle Cloud上で動作していますが…)。

また、Gmailのアカウント情報+信頼性の低いアプリケーションからのログインを許可する必要があるので、セキュリティ的にもよろしくないかなと個人的には考えています。