|
7 | 7 | from django.utils.timezone import utc |
8 | 8 |
|
9 | 9 | from .base import AnymailBaseWebhookView |
10 | | -from ..exceptions import AnymailWebhookValidationFailure, AnymailInvalidAddress |
| 10 | +from ..exceptions import AnymailConfigurationError, AnymailWebhookValidationFailure, AnymailInvalidAddress |
11 | 11 | from ..inbound import AnymailInboundMessage |
12 | 12 | from ..signals import inbound, tracking, AnymailInboundEvent, AnymailTrackingEvent, EventType, RejectReason |
13 | 13 | from ..utils import get_anymail_setting, combine, querydict_getfirst, parse_single_address |
@@ -200,6 +200,12 @@ def mailgun_legacy_to_anymail_event(self, esp_event): |
200 | 200 | # to avoid potential conflicting user-data. |
201 | 201 | esp_event.getfirst = querydict_getfirst.__get__(esp_event) |
202 | 202 |
|
| 203 | + if 'event' not in esp_event and 'sender' in esp_event: |
| 204 | + # Inbound events don't (currently) have an event field |
| 205 | + raise AnymailConfigurationError( |
| 206 | + "You seem to have set Mailgun's *inbound* route " |
| 207 | + "to Anymail's Mailgun *tracking* webhook URL.") |
| 208 | + |
203 | 209 | event_type = self.legacy_event_types.get(esp_event.getfirst('event'), EventType.UNKNOWN) |
204 | 210 | timestamp = datetime.fromtimestamp(int(esp_event['timestamp']), tz=utc) # use *last* value of timestamp |
205 | 211 | # Message-Id is not documented for every event, but seems to always be included. |
@@ -319,12 +325,27 @@ class MailgunInboundWebhookView(MailgunBaseWebhookView): |
319 | 325 | signal = inbound |
320 | 326 |
|
321 | 327 | def parse_events(self, request): |
| 328 | + if request.content_type == "application/json": |
| 329 | + esp_event = json.loads(request.body.decode('utf-8')) |
| 330 | + event_type = esp_event.get('event-data', {}).get('event', '') |
| 331 | + raise AnymailConfigurationError( |
| 332 | + "You seem to have set Mailgun's *%s tracking* webhook " |
| 333 | + "to Anymail's Mailgun *inbound* webhook URL. " |
| 334 | + "(Or Mailgun has changed inbound events to use json.)" |
| 335 | + % event_type) |
322 | 336 | return [self.esp_to_anymail_event(request)] |
323 | 337 |
|
324 | 338 | def esp_to_anymail_event(self, request): |
325 | 339 | # Inbound uses the entire Django request as esp_event, because we need POST and FILES. |
326 | 340 | # Note that request.POST is case-sensitive (unlike email.message.Message headers). |
327 | 341 | esp_event = request |
| 342 | + |
| 343 | + if request.POST.get('event', 'inbound') != 'inbound': |
| 344 | + # (Legacy) tracking event |
| 345 | + raise AnymailConfigurationError( |
| 346 | + "You seem to have set Mailgun's *%s tracking* webhook " |
| 347 | + "to Anymail's Mailgun *inbound* webhook URL." % request.POST['event']) |
| 348 | + |
328 | 349 | if 'body-mime' in request.POST: |
329 | 350 | # Raw-MIME |
330 | 351 | message = AnymailInboundMessage.parse_raw_mime(request.POST['body-mime']) |
|
0 commit comments