From ce125b63011414b7616b54243645bc80b873cce5 Mon Sep 17 00:00:00 2001
From: "J.-S. Caux" <J.S.Caux@uva.nl>
Date: Wed, 13 Nov 2019 14:37:44 +0100
Subject: [PATCH] Add management command to get Events from Mailgun Events API

---
 SciPost_v1/settings/base.py                   |  5 ++
 SciPost_v1/settings/local_JSC.py              |  4 ++
 apimail/exceptions.py                         | 10 ++++
 .../management/commands/mailgun_get_events.py | 52 +++++++++++++++++++
 4 files changed, 71 insertions(+)
 create mode 100644 apimail/exceptions.py
 create mode 100644 apimail/management/commands/mailgun_get_events.py

diff --git a/SciPost_v1/settings/base.py b/SciPost_v1/settings/base.py
index 37eb332de..35b254683 100644
--- a/SciPost_v1/settings/base.py
+++ b/SciPost_v1/settings/base.py
@@ -433,3 +433,8 @@ CELERY_IMPORTS = ('submissions.tasks',)
 
 # Automation.
 ED_ASSIGMENT_DT_DELTA = timedelta(hours=6)
+
+
+# Mailgun credentials
+MAILGUN_DOMAIN_NAME = ''
+MAILGUN_API_KEY = ''
diff --git a/SciPost_v1/settings/local_JSC.py b/SciPost_v1/settings/local_JSC.py
index b66489105..925c9ce53 100644
--- a/SciPost_v1/settings/local_JSC.py
+++ b/SciPost_v1/settings/local_JSC.py
@@ -29,3 +29,7 @@ EMAIL_BACKEND_ORIGINAL = "mails.backends.filebased.EmailBackend"
 # CSP
 CSP_REPORT_URI = get_secret('CSP_SENTRY')
 CSP_REPORT_ONLY = True
+
+# Mailgun credentials
+MAILGUN_DOMAIN_NAME = get_secret('MAILGUN_DOMAIN_NAME')
+MAILGUN_API_KEY = get_secret('MAILGUN_API_KEY')
diff --git a/apimail/exceptions.py b/apimail/exceptions.py
new file mode 100644
index 000000000..25085986c
--- /dev/null
+++ b/apimail/exceptions.py
@@ -0,0 +1,10 @@
+__copyright__ = "Copyright © Stichting SciPost (SciPost Foundation)"
+__license__ = "AGPL v3"
+
+
+class APIMailError(Exception):
+    def __init__(self, name):
+        self.name = name
+
+    def __str__(self):
+        return 'API Mail error: {}'.format(self.name)
diff --git a/apimail/management/commands/mailgun_get_events.py b/apimail/management/commands/mailgun_get_events.py
new file mode 100644
index 000000000..49135e738
--- /dev/null
+++ b/apimail/management/commands/mailgun_get_events.py
@@ -0,0 +1,52 @@
+__copyright__ = "Copyright © Stichting SciPost (SciPost Foundation)"
+__license__ = "AGPL v3"
+
+
+import requests
+
+from django.conf import settings
+from django.core.management import BaseCommand
+
+from ...exceptions import APIMailError
+from ...models import Event
+
+
+def get_and_save_events(url=None):
+    """
+    Get events from Mailgun Events API.
+
+    This method treats a single page and saves new Events to the database.
+    If no url is given, get the first page.
+    Returns the paging JSON, if present, so traversing can be performed.
+    """
+    response = requests.get(
+        url if url else "https://api.eu.mailgun.net/v3/%s/events" % settings.MAILGUN_DOMAIN_NAME,
+        auth=("api", settings.MAILGUN_API_KEY)
+    ).json()
+    events = response['items']
+    for item in events:
+        if not Event.objects.filter(data__timestamp=item['timestamp'],
+                                    data__id=item['id']).exists():
+            Event.objects.create(data=item)
+    info = {'nitems': len(events)}
+    if 'paging' in response:
+        info['paging'] = response['paging']
+    return info
+
+
+class Command(BaseCommand):
+    """
+    Perform a GET request to harvest Events from the Mailgun API, saving them to the DB.
+    """
+
+    help = 'Gets Events from the Maigun Events API and saves them to the DB.'
+
+    def handle(self, *args, **kwargs):
+        info = get_and_save_events()
+        ctr = 1 # Safety: ensure no runaway requests
+        while ctr < 100 and info['nitems'] > 0:
+            info = get_and_save_events(url=info['paging']['next'])
+            ctr += 1
+            if ctr == 100:
+                raise APIMailError('Hard stop of mailgun_get_events: '
+                                   'harvested above 100 pages from Mailgun Events API')
-- 
GitLab