nsupdate.info/nsupdate/accounts/registration_form.py
Thomas Waldmann 7dcf5a22bb validate domain of email address in registration form, fixes #284
- via DNS (MX, A/AAAA records)
- against blacklist with regexes

This is implemented because without it, postmasters get tons of mailer daemon
emails each day, just because emails are invalid, domain has no mx, ...
2018-10-14 14:52:52 +02:00

76 lines
2.4 KiB
Python

# -*- coding: utf-8 -*-
import re
import logging
logger = logging.getLogger(__name__)
from django import forms
from django.conf import settings
from django.utils.translation import ugettext_lazy as _
from registration.forms import RegistrationForm
import dns.resolver
import dns.name
resolver = dns.resolver.Resolver()
resolver.search = [dns.name.root, ]
resolver.lifetime = 5.0
resolver.nameservers = settings.NAMESERVERS
maildomain_blacklist = settings.MAILDOMAIN_BLACKLIST.strip().splitlines()
def check_mx(domain):
valid = False
try:
mx_answers = resolver.query(domain, 'MX')
# domain exists in DNS, domain has MX
mx_entries = sorted([(mx_rdata.preference, mx_rdata.exchange) for mx_rdata in mx_answers])
for preference, mx in mx_entries:
try:
addr_answers = resolver.query(mx, 'A')
except dns.resolver.NoAnswer:
addr_answers = resolver.query(mx, 'AAAA')
# MX has IP addr
mx_addrs = [addr_rdata.address for addr_rdata in addr_answers]
for mx_addr in mx_addrs:
if mx_addr not in (u'127.0.0.1', u'::1', u'0.0.0.0', ):
valid = True
break
if valid:
break
except (dns.resolver.Timeout, dns.resolver.NoAnswer, dns.resolver.NoNameservers, dns.resolver.NXDOMAIN, ):
# expected exceptions (e.g. due to non-existing or misconfigured crap domains)
pass
return valid
def check_blacklist(domain):
for blacklisted_re in maildomain_blacklist:
if re.search(blacklisted_re, domain):
return False
return True
class RegistrationFormValidateEmail(RegistrationForm):
def clean_email(self):
"""
Validate the supplied email address to avoid undeliverable email and mailer daemon spam.
"""
email = self.cleaned_data.get('email')
valid_mx = False
try:
domain = email.split('@')[1]
valid_mx = check_mx(domain)
except Exception as e:
logger.exception('RegistrationFormValidateEmail raised an exception:')
not_blacklisted = check_blacklist(domain)
if valid_mx and not_blacklisted:
return email
logger.info('RegistrationFormValidateEmail: rejecting email address %r' % email)
raise forms.ValidationError(_("Enter a valid email address."))