✉️

SendGrid のInbound Email Parse Webhook で受け取ったメールから添付ファイルを取得する

2023/11/07に公開

SendGrid の公式で、 Python のサンプルを見ると Flask だったので、 FastAPI だったらどう書くかメモ。
結論、FastAPI らしい書き方で書くことはできず、Flask の書き方とほぼ同一になってしまった 😢(理由は後述)

コード


@router.post(
    "/webhook",
    status_code=status.HTTP_200_OK,
)
async def sendgrid_webhook( # 1
    request: Request,
):
    form = await request.form()
    headers = form.get("headers")
    envelope = form.get("envelope")
    subject = form.get("subject")
    text = form.get("text")
    html = form.get("html")
    charsets = form.get("charsets")
    num_attachments = int(form.get("attachments")) # 2

    attachments = []
    for i in range(1, num_attachments + 1):
        uploaded_file: UploadFile = form.get(f"attachment{i}") # 3
        if uploaded_file is not None:
            contents = await uploaded_file.read()
            attachments.append(
                {
                    "filename": uploaded_file.filename,
                    "contents": contents,
                    "type": uploaded_file.content_type,
                }
            )
		return {"message": "ok" }

  1. もともと Webhook のエンドポイントは同期関数で書いていたが、Request オブジェクトを扱う都合上、非同期関数が必須になる。
    実際のコードでは、同期処理だった部分は starlette.concurrency.run_in_threadpool メソッドに押し込んだ。
  2. Inbound Email Parse Webhook では attachments に添付ファイルの数が str 型で渡されるので、 int にキャストする
  3. 実際の添付ファイルのデータ部分は attachment{n} と動的なので、ループで回して取得する必要がある。この引数名が動的なため、Request オブジェクトを使わざるを得なかった。

参考

Python - Parse Webhook


/以上

GitHubで編集を提案

Discussion