diff --git a/SciPost_v1/settings/base.py b/SciPost_v1/settings/base.py index 51a10963c7c654175f48abce12b0a32f5dc41aa3..048a1ac8bde00ac693a579c240ec4f853b577083 100644 --- a/SciPost_v1/settings/base.py +++ b/SciPost_v1/settings/base.py @@ -489,7 +489,6 @@ ED_ASSIGMENT_DT_DELTA = timedelta(hours=6) # Mailgun credentials -MAILGUN_DOMAIN_NAME = '' MAILGUN_API_KEY = '' # Pawning verification token diff --git a/SciPost_v1/settings/local_JSC.py b/SciPost_v1/settings/local_JSC.py index 03c966d65b8e5a36535260179180af6940ae08ba..98bf0c4dbbe35dc1258649fdaf1ed283104b43e3 100644 --- a/SciPost_v1/settings/local_JSC.py +++ b/SciPost_v1/settings/local_JSC.py @@ -34,7 +34,6 @@ 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') # CORS headers diff --git a/SciPost_v1/settings/staging_do1.py b/SciPost_v1/settings/staging_do1.py index 707705b3351097a504e0a5287815dd33e0a39615..b2812d090e6789b81ce8a67b8ff059cc7580388d 100644 --- a/SciPost_v1/settings/staging_do1.py +++ b/SciPost_v1/settings/staging_do1.py @@ -38,5 +38,4 @@ WSGI_APPLICATION = 'SciPost_v1.wsgi_staging_do1.application' #MONGO_DATABASE['port'] = get_secret('MONGO_DB_PORT') # Mailgun credentials -MAILGUN_DOMAIN_NAME = get_secret('MAILGUN_DOMAIN_NAME') MAILGUN_API_KEY = get_secret('MAILGUN_API_KEY') diff --git a/apimail/management/commands/mailgun_get_events.py b/apimail/management/commands/mailgun_get_events.py index da257277805684d39c62b4505371d720b64b8a41..5a96c6611b69978959d0126d2632e8ca8f0c3efb 100644 --- a/apimail/management/commands/mailgun_get_events.py +++ b/apimail/management/commands/mailgun_get_events.py @@ -8,19 +8,21 @@ from django.conf import settings from django.core.management import BaseCommand from ...exceptions import APIMailError -from ...models import Event +from ...models import Domain, Event -def get_and_save_events(url=None): +def get_and_save_events(url=None, domain_name=None): """ - Get events from Mailgun Events API. + For the given domain, 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. """ + if url is None and domain_name is None: + raise APIMailError('Please provide either a url or domain_name to get_and_save_events.') response = requests.get( - url if url else "https://api.eu.mailgun.net/v3/%s/events" % settings.MAILGUN_DOMAIN_NAME, + url if url else "https://api.eu.mailgun.net/v3/%s/events" % domain_name, auth=("api", settings.MAILGUN_API_KEY) ).json() events = response['items'] @@ -42,11 +44,12 @@ class Command(BaseCommand): help = 'Gets Events from the Mailgun 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') + for domain in Domain.objects.active(): + info = get_and_save_events(domain.name) + 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') diff --git a/apimail/management/commands/mailgun_send_messages.py b/apimail/management/commands/mailgun_send_messages.py index aa4589bfa955309a34141bf2b86c024a2f01b053..790fffcf65c261f0f5c9a336f9d03dda23edaa6f 100644 --- a/apimail/management/commands/mailgun_send_messages.py +++ b/apimail/management/commands/mailgun_send_messages.py @@ -32,7 +32,7 @@ class Command(BaseCommand): for att in msg.attachment_files.all()] response = requests.post( - "https://api.eu.mailgun.net/v3/%s/messages" % settings.MAILGUN_DOMAIN_NAME, + "https://api.eu.mailgun.net/v3/%s/messages" % msg.from_account.domain.name, auth=("api", settings.MAILGUN_API_KEY), files=files, data=data) diff --git a/apimail/management/commands/mailgun_send_test_email.py b/apimail/management/commands/mailgun_send_test_email.py index 76c40f2163a39bbc5de10ff0ede31a4939d56a2e..777c289146dc977b82d1a0af247b184255b6d1cd 100644 --- a/apimail/management/commands/mailgun_send_test_email.py +++ b/apimail/management/commands/mailgun_send_test_email.py @@ -7,24 +7,37 @@ import requests from django.conf import settings from django.core.management import BaseCommand +from ...exceptions import APIMailError +from ...models import Domain + class Command(BaseCommand): def add_arguments(self, parser): + parser.add_argument( + '--from', type=str, required=True, + help='from address') parser.add_argument( '--to', type=str, required=True, help='to address') def handle(self, *args, **options): - data = { - 'to': options.get('to'), - 'from': 'techsupport@%s' % settings.MAILGUN_DOMAIN_NAME, - 'subject': 'Test outgoing email', - 'text': 'Testing outgoing email.' - } - response = requests.post( - "https://api.eu.mailgun.net/v3/%s/messages" % settings.MAILGUN_DOMAIN_NAME, - auth=("api", settings.MAILGUN_API_KEY), - data=data) - print(data) - print(response) + domain_name = options.get('from').rpartition('@')[2] + try: + Domain.objects.active().get(name=domain_name) + data = { + 'from': options.get('from'), + 'to': options.get('to'), + 'subject': 'Test outgoing email', + 'text': 'Testing outgoing email.' + } + response = requests.post( + "https://api.eu.mailgun.net/v3/%s/messages" % domain_name, + auth=("api", settings.MAILGUN_API_KEY), + data=data) + print(data) + print(response) + except Domain.MultipleObjectsReturned: + raise APIMailError('Multiple domains found in mailgun_send_test_email') + except Domain.DoesNotExist: + raise APIMailError('The sending domain was not recognized in mailgun_send_test_email') diff --git a/apimail/managers.py b/apimail/managers.py index f37512358243889b5e0b9a992ac4740d665663e0..c25d3c97fc3c197f5b94e0d7a94fe5f373285dae 100644 --- a/apimail/managers.py +++ b/apimail/managers.py @@ -7,6 +7,12 @@ import datetime from django.db import models +class DomainQuerySet(models.QuerySet): + def active(self): + from apimail.models import Domain + return self.filter(status=Domain.STATUS_ACTIVE) + + class EmailAccountAccessQuerySet(models.QuerySet): def current(self): today = datetime.date.today() diff --git a/apimail/migrations/0023_domain_status.py b/apimail/migrations/0023_domain_status.py new file mode 100644 index 0000000000000000000000000000000000000000..615221464335fde1fa7824c86217f28ec28a8006 --- /dev/null +++ b/apimail/migrations/0023_domain_status.py @@ -0,0 +1,18 @@ +# Generated by Django 2.2.16 on 2020-10-17 08:48 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('apimail', '0022_auto_20201017_1018'), + ] + + operations = [ + migrations.AddField( + model_name='domain', + name='status', + field=models.CharField(choices=[('active', 'Active'), ('archived', 'Archived')], default='active', max_length=16), + ), + ] diff --git a/apimail/models/domain.py b/apimail/models/domain.py index 92184bd46732ccf44aa275285e1a4919dffc8155..d278d8fc229f3af4d16eaff34cf672cdaed50707 100644 --- a/apimail/models/domain.py +++ b/apimail/models/domain.py @@ -4,6 +4,7 @@ __license__ = "AGPL v3" from django.db import models +from ..managers import DomainQuerySet from ..validators import _simple_domain_name_validator @@ -11,11 +12,25 @@ class Domain(models.Model): """ Domain name information. """ + STATUS_ACTIVE = 'active' + STATUS_ARCHIVED = 'archived' + STATUS_CHOICES = ( + (STATUS_ACTIVE, 'Active'), + (STATUS_ARCHIVED, 'Archived') + ) + name = models.CharField( max_length=100, validators=[_simple_domain_name_validator], unique=True, ) + status = models.CharField( + max_length=16, + choices=STATUS_CHOICES, + default=STATUS_ACTIVE + ) + + objects = DomainQuerySet.as_manager() class Meta: ordering = ('name',)