Compare commits

...

3 Commits

Author SHA1 Message Date
Raphael Michel
fe5a2286a4 Update cache handling 2021-01-01 20:13:09 +01:00
Raphael Michel
3d66bfee7f Update checkout.py 2021-01-01 20:13:09 +01:00
Raphael Michel
0b495a4070 Validate email addresses fo valid DNS names 2021-01-01 20:13:09 +01:00
3 changed files with 48 additions and 4 deletions

View File

@@ -1,6 +1,8 @@
from itertools import chain from itertools import chain
import dns.resolver
from django import forms from django import forms
from django.core.cache import cache
from django.core.exceptions import ValidationError from django.core.exceptions import ValidationError
from django.utils.encoding import force_str from django.utils.encoding import force_str
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
@@ -18,12 +20,52 @@ from pretix.base.validators import EmailBanlistValidator
from pretix.presale.signals import contact_form_fields from pretix.presale.signals import contact_form_fields
class EmailDNSValidator:
msg = _('Please check your email domain, it does not look like "%(value)s" is able to receive emails.')
def __call__(self, value):
domain = value.split('@')[-1]
works = cache.get(f"mail_domain_exists_{domain}")
if works == "true":
return value
if works == "false":
raise ValidationError(self.msg, code='dns', params={'value': domain})
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 (dns.resolver.NoAnswer, dns.resolver.NXDOMAIN, dns.resolver.YXDOMAIN):
# These errors represent a non-existing domain or entry, we want to continue with the
# other types of records and if all fail, we'll report an error.
continue
except:
# Timeout, IO errors, etc.: We don't know what's happening! Let's not stop the user
# from buying and just not validate this. Let's cache this result for a short while
# to prevent issues during peak load
cache.set(f"mail_domain_exists_{domain}", "false", 60)
return value
# No valid record found, even though the requests did not fail. This domain will not receive email.
# Cache this result for a short time.
cache.set(f"mail_domain_exists_{domain}", "false", 300)
raise ValidationError(self.msg, code='dns', params={'value': domain})
class ContactForm(forms.Form): class ContactForm(forms.Form):
required_css_class = 'required' required_css_class = 'required'
email = forms.EmailField(label=_('E-mail'), email = forms.EmailField(
validators=[EmailBanlistValidator()], label=_('E-mail'),
widget=forms.EmailInput(attrs={'autocomplete': 'section-contact email'}) validators=[
) EmailBanlistValidator(),
EmailDNSValidator(),
],
widget=forms.EmailInput(attrs={'autocomplete': 'section-contact email'})
)
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
self.event = kwargs.pop('event') self.event = kwargs.pop('event')

View File

@@ -44,6 +44,7 @@ oauthlib==3.1.*
django-jsonfallback>=2.1.2 django-jsonfallback>=2.1.2
psycopg2-binary psycopg2-binary
tqdm==4.* tqdm==4.*
dnspython==1.16.*
# Stripe # Stripe
stripe==2.42.* stripe==2.42.*
# PayPal # PayPal

View File

@@ -134,6 +134,7 @@ setup(
'django-i18nfield>=1.7.0', 'django-i18nfield>=1.7.0',
'django-jsonfallback>=2.1.2', 'django-jsonfallback>=2.1.2',
'psycopg2-binary', 'psycopg2-binary',
'dnspython==1.16.*',
'tqdm==4.*', 'tqdm==4.*',
'vobject==0.9.*', 'vobject==0.9.*',
'pycountry', 'pycountry',