SendGrid APIでハマったところ

記事タイトルとURLをコピーする

はじめに

こんにちは。プロセスエンジニアリング部の谷です。
SendGrid APIで手こずったところを紹介します。

SendGridとは

sendgrid.kke.co.jp

SendGridとは確実なメール配信、高い処理性能と安定性、豊富な分析機能などの特徴を持つメール配信サービスです。
弊社でもメールマガジンやキャンペーンメール、障害時の一斉通知などに利用しています。

ハマったところ

既存のシステム

SendGridではCSVファイルをアップロードして宛先の追加を行うことができます。

sendgrid.kke.co.jp

手間とセキュリティの観点から、SendGridへの宛先追加を自動で行うスクリプトを作成しました。

処理の中身は以下の通りです。

現在SendGridに登録されている宛先一覧を取得する

上記リストをもとに宛先の削除を行う

新規宛先リストをもとに複数の宛先の追加を行う

問題

一部の宛先がSendGridへ追加されていないことが判明しました。
Contacts APIは、非同期処理で行われるため、削除が完了する前に宛先の追加処理が始まってしまい、複数宛先の追加レスポンスにあるunmodified_indicesに値が入ってしまうのが原因でした。

重複した宛先をアップロードしたり、元の宛先に変更のない要求を送信した場合、元の宛先は変更されず、そのindexがunmodified_indicesリストに追加されます。Contacts API

解決策

処理を以下のとおりに変更しました。

現在SendGridに登録されている宛先一覧を取得する

上記リストをもとに現在の宛先の削除を行う

宛先件数のチェックを行う(宛先削除の確認)
↓ 0件なら次へ
上記確認後、新規宛先リストをもとに複数の宛先の追加を行う

なにかしらの理由で追加されなかった宛先のリトライ処理を行う

宛先削除のレスポンスに進捗度を示すようなオブジェクトがないので、無限ループと宛先数の取得を用いました。
これにより非同期処理が完了するまで待つことができるので、エラーが発生しなくなりました。

# IDリストをもとに宛先を削除
delete_response = sendgrid.request_sendgrid('DELETE', url, recipients_id_list)
try:
  delete_response.raise_for_status()
except Exception as e:
  logger.error(e)
# 削除が完了したことを確認
while True:
  count_response = sendgrid.request_sendgrid('GET', url+'/count', '')
  logger.info(count_response.text)
  count_response_dict = json.loads(count_response.text)
  if count_response_dict['recipient_count'] != 0:
        time.sleep(30)
        continue
  else:
        break

まとめ

もっとスマートな解決策がないものか...