From 0b495a4070a76fddbcd548ea7f6550a5a75b8a5b Mon Sep 17 00:00:00 2001 From: Raphael Michel Date: Wed, 2 Sep 2020 19:41:24 +0200 Subject: [PATCH] Validate email addresses fo valid DNS names --- src/pretix/presale/forms/checkout.py | 39 +++++++++++++++++++++++++--- src/requirements/production.txt | 1 + src/setup.py | 1 + 3 files changed, 37 insertions(+), 4 deletions(-) diff --git a/src/pretix/presale/forms/checkout.py b/src/pretix/presale/forms/checkout.py index b8e5a223e..052a06971 100644 --- a/src/pretix/presale/forms/checkout.py +++ b/src/pretix/presale/forms/checkout.py @@ -1,6 +1,8 @@ from itertools import chain +import dns from django import forms +from django.core.cache import cache from django.core.exceptions import ValidationError from django.utils.encoding import force_str from django.utils.translation import gettext_lazy as _ @@ -18,12 +20,41 @@ from pretix.base.validators import EmailBanlistValidator from pretix.presale.signals import contact_form_fields +class EmailDNSValidator(): + def __call__(self, value): + domain = value.split('@')[-1] + works = cache.get(f"mail_domain_exists_{domain}") + if works: + return value + + resolver = dns.resolver.Resolver() + resolver.lifetime = 0.5 + resolver.timeout = 0.5 + record_types = ('MX', 'AAAA', 'A') + for record_type in record_types: + try: + if len(resolver.query(domain, record_type)): + cache.set(f"mail_domain_exists_{domain}", "true", 3600 * 24 * 7) + return value + except: + continue + raise ValidationError( + _('Please check your email domain, it does not look like "%(value)s" is able to receive emails.'), + code='dns', + params={'value': domain}, + ) + + class ContactForm(forms.Form): required_css_class = 'required' - email = forms.EmailField(label=_('E-mail'), - validators=[EmailBanlistValidator()], - widget=forms.EmailInput(attrs={'autocomplete': 'section-contact email'}) - ) + email = forms.EmailField( + label=_('E-mail'), + validators=[ + EmailBanlistValidator(), + EmailDNSValidator(), + ], + widget=forms.EmailInput(attrs={'autocomplete': 'section-contact email'}) + ) def __init__(self, *args, **kwargs): self.event = kwargs.pop('event') diff --git a/src/requirements/production.txt b/src/requirements/production.txt index 2fe5ccbb9..52fd46b4d 100644 --- a/src/requirements/production.txt +++ b/src/requirements/production.txt @@ -44,6 +44,7 @@ oauthlib==3.1.* django-jsonfallback>=2.1.2 psycopg2-binary tqdm==4.* +dnspython==1.16.* # Stripe stripe==2.42.* # PayPal diff --git a/src/setup.py b/src/setup.py index 67a9848b3..3302c9487 100644 --- a/src/setup.py +++ b/src/setup.py @@ -134,6 +134,7 @@ setup( 'django-i18nfield>=1.7.0', 'django-jsonfallback>=2.1.2', 'psycopg2-binary', + 'dnspython==1.16.*', 'tqdm==4.*', 'vobject==0.9.*', 'pycountry',