PC

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

  • この記事を書いた人

たかけの夫。IT系コンサルティング会社に勤務し、主にクラウドや機械学習に関するコンサルティング業務を行う三十路男。IT技術・投資に興味を持ち、家族と楽に人生を楽しみたい人。

-PC
-