SciPost Code Repository

Skip to content
Snippets Groups Projects
Commit 5f02d81e authored by Jean-Sébastien Caux's avatar Jean-Sébastien Caux
Browse files

Add ValidatedAddress model

parent aec924d4
No related branches found
No related tags found
No related merge requests found
...@@ -11,7 +11,9 @@ from .models import ( ...@@ -11,7 +11,9 @@ from .models import (
ComposedMessage, ComposedMessageAPIResponse, ComposedMessage, ComposedMessageAPIResponse,
Event, Event,
StoredMessage, StoredMessage,
UserTag) UserTag,
ValidatedAddress, AddressValidation
)
admin.site.register(Domain) admin.site.register(Domain)
...@@ -66,3 +68,15 @@ class UserTagAdmin(admin.ModelAdmin): ...@@ -66,3 +68,15 @@ class UserTagAdmin(admin.ModelAdmin):
pass pass
admin.site.register(UserTag, UserTagAdmin) admin.site.register(UserTag, UserTagAdmin)
class AddressValidationInline(admin.StackedInline):
model = AddressValidation
extra = 0
min_num = 0
class ValidatedAddressAdmin(admin.ModelAdmin):
inlines = [AddressValidationInline,]
admin.site.register(ValidatedAddress, ValidatedAddressAdmin)
# Generated by Django 2.2.16 on 2020-10-24 15:51
import datetime
import django.contrib.postgres.fields.jsonb
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('apimail', '0025_composedmessage_headers_added'),
]
operations = [
migrations.CreateModel(
name='ValidatedAddress',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('address', models.EmailField(max_length=512, unique=True)),
],
options={
'ordering': ['address'],
},
),
migrations.CreateModel(
name='AddressValidation',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('data', django.contrib.postgres.fields.jsonb.JSONField(default=dict)),
('datestamp', models.DateField(default=datetime.date.today)),
('address', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='validations', to='apimail.ValidatedAddress')),
],
options={
'ordering': ['address__address', '-datestamp'],
},
),
]
...@@ -15,3 +15,5 @@ from .event import Event ...@@ -15,3 +15,5 @@ from .event import Event
from .stored_message import StoredMessage from .stored_message import StoredMessage
from .tag import UserTag from .tag import UserTag
from .validated_address import ValidatedAddress, AddressValidation
__copyright__ = "Copyright © Stichting SciPost (SciPost Foundation)" __copyright__ = "Copyright © Stichting SciPost (SciPost Foundation)"
__license__ = "AGPL v3" __license__ = "AGPL v3"
import pytz
#import pytz
import uuid as uuid_lib import uuid as uuid_lib
from django.conf import settings from django.conf import settings
......
__copyright__ = "Copyright © Stichting SciPost (SciPost Foundation)"
__license__ = "AGPL v3"
import datetime
import requests
from django.conf import settings
from django.contrib.postgres.fields import JSONField
from django.db import models
class ValidatedAddress(models.Model):
"""
Email address (lowercased) with related validation info.
The Mailgun email validation v4 API is queried at least once per year
and the response is saved as a related AddressValidation object.
"""
address = models.EmailField(
max_length=512, # as per Mailgun limit
unique=True
)
class Meta:
ordering = ['address',]
def save(self, *args, **kwargs):
self.address = self.address.lower()
return super().save(*args, **kwargs)
def __str__(self):
return self.address
@property
def is_good_for_sending(self):
"""
Return the status of the latest Mailgun validation.
"""
self.update_mailgun_validation()
try:
return self.validations.first().data['result'] \
in ('deliverable', 'catch_all', 'unknown')
except AttributeError:
return False
def update_mailgun_validation(self):
"""
If no validation check within last year, call the Mailgun validation v4 API.
"""
one_year_ago = datetime.date.today() - datetime.timedelta(days=365)
if not self.validations.filter(datestamp__gt=one_year_ago).exists():
response = requests.get(
"https://api.mailgun.net/v4/address/validate",
auth=("api", settings.MAILGUN_API_KEY),
params={"address": self.address}
).json()
validation = AddressValidation(
address=self,
data=response
)
validation.save()
class AddressValidation(models.Model):
"""
For a given ValidatedAddress, timestamped response from a Mailgun API validation v4 query.
"""
address = models.ForeignKey(
'apimail.ValidatedAddress',
related_name='validations',
on_delete=models.CASCADE)
data = JSONField(default=dict)
datestamp = models.DateField(default=datetime.date.today)
class Meta:
ordering = [
'address__address',
'-datestamp'
]
def __str__(self):
return "%s: %s (%s)" % (self.address, self.data['result'], self.datestamp)
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment