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