Skip to content

Commit

Permalink
Merge e3acaa4 into 90e59c7
Browse files Browse the repository at this point in the history
  • Loading branch information
ThomasWaldmann committed Oct 14, 2018
2 parents 90e59c7 + e3acaa4 commit c7bf6dc
Show file tree
Hide file tree
Showing 2 changed files with 103 additions and 0 deletions.
76 changes: 76 additions & 0 deletions nsupdate/accounts/registration_form.py
@@ -0,0 +1,76 @@
# -*- coding: utf-8 -*-

import os
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."))
27 changes: 27 additions & 0 deletions nsupdate/settings/base.py
Expand Up @@ -51,6 +51,32 @@
from netaddr import IPSet, IPAddress, IPNetwork
BAD_IPS_HOST = IPSet([]) # inner list can have IPAddress and IPNetwork elements

# nameservers used e.g. for MX lookups in the registration email validation
# TODO: this is nsupdate.info site specific:
# - we only have ipv6 (thus transform the v4 addrs to v6)
# - dnspython stumbles over our own scoped ipv6 nameserver ip (fe80::1%eth0,
# see https://github.com/rthalley/dnspython/issues/283 ), so we use google / cloudflare :-|
NAMESERVERS = ['64:ff9b::8.8.8.8', '64:ff9b::1.1.1.1', ]

# domains that have a non-working mx / that are frequently abused:
MAILDOMAIN_BLACKLIST = """
babau\.ga$
bezeqint\.net$
everytg\.ml$
flu\.cc$
goerieblog\.com$
igg\.biz$
lady-and-lunch\.xyz$
mailcatch\.com$
mailspam\.xyz$
napalm51\.gq$
nut\.cc$
pine-and-onyx\.xyz$
stars-and-glory\.top$
usa\.cc$
xoxy\.net$
"""

# Local time zone for this installation. Choices can be found here:
# http://en.wikipedia.org/wiki/List_of_tz_zones_by_name
# although not all choices may be available on all operating systems.
Expand Down Expand Up @@ -245,6 +271,7 @@

ACCOUNT_ACTIVATION_DAYS = 7
REGISTRATION_EMAIL_HTML = False # we override the text, but not the html email template
REGISTRATION_FORM = 'nsupdate.accounts.registration_form.RegistrationFormValidateEmail'

LOGIN_REDIRECT_URL = '/overview/'
LOGOUT_REDIRECT_URL = '/'
Expand Down

0 comments on commit c7bf6dc

Please sign in to comment.