SendGridのEventWebhookでBounceイベントがPostされたのにメールは送信できていた話

# はじめに
これは[モチベーションクラウドAdvent Calendar](https://qiita.com/advent-calendar/2018/mcs) 18日目の記事です。

モチベーションクラウドではメール配信にSendGridを利用させていただいています。
![SG_Logo_Blog.jpg](https://qiita-image-store.s3.amazonaws.com/0/296657/fdc67fe8-4615-a304-543a-c8495ad0a639.jpeg)

この記事では先日、SendGridのEvent Webhookの挙動に関して、SendGrid日本代理店へ問い合わせして得られたちょっとした知見を書いていきます。

# 前提
SendGridには[Event Webhook](https://sendgrid.kke.co.jp/docs/API_Reference/Webhooks/event.html#-Parameter-Details)機能があり、メールを送信する際に発生するイベントを指定のURLにPOSTできます。

モチベーションクラウドではこのEvent Webhookを利用して、受信側メールサーバへ正常に配信できなかったメールの一覧をエラーメール一覧機能として提供しています。
具体的には[Email Activity](https://sendgrid.kke.co.jp/docs/User_Manual_JP/email_activity.html#-Email-Events)の `deferred` `drops` `bounces` `block`などが発生したメールをエラーメールと位置付けています。


# 起きたこと
とあるお客様からエラーメール一覧に表示されているメールが正常に受信できている旨の問い合わせがありました。
Event WebhookのPOST先サーバログを確認したところ、以下、2件のEventがPOSTされていました。

1. 09:05:16に`deliverd`イベントがPOSTされる

```09_05_16.log(一部抜粋)
    {
      "email": "sample-1@***.com",
      "event": "delivered",
      "ip": "******",
      "response": "250 Message accepted for delivery"
    }
```
2. 09:09:52に`bounce`イベント(`type:blocked`)がPOSTされる

```09_09_52.log(一部抜粋)
    {
      "status": "5.0.0",
      "reason": "552 We failed to deliver mail because the volume of recipient's mailbox exceeded the local limit. sample-2@***.com",
      "event": "bounce",
      "email": "sample-1@***.com",
      "type": "blocked"
    }
```

# 今回のEvent Webhookの挙動に対する疑問

- [このページのイベントツリー](https://sendgrid.kke.co.jp/docs/User_Manual_JP/email_activity.html#-Email-Events)を 見る限り、
`delivered`イベントと`bounce`イベントはどちらかに切り分けられるように見えるが違うのか。
なぜ、`deliverd`イベントの直後に`bounce`イベントが発生しているのか。

- `bounce`イベントの`reason`を見る限り、[ソフトバウンス](https://sendgrid.kke.co.jp/docs/Tutorials/A_Transaction_Mail/manage_bounces.html#-Softbounces-And-Hardbounces)である。
ソフトバウンスの際は、`deferred`イベントが発生し、72時間自動再送をしてもだめだった場合に`block`イベントが発生するとあるが、なぜ、今回は`deferred`イベントが発生していないのか。


# 問い合わせた内容とその回答(一部抜粋)

## 1回目の問い合わせ

```1回目の問い合わせ内容(一部抜粋).log
下記の事象が発生したため、SendGrid側のEventWebhookの仕様を確認させてください。
【発生事象】
1. 09:05:16に`deliverd`イベントがPOSTされる
    {
      "email": "sample-1@***.com",
      "event": "delivered",
      "ip": "******",
      "response": "250 Message accepted for delivery"
    }
2. 09:09:52に`bounce`イベントがPOSTされる
    {
      "status": "5.0.0",
      "reason": "552 We failed to deliver mail because the volume of recipient's mailbox exceeded the local limit. sample-2@***.com",
      "event": "bounce",
      "email": "sample-1@***.com",
      "type": "blocked"
    }
3. 該当ユーザーへのメールは正常に送信される


【質問事項】
1.
受信者のメールボックスが一杯等のソフトバウンスはdeferredイベントが発生すると記載されておりますが、
短時間にbounceが発生する原因は何が考えられるでしょうか？

2.
deliverdが発生後、bounceが発生するのは想定される挙動でしょうか？

```

## 1回目の回答

```1回目の回答(一部抜粋).log
各ご質問へ回答する前に、事象に関してご説明いたします。

ご連絡いただいた事象は、3で該当ユーザが正常に受信されていることから
宛先サーバが「sample-1@***.com」宛てのメールを正常に受信したのち
転送設定などによって他の宛先へ送信しようとして、そこでバウンスが発生したものかと存じます。

エラー内容は宛先サーバによって異なるため、推測となりますが
メッセージにある「sample-2@***.com」への転送でバウンスしたと考えられます。

Deferredイベントによる再送は宛先のメールアドレスに対するものであるため、
今回のような転送先ではイベントが発生いたしません。
バウンスのTypeは応答内容によってbounceかblockedか決まり、
今回はblockedイベントと識別されたものとなります。

以上より、ご連絡の以下状況となったかと存じます。
・宛先の「sample-1@***.com」にはメールが正常に届き、Deliveredイベントが発生した
・転送先の宛先でエラーとなったため、Blockedイベントが発生した


> 1.
> 受信者のメールボックスが一杯等のソフトバウンスはdeferredイベントが発生すると記載されておりますが、
> 短時間にbounceイベントが発生する原因は何が考えられるでしょうか？

前述のとおり、今回の場合は宛先の先でバウンスが発生したため、
deferredは発生せずblockedイベントが発生したものとなります

> 2.
> deliverdが発生後、bounceが発生するのは想定される挙動でしょうか？

今回のケースに限らず、宛先へリレーする中で問題が起きるケースはございます。
遅延バウンスと呼ばれるもので、詳細については以下をご確認いただけますでしょうか。
https://support.sendgrid.kke.co.jp/hc/ja/articles/206128762

```

## 2回目の問い合わせ

```2回目の問い合わせ(一部抜粋).log
【質問事項】
1. 宛先メールアドレスで起きたバウンスなのか転送設定されたメールアドレス起きたバウンスなのかの切り分けなどはできないでしょうか？
2. 転送設定されたメールアドレスがソフトバウンスの場合はdeferredは発生しないとのことですが、一定時間（72時間）自動的に再送も行われない認識で良いですか？
```

## 2回目の回答

```2回目の回答(一部抜粋).log
> 1. 宛先メールアドレスで起きたバウンスなのか転送設定されたメールアドレス起きたバウンスなのかの切り分けなどはできないでしょうか？
今回のようにバウンスのREASONによってはある程度の推測が可能なこともあるかと存じますが、
REASONは宛先サーバごとによって異なるため、切り分けはできません。

> 2. 転送設定されたメールアドレスがソフトバウンスの場合はdeferredは発生しないとのことですが、一定時間（72時間）自動的に再送も行われない認識で良いですか？
以前ご回答差し上げたとおり、転送先の送信は
宛先サーバが行う送信であり、SendGridは関与しないため、
応答内容をみたイベントは発生せず、再送も行いません。

```

# まとめ
- [遅延バウンス](https://support.sendgrid.kke.co.jp/hc/ja/articles/206128762)や今回の転送先メールアドレスで配送不能となった場合は、`deliverd`イベントの後に`bounce`イベントが発生する
- 転送先の送信はSendGridが関与せず、宛先サーバーが行う送信のため、`deferred`イベントは発生しない。しかし配送不能レポート（Non-Delivery Report/NDR）はSendGridに返るため、`bounce`イベントが発生する。
- 転送先メールアドレスでのバウンスか宛先メールアドレスでのバウンスかは正確な切り分けはできない。