SendGridの送信履歴は数週間しか残らないので,履歴を保存するために,Webhookを利用して自分のサーバーに記録する仕組みを用意しなければなりません.
Google Cloud Functionsを利用して,かんたんにPythonで実装してみました.とりあえずverifyできるかを試すために,ログにverified
変数の結果を出力するようにしました.認証できたら,目的のデータであるpayload
変数がSendGridによって提供されたデータであると言えます.
ソースコード
hello_http
関数を用意しました.functions_frameworkはFlaskの派生なので,request
変数はFlaskの流儀で処理しました.
main.py
import os import functions_framework from sendgrid.helpers.eventwebhook import EventWebhook ew = EventWebhook(public_key=os.getenv("PUBLIC_KEY")) @functions_framework.http def hello_http(request): signature = request.headers.get("X-Twilio-Email-Event-Webhook-Signature") timestamp = request.headers.get("X-Twilio-Email-Event-Webhook-Timestamp") print(f"signature={signature}") print(f"timestamp={timestamp}") if not (signature and timestamp): return "No signature." payload = request.get_data(as_text=True) print(f"payload={payload}") verified = ew.verify_signature( payload=payload, signature=signature, timestamp=timestamp ) print(f"verified={verified}") return "OK"
requirements.txt
functions-framework==3.0.0 sendgrid==6.9.5
デプロイ
これをCloud Functionsにデプロイします.SendGridでWebhookの設定をして,テストメールを送信したところ,以下のようにpayload
変数に意図したデータが格納されていました.
payload = [ { "email": "xxxxxxx@example.com", "event": "processed", "send_at": 0, "sg_event_id": "WxxdkLTIyNTU3MjUwLVhMNkxUSG9KUmdPN3JDODJoWExSdssv", "sg_message_id": "XL6RgO7rC82hXLRvg.filterdrecv-55446c3d49-64rbq-1-61A2C9C1-85.0", "smtp-id": "<XL6RgO7rC82hXLRvg@geopod-ismtpd-1-1>", "timestamp": 1643301326, }, { "email": "xxxxxx@example.com", "event": "delivered", "ip": "xxx.xxx.xxx.xxx", "response": "250 2.0.0 OK 1643301329 a14si333819qtx.25 - gsmtp", "sg_event_id": "WxxdkXZlcmVkLTAtMjI1NTcyNTAtWEw2TFRIb0pSZ083ckM4MmhYWExSdssv", "sg_message_id": "XL6RgO7rC82hXLRvg.filterdrecv-55446c3d49-64rbq-1-61A2C9C1-85.0", "smtp-id": "<XL6RgO7rC82hXLRvg@geopod-ismtpd-1-1>", "timestamp": 1643301329, "tls": 1, }, ]
対応
送信メールのリクエストと,Webhookのデータを対応させるために,custom_argsを使用すると便利です.メール送信時にcustom_argsに適当な識別子を設定し,Webhookを受信したら一致する識別子を持つ送信データを検索します.
値段
1ヶ月に1万件のメールをSendGridで送信した履歴をCloud Functionsで処理するために必要な費用を計算しました.CPUとメモリーの割当は最小(Memory: 128MB CPU: 200MHz)で,1回あたりの平均実行時間は100ms以下でしたのでこれで十分です.料金を計算したところ0円でした.
データの保存先をログにすれば,ほぼ料金は発生しないので,お財布にやさしいです.なお,データベースに保存するならば別途費用が発生すると思われます.