emails/validators: miscellaneous adjustments (#32435)
* address preferred mx server * set connection timeout * do not raise validation error on temporary failures * add an option to bypass smtp validation * catch all dns exceptions
This commit is contained in:
parent
133bd51350
commit
4a5b60a95a
|
@ -23,14 +23,14 @@ from django.utils.translation import ugettext_lazy as _
|
|||
|
||||
|
||||
def validate_email_address(value):
|
||||
if not settings.HOBO_VALIDATE_EMAIL_WITH_SMTP:
|
||||
return
|
||||
email_domain = value.split('@')[-1]
|
||||
try:
|
||||
mx_server = dns.resolver.query(email_domain, 'MX')[0].exchange.to_text()
|
||||
except dns.resolver.NXDOMAIN as e:
|
||||
mx_server = sorted(dns.resolver.query(email_domain, 'MX'), key=lambda rdata: rdata.preference)[0].exchange.to_text()
|
||||
except dns.exception.DNSException as e:
|
||||
raise ValidationError(_('Error: %s') % str(e))
|
||||
except dns.resolver.NoAnswer as e:
|
||||
raise ValidationError(_('Error: %s') % str(e))
|
||||
smtp = smtplib.SMTP(timeout=30)
|
||||
smtp = smtplib.SMTP(timeout=10)
|
||||
try:
|
||||
smtp.connect(mx_server)
|
||||
except socket.error as e:
|
||||
|
@ -41,11 +41,9 @@ def validate_email_address(value):
|
|||
raise ValidationError(_('Error while connecting to %(server)s: %(msg)s') % {'server': mx_server, 'msg': msg})
|
||||
smtp.mail('')
|
||||
status, msg = smtp.rcpt(value)
|
||||
if status == 250:
|
||||
smtp.quit()
|
||||
return
|
||||
smtp.quit()
|
||||
raise ValidationError(_('Email address not found on %s') % mx_server)
|
||||
if status // 100 == 5:
|
||||
raise ValidationError(_('Email address not found on %s') % mx_server)
|
||||
|
||||
|
||||
def validate_email_spf(value, strict=False):
|
||||
|
|
|
@ -26,6 +26,7 @@ DEBUG = True
|
|||
|
||||
ALLOWED_HOSTS = []
|
||||
|
||||
HOBO_VALIDATE_EMAIL_WITH_SMTP = True
|
||||
ALLOWED_SPF_RECORDS = []
|
||||
|
||||
# Application definition
|
||||
|
|
|
@ -22,6 +22,9 @@ def dns_resolver(monkeypatch):
|
|||
mx.exchange = mock.create_autospec(name.Name)
|
||||
mx.exchange.to_text = mock.MagicMock()
|
||||
mx.exchange.to_text.return_value = 'localhost:10025'
|
||||
mx.preference = mock.create_autospec(name.Name)
|
||||
mx.preference.to_text = mock.MagicMock()
|
||||
mx.preference.to_text.return_value = 10
|
||||
return [mx]
|
||||
if kind == 'TXT':
|
||||
txt = mock.create_autospec(TXT)
|
||||
|
@ -86,6 +89,11 @@ def test_validate_email_address_socket_error(dns_resolver, monkeypatch):
|
|||
assert 'Error while connecting' in str(e.value)
|
||||
|
||||
|
||||
def test_validate_email_address_bypass(settings):
|
||||
settings.HOBO_VALIDATE_EMAIL_WITH_SMTP = False
|
||||
assert validate_email_address('foo') == None
|
||||
|
||||
|
||||
def test_invalid_address(client, admin_user):
|
||||
client.post('/login/', {'username': 'admin', 'password': 'password'})
|
||||
response = client.post('/emails/', {'default_from_email': 'foobar'})
|
||||
|
|
Loading…
Reference in New Issue